export type ReportGridQueryState = { sort: { columnId: string; direction: "asc" | "desc" } | null; filters: Record; }; export const DEFAULT_REPORT_GRID_SORT = { columnId: "number", direction: "asc" as const }; export type ReportGridShortcutId = | "all" | "smtp_accepted" | "smtp_active" | "smtp_queued" | "postbox_accepted" | "print_accepted" | "failed" | "outcome_unknown" | "not_attempted" | "smtp_skipped" | "cancelled" | "imap_appended" | "imap_failed" | "imap_pending" | "imap_active" | "imap_unknown" | "imap_skipped"; const REPORT_GRID_SHORTCUT_FILTERS: Record> = { all: {}, smtp_accepted: { send: listFilter(["smtp_accepted", "sent"]) }, smtp_active: { send: listFilter(["claimed", "sending"]) }, smtp_queued: { send: listFilter(["queued"]) }, postbox_accepted: { send: listFilter(["postbox_accepted"]) }, print_accepted: { send: listFilter(["print_accepted"]) }, 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_pending: { imap: listFilter(["pending"]) }, imap_active: { imap: listFilter(["appending"]) }, imap_unknown: { imap: listFilter(["outcome_unknown"]) }, 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, right: Record): 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; }