Add jail control actions to useJailDetail hook
Implement TASK F-2: Wrap JailDetailPage jail-control API calls in a hook. Changes: - Add start(), stop(), reload(), and setIdle() methods to useJailDetail hook - Update JailDetailPage to use hook control methods instead of direct API imports - Update error handling to remove dependency on ApiError type - Add comprehensive tests for new control methods (8 tests) - Update existing test to include new hook methods in mock The control methods handle refetching jail data after each operation, consistent with the pattern used in useJails hook.
This commit is contained in:
@@ -33,15 +33,8 @@ import {
|
||||
StopRegular,
|
||||
} from "@fluentui/react-icons";
|
||||
import { Link, useNavigate, useParams } from "react-router-dom";
|
||||
import {
|
||||
reloadJail,
|
||||
setJailIdle,
|
||||
startJail,
|
||||
stopJail,
|
||||
} from "../api/jails";
|
||||
import { useJailDetail } from "../hooks/useJails";
|
||||
import type { Jail } from "../types/jail";
|
||||
import { ApiError } from "../api/client";
|
||||
import { BannedIpsSection } from "../components/jail/BannedIpsSection";
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -186,9 +179,13 @@ function CodeList({ items, empty }: { items: string[]; empty: string }): React.J
|
||||
interface JailInfoProps {
|
||||
jail: Jail;
|
||||
onRefresh: () => void;
|
||||
onStart: () => Promise<void>;
|
||||
onStop: () => Promise<void>;
|
||||
onSetIdle: (on: boolean) => Promise<void>;
|
||||
onReload: () => Promise<void>;
|
||||
}
|
||||
|
||||
function JailInfoSection({ jail, onRefresh }: JailInfoProps): React.JSX.Element {
|
||||
function JailInfoSection({ jail, onRefresh, onStart, onStop, onSetIdle, onReload }: JailInfoProps): React.JSX.Element {
|
||||
const styles = useStyles();
|
||||
const navigate = useNavigate();
|
||||
const [ctrlError, setCtrlError] = useState<string | null>(null);
|
||||
@@ -207,11 +204,9 @@ function JailInfoSection({ jail, onRefresh }: JailInfoProps): React.JSX.Element
|
||||
})
|
||||
.catch((err: unknown) => {
|
||||
const msg =
|
||||
err instanceof ApiError
|
||||
? `${String(err.status)}: ${err.body}`
|
||||
: err instanceof Error
|
||||
? err.message
|
||||
: String(err);
|
||||
err instanceof Error
|
||||
? err.message
|
||||
: String(err);
|
||||
setCtrlError(msg);
|
||||
});
|
||||
};
|
||||
@@ -259,7 +254,7 @@ function JailInfoSection({ jail, onRefresh }: JailInfoProps): React.JSX.Element
|
||||
<Button
|
||||
appearance="secondary"
|
||||
icon={<StopRegular />}
|
||||
onClick={handle(() => stopJail(jail.name).then(() => void 0))}
|
||||
onClick={handle(onStop)}
|
||||
>
|
||||
Stop
|
||||
</Button>
|
||||
@@ -269,7 +264,7 @@ function JailInfoSection({ jail, onRefresh }: JailInfoProps): React.JSX.Element
|
||||
<Button
|
||||
appearance="primary"
|
||||
icon={<PlayRegular />}
|
||||
onClick={handle(() => startJail(jail.name).then(() => void 0))}
|
||||
onClick={handle(onStart)}
|
||||
>
|
||||
Start
|
||||
</Button>
|
||||
@@ -282,7 +277,7 @@ function JailInfoSection({ jail, onRefresh }: JailInfoProps): React.JSX.Element
|
||||
<Button
|
||||
appearance="outline"
|
||||
icon={<PauseRegular />}
|
||||
onClick={handle(() => setJailIdle(jail.name, !jail.idle).then(() => void 0))}
|
||||
onClick={handle(() => onSetIdle(!jail.idle))}
|
||||
disabled={!jail.running}
|
||||
>
|
||||
{jail.idle ? "Resume" : "Set Idle"}
|
||||
@@ -292,7 +287,7 @@ function JailInfoSection({ jail, onRefresh }: JailInfoProps): React.JSX.Element
|
||||
<Button
|
||||
appearance="outline"
|
||||
icon={<ArrowSyncRegular />}
|
||||
onClick={handle(() => reloadJail(jail.name).then(() => void 0))}
|
||||
onClick={handle(onReload)}
|
||||
>
|
||||
Reload
|
||||
</Button>
|
||||
@@ -467,12 +462,7 @@ function IgnoreListSection({
|
||||
setInputVal("");
|
||||
})
|
||||
.catch((err: unknown) => {
|
||||
const msg =
|
||||
err instanceof ApiError
|
||||
? `${String(err.status)}: ${err.body}`
|
||||
: err instanceof Error
|
||||
? err.message
|
||||
: String(err);
|
||||
const msg = err instanceof Error ? err.message : String(err);
|
||||
setOpError(msg);
|
||||
});
|
||||
};
|
||||
@@ -480,12 +470,7 @@ function IgnoreListSection({
|
||||
const handleRemove = (ip: string): void => {
|
||||
setOpError(null);
|
||||
onRemove(ip).catch((err: unknown) => {
|
||||
const msg =
|
||||
err instanceof ApiError
|
||||
? `${String(err.status)}: ${err.body}`
|
||||
: err instanceof Error
|
||||
? err.message
|
||||
: String(err);
|
||||
const msg = err instanceof Error ? err.message : String(err);
|
||||
setOpError(msg);
|
||||
});
|
||||
};
|
||||
@@ -507,12 +492,7 @@ function IgnoreListSection({
|
||||
checked={ignoreSelf}
|
||||
onChange={(_e, data): void => {
|
||||
onToggleIgnoreSelf(data.checked).catch((err: unknown) => {
|
||||
const msg =
|
||||
err instanceof ApiError
|
||||
? `${String(err.status)}: ${err.body}`
|
||||
: err instanceof Error
|
||||
? err.message
|
||||
: String(err);
|
||||
const msg = err instanceof Error ? err.message : String(err);
|
||||
setOpError(msg);
|
||||
});
|
||||
}}
|
||||
@@ -592,7 +572,7 @@ function IgnoreListSection({
|
||||
export function JailDetailPage(): React.JSX.Element {
|
||||
const styles = useStyles();
|
||||
const { name = "" } = useParams<{ name: string }>();
|
||||
const { jail, ignoreList, ignoreSelf, loading, error, refresh, addIp, removeIp, toggleIgnoreSelf } =
|
||||
const { jail, ignoreList, ignoreSelf, loading, error, refresh, addIp, removeIp, toggleIgnoreSelf, start, stop, reload, setIdle } =
|
||||
useJailDetail(name);
|
||||
|
||||
if (loading && !jail) {
|
||||
@@ -637,7 +617,7 @@ export function JailDetailPage(): React.JSX.Element {
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<JailInfoSection jail={jail} onRefresh={refresh} />
|
||||
<JailInfoSection jail={jail} onRefresh={refresh} onStart={start} onStop={stop} onReload={reload} onSetIdle={setIdle} />
|
||||
<BannedIpsSection jailName={name} />
|
||||
<PatternsSection jail={jail} />
|
||||
<BantimeEscalationSection jail={jail} />
|
||||
|
||||
@@ -101,6 +101,10 @@ function mockHook(ignoreSelf: boolean): void {
|
||||
addIp: mockAddIp,
|
||||
removeIp: mockRemoveIp,
|
||||
toggleIgnoreSelf: mockToggleIgnoreSelf,
|
||||
start: vi.fn().mockResolvedValue(undefined),
|
||||
stop: vi.fn().mockResolvedValue(undefined),
|
||||
reload: vi.fn().mockResolvedValue(undefined),
|
||||
setIdle: vi.fn().mockResolvedValue(undefined),
|
||||
};
|
||||
vi.mocked(useJailDetail).mockReturnValue(result);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user