API lib cleanup, 404 hosts WIP

This commit is contained in:
Jamie Curnow
2025-09-21 17:16:46 +10:00
parent 17f40dd8b2
commit 553178aa6b
78 changed files with 1375 additions and 647 deletions

View File

@@ -4,15 +4,18 @@ import { intl } from "src/locale";
interface Props {
tableInstance: ReactTable<any>;
onNew?: () => void;
}
export default function Empty({ tableInstance }: Props) {
export default function Empty({ tableInstance, onNew }: Props) {
return (
<tr>
<td colSpan={tableInstance.getVisibleFlatColumns().length}>
<div className="text-center my-4">
<h2>{intl.formatMessage({ id: "dead-hosts.empty" })}</h2>
<p className="text-muted">{intl.formatMessage({ id: "empty-subtitle" })}</p>
<Button className="btn-red my-3">{intl.formatMessage({ id: "dead-hosts.add" })}</Button>
<Button className="btn-red my-3" onClick={onNew}>
{intl.formatMessage({ id: "dead-hosts.add" })}
</Button>
</div>
</td>
</tr>

View File

@@ -10,8 +10,10 @@ import Empty from "./Empty";
interface Props {
data: DeadHost[];
isFetching?: boolean;
onDelete?: (id: number) => void;
onNew?: () => void;
}
export default function Table({ data, isFetching }: Props) {
export default function Table({ data, isFetching, onDelete, onNew }: Props) {
const columnHelper = createColumnHelper<DeadHost>();
const columns = useMemo(
() => [
@@ -78,7 +80,14 @@ export default function Table({ data, isFetching }: Props) {
{intl.formatMessage({ id: "action.disable" })}
</a>
<div className="dropdown-divider" />
<a className="dropdown-item" href="#">
<a
className="dropdown-item"
href="#"
onClick={(e) => {
e.preventDefault();
onDelete?.(info.row.original.id);
}}
>
<IconTrash size={16} />
{intl.formatMessage({ id: "action.delete" })}
</a>
@@ -91,7 +100,7 @@ export default function Table({ data, isFetching }: Props) {
},
}),
],
[columnHelper],
[columnHelper, onDelete],
);
const tableInstance = useReactTable<DeadHost>({
@@ -105,5 +114,7 @@ export default function Table({ data, isFetching }: Props) {
enableSortingRemoval: false,
});
return <TableLayout tableInstance={tableInstance} emptyState={<Empty tableInstance={tableInstance} />} />;
return (
<TableLayout tableInstance={tableInstance} emptyState={<Empty tableInstance={tableInstance} onNew={onNew} />} />
);
}

View File

@@ -1,11 +1,16 @@
import { IconSearch } from "@tabler/icons-react";
import { useState } from "react";
import Alert from "react-bootstrap/Alert";
import { Button, LoadingPage } from "src/components";
import { useDeadHosts } from "src/hooks";
import { intl } from "src/locale";
import { DeadHostModal, DeleteConfirmModal } from "src/modals";
import { showSuccess } from "src/notifications";
import Table from "./Table";
export default function TableWrapper() {
const [deleteId, setDeleteId] = useState(0);
const [editId, setEditId] = useState(0 as number | "new");
const { isFetching, isLoading, isError, error, data } = useDeadHosts(["owner", "certificate"]);
if (isLoading) {
@@ -16,6 +21,11 @@ export default function TableWrapper() {
return <Alert variant="danger">{error?.message || "Unknown error"}</Alert>;
}
const handleDelete = async () => {
// await deleteUser(deleteId);
showSuccess(intl.formatMessage({ id: "notification.host-deleted" }));
};
return (
<div className="card mt-4">
<div className="card-status-top bg-red" />
@@ -38,14 +48,30 @@ export default function TableWrapper() {
autoComplete="off"
/>
</div>
<Button size="sm" className="btn-red">
<Button size="sm" className="btn-red" onClick={() => setEditId("new")}>
{intl.formatMessage({ id: "dead-hosts.add" })}
</Button>
</div>
</div>
</div>
</div>
<Table data={data ?? []} isFetching={isFetching} />
<Table
data={data ?? []}
isFetching={isFetching}
onDelete={(id: number) => setDeleteId(id)}
onNew={() => setEditId("new")}
/>
{editId ? <DeadHostModal id={editId} onClose={() => setEditId(0)} /> : null}
{deleteId ? (
<DeleteConfirmModal
title={intl.formatMessage({ id: "user.delete.title" })}
onConfirm={handleDelete}
onClose={() => setDeleteId(0)}
invalidations={[["dead-hosts"], ["dead-host", deleteId]]}
>
{intl.formatMessage({ id: "user.delete.content" })}
</DeleteConfirmModal>
) : null}
</div>
</div>
);