diff --git a/Docs/Tasks.md b/Docs/Tasks.md index 4eb0b22..a86be9b 100644 --- a/Docs/Tasks.md +++ b/Docs/Tasks.md @@ -4,723 +4,100 @@ This document breaks the entire BanGUI project into development stages, ordered --- -## Stage 1 — Dashboard Charts Foundation +## Task 1 — Make Geo-Cache Persistent ✅ DONE -### Task 1.1 — Install and configure a charting library +**Goal:** Minimise calls to the external geo-IP lookup service by caching results in the database. -**Status:** `done` +**Details:** -The frontend currently has no charting library. Install **Recharts** (`recharts`) as the project charting library. Recharts is React-native, composable, and integrates cleanly with Fluent UI v9 theming. - -**Steps:** - -1. Run `npm install recharts` in the `frontend/` directory. -2. Verify the dependency appears in `package.json` under `dependencies`. -3. Confirm the build still succeeds with `npm run build` (no type errors, no warnings). - -No wrapper or configuration file is needed — Recharts components are imported directly where used. - -**Acceptance criteria:** - -- `recharts` is listed in `frontend/package.json`. -- `npm run build` succeeds with zero errors or warnings. +- Currently geo-IP results may only live in memory and are lost on restart. Persist every successful geo-lookup result into the database so the external service is called as rarely as possible. +- On each geo-lookup request, first query the database for a cached entry for that IP. Only call the external service if no cached entry exists (or the entry has expired, if a TTL policy is desired). +- After a successful external lookup, write the result back to the database immediately. +- Review the existing implementation in `app/services/geo_service.py` and the related repository/model code. Verify that: + - The DB table/model for geo-cache entries exists and has the correct schema (IP, country, city, latitude, longitude, looked-up timestamp, etc.). + - The repository layer exposes `get_by_ip` and `upsert` (or equivalent) methods. + - The service checks the cache before calling the external API. + - Bulk inserts are used where multiple IPs need to be resolved at once (see Task 3). --- -### Task 1.2 — Create a shared chart theme utility +## Task 2 — Fix `geo_lookup_request_failed` Warnings ✅ DONE -**Status:** `done` +**Goal:** Investigate and fix the frequent `geo_lookup_request_failed` log warnings that occur with an empty `error` field. -Create a small utility at `frontend/src/utils/chartTheme.ts` that exports a function (or constant object) mapping Fluent UI v9 design tokens to Recharts-compatible colour values. The charts must respect the current Fluent theme (light and dark mode). At minimum export: +**Resolution:** The root cause was `str(exc)` returning `""` for aiohttp exceptions with no message (e.g. `ServerDisconnectedError`). Fixed by: +- Replacing `error=str(exc)` with `error=repr(exc)` in both `lookup()` and `_batch_api_call()` so the exception class name is always present in the log. +- Adding `exc_type=type(exc).__name__` field to every network-error log event for easy filtering. +- Moving `import aiohttp` from the `TYPE_CHECKING` block to a regular runtime import and replacing the raw-float `timeout` arguments with `aiohttp.ClientTimeout(total=...)`, removing the `# type: ignore[arg-type]` workarounds. +- Three new tests in `TestErrorLogging` verify empty-message exceptions are correctly captured. -- A palette of 5+ distinct categorical colours for pie/bar slices, derived from Fluent token aliases (e.g. `colorPaletteBlueBorderActive`, `colorPaletteRedBorderActive`, etc.). -- Axis/grid/tooltip colours derived from `colorNeutralForeground2`, `colorNeutralStroke2`, `colorNeutralBackground1`, etc. -- A helper that returns the CSS value of a Fluent token at runtime (since Recharts needs literal CSS colour strings, not CSS custom properties). - -Keep the file under 60 lines. No React components here — pure utility. - -**References:** [Web-Design.md](Web-Design.md) § colour tokens. - -**Acceptance criteria:** - -- The exported palette contains at least 5 distinct colours. -- Colours change correctly between light and dark mode. -- `tsc --noEmit` and `eslint` pass with zero warnings. - ---- - -## Stage 2 — Country Pie Chart (Top 4 + Other) - -### Task 2.1 — Create the `TopCountriesPieChart` component - -**Status:** `done` - -Create `frontend/src/components/TopCountriesPieChart.tsx`. This component renders a **pie chart (Kuchendiagramm)** showing the **top 4 countries by ban count** plus an **"Other"** slice that aggregates every remaining country. - -**Data source:** The component receives the `countries` map (`Record`) and `country_names` map (`Record`) from the existing `/api/dashboard/bans/by-country` endpoint response (`BansByCountryResponse`). No new API endpoint is needed. - -**Aggregation logic (frontend):** - -1. Sort the `countries` entries descending by ban count. -2. Take the top 4 entries. -3. Sum all remaining entries into a single `"Other"` bucket. -4. The result is exactly 5 slices (or fewer if fewer than 5 countries exist). - -**Visual requirements:** - -- Use `` and `` from Recharts with `` for per-slice colours from the chart theme palette (Task 1.2). -- Display a `` on hover showing the country name and ban count. -- Display a `` listing each slice with its country name (full name from `country_names`, not just the code) and percentage. -- Label each slice with the percentage (use Recharts `label` prop or `