Implement tasks 1-3: sidebar order, jail activation rollback, pie chart colors

Task 1: Move Configuration to last position in sidebar NAV_ITEMS

Task 2: Add automatic rollback when jail activation fails
- Back up .local override file before writing
- Restore original file (or delete) on reload failure, health-check
  failure, or jail not appearing post-reload
- Return recovered=True/False in JailActivationResponse
- Show warning/critical banner in ActivateJailDialog based on recovery
- Add _restore_local_file_sync and _rollback_activation_async helpers
- Add 3 new tests: rollback on reload failure, health-check failure,
  and double failure (recovered=False)

Task 3: Color pie chart legend labels to match their slice color
- legendFormatter now returns ReactNode with span style={{ color }}
- Import LegendPayload from recharts/types/component/DefaultLegendContent
This commit was merged in pull request #1.
This commit is contained in:
2026-03-14 21:16:58 +01:00
parent 6bb38dbd8c
commit 4be2469f92
8 changed files with 449 additions and 581 deletions

View File

@@ -12,6 +12,7 @@ import {
Tooltip,
} from "recharts";
import type { PieLabelRenderProps } from "recharts";
import type { LegendPayload } from "recharts/types/component/DefaultLegendContent";
import type { TooltipContentProps } from "recharts/types/component/Tooltip";
import { tokens, makeStyles, Text } from "@fluentui/react-components";
import { CHART_PALETTE, resolveFluentToken } from "../utils/chartTheme";
@@ -153,12 +154,19 @@ export function TopCountriesPieChart({
);
}
/** Format legend entries as "Country Name (xx%)" */
const legendFormatter = (value: string): string => {
/** Format legend entries as "Country Name (xx%)" and colour them to match their slice. */
const legendFormatter = (
value: string,
entry: LegendPayload,
): React.ReactNode => {
const slice = slices.find((s) => s.name === value);
if (slice == null || total === 0) return value;
const pct = ((slice.value / total) * 100).toFixed(1);
return `${value} (${pct}%)`;
return (
<span style={{ color: entry.color }}>
{value} ({pct}%)
</span>
);
};
return (