import { Button } from "@mui/material"; import React from "react"; import { useNavigate, useParams } from "react-router-dom"; import { NetworkApi, NetworkInfo, NetworkURL } from "../api/NetworksApi"; import { useAlert } from "../hooks/providers/AlertDialogProvider"; import { useLoadingMessage } from "../hooks/providers/LoadingMessageProvider"; import { useSnackbar } from "../hooks/providers/SnackbarProvider"; import { AsyncWidget } from "../widgets/AsyncWidget"; import { ConfigImportExportButtons } from "../widgets/ConfigImportExportButtons"; import { VirtWebRouteContainer } from "../widgets/VirtWebRouteContainer"; import { NetworkDetails } from "../widgets/net/NetworkDetails"; export function CreateNetworkRoute(): React.ReactElement { const alert = useAlert(); const snackbar = useSnackbar(); const navigate = useNavigate(); const [network, setNetwork] = React.useState<NetworkInfo>({ name: "NewNetwork", forward_mode: "Isolated", }); const createNetwork = async (n: NetworkInfo) => { try { const res = await NetworkApi.Create(n); snackbar("The network was successfully created!"); navigate(`/net/${res.uid}`); } catch (e) { console.error(e); alert(`Failed to create network!\n${e}`); } }; return ( <EditNetworkRouteInner network={network} creating={true} onCancel={() => navigate("/net")} onSave={createNetwork} onReplace={setNetwork} /> ); } export function EditNetworkRoute(): React.ReactElement { const alert = useAlert(); const snackbar = useSnackbar(); const { uuid } = useParams(); const navigate = useNavigate(); const [network, setNetwork] = React.useState<NetworkInfo | undefined>(); const load = async () => { setNetwork(await NetworkApi.GetSingle(uuid!)); }; const updateNetwork = async (n: NetworkInfo) => { try { await NetworkApi.Update(n); snackbar("The network was successfully updated!"); navigate(NetworkURL(network!)); } catch (e) { console.error(e); alert(`Failed to update network!\n${e}`); } }; return ( <AsyncWidget loadKey={uuid} ready={network !== undefined} errMsg="Failed to fetch network information!" load={load} build={() => ( <EditNetworkRouteInner network={network!} creating={false} onCancel={() => navigate(`/net/${uuid}`)} onSave={updateNetwork} onReplace={setNetwork} /> )} /> ); } function EditNetworkRouteInner(p: { network: NetworkInfo; creating: boolean; onCancel: () => void; onSave: (vm: NetworkInfo) => Promise<void>; onReplace: (vm: NetworkInfo) => void; }): React.ReactElement { const loadingMessage = useLoadingMessage(); const [changed, setChanged] = React.useState(false); const [, updateState] = React.useState<any>(); const forceUpdate = React.useCallback(() => updateState({}), []); const valueChanged = () => { setChanged(true); forceUpdate(); }; const save = async () => { loadingMessage.show("Saving network configuration..."); await p.onSave(p.network); loadingMessage.hide(); }; return ( <VirtWebRouteContainer label={p.creating ? "Create a Network" : "Edit Network"} actions={ <span> <ConfigImportExportButtons currentConf={p.network} filename={`net-${p.network.name}.json`} importConf={(c) => { p.onReplace(c); valueChanged(); }} /> {changed && ( <Button variant="contained" onClick={save} style={{ marginRight: "10px" }} > {p.creating ? "Create" : "Save"} </Button> )} <Button onClick={p.onCancel} variant="outlined"> Cancel </Button> </span> } > <NetworkDetails net={p.network} editable={true} onChange={valueChanged} /> </VirtWebRouteContainer> ); }