Reorganize networks page
This commit is contained in:
parent
085deff4f7
commit
afe5db1fcd
@ -17,66 +17,31 @@ import { NetworkApi, NetworkInfo, NetworkURL } from "../api/NetworksApi";
|
|||||||
import { AsyncWidget } from "../widgets/AsyncWidget";
|
import { AsyncWidget } from "../widgets/AsyncWidget";
|
||||||
import { RouterLink } from "../widgets/RouterLink";
|
import { RouterLink } from "../widgets/RouterLink";
|
||||||
import { VirtWebRouteContainer } from "../widgets/VirtWebRouteContainer";
|
import { VirtWebRouteContainer } from "../widgets/VirtWebRouteContainer";
|
||||||
import { useConfirm } from "../hooks/providers/ConfirmDialogProvider";
|
|
||||||
import { useSnackbar } from "../hooks/providers/SnackbarProvider";
|
|
||||||
import { useAlert } from "../hooks/providers/AlertDialogProvider";
|
|
||||||
import { NetworkStatusWidget } from "../widgets/net/NetworkStatusWidget";
|
import { NetworkStatusWidget } from "../widgets/net/NetworkStatusWidget";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
export function NetworksListRoute(): React.ReactElement {
|
export function NetworksListRoute(): React.ReactElement {
|
||||||
const confirm = useConfirm();
|
|
||||||
const snackbar = useSnackbar();
|
|
||||||
const alert = useAlert();
|
|
||||||
|
|
||||||
const [list, setList] = React.useState<NetworkInfo[] | undefined>();
|
const [list, setList] = React.useState<NetworkInfo[] | undefined>();
|
||||||
|
|
||||||
const [count, setCount] = React.useState(1);
|
const [count] = React.useState(1);
|
||||||
|
|
||||||
const load = async () => {
|
const load = async () => {
|
||||||
setList(await NetworkApi.GetList());
|
setList(await NetworkApi.GetList());
|
||||||
};
|
};
|
||||||
|
|
||||||
const reload = () => {
|
|
||||||
setList(undefined);
|
|
||||||
setCount(count + 1);
|
|
||||||
};
|
|
||||||
|
|
||||||
const requestDelete = async (n: NetworkInfo) => {
|
|
||||||
try {
|
|
||||||
if (
|
|
||||||
!(await confirm(
|
|
||||||
"Do you really want to delete this network?",
|
|
||||||
`Delete network ${n.name}`,
|
|
||||||
"Delete"
|
|
||||||
))
|
|
||||||
)
|
|
||||||
return;
|
|
||||||
|
|
||||||
await NetworkApi.Delete(n);
|
|
||||||
reload();
|
|
||||||
snackbar("The network was successfully deleted!");
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
alert(`Failed to delete the network!\n${e}`);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AsyncWidget
|
<AsyncWidget
|
||||||
loadKey={count}
|
loadKey={count}
|
||||||
load={load}
|
load={load}
|
||||||
ready={list !== undefined}
|
ready={list !== undefined}
|
||||||
errMsg="Failed to load the list of networks!"
|
errMsg="Failed to load the list of networks!"
|
||||||
build={() => (
|
build={() => <NetworksListRouteInner list={list!} />}
|
||||||
<NetworksListRouteInner list={list!} onRequestDelete={requestDelete} />
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function NetworksListRouteInner(p: {
|
function NetworksListRouteInner(p: {
|
||||||
list: NetworkInfo[];
|
list: NetworkInfo[];
|
||||||
onRequestDelete: (n: NetworkInfo) => void;
|
|
||||||
}): React.ReactElement {
|
}): React.ReactElement {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
@ -130,9 +95,6 @@ function NetworksListRouteInner(p: {
|
|||||||
<VisibilityIcon />
|
<VisibilityIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
<IconButton onClick={() => p.onRequestDelete(t)}>
|
|
||||||
<DeleteIcon />
|
|
||||||
</IconButton>
|
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
);
|
);
|
||||||
|
@ -1,16 +1,19 @@
|
|||||||
import { Checkbox, Grid, Paper } from "@mui/material";
|
import { Box, Button, Checkbox, Grid, Paper, Tab, Tabs } from "@mui/material";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { IpConfig, NetworkApi, NetworkInfo } from "../../api/NetworksApi";
|
import { IpConfig, NetworkApi, NetworkInfo } from "../../api/NetworksApi";
|
||||||
import { ServerApi } from "../../api/ServerApi";
|
import { ServerApi } from "../../api/ServerApi";
|
||||||
|
import { useAlert } from "../../hooks/providers/AlertDialogProvider";
|
||||||
|
import { useConfirm } from "../../hooks/providers/ConfirmDialogProvider";
|
||||||
|
import { useSnackbar } from "../../hooks/providers/SnackbarProvider";
|
||||||
import { AsyncWidget } from "../AsyncWidget";
|
import { AsyncWidget } from "../AsyncWidget";
|
||||||
|
import { CheckboxInput } from "../forms/CheckboxInput";
|
||||||
import { EditSection } from "../forms/EditSection";
|
import { EditSection } from "../forms/EditSection";
|
||||||
import { IPInput } from "../forms/IPInput";
|
import { IPInput } from "../forms/IPInput";
|
||||||
|
import { ResAutostartInput } from "../forms/ResAutostartInput";
|
||||||
import { SelectInput } from "../forms/SelectInput";
|
import { SelectInput } from "../forms/SelectInput";
|
||||||
import { TextInput } from "../forms/TextInput";
|
import { TextInput } from "../forms/TextInput";
|
||||||
import { useConfirm } from "../../hooks/providers/ConfirmDialogProvider";
|
|
||||||
import { CheckboxInput } from "../forms/CheckboxInput";
|
|
||||||
import { ResAutostartInput } from "../forms/ResAutostartInput";
|
|
||||||
import { DHCPHostReservations } from "./DHCPHostReservations";
|
import { DHCPHostReservations } from "./DHCPHostReservations";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
interface DetailsProps {
|
interface DetailsProps {
|
||||||
net: NetworkInfo;
|
net: NetworkInfo;
|
||||||
@ -35,9 +38,44 @@ export function NetworkDetails(p: DetailsProps): React.ReactElement {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function NetworkDetailsInner(
|
enum VMTab {
|
||||||
p: DetailsProps & { cardsList: string[] }
|
General = 0,
|
||||||
): React.ReactElement {
|
IPv4,
|
||||||
|
IPv6,
|
||||||
|
Danger,
|
||||||
|
}
|
||||||
|
|
||||||
|
type DetailsInnerProps = DetailsProps & { cardsList: string[] };
|
||||||
|
|
||||||
|
function NetworkDetailsInner(p: DetailsInnerProps): React.ReactElement {
|
||||||
|
const [currTab, setCurrTab] = React.useState(VMTab.General);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Box sx={{ borderBottom: 1, borderColor: "divider" }}>
|
||||||
|
<Tabs value={currTab} onChange={(_ev, newVal) => setCurrTab(newVal)}>
|
||||||
|
<Tab label="General" tabIndex={VMTab.General} />
|
||||||
|
<Tab label="IPv4" tabIndex={VMTab.IPv4} />
|
||||||
|
<Tab label="IPv6" tabIndex={VMTab.IPv6} />
|
||||||
|
{!p.editable && (
|
||||||
|
<Tab
|
||||||
|
label="Danger zone"
|
||||||
|
style={{ color: "red" }}
|
||||||
|
tabIndex={VMTab.Danger}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Tabs>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{currTab === VMTab.General && <NetworkDetailsTabGeneral {...p} />}
|
||||||
|
{currTab === VMTab.IPv4 && <NetworkDetailsTabIPv4 {...p} />}
|
||||||
|
{currTab === VMTab.IPv6 && <NetworkDetailsTabIPv6 {...p} />}
|
||||||
|
{currTab === VMTab.Danger && <NetworkDetailsTabDanger {...p} />}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function NetworkDetailsTabGeneral(p: DetailsInnerProps): React.ReactElement {
|
||||||
return (
|
return (
|
||||||
<Grid container spacing={2}>
|
<Grid container spacing={2}>
|
||||||
{/* Metadata section */}
|
{/* Metadata section */}
|
||||||
@ -161,7 +199,13 @@ function NetworkDetailsInner(
|
|||||||
multiline={true}
|
multiline={true}
|
||||||
/>
|
/>
|
||||||
</EditSection>
|
</EditSection>
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function NetworkDetailsTabIPv4(p: DetailsInnerProps): React.ReactElement {
|
||||||
|
return (
|
||||||
|
<Grid container spacing={2}>
|
||||||
<IPSection
|
<IPSection
|
||||||
editable={p.editable}
|
editable={p.editable}
|
||||||
config={p.net.ip_v4}
|
config={p.net.ip_v4}
|
||||||
@ -171,7 +215,13 @@ function NetworkDetailsInner(
|
|||||||
}}
|
}}
|
||||||
version={4}
|
version={4}
|
||||||
/>
|
/>
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function NetworkDetailsTabIPv6(p: DetailsInnerProps): React.ReactElement {
|
||||||
|
return (
|
||||||
|
<Grid container spacing={2}>
|
||||||
<IPSection
|
<IPSection
|
||||||
editable={p.editable}
|
editable={p.editable}
|
||||||
config={p.net.ip_v6}
|
config={p.net.ip_v6}
|
||||||
@ -309,3 +359,37 @@ function IPSection(p: {
|
|||||||
</EditSection>
|
</EditSection>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function NetworkDetailsTabDanger(p: DetailsInnerProps): React.ReactElement {
|
||||||
|
const confirm = useConfirm();
|
||||||
|
const snackbar = useSnackbar();
|
||||||
|
const alert = useAlert();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const requestDelete = async () => {
|
||||||
|
try {
|
||||||
|
if (
|
||||||
|
!(await confirm(
|
||||||
|
"Do you really want to delete this network?",
|
||||||
|
`Delete network ${p.net.name}`,
|
||||||
|
"Delete"
|
||||||
|
))
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
|
await NetworkApi.Delete(p.net);
|
||||||
|
|
||||||
|
navigate("/net");
|
||||||
|
snackbar("The network was successfully deleted!");
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
alert(`Failed to delete the network!\n${e}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button color="error" onClick={requestDelete}>
|
||||||
|
Delete the network
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user