Global tab provided the same four editable fields as Server tab: log_level, log_target, db_purge_age, db_max_matches. Server tab already has these fields plus additional read-only info (db_path, syslog_socket) and a Flush Logs button. - Add hint text to DB Purge Age and DB Max Matches fields in ServerTab - Remove GlobalTab component import from ConfigPage - Remove 'global' from TabValue type - Remove Global tab element from TabList - Remove conditional render for GlobalTab - Remove GlobalTab from barrel export (index.ts) - Delete GlobalTab.tsx file - Update ConfigPage test to remove Global tab test case All 123 frontend tests pass.
164 lines
10 KiB
Markdown
164 lines
10 KiB
Markdown
# 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 3 — Fix Transparent Pie Chart Slices and Match Legend Label Colors to Slice Colors
|
|
|
|
### Root Cause
|
|
|
|
The pie chart slices appear transparent because `resolveFluentToken` in `frontend/src/utils/chartTheme.ts` fails to resolve Fluent UI CSS custom properties. It calls `getComputedStyle(document.documentElement)` — but `document.documentElement` is the `<html>` element, and Fluent UI v9's `FluentProvider` injects its CSS custom properties on its own wrapper `<div class="fui-FluentProvider ...">`, **not** on `<html>` or `:root`. Therefore:
|
|
|
|
1. `getComputedStyle(document.documentElement).getPropertyValue('--colorPaletteBlueBorderActive')` returns `""` (empty string).
|
|
2. `resolveFluentToken` falls back to returning the raw token string, e.g. `"var(--colorPaletteBlueBorderActive)"`.
|
|
3. Recharts internally parses colour values for SVG rendering and animation interpolation. It cannot parse a `var(...)` reference so the SVG `fill` attribute ends up transparent/unset.
|
|
|
|
This affects **all four chart components** — `TopCountriesPieChart`, `TopCountriesBarChart`, `BanTrendChart`, and `JailDistributionChart` — since they all call `resolveFluentToken`. However the pie chart is the most visually obvious case because its slices have no fallback colour.
|
|
|
|
### Fix
|
|
|
|
**File:** `frontend/src/utils/chartTheme.ts` — `resolveFluentToken` function (around line 30)
|
|
|
|
Change the element passed to `getComputedStyle` from `document.documentElement` to the FluentProvider's wrapper element. The FluentProvider wrapper always has the CSS class `fui-FluentProvider` (this is a stable class name defined in `@fluentui/react-provider`). Query for it with `document.querySelector`:
|
|
|
|
```typescript
|
|
export function resolveFluentToken(tokenValue: string): string {
|
|
const match = /var\((--[^,)]+)/.exec(tokenValue);
|
|
if (match == null || match[1] == null) return tokenValue;
|
|
|
|
// FluentProvider injects CSS custom properties on its own wrapper <div>,
|
|
// not on :root. Query that element so we resolve actual colour values.
|
|
const el =
|
|
document.querySelector(".fui-FluentProvider") ?? document.documentElement;
|
|
const resolved = getComputedStyle(el)
|
|
.getPropertyValue(match[1])
|
|
.trim();
|
|
return resolved !== "" ? resolved : tokenValue;
|
|
}
|
|
```
|
|
|
|
This is the **only change needed** in this file. Do not modify `CHART_PALETTE` or any other export.
|
|
|
|
### Verification
|
|
|
|
After applying the fix above:
|
|
|
|
- Open the Dashboard page in the browser.
|
|
- The pie chart slices must be filled with the palette colours (blue, red, green, gold, purple).
|
|
- The bar chart, area chart, and jail distribution chart should also display their colours correctly.
|
|
- The legend labels next to the pie chart must have the same font colour as their corresponding slice (this was already implemented by the previous agent in `TopCountriesPieChart.tsx` via the `legendFormatter` that wraps text in a `<span style={{ color: entry.color }}>`). Since `entry.color` comes from the Recharts payload which reads the Cell `fill`, once the fill values are real hex strings the legend colours will also be correct.
|
|
|
|
### What NOT to change
|
|
|
|
- Do **not** modify `TopCountriesPieChart.tsx` — the `legendFormatter` changes already applied there are correct and will work once colours resolve properly.
|
|
- Do **not** modify `CHART_PALETTE` or switch from Fluent tokens to hard-coded hex values — the token-based approach is correct; only the resolution target element was wrong.
|
|
- Do **not** add refs or hooks to individual chart components — the single-line fix in `resolveFluentToken` is sufficient.
|
|
|
|
---
|
|
|
|
## Task 4 — Merge Global Tab into Server Tab (Remove Duplicates)
|
|
|
|
The Global tab (`frontend/src/components/config/GlobalTab.tsx`) and the Server tab (`frontend/src/components/config/ServerTab.tsx`) both expose the same four editable fields: **Log Level**, **Log Target**, **DB Purge Age**, and **DB Max Matches**. The server tab additionally shows read-only **DB Path** and **Syslog Socket** fields, plus a **Flush Logs** button. Having both tabs is confusing and can cause conflicting writes.
|
|
|
|
### Changes
|
|
|
|
1. **Remove the Global tab entirely.**
|
|
- In `frontend/src/pages/ConfigPage.tsx`:
|
|
- Remove `"global"` from the `TabValue` union type.
|
|
- Remove the `<Tab value="global">Global</Tab>` element from the `<TabList>`.
|
|
- Remove the `{tab === "global" && <GlobalTab />}` conditional render.
|
|
- Remove the `GlobalTab` import.
|
|
- In the barrel export file (`frontend/src/components/config/index.ts`): remove the `GlobalTab` re-export.
|
|
- Delete the file `frontend/src/components/config/GlobalTab.tsx`.
|
|
|
|
2. **Ensure the Server tab retains all functionality.** It already has all four editable fields plus extra read-only info and Flush Logs. No changes needed in `ServerTab.tsx` — it already covers everything Global had. Verify the field hints from Global ("Ban records older than this…" and "Maximum number of log-line matches…") are present on the Server tab's DB Purge Age and DB Max Matches fields. If they are missing, copy them over from `GlobalTab.tsx` before deleting it.
|
|
|
|
3. **Backend**: No backend changes needed. The `PUT /api/config/global` endpoint stays; the Server tab already uses its own update mechanism via `useServerSettings`.
|
|
|
|
---
|
|
|
|
## Task 5 — Merge Map Tab into Server Tab
|
|
|
|
The Map tab (`frontend/src/components/config/MapTab.tsx`) configures map color thresholds (Low / Medium / High). Move this section into the Server tab so all server-side and display configuration is in one place.
|
|
|
|
### Changes
|
|
|
|
1. **Add a "Map Color Thresholds" section to `ServerTab.tsx`.**
|
|
- Below the existing server settings card and Flush Logs button, add a new `sectionCard` block containing the map threshold form fields (Low, Medium, High) with the same validation logic currently in `MapTab.tsx` (high > medium > low, all positive integers).
|
|
- Use `useAutoSave` to save thresholds, calling `updateMapColorThresholds` from `frontend/src/api/config.ts`. Fetch initial values with `fetchMapColorThresholds`.
|
|
- Add a section heading: "Map Color Thresholds" and the description text explaining how thresholds drive country fill colors on the World Map page.
|
|
|
|
2. **Remove the Map tab.**
|
|
- In `frontend/src/pages/ConfigPage.tsx`: remove `"map"` from `TabValue`, remove the `<Tab value="map">Map</Tab>` element, remove the conditional render, remove the `MapTab` import.
|
|
- In the barrel export: remove the `MapTab` re-export.
|
|
- Delete `frontend/src/components/config/MapTab.tsx`.
|
|
|
|
3. **Backend**: No changes needed. The `GET/PUT /api/config/map-color-thresholds` endpoints stay as-is.
|
|
|
|
---
|
|
|
|
## Task 6 — Merge Log Tab into Server Tab
|
|
|
|
The Log tab (`frontend/src/components/config/LogTab.tsx`) shows a Service Health panel and a log viewer. Move both into the Server tab to consolidate all server-related views.
|
|
|
|
### Changes
|
|
|
|
1. **Add a "Service Health" section to `ServerTab.tsx`.**
|
|
- Below the map thresholds section (from Task 5), add the service health grid showing: online status badge, fail2ban version, active jail count, total bans, total failures, log level (read-only), log target (read-only). Fetch this data from `fetchServiceStatus` in `frontend/src/api/config.ts`.
|
|
|
|
2. **Add the "Log Viewer" section to `ServerTab.tsx`.**
|
|
- Below the health panel, add the log viewer with all its existing controls: line count selector, filter input, refresh button, auto-refresh toggle, and the colour-coded log display. Migrate all the log-related state, refs, and helper functions from `LogTab.tsx`.
|
|
- Keep the line-severity colour coding (ERROR=red, WARNING=yellow, DEBUG=gray).
|
|
|
|
3. **Remove the Log tab.**
|
|
- In `frontend/src/pages/ConfigPage.tsx`: remove `"log"` from `TabValue`, remove the `<Tab value="log">Log</Tab>` element, remove the conditional render, remove the `LogTab` import.
|
|
- In the barrel export: remove the `LogTab` re-export.
|
|
- Delete `frontend/src/components/config/LogTab.tsx`.
|
|
|
|
4. **Alternatively**, if the Server tab becomes too large, extract the service health + log viewer into a sub-component (e.g. `ServerHealthSection.tsx`) and render it inside `ServerTab.tsx`. This keeps the code manageable but still presents a single tab to the user.
|
|
|
|
5. **Backend**: No changes needed.
|
|
|
|
---
|
|
|
|
## Task 7 — Add Reload / Restart Button to Server Section
|
|
|
|
Add a button (or two buttons) in the Server tab that allows the user to reload or restart the fail2ban service on demand.
|
|
|
|
### Backend
|
|
|
|
A reload endpoint already exists: `POST /api/config/reload` (see `backend/app/routers/config.py`, around line 342). It calls `jail_service.reload_all()` which stops and restarts all jails with the current config. No new backend endpoint is needed for reload.
|
|
|
|
For a **restart** (full daemon restart, not just reload), check whether the backend already supports it. If not, add a new endpoint:
|
|
|
|
- `POST /api/config/restart` — calls `jail_service.restart()` (or equivalent `fail2ban-client restart`). This should fully stop and restart the fail2ban daemon. Return 204 on success, 502 if fail2ban is unreachable.
|
|
|
|
### Frontend
|
|
|
|
**File:** `frontend/src/components/config/ServerTab.tsx`
|
|
|
|
A frontend API function `reloadConfig` already exists in `frontend/src/api/config.ts` (around line 94).
|
|
|
|
1. In the Server tab's button row (next to the existing "Flush Logs" button), add two new buttons:
|
|
- **"Reload fail2ban"** — calls `reloadConfig()`. Show a loading spinner while in progress, and a success/error `MessageBar` when done. Use a descriptive icon such as `ArrowSync24Regular` or `ArrowClockwise24Regular`.
|
|
- **"Restart fail2ban"** — calls the restart API (if added above, or the same reload endpoint if a full restart is not available). Use a warning-style appearance or a confirmation dialog before executing, since a restart briefly takes fail2ban offline.
|
|
|
|
2. Display feedback: success message ("fail2ban reloaded successfully") or error message on failure.
|
|
|
|
3. Optionally, after a successful reload/restart, re-fetch the service health data so the health panel updates immediately.
|
|
|
|
### Frontend API
|
|
|
|
If a restart endpoint was added to the backend, add a corresponding function in `frontend/src/api/config.ts`:
|
|
|
|
```typescript
|
|
export async function restartFail2Ban(): Promise<void> {
|
|
await post<undefined>(ENDPOINTS.configRestart, undefined);
|
|
}
|
|
```
|
|
|
|
And add `configRestart: "/api/config/restart"` to the `ENDPOINTS` object.
|
|
|
|
---
|