Moved all static layout properties (display, gap, margin, padding, colour) from inline style props to makeStyles classes in: - MapBansTable.tsx: Pagination row flexbox layout - JailDetailPage.tsx: Link styling for textDecoration - HistoryPage.tsx: Summary text styling - IpDetailView.tsx: Loading container and text formatting Kept inline styles only for genuinely dynamic values: - WorldMap.tsx: Tooltip position (follows mouse) - TopCountriesPieChart.tsx: Legend color (from recharts data) - TopCountriesBarChart.tsx: Chart height (derives from data length) This change improves performance by leveraging Griffel's atomic CSS cache and ensures consistency with the established Fluent UI pattern. Updated Docs/Web-Development.md with explicit rule: inline styles only for runtime-dynamic values, all static properties go in makeStyles. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
119 lines
3.5 KiB
TypeScript
119 lines
3.5 KiB
TypeScript
/**
|
|
* Jail detail page.
|
|
*
|
|
* Fetches and displays the full configuration and state of a single jail
|
|
* identified by the `:name` route parameter.
|
|
*/
|
|
|
|
import { Button, MessageBar, MessageBarBody, Spinner, Text, makeStyles } from "@fluentui/react-components";
|
|
import { ArrowLeftRegular } from "@fluentui/react-icons";
|
|
import { Link, useParams } from "react-router-dom";
|
|
import { useJailData } from "../hooks/useJailData";
|
|
import { useJailCommands } from "../hooks/useJailCommands";
|
|
import { useJailBannedIps } from "../hooks/useJailBannedIps";
|
|
import { BannedIpsSection } from "../components/jail/BannedIpsSection";
|
|
import { JailInfoSection } from "../components/jail/JailInfoSection";
|
|
import { PatternsSection } from "../components/jail/PatternsSection";
|
|
import { BantimeEscalationSection } from "../components/jail/BantimeEscalationSection";
|
|
import { IgnoreListSection } from "../components/jail/IgnoreListSection";
|
|
import { useJailDetailPageStyles } from "../components/jail/jailDetailPageStyles";
|
|
|
|
const useLinkStyles = makeStyles({
|
|
link: {
|
|
textDecoration: "none",
|
|
},
|
|
});
|
|
|
|
export function JailDetailPage(): React.JSX.Element {
|
|
const linkStyles = useLinkStyles();
|
|
const styles = useJailDetailPageStyles();
|
|
const { name = "" } = useParams<{ name: string }>();
|
|
const { jail, ignoreList, ignoreSelf, loading, error, refresh } = useJailData(name);
|
|
const { addIp, removeIp, toggleIgnoreSelf, start, stop, reload, setIdle } = useJailCommands(name, refresh);
|
|
const {
|
|
items,
|
|
total,
|
|
page,
|
|
pageSize,
|
|
search,
|
|
loading: bannedLoading,
|
|
error: bannedError,
|
|
opError,
|
|
refresh: refreshBanned,
|
|
setPage,
|
|
setPageSize,
|
|
setSearch,
|
|
unban,
|
|
} = useJailBannedIps(name);
|
|
|
|
if (loading && !jail) {
|
|
return (
|
|
<div className={styles.centred}>
|
|
<Spinner label={`Loading jail ${name}…`} />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (error) {
|
|
return (
|
|
<div className={styles.root}>
|
|
<Link to="/jails" className={linkStyles.link}>
|
|
<Button appearance="subtle" icon={<ArrowLeftRegular />}>
|
|
Back to Jails
|
|
</Button>
|
|
</Link>
|
|
<MessageBar intent="error">
|
|
<MessageBarBody>Failed to load jail {name}: {error}</MessageBarBody>
|
|
</MessageBar>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (!jail) return <></>;
|
|
|
|
return (
|
|
<div className={styles.root}>
|
|
<div className={styles.breadcrumb}>
|
|
<Link to="/jails" className={linkStyles.link}>
|
|
<Button appearance="subtle" size="small" icon={<ArrowLeftRegular />}>
|
|
Jails
|
|
</Button>
|
|
</Link>
|
|
<Text size={200} style={{ color: "var(--colorNeutralForeground3)" }}>
|
|
/
|
|
</Text>
|
|
<Text size={200} className={styles.mono}>
|
|
{name}
|
|
</Text>
|
|
</div>
|
|
|
|
<JailInfoSection jail={jail} onRefresh={refresh} onStart={start} onStop={stop} onReload={reload} onSetIdle={setIdle} />
|
|
<BannedIpsSection
|
|
items={items}
|
|
total={total}
|
|
page={page}
|
|
pageSize={pageSize}
|
|
search={search}
|
|
loading={bannedLoading}
|
|
error={bannedError}
|
|
opError={opError}
|
|
onSearch={setSearch}
|
|
onPageChange={setPage}
|
|
onPageSizeChange={setPageSize}
|
|
onRefresh={refreshBanned}
|
|
onUnban={unban}
|
|
/>
|
|
<PatternsSection jail={jail} />
|
|
<BantimeEscalationSection jail={jail} />
|
|
<IgnoreListSection
|
|
jailName={name}
|
|
ignoreList={ignoreList}
|
|
ignoreSelf={ignoreSelf}
|
|
onAdd={addIp}
|
|
onRemove={removeIp}
|
|
onToggleIgnoreSelf={toggleIgnoreSelf}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|