feat: implement HTTP method filtering, parallelize initialization requests, and replace native alerts with toast notifications for audit log exports
This commit is contained in:
parent
2a2798cd0f
commit
fd8fd3a4e8
3
package-lock.json
generated
3
package-lock.json
generated
@ -58,6 +58,9 @@
|
||||
"typescript": "~5.9.3",
|
||||
"typescript-eslint": "^8.46.4",
|
||||
"vite": "^7.2.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
|
||||
@ -21,6 +21,7 @@ import { tenantService } from "@/services/tenant-service";
|
||||
import type { AuditLog } from "@/types/audit-log";
|
||||
import type { Tenant } from "@/types/tenant";
|
||||
import { useAppTheme } from "@/hooks/useAppTheme";
|
||||
import { showToast } from "@/utils/toast";
|
||||
|
||||
// Helper function to format date
|
||||
const formatDate = (dateString: string): string => {
|
||||
@ -137,7 +138,7 @@ const AuditLogs = (): ReactElement => {
|
||||
null,
|
||||
);
|
||||
|
||||
// Fetch tenants on mount for the selector
|
||||
// FE-1: Run all three independent fetches in parallel instead of sequentially
|
||||
useEffect(() => {
|
||||
const fetchTenants = async () => {
|
||||
try {
|
||||
@ -176,9 +177,11 @@ const AuditLogs = (): ReactElement => {
|
||||
}
|
||||
};
|
||||
|
||||
fetchTenants();
|
||||
fetchResourceTypes();
|
||||
fetchModules();
|
||||
Promise.all([
|
||||
fetchTenants(),
|
||||
fetchResourceTypes(),
|
||||
fetchModules(),
|
||||
]);
|
||||
}, []);
|
||||
|
||||
|
||||
@ -254,6 +257,15 @@ const AuditLogs = (): ReactElement => {
|
||||
tenantId: tenantFilter || undefined,
|
||||
});
|
||||
if (response.success) {
|
||||
// FE-3 (BE-8 truncation warning): Notify when results were silently limited
|
||||
if (response.data.truncated) {
|
||||
showToast.warning(
|
||||
"Export Truncated",
|
||||
response.data.warning ||
|
||||
`Only ${(response.data.exported ?? 10000).toLocaleString()} of ${response.data.total.toLocaleString()} records were exported. Use date filters to narrow the range.`
|
||||
);
|
||||
}
|
||||
|
||||
const blob = new Blob(
|
||||
[JSON.stringify(response.data.records, null, 2)],
|
||||
{ type: "application/json" },
|
||||
@ -267,7 +279,11 @@ const AuditLogs = (): ReactElement => {
|
||||
document.body.removeChild(link);
|
||||
}
|
||||
} catch (err: any) {
|
||||
alert("Export failed: " + err.message);
|
||||
// FE-3: Use app toast system instead of native alert()
|
||||
showToast.error(
|
||||
"Export Failed",
|
||||
err?.response?.data?.error?.message || err.message || "An unexpected error occurred"
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -20,6 +20,7 @@ import type { AuditLog } from "@/types/audit-log";
|
||||
import { useAppTheme } from "@/hooks/useAppTheme";
|
||||
import { PrimaryButton } from "@/components/shared";
|
||||
import { useAppSelector } from "@/hooks/redux-hooks";
|
||||
import { showToast } from "@/utils/toast";
|
||||
|
||||
export interface AuditLogsProps {
|
||||
customTenantId?: string;
|
||||
@ -123,7 +124,8 @@ const AuditLogs = ({
|
||||
});
|
||||
|
||||
// Filter state
|
||||
const methodFilter = null;
|
||||
// FE-2: methodFilter converted from a hardcoded null constant to real controllable state
|
||||
const [methodFilter, setMethodFilter] = useState<string | null>(null);
|
||||
const [actionFilter, setActionFilter] = useState<string | null>(null);
|
||||
const [resourceTypeFilter, setResourceTypeFilter] = useState<string | null>(
|
||||
null,
|
||||
@ -226,10 +228,12 @@ const AuditLogs = ({
|
||||
}
|
||||
};
|
||||
|
||||
// Fetch resource types and modules on mount
|
||||
// FE-1: Fetch resource types and modules in parallel (were sequential before)
|
||||
useEffect(() => {
|
||||
fetchResourceTypes();
|
||||
fetchModules();
|
||||
Promise.all([
|
||||
fetchResourceTypes(),
|
||||
fetchModules(),
|
||||
]);
|
||||
}, [tenantId]);
|
||||
|
||||
// Debouncing for Search
|
||||
@ -275,9 +279,15 @@ const AuditLogs = ({
|
||||
});
|
||||
|
||||
if (response.success) {
|
||||
// In a real app, we'd trigger a file download here.
|
||||
// For now, we'll just log and show a message since the response is JSON.
|
||||
console.log("Export data:", response.data.records);
|
||||
// FE-3 (export truncation warning from BE-8): Inform the user if results were truncated
|
||||
if (response.data.truncated) {
|
||||
showToast.warning(
|
||||
"Export Truncated",
|
||||
response.data.warning ||
|
||||
`Only ${(response.data.exported ?? 10000).toLocaleString()} of ${response.data.total.toLocaleString()} records were exported. Use date filters to narrow the range.`
|
||||
);
|
||||
}
|
||||
|
||||
const blob = new Blob(
|
||||
[JSON.stringify(response.data.records, null, 2)],
|
||||
{ type: "application/json" },
|
||||
@ -291,7 +301,11 @@ const AuditLogs = ({
|
||||
document.body.removeChild(link);
|
||||
}
|
||||
} catch (err: any) {
|
||||
alert("Failed to export audit logs: " + (err.message || "Unknown error"));
|
||||
// FE-3: Use app toast system instead of native alert()
|
||||
showToast.error(
|
||||
"Export Failed",
|
||||
err?.response?.data?.error?.message || err.message || "An unexpected error occurred"
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -564,6 +578,26 @@ const AuditLogs = ({
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* FE-2: HTTP Method filter — methodFilter is now real state */}
|
||||
{isTenantAdmin && (
|
||||
<FilterDropdown
|
||||
label="Method"
|
||||
options={[
|
||||
{ value: "GET", label: "GET" },
|
||||
{ value: "POST", label: "POST" },
|
||||
{ value: "PUT", label: "PUT" },
|
||||
{ value: "PATCH", label: "PATCH" },
|
||||
{ value: "DELETE", label: "DELETE" },
|
||||
]}
|
||||
value={methodFilter}
|
||||
onChange={(value) => {
|
||||
setMethodFilter(value as string | null);
|
||||
setCurrentPage(1);
|
||||
}}
|
||||
placeholder="All Methods"
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Module Filter */}
|
||||
<FilterDropdown
|
||||
label="Module"
|
||||
@ -659,6 +693,7 @@ const AuditLogs = ({
|
||||
{(startDate ||
|
||||
endDate ||
|
||||
actionFilter ||
|
||||
methodFilter ||
|
||||
resourceTypeFilter ||
|
||||
moduleIdFilter ||
|
||||
search ||
|
||||
@ -668,6 +703,7 @@ const AuditLogs = ({
|
||||
setStartDate("");
|
||||
setEndDate("");
|
||||
setActionFilter(null);
|
||||
setMethodFilter(null);
|
||||
setResourceTypeFilter(null);
|
||||
setModuleIdFilter(null);
|
||||
setOrderBy(null);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user