import { Button, Checkbox, Grid } from "@mui/material"; import React from "react"; import { useNavigate } from "react-router-dom"; 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 { TabsWidget } from "../TabsWidget"; 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 { NetDHCPHostReservations } from "../forms/NetDHCPHostReservations"; import { XMLAsyncWidget } from "../XMLWidget"; interface DetailsProps { net: NetworkInfo; editable: boolean; onChange?: () => void; } export function NetworkDetails(p: DetailsProps): React.ReactElement { const [nicsList, setNicsList] = React.useState(); const load = async () => { setNicsList(await ServerApi.GetNetworksList()); }; return ( } /> ); } enum NetTab { General = 0, IPv4, IPv6, XML, Danger, } type DetailsInnerProps = DetailsProps & { nicsList: string[] }; function NetworkDetailsInner(p: DetailsInnerProps): React.ReactElement { const [currTab, setCurrTab] = React.useState(NetTab.General); return ( <> {currTab === NetTab.General && } {currTab === NetTab.IPv4 && } {currTab === NetTab.IPv6 && } {currTab === NetTab.XML && } {currTab === NetTab.Danger && } ); } function NetworkDetailsTabGeneral(p: DetailsInnerProps): React.ReactElement { return ( {/* Metadata section */} { p.net.name = v ?? ""; p.onChange?.(); }} checkValue={(v) => /^[a-zA-Z0-9]+$/.test(v)} size={ServerApi.Config.constraints.net_name_size} /> { p.net.title = v; p.onChange?.(); }} size={ServerApi.Config.constraints.net_title_size} /> { p.net.description = v; p.onChange?.(); }} multiline={true} /> {p.net.uuid && ( NetworkApi.IsAutostart(p.net)} setAutotostart={(e) => NetworkApi.SetAutostart(p.net, e)} /> )} { p.net.forward_mode = v as any; p.onChange?.(); }} value={p.net.forward_mode} options={[ { label: "NAT", value: "NAT", }, { label: "Isolated network", value: "Isolated", }, ]} /> {p.net.forward_mode === "NAT" && ( { p.net.device = v; p.onChange?.(); }} value={p.net.device} options={[ { label: "Default interface", value: undefined }, ...p.nicsList.map((d) => { return { label: d, value: d }; }), ]} /> )} { p.net.bridge_name = v; p.onChange?.(); }} value={p.net.bridge_name} checkValue={(v) => v === "" || /^[a-zA-Z0-9]+$/.test(v)} /> { p.net.dns_server = v; p.onChange?.(); }} version={4} /> { p.net.domain = v; p.onChange?.(); }} multiline={true} /> ); } function NetworkDetailsTabIPv4(p: DetailsInnerProps): React.ReactElement { return ( { p.net.ip_v4 = c; p.onChange?.(); }} version={4} /> ); } function NetworkDetailsTabIPv6(p: DetailsInnerProps): React.ReactElement { return ( { p.net.ip_v6 = c; p.onChange?.(); }} version={6} /> ); } function IPSection(p: { editable: boolean; config?: IpConfig; onChange: (c: IpConfig | undefined) => void; version: 4 | 6; }): React.ReactElement { const confirm = useConfirm(); const toggleNetwork = async () => { if (!!p.config) { if ( !(await confirm( `Do you really want to disable IPv${p.version} on this network?` )) ) return; p.onChange?.(undefined); return; } p.onChange?.({ bridge_address: p.version === 4 ? "192.168.1.1" : "fd00::1", prefix: p.version === 4 ? 24 : 8, }); }; const toggleDHCP = (v: boolean) => { if (v) p.config!.dhcp = p.version === 4 ? { start: "192.168.1.100", end: "192.168.1.200", hosts: [], } : { start: "fd00::100", end: "fd00::f00", hosts: [] }; else p.config!.dhcp = undefined; p.onChange?.(p.config); }; if (!p.config && !p.editable) return <>; return ( } > {p.config && ( <> { p.config!.bridge_address = v ?? ""; p.onChange?.(p.config); }} /> { p.config!.prefix = Number(v); p.onChange?.(p.config); }} size={ p.version === 4 ? { min: 0, max: 32 } : { min: 0, max: 128 } } /> )} {p.config && (p.editable || p.config.dhcp) && ( toggleDHCP(val)} /> } > {p.config.dhcp && ( <> { p.config!.dhcp!.start = v!; p.onChange(p.config); }} /> { p.config!.dhcp!.end = v!; p.onChange(p.config); }} /> )} )} {p.config?.dhcp && (p.editable || p.config.dhcp.hosts.length > 0) && ( { p.config!.dhcp = d; p.onChange?.(p.config); }} /> )} ); } function NetworkDetailsTabXML(p: DetailsInnerProps): React.ReactElement { return ( NetworkApi.GetSingleXML(p.net.uuid!)} /> ); } 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 ( ); }