chore: verify and finalize task completion for existing refactor tasks
This commit is contained in:
@@ -14,6 +14,7 @@ import {
|
||||
makeStyles,
|
||||
tokens,
|
||||
} from "@fluentui/react-components";
|
||||
import { useCardStyles } from "../theme/commonStyles";
|
||||
import type { BanOriginFilter, TimeRange } from "../types/ban";
|
||||
import {
|
||||
BAN_ORIGIN_FILTER_LABELS,
|
||||
@@ -57,20 +58,6 @@ const useStyles = makeStyles({
|
||||
alignItems: "center",
|
||||
flexWrap: "wrap",
|
||||
gap: tokens.spacingVerticalS,
|
||||
backgroundColor: tokens.colorNeutralBackground1,
|
||||
borderRadius: tokens.borderRadiusMedium,
|
||||
borderTopWidth: "1px",
|
||||
borderTopStyle: "solid",
|
||||
borderTopColor: tokens.colorNeutralStroke2,
|
||||
borderRightWidth: "1px",
|
||||
borderRightStyle: "solid",
|
||||
borderRightColor: tokens.colorNeutralStroke2,
|
||||
borderBottomWidth: "1px",
|
||||
borderBottomStyle: "solid",
|
||||
borderBottomColor: tokens.colorNeutralStroke2,
|
||||
borderLeftWidth: "1px",
|
||||
borderLeftStyle: "solid",
|
||||
borderLeftColor: tokens.colorNeutralStroke2,
|
||||
paddingTop: tokens.spacingVerticalS,
|
||||
paddingBottom: tokens.spacingVerticalS,
|
||||
paddingLeft: tokens.spacingHorizontalM,
|
||||
@@ -107,9 +94,10 @@ export function DashboardFilterBar({
|
||||
onOriginFilterChange,
|
||||
}: DashboardFilterBarProps): React.JSX.Element {
|
||||
const styles = useStyles();
|
||||
const cardStyles = useCardStyles();
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<div className={`${styles.container} ${cardStyles.card}`}>
|
||||
{/* Time-range group */}
|
||||
<div className={styles.group}>
|
||||
<Text weight="semibold" size={300}>
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
tokens,
|
||||
Tooltip,
|
||||
} from "@fluentui/react-components";
|
||||
import { useCardStyles } from "../theme/commonStyles";
|
||||
import { ArrowClockwiseRegular, ShieldRegular } from "@fluentui/react-icons";
|
||||
import { useServerStatus } from "../hooks/useServerStatus";
|
||||
|
||||
@@ -31,20 +32,6 @@ const useStyles = makeStyles({
|
||||
alignItems: "center",
|
||||
gap: tokens.spacingHorizontalL,
|
||||
padding: `${tokens.spacingVerticalS} ${tokens.spacingHorizontalL}`,
|
||||
backgroundColor: tokens.colorNeutralBackground1,
|
||||
borderRadius: tokens.borderRadiusMedium,
|
||||
borderTopWidth: "1px",
|
||||
borderTopStyle: "solid",
|
||||
borderTopColor: tokens.colorNeutralStroke2,
|
||||
borderRightWidth: "1px",
|
||||
borderRightStyle: "solid",
|
||||
borderRightColor: tokens.colorNeutralStroke2,
|
||||
borderBottomWidth: "1px",
|
||||
borderBottomStyle: "solid",
|
||||
borderBottomColor: tokens.colorNeutralStroke2,
|
||||
borderLeftWidth: "1px",
|
||||
borderLeftStyle: "solid",
|
||||
borderLeftColor: tokens.colorNeutralStroke2,
|
||||
marginBottom: tokens.spacingVerticalL,
|
||||
flexWrap: "wrap",
|
||||
},
|
||||
@@ -85,8 +72,10 @@ export function ServerStatusBar(): React.JSX.Element {
|
||||
const styles = useStyles();
|
||||
const { status, banguiVersion, loading, error, refresh } = useServerStatus();
|
||||
|
||||
const cardStyles = useCardStyles();
|
||||
|
||||
return (
|
||||
<div className={styles.bar} role="status" aria-label="fail2ban server status">
|
||||
<div className={`${cardStyles.card} ${styles.bar}`} role="status" aria-label="fail2ban server status">
|
||||
{/* ---------------------------------------------------------------- */}
|
||||
{/* Online / Offline badge */}
|
||||
{/* ---------------------------------------------------------------- */}
|
||||
|
||||
@@ -11,6 +11,7 @@ import { createPortal } from "react-dom";
|
||||
import { useCallback, useState } from "react";
|
||||
import { ComposableMap, ZoomableGroup, Geography, useGeographies } from "react-simple-maps";
|
||||
import { Button, makeStyles, tokens } from "@fluentui/react-components";
|
||||
import { useCardStyles } from "../theme/commonStyles";
|
||||
import type { GeoPermissibleObjects } from "d3-geo";
|
||||
import { ISO_NUMERIC_TO_ALPHA2 } from "../data/isoNumericToAlpha2";
|
||||
import { getBanCountColor } from "../utils/mapColors";
|
||||
@@ -30,9 +31,6 @@ const useStyles = makeStyles({
|
||||
mapWrapper: {
|
||||
width: "100%",
|
||||
position: "relative",
|
||||
backgroundColor: tokens.colorNeutralBackground2,
|
||||
borderRadius: tokens.borderRadiusMedium,
|
||||
border: `1px solid ${tokens.colorNeutralStroke1}`,
|
||||
overflow: "hidden",
|
||||
},
|
||||
countLabel: {
|
||||
@@ -290,6 +288,7 @@ export function WorldMap({
|
||||
thresholdHigh = 100,
|
||||
}: WorldMapProps): React.JSX.Element {
|
||||
const styles = useStyles();
|
||||
const cardStyles = useCardStyles();
|
||||
const [zoom, setZoom] = useState<number>(1);
|
||||
const [center, setCenter] = useState<[number, number]>([0, 0]);
|
||||
|
||||
@@ -308,7 +307,7 @@ export function WorldMap({
|
||||
|
||||
return (
|
||||
<div
|
||||
className={styles.mapWrapper}
|
||||
className={`${cardStyles.card} ${styles.mapWrapper}`}
|
||||
role="img"
|
||||
aria-label="World map showing banned IP counts by country. Click a country to filter the table below."
|
||||
>
|
||||
|
||||
@@ -32,6 +32,7 @@ import {
|
||||
type TableColumnDefinition,
|
||||
createTableColumn,
|
||||
} from "@fluentui/react-components";
|
||||
import { useCommonSectionStyles } from "../../theme/commonStyles";
|
||||
import { formatTimestamp } from "../../utils/formatDate";
|
||||
import {
|
||||
ArrowClockwiseRegular,
|
||||
@@ -54,26 +55,6 @@ const PAGE_SIZE_OPTIONS = [10, 25, 50, 100] as const;
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const useStyles = makeStyles({
|
||||
root: {
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: tokens.spacingVerticalS,
|
||||
backgroundColor: tokens.colorNeutralBackground1,
|
||||
borderRadius: tokens.borderRadiusMedium,
|
||||
borderTopWidth: "1px",
|
||||
borderTopStyle: "solid",
|
||||
borderTopColor: tokens.colorNeutralStroke2,
|
||||
borderRightWidth: "1px",
|
||||
borderRightStyle: "solid",
|
||||
borderRightColor: tokens.colorNeutralStroke2,
|
||||
borderBottomWidth: "1px",
|
||||
borderBottomStyle: "solid",
|
||||
borderBottomColor: tokens.colorNeutralStroke2,
|
||||
borderLeftWidth: "1px",
|
||||
borderLeftStyle: "solid",
|
||||
borderLeftColor: tokens.colorNeutralStroke2,
|
||||
padding: tokens.spacingVerticalM,
|
||||
},
|
||||
header: {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
@@ -243,6 +224,7 @@ export function BannedIpsSection({
|
||||
onUnban,
|
||||
}: BannedIpsSectionProps): React.JSX.Element {
|
||||
const styles = useStyles();
|
||||
const sectionStyles = useCommonSectionStyles();
|
||||
|
||||
const rows: BanRow[] = items.map((ban) => ({
|
||||
ban,
|
||||
@@ -252,7 +234,7 @@ export function BannedIpsSection({
|
||||
const totalPages = pageSize > 0 ? Math.ceil(total / pageSize) : 1;
|
||||
|
||||
return (
|
||||
<div className={styles.root}>
|
||||
<div className={sectionStyles.section}>
|
||||
{/* Section header */}
|
||||
<div className={styles.header}>
|
||||
<div className={styles.headerLeft}>
|
||||
|
||||
@@ -37,6 +37,7 @@ import {
|
||||
makeStyles,
|
||||
tokens,
|
||||
} from "@fluentui/react-components";
|
||||
import { useCommonSectionStyles } from "../theme/commonStyles";
|
||||
import {
|
||||
AddRegular,
|
||||
ArrowClockwiseRegular,
|
||||
@@ -69,35 +70,7 @@ const useStyles = makeStyles({
|
||||
flexDirection: "column",
|
||||
gap: tokens.spacingVerticalXL,
|
||||
},
|
||||
section: {
|
||||
backgroundColor: tokens.colorNeutralBackground1,
|
||||
borderRadius: tokens.borderRadiusMedium,
|
||||
borderTopWidth: "1px",
|
||||
borderTopStyle: "solid",
|
||||
borderTopColor: tokens.colorNeutralStroke2,
|
||||
borderRightWidth: "1px",
|
||||
borderRightStyle: "solid",
|
||||
borderRightColor: tokens.colorNeutralStroke2,
|
||||
borderBottomWidth: "1px",
|
||||
borderBottomStyle: "solid",
|
||||
borderBottomColor: tokens.colorNeutralStroke2,
|
||||
borderLeftWidth: "1px",
|
||||
borderLeftStyle: "solid",
|
||||
borderLeftColor: tokens.colorNeutralStroke2,
|
||||
padding: tokens.spacingVerticalM,
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: tokens.spacingVerticalS,
|
||||
},
|
||||
sectionHeader: {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
paddingBottom: tokens.spacingVerticalS,
|
||||
borderBottomWidth: "1px",
|
||||
borderBottomStyle: "solid",
|
||||
borderBottomColor: tokens.colorNeutralStroke2,
|
||||
},
|
||||
|
||||
tableWrapper: { overflowX: "auto" },
|
||||
actionsCell: { display: "flex", gap: tokens.spacingHorizontalS, flexWrap: "wrap" },
|
||||
mono: { fontFamily: "Consolas, 'Courier New', monospace", fontSize: "12px" },
|
||||
@@ -400,6 +373,7 @@ interface SourcesSectionProps {
|
||||
|
||||
function SourcesSection({ onRunImport, runImportRunning }: SourcesSectionProps): React.JSX.Element {
|
||||
const styles = useStyles();
|
||||
const sectionStyles = useCommonSectionStyles();
|
||||
const { sources, loading, error, refresh, createSource, updateSource, removeSource, previewSource } =
|
||||
useBlocklists();
|
||||
|
||||
@@ -471,8 +445,8 @@ function SourcesSection({ onRunImport, runImportRunning }: SourcesSectionProps):
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className={styles.section}>
|
||||
<div className={styles.sectionHeader}>
|
||||
<div className={sectionStyles.section}>
|
||||
<div className={sectionStyles.sectionHeader}>
|
||||
<Text size={500} weight="semibold">
|
||||
Blocklist Sources
|
||||
</Text>
|
||||
@@ -631,6 +605,7 @@ interface ScheduleSectionProps {
|
||||
|
||||
function ScheduleSection({ onRunImport, runImportRunning }: ScheduleSectionProps): React.JSX.Element {
|
||||
const styles = useStyles();
|
||||
const sectionStyles = useCommonSectionStyles();
|
||||
const { info, loading, error, saveSchedule } = useSchedule();
|
||||
const [saving, setSaving] = useState(false);
|
||||
const [saveMsg, setSaveMsg] = useState<string | null>(null);
|
||||
@@ -663,8 +638,8 @@ function ScheduleSection({ onRunImport, runImportRunning }: ScheduleSectionProps
|
||||
}, [draft, saveSchedule]);
|
||||
|
||||
return (
|
||||
<div className={styles.section}>
|
||||
<div className={styles.sectionHeader}>
|
||||
<div className={sectionStyles.section}>
|
||||
<div className={sectionStyles.sectionHeader}>
|
||||
<Text size={500} weight="semibold">
|
||||
Import Schedule
|
||||
</Text>
|
||||
@@ -810,11 +785,12 @@ function ScheduleSection({ onRunImport, runImportRunning }: ScheduleSectionProps
|
||||
|
||||
function ImportLogSection(): React.JSX.Element {
|
||||
const styles = useStyles();
|
||||
const sectionStyles = useCommonSectionStyles();
|
||||
const { data, loading, error, page, setPage, refresh } = useImportLog(undefined, 20);
|
||||
|
||||
return (
|
||||
<div className={styles.section}>
|
||||
<div className={styles.sectionHeader}>
|
||||
<div className={sectionStyles.section}>
|
||||
<div className={sectionStyles.sectionHeader}>
|
||||
<Text size={500} weight="semibold">
|
||||
Import Log
|
||||
</Text>
|
||||
|
||||
@@ -15,6 +15,7 @@ import { DashboardFilterBar } from "../components/DashboardFilterBar";
|
||||
import { ServerStatusBar } from "../components/ServerStatusBar";
|
||||
import { TopCountriesBarChart } from "../components/TopCountriesBarChart";
|
||||
import { TopCountriesPieChart } from "../components/TopCountriesPieChart";
|
||||
import { useCommonSectionStyles } from "../theme/commonStyles";
|
||||
import { useDashboardCountryData } from "../hooks/useDashboardCountryData";
|
||||
import type { BanOriginFilter, TimeRange } from "../types/ban";
|
||||
|
||||
@@ -29,26 +30,6 @@ const useStyles = makeStyles({
|
||||
flexDirection: "column",
|
||||
gap: tokens.spacingVerticalM,
|
||||
},
|
||||
section: {
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: tokens.spacingVerticalS,
|
||||
backgroundColor: tokens.colorNeutralBackground1,
|
||||
borderRadius: tokens.borderRadiusMedium,
|
||||
borderTopWidth: "1px",
|
||||
borderTopStyle: "solid",
|
||||
borderTopColor: tokens.colorNeutralStroke2,
|
||||
borderRightWidth: "1px",
|
||||
borderRightStyle: "solid",
|
||||
borderRightColor: tokens.colorNeutralStroke2,
|
||||
borderBottomWidth: "1px",
|
||||
borderBottomStyle: "solid",
|
||||
borderBottomColor: tokens.colorNeutralStroke2,
|
||||
borderLeftWidth: "1px",
|
||||
borderLeftStyle: "solid",
|
||||
borderLeftColor: tokens.colorNeutralStroke2,
|
||||
padding: tokens.spacingVerticalM,
|
||||
},
|
||||
sectionHeader: {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
@@ -93,6 +74,8 @@ export function DashboardPage(): React.JSX.Element {
|
||||
const { countries, countryNames, isLoading: countryLoading, error: countryError, reload: reloadCountry } =
|
||||
useDashboardCountryData(timeRange, originFilter);
|
||||
|
||||
const sectionStyles = useCommonSectionStyles();
|
||||
|
||||
return (
|
||||
<div className={styles.root}>
|
||||
{/* ------------------------------------------------------------------ */}
|
||||
@@ -113,7 +96,7 @@ export function DashboardPage(): React.JSX.Element {
|
||||
{/* ------------------------------------------------------------------ */}
|
||||
{/* Ban Trend section */}
|
||||
{/* ------------------------------------------------------------------ */}
|
||||
<div className={styles.section}>
|
||||
<div className={sectionStyles.section}>
|
||||
<div className={styles.sectionHeader}>
|
||||
<Text as="h2" size={500} weight="semibold">
|
||||
Ban Trend
|
||||
@@ -127,7 +110,7 @@ export function DashboardPage(): React.JSX.Element {
|
||||
{/* ------------------------------------------------------------------ */}
|
||||
{/* Charts section */}
|
||||
{/* ------------------------------------------------------------------ */}
|
||||
<div className={styles.section}>
|
||||
<div className={sectionStyles.section}>
|
||||
<div className={styles.sectionHeader}>
|
||||
<Text as="h2" size={500} weight="semibold">
|
||||
Top Countries
|
||||
@@ -162,7 +145,7 @@ export function DashboardPage(): React.JSX.Element {
|
||||
{/* ------------------------------------------------------------------ */}
|
||||
{/* Ban list section */}
|
||||
{/* ------------------------------------------------------------------ */}
|
||||
<div className={styles.section}>
|
||||
<div className={sectionStyles.section}>
|
||||
<div className={styles.sectionHeader}>
|
||||
<Text as="h2" size={500} weight="semibold">
|
||||
Ban List
|
||||
|
||||
@@ -35,6 +35,7 @@ import {
|
||||
makeStyles,
|
||||
tokens,
|
||||
} from "@fluentui/react-components";
|
||||
import { useCardStyles } from "../theme/commonStyles";
|
||||
import {
|
||||
ArrowCounterclockwiseRegular,
|
||||
ArrowLeftRegular,
|
||||
@@ -112,9 +113,6 @@ const useStyles = makeStyles({
|
||||
gridTemplateColumns: "repeat(auto-fit, minmax(160px, 1fr))",
|
||||
gap: tokens.spacingVerticalM,
|
||||
padding: tokens.spacingVerticalM,
|
||||
background: tokens.colorNeutralBackground2,
|
||||
borderRadius: tokens.borderRadiusMedium,
|
||||
border: `1px solid ${tokens.colorNeutralStroke1}`,
|
||||
marginBottom: tokens.spacingVerticalM,
|
||||
},
|
||||
detailField: {
|
||||
@@ -216,6 +214,7 @@ interface IpDetailViewProps {
|
||||
|
||||
function IpDetailView({ ip, onBack }: IpDetailViewProps): React.JSX.Element {
|
||||
const styles = useStyles();
|
||||
const cardStyles = useCardStyles();
|
||||
const { detail, loading, error, refresh } = useIpHistory(ip);
|
||||
|
||||
if (loading) {
|
||||
@@ -272,7 +271,7 @@ function IpDetailView({ ip, onBack }: IpDetailViewProps): React.JSX.Element {
|
||||
</div>
|
||||
|
||||
{/* Summary grid */}
|
||||
<div className={styles.detailGrid}>
|
||||
<div className={`${cardStyles.card} ${styles.detailGrid}`}>
|
||||
<div className={styles.detailField}>
|
||||
<span className={styles.detailLabel}>Total Bans</span>
|
||||
<span className={styles.detailValue}>{String(detail.total_bans)}</span>
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
makeStyles,
|
||||
tokens,
|
||||
} from "@fluentui/react-components";
|
||||
import { useCommonSectionStyles } from "../theme/commonStyles";
|
||||
import {
|
||||
ArrowClockwiseRegular,
|
||||
ArrowLeftRegular,
|
||||
@@ -53,36 +54,7 @@ const useStyles = makeStyles({
|
||||
alignItems: "center",
|
||||
gap: tokens.spacingHorizontalS,
|
||||
},
|
||||
section: {
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: tokens.spacingVerticalS,
|
||||
backgroundColor: tokens.colorNeutralBackground1,
|
||||
borderRadius: tokens.borderRadiusMedium,
|
||||
borderTopWidth: "1px",
|
||||
borderTopStyle: "solid",
|
||||
borderTopColor: tokens.colorNeutralStroke2,
|
||||
borderRightWidth: "1px",
|
||||
borderRightStyle: "solid",
|
||||
borderRightColor: tokens.colorNeutralStroke2,
|
||||
borderBottomWidth: "1px",
|
||||
borderBottomStyle: "solid",
|
||||
borderBottomColor: tokens.colorNeutralStroke2,
|
||||
borderLeftWidth: "1px",
|
||||
borderLeftStyle: "solid",
|
||||
borderLeftColor: tokens.colorNeutralStroke2,
|
||||
padding: tokens.spacingVerticalM,
|
||||
},
|
||||
sectionHeader: {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
gap: tokens.spacingHorizontalM,
|
||||
paddingBottom: tokens.spacingVerticalS,
|
||||
borderBottomWidth: "1px",
|
||||
borderBottomStyle: "solid",
|
||||
borderBottomColor: tokens.colorNeutralStroke2,
|
||||
},
|
||||
|
||||
headerRow: {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
@@ -181,6 +153,7 @@ interface JailInfoProps {
|
||||
|
||||
function JailInfoSection({ jail, onRefresh, onStart, onStop, onSetIdle, onReload }: JailInfoProps): React.JSX.Element {
|
||||
const styles = useStyles();
|
||||
const sectionStyles = useCommonSectionStyles();
|
||||
const navigate = useNavigate();
|
||||
const [ctrlError, setCtrlError] = useState<string | null>(null);
|
||||
|
||||
@@ -206,8 +179,8 @@ function JailInfoSection({ jail, onRefresh, onStart, onStop, onSetIdle, onReload
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.section}>
|
||||
<div className={styles.sectionHeader}>
|
||||
<div className={sectionStyles.section}>
|
||||
<div className={sectionStyles.sectionHeader}>
|
||||
<div className={styles.headerRow}>
|
||||
<Text
|
||||
size={600}
|
||||
@@ -334,10 +307,10 @@ function JailInfoSection({ jail, onRefresh, onStart, onStop, onSetIdle, onReload
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function PatternsSection({ jail }: { jail: Jail }): React.JSX.Element {
|
||||
const styles = useStyles();
|
||||
const sectionStyles = useCommonSectionStyles();
|
||||
return (
|
||||
<div className={styles.section}>
|
||||
<div className={styles.sectionHeader}>
|
||||
<div className={sectionStyles.section}>
|
||||
<div className={sectionStyles.sectionHeader}>
|
||||
<Text as="h2" size={500} weight="semibold">
|
||||
Log Paths & Patterns
|
||||
</Text>
|
||||
@@ -374,12 +347,13 @@ function PatternsSection({ jail }: { jail: Jail }): React.JSX.Element {
|
||||
|
||||
function BantimeEscalationSection({ jail }: { jail: Jail }): React.JSX.Element | null {
|
||||
const styles = useStyles();
|
||||
const sectionStyles = useCommonSectionStyles();
|
||||
const esc = jail.bantime_escalation;
|
||||
if (!esc?.increment) return null;
|
||||
|
||||
return (
|
||||
<div className={styles.section}>
|
||||
<div className={styles.sectionHeader}>
|
||||
<div className={sectionStyles.section}>
|
||||
<div className={sectionStyles.sectionHeader}>
|
||||
<Text as="h2" size={500} weight="semibold">
|
||||
Ban-time Escalation
|
||||
</Text>
|
||||
@@ -445,6 +419,7 @@ function IgnoreListSection({
|
||||
onToggleIgnoreSelf,
|
||||
}: IgnoreListSectionProps): React.JSX.Element {
|
||||
const styles = useStyles();
|
||||
const sectionStyles = useCommonSectionStyles();
|
||||
const [inputVal, setInputVal] = useState("");
|
||||
const [opError, setOpError] = useState<string | null>(null);
|
||||
|
||||
@@ -470,8 +445,8 @@ function IgnoreListSection({
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.section}>
|
||||
<div className={styles.sectionHeader}>
|
||||
<div className={sectionStyles.section}>
|
||||
<div className={sectionStyles.sectionHeader}>
|
||||
<div style={{ display: "flex", alignItems: "center", gap: tokens.spacingHorizontalM }}>
|
||||
<Text as="h2" size={500} weight="semibold">
|
||||
Ignore List (IP Whitelist)
|
||||
|
||||
@@ -33,6 +33,7 @@ import {
|
||||
type TableColumnDefinition,
|
||||
createTableColumn,
|
||||
} from "@fluentui/react-components";
|
||||
import { useCardStyles, useCommonSectionStyles } from "../theme/commonStyles";
|
||||
import {
|
||||
ArrowClockwiseRegular,
|
||||
ArrowSyncRegular,
|
||||
@@ -58,36 +59,7 @@ const useStyles = makeStyles({
|
||||
flexDirection: "column",
|
||||
gap: tokens.spacingVerticalL,
|
||||
},
|
||||
section: {
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: tokens.spacingVerticalS,
|
||||
backgroundColor: tokens.colorNeutralBackground1,
|
||||
borderRadius: tokens.borderRadiusMedium,
|
||||
borderTopWidth: "1px",
|
||||
borderTopStyle: "solid",
|
||||
borderTopColor: tokens.colorNeutralStroke2,
|
||||
borderRightWidth: "1px",
|
||||
borderRightStyle: "solid",
|
||||
borderRightColor: tokens.colorNeutralStroke2,
|
||||
borderBottomWidth: "1px",
|
||||
borderBottomStyle: "solid",
|
||||
borderBottomColor: tokens.colorNeutralStroke2,
|
||||
borderLeftWidth: "1px",
|
||||
borderLeftStyle: "solid",
|
||||
borderLeftColor: tokens.colorNeutralStroke2,
|
||||
padding: tokens.spacingVerticalM,
|
||||
},
|
||||
sectionHeader: {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
gap: tokens.spacingHorizontalM,
|
||||
paddingBottom: tokens.spacingVerticalS,
|
||||
borderBottomWidth: "1px",
|
||||
borderBottomStyle: "solid",
|
||||
borderBottomColor: tokens.colorNeutralStroke2,
|
||||
},
|
||||
|
||||
tableWrapper: { overflowX: "auto" },
|
||||
centred: {
|
||||
display: "flex",
|
||||
@@ -117,20 +89,6 @@ const useStyles = makeStyles({
|
||||
gap: tokens.spacingVerticalS,
|
||||
marginTop: tokens.spacingVerticalS,
|
||||
padding: tokens.spacingVerticalS,
|
||||
backgroundColor: tokens.colorNeutralBackground2,
|
||||
borderRadius: tokens.borderRadiusMedium,
|
||||
borderTopWidth: "1px",
|
||||
borderTopStyle: "solid",
|
||||
borderTopColor: tokens.colorNeutralStroke2,
|
||||
borderRightWidth: "1px",
|
||||
borderRightStyle: "solid",
|
||||
borderRightColor: tokens.colorNeutralStroke2,
|
||||
borderBottomWidth: "1px",
|
||||
borderBottomStyle: "solid",
|
||||
borderBottomColor: tokens.colorNeutralStroke2,
|
||||
borderLeftWidth: "1px",
|
||||
borderLeftStyle: "solid",
|
||||
borderLeftColor: tokens.colorNeutralStroke2,
|
||||
},
|
||||
lookupRow: {
|
||||
display: "flex",
|
||||
@@ -208,6 +166,7 @@ const jailColumns: TableColumnDefinition<JailSummary>[] = [
|
||||
|
||||
function JailOverviewSection(): React.JSX.Element {
|
||||
const styles = useStyles();
|
||||
const sectionStyles = useCommonSectionStyles();
|
||||
const { jails, total, loading, error, refresh, startJail, stopJail, setIdle, reloadJail, reloadAll } =
|
||||
useJails();
|
||||
const [opError, setOpError] = useState<string | null>(null);
|
||||
@@ -220,8 +179,8 @@ function JailOverviewSection(): React.JSX.Element {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.section}>
|
||||
<div className={styles.sectionHeader}>
|
||||
<div className={sectionStyles.section}>
|
||||
<div className={sectionStyles.sectionHeader}>
|
||||
<Text as="h2" size={500} weight="semibold">
|
||||
Jail Overview
|
||||
{total > 0 && (
|
||||
@@ -358,6 +317,7 @@ interface BanUnbanFormProps {
|
||||
|
||||
function BanUnbanForm({ jailNames, onBan, onUnban }: BanUnbanFormProps): React.JSX.Element {
|
||||
const styles = useStyles();
|
||||
const sectionStyles = useCommonSectionStyles();
|
||||
const [banIpVal, setBanIpVal] = useState("");
|
||||
const [banJail, setBanJail] = useState("");
|
||||
const [unbanIpVal, setUnbanIpVal] = useState("");
|
||||
@@ -415,8 +375,8 @@ function BanUnbanForm({ jailNames, onBan, onUnban }: BanUnbanFormProps): React.J
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.section}>
|
||||
<div className={styles.sectionHeader}>
|
||||
<div className={sectionStyles.section}>
|
||||
<div className={sectionStyles.sectionHeader}>
|
||||
<Text as="h2" size={500} weight="semibold">
|
||||
Ban / Unban IP
|
||||
</Text>
|
||||
@@ -544,6 +504,8 @@ function BanUnbanForm({ jailNames, onBan, onUnban }: BanUnbanFormProps): React.J
|
||||
|
||||
function IpLookupSection(): React.JSX.Element {
|
||||
const styles = useStyles();
|
||||
const sectionStyles = useCommonSectionStyles();
|
||||
const cardStyles = useCardStyles();
|
||||
const { result, loading, error, lookup, clear } = useIpLookup();
|
||||
const [inputVal, setInputVal] = useState("");
|
||||
|
||||
@@ -554,8 +516,8 @@ function IpLookupSection(): React.JSX.Element {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.section}>
|
||||
<div className={styles.sectionHeader}>
|
||||
<div className={sectionStyles.section}>
|
||||
<div className={sectionStyles.sectionHeader}>
|
||||
<Text as="h2" size={500} weight="semibold">
|
||||
IP Lookup
|
||||
</Text>
|
||||
@@ -595,7 +557,7 @@ function IpLookupSection(): React.JSX.Element {
|
||||
)}
|
||||
|
||||
{result && (
|
||||
<div className={styles.lookupResult}>
|
||||
<div className={`${cardStyles.card} ${styles.lookupResult}`}>
|
||||
<div className={styles.lookupRow}>
|
||||
<Text className={styles.lookupLabel}>IP:</Text>
|
||||
<Text className={styles.mono}>{result.ip}</Text>
|
||||
|
||||
30
frontend/src/theme/commonStyles.ts
Normal file
30
frontend/src/theme/commonStyles.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { makeStyles, tokens } from "@fluentui/react-components";
|
||||
|
||||
export const useCommonSectionStyles = makeStyles({
|
||||
section: {
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: tokens.spacingVerticalS,
|
||||
backgroundColor: tokens.colorNeutralBackground1,
|
||||
borderRadius: tokens.borderRadiusMedium,
|
||||
border: `1px solid ${tokens.colorNeutralStroke2}`,
|
||||
padding: tokens.spacingVerticalM,
|
||||
},
|
||||
sectionHeader: {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
gap: tokens.spacingHorizontalM,
|
||||
paddingBottom: tokens.spacingVerticalS,
|
||||
borderBottom: `1px solid ${tokens.colorNeutralStroke2}`,
|
||||
},
|
||||
});
|
||||
|
||||
export const useCardStyles = makeStyles({
|
||||
card: {
|
||||
backgroundColor: tokens.colorNeutralBackground1,
|
||||
borderRadius: tokens.borderRadiusMedium,
|
||||
border: `1px solid ${tokens.colorNeutralStroke2}`,
|
||||
padding: tokens.spacingVerticalM,
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user