Replace inline frontend styles with makeStyles and design tokens

This commit is contained in:
2026-04-19 12:04:24 +02:00
parent 91269448d0
commit d99d6bd119
16 changed files with 344 additions and 265 deletions

View File

@@ -1,4 +1,4 @@
import { useState } from "react";
import { useMemo, useState } from "react";
import { Link } from "react-router-dom";
import { formatSeconds } from "../../utils/formatDate";
import {
@@ -15,6 +15,8 @@ import {
Spinner,
Text,
Tooltip,
makeStyles,
tokens,
} from "@fluentui/react-components";
import {
ArrowClockwiseRegular,
@@ -28,77 +30,27 @@ import { useJailsPageStyles } from "./jailsPageStyles";
import { useJails } from "../../hooks/useJails";
import type { JailSummary } from "../../types/jail";
const jailColumns = [
{
columnId: "name",
renderHeaderCell: () => "Jail",
renderCell: (j: JailSummary) => (
<Link to={`/jails/${encodeURIComponent(j.name)}`} style={{ textDecoration: "none" }}>
<Text style={{ fontFamily: "Consolas, 'Courier New', monospace", fontSize: "0.85rem" }}>
{j.name}
</Text>
</Link>
),
compare: (a: JailSummary, b: JailSummary) => a.name.localeCompare(b.name),
const useOverviewStyles = makeStyles({
link: {
textDecoration: "none",
},
{
columnId: "status",
renderHeaderCell: () => "Status",
renderCell: (j: JailSummary) => {
if (!j.running) return <Badge appearance="filled" color="danger">stopped</Badge>;
if (j.idle) return <Badge appearance="filled" color="warning">idle</Badge>;
return <Badge appearance="filled" color="success">running</Badge>;
},
compare: (a: JailSummary, b: JailSummary) => {
if (a.running !== b.running) return a.running ? -1 : 1;
if (a.idle !== b.idle) return a.idle ? 1 : -1;
return 0;
},
jailName: {
fontFamily: tokens.fontFamilyMonospace,
fontSize: tokens.fontSizeBase200,
},
{
columnId: "backend",
renderHeaderCell: () => "Backend",
renderCell: (j: JailSummary) => <Text size={200}>{j.backend}</Text>,
compare: (a: JailSummary, b: JailSummary) => a.backend.localeCompare(b.backend),
badgeCount: {
marginLeft: tokens.spacingHorizontalXS,
},
{
columnId: "banned",
renderHeaderCell: () => "Banned",
renderCell: (j: JailSummary) => (
<Text size={200}>{j.status ? String(j.status.currently_banned) : "—"}</Text>
),
compare: (a: JailSummary, b: JailSummary) => (a.status?.currently_banned ?? 0) - (b.status?.currently_banned ?? 0),
statusActionGroup: {
display: "flex",
gap: tokens.spacingHorizontalS,
alignItems: "center",
},
{
columnId: "failed",
renderHeaderCell: () => "Failed",
renderCell: (j: JailSummary) => (
<Text size={200}>{j.status ? String(j.status.currently_failed) : "—"}</Text>
),
compare: (a: JailSummary, b: JailSummary) => (a.status?.currently_failed ?? 0) - (b.status?.currently_failed ?? 0),
},
{
columnId: "findTime",
renderHeaderCell: () => "Find Time",
renderCell: (j: JailSummary) => <Text size={200}>{formatSeconds(j.find_time)}</Text>,
compare: (a: JailSummary, b: JailSummary) => a.find_time - b.find_time,
},
{
columnId: "banTime",
renderHeaderCell: () => "Ban Time",
renderCell: (j: JailSummary) => <Text size={200}>{formatSeconds(j.ban_time)}</Text>,
compare: (a: JailSummary, b: JailSummary) => a.ban_time - b.ban_time,
},
{
columnId: "maxRetry",
renderHeaderCell: () => "Max Retry",
renderCell: (j: JailSummary) => <Text size={200}>{String(j.max_retry)}</Text>,
compare: (a: JailSummary, b: JailSummary) => a.max_retry - b.max_retry,
},
];
});
export function JailOverviewSection(): React.JSX.Element {
const styles = useJailsPageStyles();
const pageStyles = useJailsPageStyles();
const overviewStyles = useOverviewStyles();
const sectionStyles = useCommonSectionStyles();
const { jails, total, loading, error, refresh, startJail, stopJail, setIdle, reloadJail, reloadAll } = useJails();
const [opError, setOpError] = useState<string | null>(null);
@@ -110,18 +62,84 @@ export function JailOverviewSection(): React.JSX.Element {
});
};
const jailColumns = useMemo(
() => [
{
columnId: "name",
renderHeaderCell: () => "Jail",
renderCell: (j: JailSummary) => (
<Link to={`/jails/${encodeURIComponent(j.name)}`} className={overviewStyles.link}>
<Text className={overviewStyles.jailName}>{j.name}</Text>
</Link>
),
compare: (a: JailSummary, b: JailSummary) => a.name.localeCompare(b.name),
},
{
columnId: "status",
renderHeaderCell: () => "Status",
renderCell: (j: JailSummary) => {
if (!j.running) return <Badge appearance="filled" color="danger">stopped</Badge>;
if (j.idle) return <Badge appearance="filled" color="warning">idle</Badge>;
return <Badge appearance="filled" color="success">running</Badge>;
},
compare: (a: JailSummary, b: JailSummary) => {
if (a.running !== b.running) return a.running ? -1 : 1;
if (a.idle !== b.idle) return a.idle ? 1 : -1;
return 0;
},
},
{
columnId: "backend",
renderHeaderCell: () => "Backend",
renderCell: (j: JailSummary) => <Text size={200}>{j.backend}</Text>,
compare: (a: JailSummary, b: JailSummary) => a.backend.localeCompare(b.backend),
},
{
columnId: "banned",
renderHeaderCell: () => "Banned",
renderCell: (j: JailSummary) => <Text size={200}>{j.status ? String(j.status.currently_banned) : "—"}</Text>,
compare: (a: JailSummary, b: JailSummary) => (a.status?.currently_banned ?? 0) - (b.status?.currently_banned ?? 0),
},
{
columnId: "failed",
renderHeaderCell: () => "Failed",
renderCell: (j: JailSummary) => <Text size={200}>{j.status ? String(j.status.currently_failed) : "—"}</Text>,
compare: (a: JailSummary, b: JailSummary) => (a.status?.currently_failed ?? 0) - (b.status?.currently_failed ?? 0),
},
{
columnId: "findTime",
renderHeaderCell: () => "Find Time",
renderCell: (j: JailSummary) => <Text size={200}>{formatSeconds(j.find_time)}</Text>,
compare: (a: JailSummary, b: JailSummary) => a.find_time - b.find_time,
},
{
columnId: "banTime",
renderHeaderCell: () => "Ban Time",
renderCell: (j: JailSummary) => <Text size={200}>{formatSeconds(j.ban_time)}</Text>,
compare: (a: JailSummary, b: JailSummary) => a.ban_time - b.ban_time,
},
{
columnId: "maxRetry",
renderHeaderCell: () => "Max Retry",
renderCell: (j: JailSummary) => <Text size={200}>{String(j.max_retry)}</Text>,
compare: (a: JailSummary, b: JailSummary) => a.max_retry - b.max_retry,
},
],
[overviewStyles],
);
return (
<div className={sectionStyles.section}>
<div className={sectionStyles.sectionHeader}>
<Text as="h2" size={500} weight="semibold">
Jail Overview
{total > 0 && (
<Badge appearance="tint" style={{ marginLeft: "8px" }}>
<Badge appearance="tint" className={overviewStyles.badgeCount}>
{String(total)}
</Badge>
)}
</Text>
<div className={styles.actionRow}>
<div className={pageStyles.actionRow}>
<Button
size="small"
appearance="subtle"
@@ -148,11 +166,11 @@ export function JailOverviewSection(): React.JSX.Element {
)}
{loading && jails.length === 0 ? (
<div className={styles.centred}>
<div className={pageStyles.centred}>
<Spinner label="Loading jails…" />
</div>
) : (
<div className={styles.tableWrapper}>
<div className={pageStyles.tableWrapper}>
<DataGrid items={jails} columns={jailColumns} getRowId={(j: JailSummary) => j.name} focusMode="composite">
<DataGridHeader>
<DataGridRow>
@@ -166,7 +184,7 @@ export function JailOverviewSection(): React.JSX.Element {
if (columnId === "status") {
return (
<DataGridCell>
<div style={{ display: "flex", gap: "6px", alignItems: "center" }}>
<div className={overviewStyles.statusActionGroup}>
{renderCell(item)}
<Tooltip content={item.running ? "Stop jail" : "Start jail"} relationship="label">
<Button