Remove inactive jails section from Jail management page

The Jail page is now a pure operational view showing only jails that
fail2ban reports as active. The backend GET /api/jails already queried
only the fail2ban socket status command, so no backend changes were
needed.

Frontend changes:
- Remove Inactive Jails table, Show-inactive toggle, and all related
  state (showInactive, inactiveJails, activateTarget)
- Remove fetchInactiveJails() call and loadInactive/handleActivated
  callbacks
- Remove ActivateJailDialog import and usage
- Remove unused imports: useCallback, useEffect, Switch, InactiveJail

Inactive-jail discovery and activation remain fully functional via the
Configuration page Jails tab (JailsTab.tsx) — unchanged.
This commit is contained in:
2026-03-14 11:44:05 +01:00
parent 2f2e5a7419
commit 5e1b8134d9
2 changed files with 233 additions and 362 deletions

View File

@@ -10,7 +10,7 @@
* geo-location details.
*/
import { useCallback, useEffect, useState } from "react";
import { useState } from "react";
import {
Badge,
Button,
@@ -32,7 +32,6 @@ import {
MessageBarBody,
Select,
Spinner,
Switch,
Text,
Tooltip,
makeStyles,
@@ -53,11 +52,8 @@ import {
StopRegular,
} from "@fluentui/react-icons";
import { Link } from "react-router-dom";
import { fetchInactiveJails } from "../api/config";
import { ActivateJailDialog } from "../components/config";
import { useActiveBans, useIpLookup, useJails } from "../hooks/useJails";
import type { ActiveBan, JailSummary } from "../types/jail";
import type { InactiveJail } from "../types/config";
import { ApiError } from "../api/client";
// ---------------------------------------------------------------------------
@@ -323,25 +319,6 @@ function JailOverviewSection(): React.JSX.Element {
const { jails, total, loading, error, refresh, startJail, stopJail, setIdle, reloadJail, reloadAll } =
useJails();
const [opError, setOpError] = useState<string | null>(null);
const [showInactive, setShowInactive] = useState(true);
const [inactiveJails, setInactiveJails] = useState<InactiveJail[]>([]);
const [activateTarget, setActivateTarget] = useState<InactiveJail | null>(null);
const loadInactive = useCallback((): void => {
fetchInactiveJails()
.then((res) => { setInactiveJails(res.jails); })
.catch(() => { /* non-critical */ });
}, []);
useEffect(() => {
loadInactive();
}, [loadInactive]);
const handleActivated = useCallback((): void => {
setActivateTarget(null);
refresh();
loadInactive();
}, [refresh, loadInactive]);
const handle = (fn: () => Promise<void>): void => {
setOpError(null);
@@ -350,9 +327,6 @@ function JailOverviewSection(): React.JSX.Element {
});
};
const activeNameSet = new Set(jails.map((j) => j.name));
const inactiveToShow = inactiveJails.filter((j) => !activeNameSet.has(j.name));
return (
<div className={styles.section}>
<div className={styles.sectionHeader}>
@@ -365,11 +339,6 @@ function JailOverviewSection(): React.JSX.Element {
)}
</Text>
<div className={styles.actionRow}>
<Switch
label="Show inactive"
checked={showInactive}
onChange={(_e, d) => { setShowInactive(d.checked); }}
/>
<Button
size="small"
appearance="subtle"
@@ -481,85 +450,6 @@ function JailOverviewSection(): React.JSX.Element {
</div>
)}
{/* Inactive jails table */}
{showInactive && inactiveToShow.length > 0 && (
<div style={{ marginTop: tokens.spacingVerticalM }}>
<Text
size={300}
weight="semibold"
style={{ color: tokens.colorNeutralForeground3, marginBottom: tokens.spacingVerticalXS }}
block
>
Inactive jails ({String(inactiveToShow.length)})
</Text>
<div className={styles.tableWrapper}>
<table style={{ width: "100%", borderCollapse: "collapse", fontSize: tokens.fontSizeBase200 }}>
<thead>
<tr style={{ borderBottom: `1px solid ${tokens.colorNeutralStroke2}` }}>
<th style={{ textAlign: "left", padding: "6px 8px", fontWeight: tokens.fontWeightSemibold }}>Jail</th>
<th style={{ textAlign: "left", padding: "6px 8px", fontWeight: tokens.fontWeightSemibold }}>Status</th>
<th style={{ textAlign: "left", padding: "6px 8px", fontWeight: tokens.fontWeightSemibold }}>Filter</th>
<th style={{ textAlign: "left", padding: "6px 8px", fontWeight: tokens.fontWeightSemibold }}>Port</th>
<th style={{ textAlign: "left", padding: "6px 8px" }} />
</tr>
</thead>
<tbody>
{inactiveToShow.map((j) => (
<tr
key={j.name}
style={{
borderBottom: `1px solid ${tokens.colorNeutralStroke2}`,
opacity: 0.7,
}}
>
<td style={{ padding: "6px 8px" }}>
<Link
to="/config"
style={{
fontFamily: "Consolas, 'Courier New', monospace",
fontSize: "0.85rem",
textDecoration: "none",
color: tokens.colorBrandForeground1,
}}
>
{j.name}
</Link>
</td>
<td style={{ padding: "6px 8px" }}>
<Badge appearance="filled" color="subtle">inactive</Badge>
</td>
<td style={{ padding: "6px 8px" }}>
<Text size={200} style={{ fontFamily: "Consolas, 'Courier New', monospace" }}>
{j.filter || "—"}
</Text>
</td>
<td style={{ padding: "6px 8px" }}>
<Text size={200}>{j.port ?? "—"}</Text>
</td>
<td style={{ padding: "6px 8px" }}>
<Button
size="small"
appearance="primary"
icon={<PlayRegular />}
onClick={() => { setActivateTarget(j); }}
>
Activate
</Button>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
)}
<ActivateJailDialog
jail={activateTarget}
open={activateTarget !== null}
onClose={() => { setActivateTarget(null); }}
onActivated={handleActivated}
/>
</div>
);
}