- Add BAN_PAGE_SIZE (100) and HISTORY_PAGE_SIZE (50) to frontend/src/utils/constants.ts
- Replace local PAGE_SIZE definitions in useBans.ts and HistoryPage.tsx with imports
- Eliminates risk of pagination constants silently diverging from backend defaults
- Single source of truth for all pagination sizes
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move reusable UI section components (JailInfoSection, PatternsSection,
BantimeEscalationSection, IgnoreListSection, CodeList) from pages/jail/
to components/jail/, aligning with the project convention that pages/
contains only route-level entry points while components/ contains reusable
UI building blocks.
Changes:
- Move 5 section components + jailDetailPageStyles.ts to components/jail/
- Update import paths in moved components (relative paths to commonStyles)
- Update JailDetailPage.tsx imports to reference components/jail/
- Delete empty pages/jail/ directory
- Document pages/ vs components/ distinction in Web-Development.md
All components use standard import structure and TypeScript passes type
checking. BannedIpsSection was already correctly placed in components/jail/.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Split monolithic useJailDetail hook into separate concerns
- Created useJailData for fetching and managing jail data
- Created useJailCommands for jail operations (power, console, etc.)
- Updated JailDetailPage to use new hooks
- Updated tests to reflect new hook structure
- Removed old useJailDetail hook
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Replace console.warn with visible MessageBar warning when map color thresholds fail to load
- Add DismissRegular icon button to allow users to dismiss the warning
- Add dismissedThresholdWarning state to manage warning visibility
- Add mock and test for useMapColorThresholds hook
- Add test case verifying warning displays and can be dismissed
- Remove TASK-QUALITY-04 from Tasks.md (completed)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Split useHistory interface to accept explicit parameters (page, pageSize, range, origin, jail, ip, source) instead of HistoryQuery object
- Add comprehensive JSDoc for useHistory function
- Update HistoryPage and tests to use new parameter structure
- Move TaskList documentation from Tasks.md to Web-Development.md
- Improve type safety with explicit TimeRange and BanOriginFilter types
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Extract schedule logic into custom useSchedule hook
- Update BlocklistScheduleSection to use the new hook
- Add tests for useSchedule hook
- Update documentation with task progress
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- DashboardFilterBar now requires all filter props (timeRange, onTimeRangeChange, originFilter, onOriginFilterChange) instead of falling back to context
- Removed useDashboardFilters() hook dependency from DashboardFilterBar, BanTrendChart, and JailDistributionChart
- Updated DashboardPage to explicitly pass all filter values and callbacks from context to components
- Made props required on BanTrendChart and JailDistributionChart
- Updated all tests to reflect new prop requirements
- This eliminates the silent dual-source behavior that could lead to subtle bugs when components are used with different data sources
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
TASK-BUG-07: Remove duplicate useJails() hook call on JailsPage
Previously, useJails() was called twice on page load:
1. In JailsPage to extract jailNames for BanUnbanForm
2. In JailOverviewSection to manage the jail table
This caused two parallel GET /api/jails requests on every page load.
Changes:
- Lift useJails() to JailsPage as the single source of truth
- Accept jail state as props in JailOverviewSection
- Thread all required state (jails, total, loading, error, and action
handlers) down from JailsPage to JailOverviewSection
- Remove useJails hook import from JailOverviewSection
This consolidation reduces unnecessary HTTP requests and improves
page load performance, especially with many jails.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove 'bans' from the useEffect dependency array that resets pagination.
Since 'bans' changes with every background data refresh (new array reference),
the page was being reset to 1 every 30 seconds, making the table unusable for
pagination beyond the first page.
Add a separate effect that clamps the current page to totalPages when the
data shrinks below the current page offset (edge case when filtered results
are fewer than displayed page).
Fixes TASK-BUG-03.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Previously, the tab content wrapper used 'key={tab}' which caused React to
unmount and remount the entire subtree when switching tabs. This destroyed
all component state, including unsaved form data and pending auto-saves.
Changes:
- Removed 'key={tab}' from the wrapper div
- All tab panels now render at page initialization
- Inactive tabs use CSS 'display: none' to hide without unmounting
- Tabs remain mounted throughout the page lifetime
- Users can now switch tabs without losing form input
Updated ConfigPage.test.tsx to reflect that inactive tabs remain in the DOM
(just hidden with CSS) rather than being removed entirely.
Documentation: Added 'Tab Panels' section to Web-Development.md
explaining the rule and rationale.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Validate the ?next= query parameter to prevent open redirects to
external URLs. The parameter is validated to ensure it is a relative
path (starts with / but not //) before using it for navigation.
Invalid paths fall back to '/'.
This prevents attackers from crafting login links like /login?next=https://evil.com
that would transparently redirect authenticated users to malicious sites.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
HistoryPage no longer requires Apply/Clear; filter state auto-syncs with query. Added guard to avoid redundant state updates. Updated task list in Docs/Tasks.md to mark completion.
Implement TASK F-2: Wrap JailDetailPage jail-control API calls in a hook.
Changes:
- Add start(), stop(), reload(), and setIdle() methods to useJailDetail hook
- Update JailDetailPage to use hook control methods instead of direct API imports
- Update error handling to remove dependency on ApiError type
- Add comprehensive tests for new control methods (8 tests)
- Update existing test to include new hook methods in mock
The control methods handle refetching jail data after each operation,
consistent with the pattern used in useJails hook.
- Add Toolbar and ToolbarButton to HistoryPage imports
- Add Tooltip import and filterBar style to MapPage
- Fix JailsTab test: use new Set<string>() instead of [] for activeJails
- Add --security-opt=no-new-privileges:true to push.sh build commands