From fb68d192a64e6e8243fdfdfbbba5e65d76b827c0 Mon Sep 17 00:00:00 2001 From: kraysent Date: Sun, 22 Feb 2026 18:46:51 +0000 Subject: [PATCH 1/2] Add modification date to table list page --- src/pages/Tables.tsx | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/pages/Tables.tsx b/src/pages/Tables.tsx index cc8048f..05e6b57 100644 --- a/src/pages/Tables.tsx +++ b/src/pages/Tables.tsx @@ -86,6 +86,17 @@ interface TablesResultsProps { loading?: boolean; } +function formatModificationDate(isoString: string): string { + const d = new Date(isoString); + return d + .toLocaleDateString("en-US", { + month: "short", + day: "2-digit", + year: "numeric", + }) + .replace(",", ""); +} + function TablesResults({ data, loading }: TablesResultsProps): ReactElement { const columns: Column[] = [ { @@ -100,6 +111,7 @@ function TablesResults({ data, loading }: TablesResultsProps): ReactElement { { name: "Description" }, { name: "Number of records" }, { name: "Number of columns" }, + { name: "Modification date" }, ]; const tableData: Record[] = @@ -108,6 +120,9 @@ function TablesResults({ data, loading }: TablesResultsProps): ReactElement { Description: table.description, "Number of records": table.num_entries, "Number of columns": table.num_fields, + "Modification date": table.modification_dt + ? formatModificationDate(table.modification_dt) + : "—", })) ?? []; return ; From bb48d1851b75227485b316c51c3fa335eebf1bc0 Mon Sep 17 00:00:00 2001 From: kraysent Date: Sun, 22 Feb 2026 19:03:48 +0000 Subject: [PATCH 2/2] #35: add triage status to crossmatch list page --- src/assets/texts.json | 4 ++- src/pages/CrossmatchResults.tsx | 60 ++++++++++++++++++++++++++++++--- 2 files changed, 58 insertions(+), 6 deletions(-) diff --git a/src/assets/texts.json b/src/assets/texts.json index 2a48371..b296860 100644 --- a/src/assets/texts.json +++ b/src/assets/texts.json @@ -6,6 +6,8 @@ "crossmatch.status.unprocessed": "Unprocessed", "crossmatch.status.new": "New", "crossmatch.status.collided": "Collided", - "crossmatch.status.existing": "Existing" + "crossmatch.status.existing": "Existing", + "crossmatch.triage.pending": "Pending", + "crossmatch.triage.resolved": "Resolved" } } diff --git a/src/pages/CrossmatchResults.tsx b/src/pages/CrossmatchResults.tsx index de1891f..456fd01 100644 --- a/src/pages/CrossmatchResults.tsx +++ b/src/pages/CrossmatchResults.tsx @@ -13,6 +13,7 @@ import type { GetRecordsCrossmatchResponse, RecordCrossmatch, RecordCrossmatchStatus, + RecordTriageStatus, ValidationError, } from "../clients/admin/types.gen"; import { getResource } from "../resources/resources"; @@ -27,28 +28,44 @@ import { adminClient } from "../clients/config"; interface CrossmatchFiltersProps { tableName: string | null; status: RecordCrossmatchStatus | null; + triageStatus: string | null; pageSize: number; - onApplyFilters: (tableName: string, status: string, pageSize: number) => void; + onApplyFilters: ( + tableName: string, + status: string, + triageStatus: string, + pageSize: number, + ) => void; } function CrossmatchFilters({ tableName, status, + triageStatus, pageSize, onApplyFilters, }: CrossmatchFiltersProps): ReactElement { const [localStatus, setLocalStatus] = useState(status || "all"); + const [localTriageStatus, setLocalTriageStatus] = useState( + triageStatus ?? "pending", + ); const [localPageSize, setLocalPageSize] = useState(pageSize); const [localTableName, setLocalTableName] = useState(tableName || ""); useEffect(() => { setLocalStatus(status || "all"); + setLocalTriageStatus(triageStatus ?? "pending"); setLocalPageSize(pageSize); setLocalTableName(tableName || ""); - }, [status, pageSize, tableName]); + }, [status, triageStatus, pageSize, tableName]); function applyFilters(): void { - onApplyFilters(localTableName, localStatus, localPageSize); + onApplyFilters( + localTableName, + localStatus, + localTriageStatus, + localPageSize, + ); } return ( @@ -73,6 +90,16 @@ function CrossmatchFilters({ value={localStatus} onChange={setLocalStatus} /> + { @@ -159,6 +191,7 @@ function CrossmatchResults({ data?.records.map((record: RecordCrossmatch, index: number) => ({ "Record name": index, Status: getStatusLabel(record.status), + "Manual check status": getTriageStatusLabel(record.triage_status), Candidates: index, })) || []; @@ -168,6 +201,7 @@ function CrossmatchResults({ async function fetcher( tableName: string | null, status: RecordCrossmatchStatus | null, + triageStatus: RecordTriageStatus | null, page: number, pageSize: number, ): Promise { @@ -180,6 +214,7 @@ async function fetcher( query: { table_name: tableName, status: status, + triage_status: triageStatus, page: page, page_size: pageSize, }, @@ -205,6 +240,13 @@ export function CrossmatchResultsPage(): ReactElement { const tableName = searchParams.get("table_name"); const status = searchParams.get("status") as RecordCrossmatchStatus | null; + const triageStatusParam = searchParams.get("triage_status"); + const apiTriageStatus: RecordTriageStatus | null = + triageStatusParam === null || triageStatusParam === "" + ? "pending" + : triageStatusParam === "all" + ? null + : (triageStatusParam as RecordTriageStatus); const page = parseInt(searchParams.get("page") || "0"); const pageSize = parseInt(searchParams.get("page_size") || "25"); @@ -213,8 +255,8 @@ export function CrossmatchResultsPage(): ReactElement { }, [tableName]); const { data, loading, error } = useDataFetching( - () => fetcher(tableName, status, page, pageSize), - [tableName, status, page, pageSize], + () => fetcher(tableName, status, apiTriageStatus, page, pageSize), + [tableName, status, apiTriageStatus, page, pageSize], ); function handlePageChange(newPage: number): void { @@ -226,6 +268,7 @@ export function CrossmatchResultsPage(): ReactElement { function handleApplyFilters( newTableName: string, newStatus: string, + newTriageStatus: string, newPageSize: number, ): void { const newSearchParams = new URLSearchParams(searchParams); @@ -242,6 +285,12 @@ export function CrossmatchResultsPage(): ReactElement { newSearchParams.set("status", newStatus); } + if (newTriageStatus === "all") { + newSearchParams.set("triage_status", "all"); + } else { + newSearchParams.set("triage_status", newTriageStatus); + } + newSearchParams.set("page_size", newPageSize.toString()); newSearchParams.set("page", "0"); @@ -272,6 +321,7 @@ export function CrossmatchResultsPage(): ReactElement {