feat(campaign): filter reports from outcome counts
This commit is contained in:
85
webui/src/features/campaigns/utils/reportGridShortcuts.ts
Normal file
85
webui/src/features/campaigns/utils/reportGridShortcuts.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
export type ReportGridQueryState = {
|
||||
sort: { columnId: string; direction: "asc" | "desc" } | null;
|
||||
filters: Record<string, string>;
|
||||
};
|
||||
|
||||
export const DEFAULT_REPORT_GRID_SORT = { columnId: "number", direction: "asc" as const };
|
||||
|
||||
export type ReportGridShortcutId =
|
||||
| "all"
|
||||
| "smtp_accepted"
|
||||
| "failed"
|
||||
| "outcome_unknown"
|
||||
| "not_attempted"
|
||||
| "smtp_skipped"
|
||||
| "cancelled"
|
||||
| "imap_appended"
|
||||
| "imap_failed"
|
||||
| "imap_skipped";
|
||||
|
||||
const REPORT_GRID_SHORTCUT_FILTERS: Record<ReportGridShortcutId, Record<string, string>> = {
|
||||
all: {},
|
||||
smtp_accepted: { send: listFilter(["smtp_accepted", "sent"]) },
|
||||
failed: { send: listFilter(["failed_temporary", "failed_permanent"]) },
|
||||
outcome_unknown: { send: listFilter(["outcome_unknown"]) },
|
||||
not_attempted: { send: listFilter(["not_queued"]) },
|
||||
smtp_skipped: { send: listFilter(["skipped"]) },
|
||||
cancelled: { send: listFilter(["cancelled"]) },
|
||||
imap_appended: { imap: listFilter(["appended"]) },
|
||||
imap_failed: { imap: listFilter(["failed"]) },
|
||||
imap_skipped: { imap: listFilter(["skipped"]) }
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the complete grid query for a count shortcut. Shortcuts are exact
|
||||
* report views, so applying one intentionally clears every unrelated filter
|
||||
* and restores the stable report ordering.
|
||||
*/
|
||||
export function reportGridQueryForShortcut(shortcutId: ReportGridShortcutId): ReportGridQueryState {
|
||||
return {
|
||||
sort: { ...DEFAULT_REPORT_GRID_SORT },
|
||||
filters: { ...REPORT_GRID_SHORTCUT_FILTERS[shortcutId] }
|
||||
};
|
||||
}
|
||||
|
||||
/** Applying an already selected outcome shortcut returns to the unfiltered report. */
|
||||
export function toggleReportGridShortcut(
|
||||
current: ReportGridQueryState,
|
||||
shortcutId: ReportGridShortcutId
|
||||
): ReportGridQueryState {
|
||||
const target = reportGridQueryForShortcut(shortcutId);
|
||||
if (shortcutId !== "all" && reportGridFiltersEqual(current.filters, target.filters)) {
|
||||
return reportGridQueryForShortcut("all");
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
export function activeReportGridShortcut(query: ReportGridQueryState): ReportGridShortcutId | null {
|
||||
const shortcutIds = Object.keys(REPORT_GRID_SHORTCUT_FILTERS) as ReportGridShortcutId[];
|
||||
return shortcutIds.find((shortcutId) => reportGridFiltersEqual(
|
||||
query.filters,
|
||||
REPORT_GRID_SHORTCUT_FILTERS[shortcutId]
|
||||
)) ?? null;
|
||||
}
|
||||
|
||||
export function reportGridQueriesEqual(left: ReportGridQueryState, right: ReportGridQueryState): boolean {
|
||||
if ((left.sort?.columnId ?? "") !== (right.sort?.columnId ?? "")) return false;
|
||||
if ((left.sort?.direction ?? "") !== (right.sort?.direction ?? "")) return false;
|
||||
const keys = new Set([...Object.keys(left.filters), ...Object.keys(right.filters)]);
|
||||
for (const key of keys) {
|
||||
if ((left.filters[key] ?? "") !== (right.filters[key] ?? "")) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function listFilter(values: string[]): string {
|
||||
return `list:${JSON.stringify(values)}`;
|
||||
}
|
||||
|
||||
function reportGridFiltersEqual(left: Record<string, string>, right: Record<string, string>): boolean {
|
||||
const keys = new Set([...Object.keys(left), ...Object.keys(right)]);
|
||||
for (const key of keys) {
|
||||
if ((left[key] ?? "") !== (right[key] ?? "")) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user