Group repeat pseudonymization runs by project path

This commit is contained in:
muena
2026-09-25 16:17:03 +02:00
parent c3ef1a6aed
commit 5877b7cf5f
4 changed files with 91 additions and 15 deletions

View File

@@ -249,6 +249,23 @@ function HitReview(props: { root: string; rules: ProjectRule[]; whitelist: Proje
});
}
async function apply(inPlace = false) {
if (!props.preview.drafts.length && !accepted.size) {
try {
const rejected = groups.map((group) => ({ type: group.type, original: group.original }));
if (rejected.length) {
await saveProjectWhitelist(props.root, [...await loadProjectWhitelist(props.root), ...rejected]);
props.onWhitelistChanged(await loadProjectWhitelist(props.root));
}
await showToast({ style: Toast.Style.Success, title: "Keine neuen Änderungen",
message: rejected.length
? "Der bestehende Projektstand bleibt erhalten. Abgewählte Begriffe wurden als Ausnahmen gespeichert."
: "Der bestehende Projektstand bleibt erhalten." });
} catch (error) {
await showToast({ style: Toast.Style.Failure, title: "Ausnahmen konnten nicht gespeichert werden",
message: (error as Error).message });
}
return;
}
if (inPlace && !(await confirmAlert({
title: "Originaldateien ersetzen?",
message: "Die gewählten Dateien und gegebenenfalls ihre Namen werden im Projektordner ersetzt. Die Originale werden vorher außerhalb des Projekts gesichert. PDF-Dateien werden als DOCX ausgegeben.",
@@ -438,6 +455,7 @@ export default function Command() {
const [availableTypes, setAvailableTypes] = useState<EntityType[]>([]);
const [selectedTypes, setSelectedTypes] = useState<EntityType[]>([]);
const [whitelist, setWhitelist] = useState<ProjectWhitelistEntry[]>([]);
const [existingRuns, setExistingRuns] = useState<number | null>(null);
const [busy, setBusy] = useState(false);
useEffect(() => { finderFolder().then((path) => { if (path) setRoot((current) => current || path); }); }, []);
useEffect(() => {
@@ -463,6 +481,15 @@ export default function Command() {
title: "Projekt-Whitelist nicht lesbar", message: error.message }));
return () => { active = false; };
}, [root]);
useEffect(() => {
if (!root) { setExistingRuns(null); return; }
setExistingRuns(null);
let active = true;
listRuns(root).then((found) => { if (active) setExistingRuns(found.length); })
.catch((error: Error) => showToast({ style: Toast.Style.Failure,
title: "Projektstatus nicht lesbar", message: error.message }));
return () => { active = false; };
}, [root]);
async function removeFromWhitelist(entry: ProjectWhitelistEntry) {
try {
const next = (await loadProjectWhitelist(root)).filter((item) => whitelistKey(item) !== whitelistKey(entry));
@@ -505,7 +532,7 @@ export default function Command() {
message: "Bitte den Ordner im Finder öffnen oder unten manuell auswählen." });
}
return <Form isLoading={busy} actions={<ActionPanel>
<Action title="Zuordnungen prüfen" onAction={next} />
<Action title={existingRuns ? "Bestehendes Projekt erneut prüfen" : "Zuordnungen prüfen"} onAction={next} />
<Action title="Geöffneten Finder-Ordner übernehmen" icon={Icon.Folder} onAction={useFinderFolder} />
<Action.Push title="Projekt-Whitelist bearbeiten" icon={Icon.List}
target={<ProjectWhitelist entries={whitelist} onRemove={removeFromWhitelist} />} />
@@ -513,6 +540,9 @@ export default function Command() {
<Form.FilePicker id="projectPath" title="Projektordner" allowMultipleSelection={false}
canChooseDirectories canChooseFiles={false} value={root ? [root] : []}
onChange={(paths) => setRoot(paths[0] ?? "")} />
<Form.Description title="Projektstatus" text={existingRuns === null ? "Projektordner auswählen."
: existingRuns ? `Bereits angelegt · ${existingRuns} gespeicherte Stände. Ein erneuter Lauf aktualisiert dieses Projekt; es wird kein zweites angelegt.`
: "Neues Projekt. Der erste Stand wird nach der Prüfung angelegt."} />
<Form.TextArea id="projectRules" title="Begriffe nur für dieses Projekt" value={rules}
onChange={setRules} placeholder={"BEGRIFF: KundenSuite\nPERSON: Max Mustermann"}
info="Ein Begriff pro Zeile. Ohne Typ wird BEGRIFF verwendet. Diese Regeln werden nur für dieses Projekt gespeichert und bei der Velum-Anfrage mitgesendet." />