Alessandro Tomassini
deploy(hf): overlay README/Dockerfile da huggingface/, senza docs/binari/model
c42a5a1
Raw
History Blame Contribute Delete
5.13 kB
import { create } from "zustand";
import type { PresetKey } from "@/constants";
import { LAYER_PRESETS } from "@/constants";
import type { DetectionLayer } from "@/api/types";
export type SourceKind = "text" | "pdf";
export type ThemeMode = "light" | "dark";
/**
* Stato delle IMPOSTAZIONI (pannello di sinistra) + preferenze di layout/tema.
* Equivalente alle scelte che nel frontend originale vivevano nel DOM dei
* controlli. Le run leggono questo store; i risultati stanno in sessionStore.
*/
interface UiState {
// sorgente
source: SourceKind;
docText: string;
pdfFile: File | null;
pdfFast: boolean;
// profilo + layer
preset: PresetKey;
selectedLayers: string[];
// soglia + verifica
minConfidence: number;
verify: boolean;
approver: string | null;
simulate: boolean;
// offuscamento (applicato in re-render)
mode: string;
enabledSeverities: string[];
// layout / tema
theme: ThemeMode;
settingsCollapsed: boolean;
choicesTouched: boolean;
// setters
setSource: (s: SourceKind) => void;
setDocText: (t: string) => void;
setPdfFile: (f: File | null) => void;
setPdfFast: (v: boolean) => void;
setPreset: (p: PresetKey, layers: DetectionLayer[]) => void;
setSelectedLayers: (keys: string[]) => void;
toggleLayer: (key: string, checked: boolean, layers: DetectionLayer[]) => void;
initLayers: (layers: DetectionLayer[]) => void;
setMinConfidence: (v: number) => void;
setVerify: (v: boolean) => void;
setApprover: (k: string | null) => void;
setSimulate: (v: boolean) => void;
setMode: (m: string) => void;
setEnabledSeverities: (s: string[]) => void;
setTheme: (t: ThemeMode) => void;
setSettingsCollapsed: (v: boolean) => void;
markChoiceTouched: () => void;
}
const savedTheme = (): ThemeMode =>
(typeof localStorage !== "undefined" &&
(localStorage.getItem("theme") as ThemeMode)) ||
"light";
/** Layer attivi per un profilo, escludendo i non disponibili (ML spento). */
function presetLayers(preset: PresetKey, layers: DetectionLayer[]): string[] {
if (preset === "debug") return [];
const wanted = LAYER_PRESETS[preset] || [];
const available = new Set(layers.filter((l) => l.available).map((l) => l.key));
return wanted.filter((k) => available.has(k));
}
export const useUiStore = create<UiState>((set, get) => ({
source: "text",
docText: "",
pdfFile: null,
pdfFast: true,
preset: "gdpr",
selectedLayers: [],
minConfidence: 0.82,
verify: false,
approver: null,
simulate: false,
mode: "placeholder",
enabledSeverities: ["critica", "alta", "media", "bassa"],
theme: savedTheme(),
settingsCollapsed: false,
choicesTouched: false,
setSource: (source) => set({ source }),
setDocText: (docText) => set({ docText }),
setPdfFile: (pdfFile) => set({ pdfFile }),
setPdfFast: (pdfFast) => set({ pdfFast }),
setPreset: (preset, layers) =>
set(
preset === "debug"
? { preset }
: { preset, selectedLayers: presetLayers(preset, layers) },
),
setSelectedLayers: (selectedLayers) => set({ selectedLayers }),
// Toggle in modalità Debug con isolamento dell'LLM: se l'LLM è attivato,
// disattiva gli altri layer ML (e viceversa). Le regole (CPU) restano libere.
toggleLayer: (key, checked, layers) => {
const meta = layers.find((l) => l.key === key);
let next = new Set(get().selectedLayers);
if (checked) {
next.add(key);
if (key === "llm") {
for (const l of layers)
if (l.key !== "llm" && l.requires_ml) next.delete(l.key);
} else if (meta?.requires_ml) {
next.delete("llm");
}
} else {
next.delete(key);
}
set({ selectedLayers: [...next] });
},
// Inizializza la selezione dal profilo corrente quando i layer sono caricati.
initLayers: (layers) => {
const { preset } = get();
if (preset !== "debug") {
set({ selectedLayers: presetLayers(preset, layers) });
} else {
const available = new Set(
layers.filter((l) => l.available && l.key !== "llm").map((l) => l.key),
);
set({ selectedLayers: [...available] });
}
},
setMinConfidence: (minConfidence) => set({ minConfidence }),
setVerify: (verify) => set({ verify }),
setApprover: (approver) => set({ approver }),
setSimulate: (simulate) => set({ simulate }),
setMode: (mode) => set({ mode }),
setEnabledSeverities: (enabledSeverities) => set({ enabledSeverities }),
setTheme: (theme) => {
if (typeof localStorage !== "undefined") localStorage.setItem("theme", theme);
set({ theme });
},
setSettingsCollapsed: (settingsCollapsed) => set({ settingsCollapsed }),
markChoiceTouched: () => set({ choicesTouched: true }),
}));
/** Giudice selezionato effettivo (null se la verifica è off). */
export function selectedApprover(): string | null {
const s = useUiStore.getState();
if (!s.verify) return null;
return s.approver || null;
}
/** "debug (simula llm)": true solo con verifica ON e flag attivo. */
export function isSimulating(): boolean {
const s = useUiStore.getState();
return s.verify && s.simulate;
}