Move constant inline styles into makeStyles
This commit is contained in:
@@ -354,7 +354,11 @@ const source = timeRange === "24h" ? "fail2ban" : "archive";
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### TASK-018 — Move inline `style={{…}}` objects to `makeStyles`
|
### TASK-018 — Move inline `style={{…}}` objects to `makeStyles` (done)
|
||||||
|
|
||||||
|
**Where fixed:** `frontend/src/pages/MapPage.tsx`, `frontend/src/pages/DashboardPage.tsx`, `frontend/src/pages/jail/PatternsSection.tsx`, `frontend/src/pages/jails/BanUnbanForm.tsx`, `frontend/src/layouts/MainLayout.tsx`, `frontend/src/pages/jails/jailsPageStyles.ts`
|
||||||
|
|
||||||
|
**Summary:** Moved constant inline style objects into `makeStyles` classes and used `mergeClasses` for dynamic button layout in `MainLayout`. Kept runtime-dependent opacity and collapse state as conditional class application.
|
||||||
|
|
||||||
**Where found:** 30+ instances across `frontend/src/pages/MapPage.tsx`, `frontend/src/pages/map/MapBansTable.tsx`, `frontend/src/pages/DashboardPage.tsx`, `frontend/src/pages/jail/PatternsSection.tsx`, `frontend/src/pages/jails/BanUnbanForm.tsx`, `frontend/src/layouts/MainLayout.tsx`, and others.
|
**Where found:** 30+ instances across `frontend/src/pages/MapPage.tsx`, `frontend/src/pages/map/MapBansTable.tsx`, `frontend/src/pages/DashboardPage.tsx`, `frontend/src/pages/jail/PatternsSection.tsx`, `frontend/src/pages/jails/BanUnbanForm.tsx`, `frontend/src/layouts/MainLayout.tsx`, and others.
|
||||||
|
|
||||||
|
|||||||
@@ -145,6 +145,13 @@ const useStyles = makeStyles({
|
|||||||
padding: tokens.spacingVerticalS,
|
padding: tokens.spacingVerticalS,
|
||||||
flexShrink: 0,
|
flexShrink: 0,
|
||||||
},
|
},
|
||||||
|
logoutButton: {
|
||||||
|
width: "100%",
|
||||||
|
justifyContent: "flex-start",
|
||||||
|
},
|
||||||
|
logoutButtonCollapsed: {
|
||||||
|
justifyContent: "center",
|
||||||
|
},
|
||||||
versionText: {
|
versionText: {
|
||||||
display: "block",
|
display: "block",
|
||||||
color: tokens.colorNeutralForeground4,
|
color: tokens.colorNeutralForeground4,
|
||||||
@@ -326,7 +333,10 @@ export function MainLayout(): React.JSX.Element {
|
|||||||
icon={<SignOutRegular />}
|
icon={<SignOutRegular />}
|
||||||
onClick={() => void handleLogout()}
|
onClick={() => void handleLogout()}
|
||||||
aria-label="Sign out"
|
aria-label="Sign out"
|
||||||
style={{ width: "100%", justifyContent: collapsed ? "center" : "flex-start" }}
|
className={mergeClasses(
|
||||||
|
styles.logoutButton,
|
||||||
|
collapsed && styles.logoutButtonCollapsed,
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{!collapsed && "Sign out"}
|
{!collapsed && "Sign out"}
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -31,6 +31,12 @@ const useStyles = makeStyles({
|
|||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
gap: tokens.spacingVerticalM,
|
gap: tokens.spacingVerticalM,
|
||||||
},
|
},
|
||||||
|
filterRow: {
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: tokens.spacingHorizontalM,
|
||||||
|
flexWrap: "wrap",
|
||||||
|
},
|
||||||
sectionHeader: {
|
sectionHeader: {
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
@@ -89,7 +95,7 @@ export function DashboardPage(): React.JSX.Element {
|
|||||||
{/* ------------------------------------------------------------------ */}
|
{/* ------------------------------------------------------------------ */}
|
||||||
{/* Global filter bar */}
|
{/* Global filter bar */}
|
||||||
{/* ------------------------------------------------------------------ */}
|
{/* ------------------------------------------------------------------ */}
|
||||||
<div style={{ display: "flex", alignItems: "center", gap: tokens.spacingHorizontalM, flexWrap: "wrap" }}>
|
<div className={styles.filterRow}>
|
||||||
<DashboardFilterBar
|
<DashboardFilterBar
|
||||||
timeRange={timeRange}
|
timeRange={timeRange}
|
||||||
onTimeRangeChange={setTimeRange}
|
onTimeRangeChange={setTimeRange}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import {
|
|||||||
Spinner,
|
Spinner,
|
||||||
Text,
|
Text,
|
||||||
makeStyles,
|
makeStyles,
|
||||||
|
mergeClasses,
|
||||||
tokens,
|
tokens,
|
||||||
} from "@fluentui/react-components";
|
} from "@fluentui/react-components";
|
||||||
import {
|
import {
|
||||||
@@ -71,6 +72,29 @@ const useStyles = makeStyles({
|
|||||||
borderRadius: tokens.borderRadiusMedium,
|
borderRadius: tokens.borderRadiusMedium,
|
||||||
backgroundColor: tokens.colorNeutralBackground2,
|
backgroundColor: tokens.colorNeutralBackground2,
|
||||||
},
|
},
|
||||||
|
headerActions: {
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: tokens.spacingHorizontalM,
|
||||||
|
flexWrap: "wrap",
|
||||||
|
},
|
||||||
|
initialLoad: {
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
padding: tokens.spacingVerticalXL,
|
||||||
|
},
|
||||||
|
summaryRow: {
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: tokens.spacingHorizontalS,
|
||||||
|
},
|
||||||
|
summaryText: {
|
||||||
|
color: tokens.colorNeutralForeground3,
|
||||||
|
},
|
||||||
|
tableWrapperLoading: {
|
||||||
|
opacity: 0.5,
|
||||||
|
transition: "opacity 150ms",
|
||||||
|
},
|
||||||
pagination: {
|
pagination: {
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
@@ -158,7 +182,7 @@ export function MapPage(): React.JSX.Element {
|
|||||||
World Map
|
World Map
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<div style={{ display: "flex", alignItems: "center", gap: tokens.spacingHorizontalM, flexWrap: "wrap" }}>
|
<div className={styles.headerActions}>
|
||||||
<DashboardFilterBar
|
<DashboardFilterBar
|
||||||
timeRange={range}
|
timeRange={range}
|
||||||
onTimeRangeChange={(value) => {
|
onTimeRangeChange={(value) => {
|
||||||
@@ -193,7 +217,7 @@ export function MapPage(): React.JSX.Element {
|
|||||||
|
|
||||||
{/* Initial load spinner — only shown before the first data arrives. */}
|
{/* Initial load spinner — only shown before the first data arrives. */}
|
||||||
{loading && !error && !hasLoadedOnce && (
|
{loading && !error && !hasLoadedOnce && (
|
||||||
<div style={{ display: "flex", justifyContent: "center", padding: tokens.spacingVerticalXL }}>
|
<div className={styles.initialLoad}>
|
||||||
<Spinner label="Loading map data…" />
|
<Spinner label="Loading map data…" />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -242,8 +266,8 @@ export function MapPage(): React.JSX.Element {
|
|||||||
{/* Summary line */}
|
{/* Summary line */}
|
||||||
{/* ---------------------------------------------------------------- */}
|
{/* ---------------------------------------------------------------- */}
|
||||||
{!error && hasLoadedOnce && (
|
{!error && hasLoadedOnce && (
|
||||||
<div style={{ display: "flex", alignItems: "center", gap: tokens.spacingHorizontalS }}>
|
<div className={styles.summaryRow}>
|
||||||
<Text size={300} style={{ color: tokens.colorNeutralForeground3 }}>
|
<Text size={300} className={styles.summaryText}>
|
||||||
{String(total)} total ban{total !== 1 ? "s" : ""} in the selected period
|
{String(total)} total ban{total !== 1 ? "s" : ""} in the selected period
|
||||||
{" · "}
|
{" · "}
|
||||||
{String(Object.keys(countries).length)} countr{Object.keys(countries).length !== 1 ? "ies" : "y"} affected
|
{String(Object.keys(countries).length)} countr{Object.keys(countries).length !== 1 ? "ies" : "y"} affected
|
||||||
@@ -256,7 +280,7 @@ export function MapPage(): React.JSX.Element {
|
|||||||
{/* Companion bans table */}
|
{/* Companion bans table */}
|
||||||
{/* ---------------------------------------------------------------- */}
|
{/* ---------------------------------------------------------------- */}
|
||||||
{!error && hasLoadedOnce && (
|
{!error && hasLoadedOnce && (
|
||||||
<div className={styles.tableWrapper} style={{ opacity: loading ? 0.5 : 1, transition: "opacity 150ms" }}>
|
<div className={mergeClasses(styles.tableWrapper, loading && styles.tableWrapperLoading)}>
|
||||||
<MapBansTable
|
<MapBansTable
|
||||||
pageBans={pageBans}
|
pageBans={pageBans}
|
||||||
visibleCount={visibleBans.length}
|
visibleCount={visibleBans.length}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Text } from "@fluentui/react-components";
|
import { Text, makeStyles, tokens } from "@fluentui/react-components";
|
||||||
import { useCommonSectionStyles } from "../../components/commonStyles";
|
import { useCommonSectionStyles } from "../../components/commonStyles";
|
||||||
import type { Jail } from "../../types/jail";
|
import type { Jail } from "../../types/jail";
|
||||||
import { CodeList } from "./CodeList";
|
import { CodeList } from "./CodeList";
|
||||||
@@ -7,8 +7,15 @@ interface PatternsSectionProps {
|
|||||||
jail: Jail;
|
jail: Jail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const useStyles = makeStyles({
|
||||||
|
spacedHeading: {
|
||||||
|
marginTop: tokens.spacingVerticalS,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export function PatternsSection({ jail }: PatternsSectionProps): React.JSX.Element {
|
export function PatternsSection({ jail }: PatternsSectionProps): React.JSX.Element {
|
||||||
const sectionStyles = useCommonSectionStyles();
|
const sectionStyles = useCommonSectionStyles();
|
||||||
|
const styles = useStyles();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={sectionStyles.section}>
|
<div className={sectionStyles.section}>
|
||||||
@@ -23,19 +30,19 @@ export function PatternsSection({ jail }: PatternsSectionProps): React.JSX.Eleme
|
|||||||
</Text>
|
</Text>
|
||||||
<CodeList items={jail.log_paths} empty="No log paths configured." />
|
<CodeList items={jail.log_paths} empty="No log paths configured." />
|
||||||
|
|
||||||
<Text size={300} weight="semibold" style={{ marginTop: "var(--spacingVerticalS)" }}>
|
<Text size={300} weight="semibold" className={styles.spacedHeading}>
|
||||||
Fail Regex
|
Fail Regex
|
||||||
</Text>
|
</Text>
|
||||||
<CodeList items={jail.fail_regex} empty="No fail-regex patterns." />
|
<CodeList items={jail.fail_regex} empty="No fail-regex patterns." />
|
||||||
|
|
||||||
<Text size={300} weight="semibold" style={{ marginTop: "var(--spacingVerticalS)" }}>
|
<Text size={300} weight="semibold" className={styles.spacedHeading}>
|
||||||
Ignore Regex
|
Ignore Regex
|
||||||
</Text>
|
</Text>
|
||||||
<CodeList items={jail.ignore_regex} empty="No ignore-regex patterns." />
|
<CodeList items={jail.ignore_regex} empty="No ignore-regex patterns." />
|
||||||
|
|
||||||
{jail.actions.length > 0 && (
|
{jail.actions.length > 0 && (
|
||||||
<>
|
<>
|
||||||
<Text size={300} weight="semibold" style={{ marginTop: "var(--spacingVerticalS)" }}>
|
<Text size={300} weight="semibold" className={styles.spacedHeading}>
|
||||||
Actions
|
Actions
|
||||||
</Text>
|
</Text>
|
||||||
<CodeList items={jail.actions} empty="" />
|
<CodeList items={jail.actions} empty="" />
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import {
|
|||||||
MessageBarBody,
|
MessageBarBody,
|
||||||
Select,
|
Select,
|
||||||
Text,
|
Text,
|
||||||
tokens,
|
|
||||||
} from "@fluentui/react-components";
|
} from "@fluentui/react-components";
|
||||||
import { LockClosedRegular, LockOpenRegular } from "@fluentui/react-icons";
|
import { LockClosedRegular, LockOpenRegular } from "@fluentui/react-icons";
|
||||||
import { useCommonSectionStyles } from "../../components/commonStyles";
|
import { useCommonSectionStyles } from "../../components/commonStyles";
|
||||||
@@ -142,7 +141,7 @@ export function BanUnbanForm({ jailNames, onBan, onUnban }: BanUnbanFormProps):
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Text size={300} weight="semibold" style={{ marginTop: tokens.spacingVerticalS }}>
|
<Text size={300} weight="semibold" className={styles.sectionHeadingSpacing}>
|
||||||
Unban an IP
|
Unban an IP
|
||||||
</Text>
|
</Text>
|
||||||
<div className={styles.formRow}>
|
<div className={styles.formRow}>
|
||||||
|
|||||||
@@ -43,4 +43,7 @@ export const useJailsPageStyles = makeStyles({
|
|||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
},
|
},
|
||||||
lookupLabel: { fontWeight: tokens.fontWeightSemibold },
|
lookupLabel: { fontWeight: tokens.fontWeightSemibold },
|
||||||
|
sectionHeadingSpacing: {
|
||||||
|
marginTop: tokens.spacingVerticalS,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user