From 9b73f6719db0a5a3dd38dc7dc545d0a7395bfe1c Mon Sep 17 00:00:00 2001 From: Lukas Date: Fri, 13 Mar 2026 13:48:09 +0100 Subject: [PATCH] refactor(frontend): decompose ConfigPage into dedicated config components - Extract tab components: JailsTab, ActionsTab, FiltersTab, JailFilesTab, GlobalTab, ServerTab, ConfFilesTab, RegexTesterTab, MapTab, ExportTab - Add form components: JailFileForm, ActionForm, FilterForm - Add AutoSaveIndicator, RegexList, configStyles, and barrel index - ConfigPage now composes these components; greatly reduces file size - Add tests: ConfigPage.test.tsx, useAutoSave.test.ts --- frontend/src/components/config/ActionForm.tsx | 328 +++ frontend/src/components/config/ActionsTab.tsx | 111 + .../components/config/AutoSaveIndicator.tsx | 124 ++ .../src/components/config/ConfFilesTab.tsx | 319 +++ frontend/src/components/config/ExportTab.tsx | 88 + frontend/src/components/config/FilterForm.tsx | 332 +++ frontend/src/components/config/FiltersTab.tsx | 111 + frontend/src/components/config/GlobalTab.tsx | 142 ++ .../src/components/config/JailFileForm.tsx | 474 +++++ .../src/components/config/JailFilesTab.tsx | 252 +++ frontend/src/components/config/JailsTab.tsx | 534 +++++ frontend/src/components/config/MapTab.tsx | 212 ++ frontend/src/components/config/RegexList.tsx | 103 + .../src/components/config/RegexTesterTab.tsx | 222 ++ frontend/src/components/config/ServerTab.tsx | 194 ++ .../config/__tests__/ActionForm.test.tsx | 113 + .../__tests__/AutoSaveIndicator.test.tsx | 51 + .../config/__tests__/FilterForm.test.tsx | 114 + .../src/components/config/configStyles.ts | 186 ++ frontend/src/components/config/index.ts | 28 + .../src/hooks/__tests__/useAutoSave.test.ts | 144 ++ frontend/src/pages/ConfigPage.tsx | 1857 +---------------- .../src/pages/__tests__/ConfigPage.test.tsx | 64 + 23 files changed, 4275 insertions(+), 1828 deletions(-) create mode 100644 frontend/src/components/config/ActionForm.tsx create mode 100644 frontend/src/components/config/ActionsTab.tsx create mode 100644 frontend/src/components/config/AutoSaveIndicator.tsx create mode 100644 frontend/src/components/config/ConfFilesTab.tsx create mode 100644 frontend/src/components/config/ExportTab.tsx create mode 100644 frontend/src/components/config/FilterForm.tsx create mode 100644 frontend/src/components/config/FiltersTab.tsx create mode 100644 frontend/src/components/config/GlobalTab.tsx create mode 100644 frontend/src/components/config/JailFileForm.tsx create mode 100644 frontend/src/components/config/JailFilesTab.tsx create mode 100644 frontend/src/components/config/JailsTab.tsx create mode 100644 frontend/src/components/config/MapTab.tsx create mode 100644 frontend/src/components/config/RegexList.tsx create mode 100644 frontend/src/components/config/RegexTesterTab.tsx create mode 100644 frontend/src/components/config/ServerTab.tsx create mode 100644 frontend/src/components/config/__tests__/ActionForm.test.tsx create mode 100644 frontend/src/components/config/__tests__/AutoSaveIndicator.test.tsx create mode 100644 frontend/src/components/config/__tests__/FilterForm.test.tsx create mode 100644 frontend/src/components/config/configStyles.ts create mode 100644 frontend/src/components/config/index.ts create mode 100644 frontend/src/hooks/__tests__/useAutoSave.test.ts create mode 100644 frontend/src/pages/__tests__/ConfigPage.test.tsx diff --git a/frontend/src/components/config/ActionForm.tsx b/frontend/src/components/config/ActionForm.tsx new file mode 100644 index 0000000..8903744 --- /dev/null +++ b/frontend/src/components/config/ActionForm.tsx @@ -0,0 +1,328 @@ +/** + * ActionForm — structured form editor for a single ``action.d/*.conf`` file. + * + * Displays parsed fields grouped into collapsible sections: + * - Includes (before / after) + * - Lifecycle commands (actionstart, actionstop, actioncheck, actionban, + * actionunban, actionflush) + * - Definition variables (extra [Definition] key-value pairs) + * - Init variables ([Init] section key-value pairs) + * + * Provides a Save button and shows saving/error state. + */ + +import { useEffect, useMemo, useState } from "react"; +import { + Accordion, + AccordionHeader, + AccordionItem, + AccordionPanel, + Button, + Field, + Input, + MessageBar, + MessageBarBody, + Skeleton, + SkeletonItem, + Text, + Textarea, +} from "@fluentui/react-components"; +import { Add24Regular, Delete24Regular } from "@fluentui/react-icons"; +import type { ActionConfig, ActionConfigUpdate } from "../../types/config"; +import { useActionConfig } from "../../hooks/useActionConfig"; +import { useAutoSave } from "../../hooks/useAutoSave"; +import { AutoSaveIndicator } from "./AutoSaveIndicator"; +import { useConfigStyles } from "./configStyles"; + +// --------------------------------------------------------------------------- +// Internal helpers +// --------------------------------------------------------------------------- + +/** Editable key-value table for definition_vars / init_vars. */ +interface KVEditorProps { + entries: Record; + onChange: (next: Record) => void; +} + +function KVEditor({ entries, onChange }: KVEditorProps): React.JSX.Element { + const styles = useConfigStyles(); + const rows = Object.entries(entries); + + const handleKeyChange = (oldKey: string, newKey: string): void => { + const next: Record = {}; + for (const [k, v] of Object.entries(entries)) { + next[k === oldKey ? newKey : k] = v; + } + onChange(next); + }; + + const handleValueChange = (key: string, value: string): void => { + onChange({ ...entries, [key]: value }); + }; + + const handleDelete = (key: string): void => { + const { [key]: _removed, ...rest } = entries; + onChange(rest); + }; + + const handleAdd = (): void => { + let newKey = "new_var"; + let n = 1; + while (newKey in entries) { + newKey = `new_var_${String(n)}`; + n++; + } + onChange({ ...entries, [newKey]: "" }); + }; + + return ( +
+ {rows.map(([key, value]) => ( +
+ { handleKeyChange(key, d.value); }} + /> +