# BanGUI — Task List This document breaks the entire BanGUI project into development stages, ordered so that each stage builds on the previous one. Every task is described in prose with enough detail for a developer to begin work. References point to the relevant documentation. --- ## ✅ Task 1 — Convert Backend, Log Encoding, and Date Pattern to Dropdowns in Jail Config **Completed.** Backend and Log Encoding are now `` fields (Backend and Log Encoding are read-only, Date Pattern is a free-text input). These should be `` fields with `` fields. Wire their `onChange` to local state and include them in the auto-save payload sent to the backend. 2. The backend model at `backend/app/models/config.py` line 67 already accepts `backend: str` and `log_encoding: str`, so no backend changes are needed unless you want to add server-side validation. 3. Date Pattern should use a Fluent UI `Combobox` (editable dropdown) instead of a `Select`, so users can still type a custom pattern. 4. Follow the existing DNS Mode dropdown pattern at lines 271–280 of `JailsTab.tsx` as a reference for styling and onChange handling. --- ## Task 2 — Fix Raw Action Configuration Always Blank in Actions Tab **Problem:** In the Config → Actions page, the **"Raw Action Configuration"** accordion section is always blank when expanded. **Where to look:** - **`frontend/src/components/config/ActionsTab.tsx`** — the `ActionDetail` component (lines 65–185). The `fetchRaw` callback (line 82) calls `fetchActionFile(action.name)` and returns `result.content`. - **`frontend/src/components/config/RawConfigSection.tsx`** — the collapsible raw editor. It uses a `loadedRef` (line 62) to fetch content only on first accordion expansion, and never resets. - **`frontend/src/api/config.ts`** line 257 — `fetchActionFile()` calls `GET /config/actions/{name}`. - **`backend/app/services/file_config_service.py`** line 734 — `get_action_file()` reads from `action.d/` using `_read_conf_file()`, which tries `.conf` first, then `.local`. **Root cause investigation — check these two possibilities:** ### Possibility A: Stale `loadedRef` across action switches `ActionDetail` at line 301 of `ActionsTab.tsx` is rendered **without a `key` prop**: ```tsx { setAssignOpen(true); }} onRemovedFromJail={handleRemovedFromJail} /> ``` Without `key={selectedAction.name}`, React reuses the same component instance when switching between actions. The `RawConfigSection` inside `ActionDetail` keeps its `loadedRef.current = true` from a previous expansion, so it never re-fetches for the new action. **Fix:** Add `key={selectedAction.name}` to `ActionDetail` so it fully unmounts/remounts on action switch, resetting all internal state including `loadedRef`. ### Possibility B: Backend returning empty content The `_read_conf_file` function at `file_config_service.py` line 492 tries `.conf` first then `.local`. If the action only has a `.conf` file and it's readable, content should be returned. Verify by: 1. Checking browser DevTools Network tab for the `GET /api/config/actions/{name}` response body. 2. Confirming the response has a non-empty `content` field. **Implementation:** 1. Add `key={selectedAction.name}` to the `` component in `ActionsTab.tsx` line 301. 2. Test by selecting different actions and expanding the raw config accordion — each should show the correct file content. 3. If the backend is returning empty content, debug `_read_conf_file` to check which file path it resolves and whether it can read the file. --- ## Task 3 — Give Inactive Jail Configs the Same GUI as Active Ones **Problem:** In the Config → Jails page, **inactive jails** show a minimal read-only preview (`InactiveJailDetail` component) with only basic fields (filter, port, ban time, find time, max retry, log paths, actions, source file). **Active jails** like `bangui-sim` show a full editable form (`JailConfigDetail` component) with all fields including Backend, Log Encoding, Date Pattern, DNS Mode, Prefix Regex, editable log paths, Fail/Ignore Regex lists, Ban-time Escalation, and a Raw Configuration editor. The inactive jail detail should display the same rich GUI as the active one — same layout, same fields — but in read-only mode (since the jail is not running on fail2ban). **Where to change:** - **`frontend/src/components/config/JailsTab.tsx`**: - `InactiveJailDetail` component (lines 493–580): the current minimal read-only view. - `JailConfigDetail` component (lines ~200–490): the full editable form for active jails. - Selection logic at lines 721–752 determines which component renders based on jail kind. - **`frontend/src/types/config.ts`** — `InactiveJail` type (around line 484) defines the data shape for inactive jails. Compare with `JailConfig` to see which fields are missing. - **Backend** — check that the inactive jail endpoint returns enough data. The backend model `InactiveJail` may need additional fields (backend, log_encoding, date_pattern, dns_mode, prefix_regex, failregex, ignoreregex, ban-time escalation settings) to match the active `JailConfig` model. **Implementation approach:** 1. **Extend the `InactiveJail` model** in the backend (`backend/app/models/config.py`) to include all fields that `JailConfig` has: `backend`, `log_encoding`, `date_pattern`, `usedns`, `prefixregex`, `failregex`, `ignoreregex`, `bantime_increment` (escalation settings), etc. 2. **Update the backend service** that parses inactive jail configs to extract these additional fields from the `.conf`/`.local` files. 3. **Rewrite `InactiveJailDetail`** to mirror `JailConfigDetail`'s layout but with all fields in **read-only** mode (all `` have `readOnly`, all `