Show blocklist import error badge in navigation
When the most recent scheduled import completed with errors, surface the failure in the persistent app shell: - A warning MessageBar appears at top of main content area - An amber badge is rendered on the Blocklists sidebar nav item Backend: add last_run_errors: bool | None to ScheduleInfo model and populate it in get_schedule_info() from the latest import_log row. Frontend: extend ScheduleInfo type, add useBlocklistStatus polling hook, wire both indicators into MainLayout. Tests: 3 new service tests + 1 new router test (433 total, all pass).
This commit is contained in:
@@ -235,3 +235,51 @@ export function useRunImport(): UseRunImportReturn {
|
||||
|
||||
return { running, lastResult, error, runNow };
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// useBlocklistStatus
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/** How often to re-check the schedule endpoint for import errors (ms). */
|
||||
const BLOCKLIST_POLL_INTERVAL_MS = 60_000;
|
||||
|
||||
export interface UseBlocklistStatusReturn {
|
||||
/** `true` when the most recent import run completed with errors. */
|
||||
hasErrors: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Poll `GET /api/blocklists/schedule` every 60 seconds to detect whether
|
||||
* the most recent blocklist import had errors.
|
||||
*
|
||||
* Network failures during polling are silently ignored — the indicator
|
||||
* simply retains its previous value until the next successful poll.
|
||||
*/
|
||||
export function useBlocklistStatus(): UseBlocklistStatusReturn {
|
||||
const [hasErrors, setHasErrors] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
|
||||
const poll = (): void => {
|
||||
fetchSchedule()
|
||||
.then((info) => {
|
||||
if (!cancelled) {
|
||||
setHasErrors(info.last_run_errors === true);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
// Silently swallow network errors — do not change indicator state.
|
||||
});
|
||||
};
|
||||
|
||||
poll();
|
||||
const id = window.setInterval(poll, BLOCKLIST_POLL_INTERVAL_MS);
|
||||
return (): void => {
|
||||
cancelled = true;
|
||||
window.clearInterval(id);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return { hasErrors };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user