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 { 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>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user