feat(workbench): expand SCADA monitoring and investigation presentation

This commit is contained in:
2026-11-07 19:50:14 +08:00
parent 0801e161ec
commit ba71e2d529
133 changed files with 6754 additions and 1438 deletions
@@ -0,0 +1,51 @@
import { useCallback, useEffect, useState } from "react";
import type { WorkbenchAlert } from "../types";
function readDismissed(key: string): string[] {
try {
const value: unknown = JSON.parse(localStorage.getItem(key) ?? "[]");
return Array.isArray(value) ? value.filter((item): item is string => typeof item === "string") : [];
} catch {
return [];
}
}
function alertKey(alert: WorkbenchAlert): string {
return JSON.stringify([alert.id, alert.notificationVersion ?? null]);
}
export function useDismissedWorkbenchAlerts(
alerts: WorkbenchAlert[], projectId: string | null, username: string
) {
const storageKey = `tjwater.dismissed-alerts@1:${JSON.stringify([projectId, username])}`;
const [stored, setStored] = useState(() => ({ key: storageKey, ids: readDismissed(storageKey) }));
// Switch scopes synchronously so another user's or project's rows never flash hidden.
if (stored.key !== storageKey) {
setStored({ key: storageKey, ids: readDismissed(storageKey) });
}
useEffect(() => {
const sync = (event: StorageEvent) => {
if (event.storageArea === localStorage && (event.key === storageKey || event.key === null)) {
setStored({ key: storageKey, ids: readDismissed(storageKey) });
}
};
window.addEventListener("storage", sync);
return () => window.removeEventListener("storage", sync);
}, [storageKey]);
const dismissAlert = useCallback((alert: WorkbenchAlert) => {
if (!projectId) return false;
const ids = [...new Set([...readDismissed(storageKey), alertKey(alert)])];
try {
localStorage.setItem(storageKey, JSON.stringify(ids));
} catch {
return false;
}
setStored({ key: storageKey, ids });
return true;
}, [projectId, storageKey]);
const dismissed = new Set(stored.key === storageKey ? stored.ids : readDismissed(storageKey));
return { alerts: alerts.filter((alert) => !dismissed.has(alertKey(alert))), dismissAlert };
}