Reorganize networks page
This commit is contained in:
		@@ -17,66 +17,31 @@ import { NetworkApi, NetworkInfo, NetworkURL } from "../api/NetworksApi";
 | 
			
		||||
import { AsyncWidget } from "../widgets/AsyncWidget";
 | 
			
		||||
import { RouterLink } from "../widgets/RouterLink";
 | 
			
		||||
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 { useNavigate } from "react-router-dom";
 | 
			
		||||
 | 
			
		||||
export function NetworksListRoute(): React.ReactElement {
 | 
			
		||||
  const confirm = useConfirm();
 | 
			
		||||
  const snackbar = useSnackbar();
 | 
			
		||||
  const alert = useAlert();
 | 
			
		||||
 | 
			
		||||
  const [list, setList] = React.useState<NetworkInfo[] | undefined>();
 | 
			
		||||
 | 
			
		||||
  const [count, setCount] = React.useState(1);
 | 
			
		||||
  const [count] = React.useState(1);
 | 
			
		||||
 | 
			
		||||
  const load = async () => {
 | 
			
		||||
    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 (
 | 
			
		||||
    <AsyncWidget
 | 
			
		||||
      loadKey={count}
 | 
			
		||||
      load={load}
 | 
			
		||||
      ready={list !== undefined}
 | 
			
		||||
      errMsg="Failed to load the list of networks!"
 | 
			
		||||
      build={() => (
 | 
			
		||||
        <NetworksListRouteInner list={list!} onRequestDelete={requestDelete} />
 | 
			
		||||
      )}
 | 
			
		||||
      build={() => <NetworksListRouteInner list={list!} />}
 | 
			
		||||
    />
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function NetworksListRouteInner(p: {
 | 
			
		||||
  list: NetworkInfo[];
 | 
			
		||||
  onRequestDelete: (n: NetworkInfo) => void;
 | 
			
		||||
}): React.ReactElement {
 | 
			
		||||
  const navigate = useNavigate();
 | 
			
		||||
 | 
			
		||||
@@ -130,9 +95,6 @@ function NetworksListRouteInner(p: {
 | 
			
		||||
                        <VisibilityIcon />
 | 
			
		||||
                      </IconButton>
 | 
			
		||||
                    </RouterLink>
 | 
			
		||||
                    <IconButton onClick={() => p.onRequestDelete(t)}>
 | 
			
		||||
                      <DeleteIcon />
 | 
			
		||||
                    </IconButton>
 | 
			
		||||
                  </TableCell>
 | 
			
		||||
                </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 { IpConfig, NetworkApi, NetworkInfo } from "../../api/NetworksApi";
 | 
			
		||||
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 { CheckboxInput } from "../forms/CheckboxInput";
 | 
			
		||||
import { EditSection } from "../forms/EditSection";
 | 
			
		||||
import { IPInput } from "../forms/IPInput";
 | 
			
		||||
import { ResAutostartInput } from "../forms/ResAutostartInput";
 | 
			
		||||
import { SelectInput } from "../forms/SelectInput";
 | 
			
		||||
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 { useNavigate } from "react-router-dom";
 | 
			
		||||
 | 
			
		||||
interface DetailsProps {
 | 
			
		||||
  net: NetworkInfo;
 | 
			
		||||
@@ -35,9 +38,44 @@ export function NetworkDetails(p: DetailsProps): React.ReactElement {
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function NetworkDetailsInner(
 | 
			
		||||
  p: DetailsProps & { cardsList: string[] }
 | 
			
		||||
): React.ReactElement {
 | 
			
		||||
enum VMTab {
 | 
			
		||||
  General = 0,
 | 
			
		||||
  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 (
 | 
			
		||||
    <Grid container spacing={2}>
 | 
			
		||||
      {/* Metadata section */}
 | 
			
		||||
@@ -161,7 +199,13 @@ function NetworkDetailsInner(
 | 
			
		||||
          multiline={true}
 | 
			
		||||
        />
 | 
			
		||||
      </EditSection>
 | 
			
		||||
    </Grid>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function NetworkDetailsTabIPv4(p: DetailsInnerProps): React.ReactElement {
 | 
			
		||||
  return (
 | 
			
		||||
    <Grid container spacing={2}>
 | 
			
		||||
      <IPSection
 | 
			
		||||
        editable={p.editable}
 | 
			
		||||
        config={p.net.ip_v4}
 | 
			
		||||
@@ -171,7 +215,13 @@ function NetworkDetailsInner(
 | 
			
		||||
        }}
 | 
			
		||||
        version={4}
 | 
			
		||||
      />
 | 
			
		||||
    </Grid>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function NetworkDetailsTabIPv6(p: DetailsInnerProps): React.ReactElement {
 | 
			
		||||
  return (
 | 
			
		||||
    <Grid container spacing={2}>
 | 
			
		||||
      <IPSection
 | 
			
		||||
        editable={p.editable}
 | 
			
		||||
        config={p.net.ip_v6}
 | 
			
		||||
@@ -309,3 +359,37 @@ function IPSection(p: {
 | 
			
		||||
    </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>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user