diff --git a/devfront/src/features/audit/AuditLogsPage.tsx b/devfront/src/features/audit/AuditLogsPage.tsx index 1f20529a..abbab331 100644 --- a/devfront/src/features/audit/AuditLogsPage.tsx +++ b/devfront/src/features/audit/AuditLogsPage.tsx @@ -126,16 +126,26 @@ function AuditLogsPage() { const [searchClientId, setSearchClientId] = React.useState(""); const [searchAction, setSearchAction] = React.useState(""); const [statusFilter, setStatusFilter] = React.useState("all"); + + // Use deferred values to avoid UI lag during rapid typing + const deferredSearchClientId = React.useDeferredValue(searchClientId.trim()); + const deferredSearchAction = React.useDeferredValue(searchAction.trim()); + const [expandedRows, setExpandedRows] = React.useState< Record >({}); const query = useInfiniteQuery({ - queryKey: ["dev-audit-logs", searchClientId, searchAction, statusFilter], + queryKey: [ + "dev-audit-logs", + deferredSearchClientId, + deferredSearchAction, + statusFilter, + ], queryFn: ({ pageParam }) => fetchDevAuditLogs(50, pageParam, { - client_id: searchClientId.trim() || undefined, - action: searchAction.trim() || undefined, + client_id: deferredSearchClientId || undefined, + action: deferredSearchAction || undefined, status: statusFilter !== "all" ? statusFilter : undefined, }), initialPageParam: undefined as string | undefined, @@ -160,14 +170,6 @@ function AuditLogsPage() { downloadCsv(csv, `dev-audit-logs-${stamp}.csv`); }; - if (query.isLoading) { - return ( -
- {t("msg.dev.audit.loading", "Loading audit logs...")} -
- ); - } - if (query.error) { const axiosError = query.error as AxiosError<{ error?: string }>; if (axiosError.response?.status === 403) { @@ -227,7 +229,13 @@ function AuditLogsPage() { -
+
{ + e.preventDefault(); + query.refetch(); + }} + className="grid gap-2 md:grid-cols-[1fr,1fr,180px]" + >
-
+
- - - - - {t("ui.dev.audit.table.time", "Time")} - - - {t("ui.dev.audit.table.actor", "Actor")} - - - {t("ui.dev.audit.table.action", "Action")} - - - {t("ui.dev.audit.table.target", "Target")} - - - {t("ui.dev.audit.table.status", "Status")} - - - - - - {logs.length === 0 && ( +
+
+ - - {t("msg.dev.audit.empty", "No audit logs found.")} - + + {t("ui.dev.audit.table.time", "Time")} + + + {t("ui.dev.audit.table.actor", "Actor")} + + + {t("ui.dev.audit.table.action", "Action")} + + + {t("ui.dev.audit.table.target", "Target")} + + + {t("ui.dev.audit.table.status", "Status")} + + - )} - {logs.map((row, index) => { - const details = parseDetails(row.details); - const actionLabel = details.action || row.event_type; - const targetValue = details.target_id || "-"; - const rowKey = `${row.event_id}-${row.timestamp}-${index}`; - const expanded = Boolean(expandedRows[rowKey]); - return ( - - - - {formatDateTime(row.timestamp)} - - -
- {row.user_id || "-"} - {row.user_id ? ( + + + {query.isLoading && logs.length === 0 ? ( + + + {t("msg.dev.audit.loading", "Loading audit logs...")} + + + ) : logs.length === 0 ? ( + + + {t("msg.dev.audit.empty", "No audit logs found.")} + + + ) : ( + logs.map((row, index) => { + const details = parseDetails(row.details); + const actionLabel = details.action || row.event_type; + const targetValue = details.target_id || "-"; + const rowKey = `${row.event_id}-${row.timestamp}-${index}`; + const expanded = Boolean(expandedRows[rowKey]); + return ( + + + + {formatDateTime(row.timestamp)} + + +
+ {row.user_id || "-"} + {row.user_id ? ( + + ) : null} +
+
+ {actionLabel} + +
+ {targetValue} + {targetValue !== "-" ? ( + + ) : null} +
+
+ + + {row.status} + + + - ) : null} -
-
- {actionLabel} - -
- {targetValue} - {targetValue !== "-" ? ( - - ) : null} -
-
- - - {row.status} - - - - - -
- {expanded ? ( - - -
-
-
- Request ID: {formatValue(details.request_id)} +
+
+
+ Request ID: {formatValue(details.request_id)} +
+
Method: {formatValue(details.method)}
+
Path: {formatValue(details.path)}
+
+ Tenant: {formatValue(details.tenant_id)} +
+
+
+
Before: {formatValue(details.before)}
+
After: {formatValue(details.after)}
+
Error: {formatValue(details.error)}
+
-
Method: {formatValue(details.method)}
-
Path: {formatValue(details.path)}
-
- Tenant: {formatValue(details.tenant_id)} -
-
-
-
Before: {formatValue(details.before)}
-
After: {formatValue(details.after)}
-
Error: {formatValue(details.error)}
-
-
- - - ) : null} - - ); - })} - -
+ + + ) : null} + + ); + }) + )} + + +
{query.hasNextPage ? (