Add origin field and filter for ban sources (Tasks 1 & 2)

- Task 1: Mark imported blocklist IP addresses
  - Add BanOrigin type and _derive_origin() to ban.py model
  - Populate origin field in ban_service list_bans() and bans_by_country()
  - BanTable and MapPage companion table show origin badge column
  - Tests: origin derivation in test_ban_service.py and test_dashboard.py

- Task 2: Add origin filter to dashboard and world map
  - ban_service: _origin_sql_filter() helper; origin param on list_bans()
    and bans_by_country()
  - dashboard router: optional origin query param forwarded to service
  - Frontend: BanOriginFilter type + BAN_ORIGIN_FILTER_LABELS in ban.ts
  - fetchBans / fetchBansByCountry forward origin to API
  - useBans / useMapData accept and pass origin; page resets on change
  - BanTable accepts origin prop; DashboardPage adds segmented filter
  - MapPage adds origin Select next to time-range picker
  - Tests: origin filter assertions in test_ban_service and test_dashboard
This commit is contained in:
2026-03-07 20:03:43 +01:00
parent 706d2e1df8
commit 53d664de4f
28 changed files with 1637 additions and 103 deletions

View File

@@ -271,12 +271,14 @@ The dashboard uses cards to display key figures (server status, total bans, acti
## 11. World Map View
- The map renders country outlines only — **no fill colours, no satellite imagery, no terrain shading**.
- The map renders country outlines only — **no fill colours, no satellite imagery, no terrain shading**. Countries are transparent with neutral strokes.
- **The map is fully interactive:** users can zoom in/out using mouse wheel or pinch gestures, and pan by dragging. Zoom range: 1× (full world) to 8× (regional detail).
- **Zoom controls:** Three small buttons overlaid in the top-right corner provide zoom in (+), zoom out (), and reset view (⟲) functionality. Buttons use `appearance="secondary"` and `size="small"`.
- Countries with banned IPs display a **count badge** centred inside the country polygon. Use `FontSizes.size14` semibold, `themePrimary` colour.
- Countries with zero bans remain completely blank — no label, no tint.
- On hover: country region gets a subtle `neutralLighterAlt` fill. On click: fill shifts to `themeLighterAlt` and the companion table below filters to that country.
- The map must have a **light neutral border** (`neutralLight`) around its container, at **Depth 4**.
- Time-range selector above the map uses `Pivot` with quick presets (24 h, 7 d, 30 d, 365 d).
- On hover: country region gets a subtle `neutralBackground3` fill (only if the country has data). On click: fill shifts to `brandBackgroundHover` and the companion table below filters to that country. Default state remains transparent.
- The map must have a **light neutral border** (`neutralStroke1`) around its container, with `borderRadius.medium`.
- Time-range selector above the map uses `Select` dropdown with quick presets (24 h, 7 d, 30 d, 365 d).
---