Turn XML routes into tabs
This commit is contained in:
		@@ -25,8 +25,6 @@ import { OIDCCbRoute } from "./routes/auth/OIDCCbRoute";
 | 
				
			|||||||
import { BaseAuthenticatedPage } from "./widgets/BaseAuthenticatedPage";
 | 
					import { BaseAuthenticatedPage } from "./widgets/BaseAuthenticatedPage";
 | 
				
			||||||
import { BaseLoginPage } from "./widgets/BaseLoginPage";
 | 
					import { BaseLoginPage } from "./widgets/BaseLoginPage";
 | 
				
			||||||
import { ViewNetworkRoute } from "./routes/ViewNetworkRoute";
 | 
					import { ViewNetworkRoute } from "./routes/ViewNetworkRoute";
 | 
				
			||||||
import { VMXMLRoute } from "./routes/VMXMLRoute";
 | 
					 | 
				
			||||||
import { NetXMLRoute } from "./routes/NetXMLRoute";
 | 
					 | 
				
			||||||
import { HomeRoute } from "./routes/HomeRoute";
 | 
					import { HomeRoute } from "./routes/HomeRoute";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface AuthContext {
 | 
					interface AuthContext {
 | 
				
			||||||
@@ -57,13 +55,11 @@ export function App() {
 | 
				
			|||||||
          <Route path="vm/:uuid" element={<VMRoute />} />
 | 
					          <Route path="vm/:uuid" element={<VMRoute />} />
 | 
				
			||||||
          <Route path="vm/:uuid/edit" element={<EditVMRoute />} />
 | 
					          <Route path="vm/:uuid/edit" element={<EditVMRoute />} />
 | 
				
			||||||
          <Route path="vm/:uuid/vnc" element={<VNCRoute />} />
 | 
					          <Route path="vm/:uuid/vnc" element={<VNCRoute />} />
 | 
				
			||||||
          <Route path="vm/:uuid/xml" element={<VMXMLRoute />} />
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
          <Route path="net" element={<NetworksListRoute />} />
 | 
					          <Route path="net" element={<NetworksListRoute />} />
 | 
				
			||||||
          <Route path="net/new" element={<CreateNetworkRoute />} />
 | 
					          <Route path="net/new" element={<CreateNetworkRoute />} />
 | 
				
			||||||
          <Route path="net/:uuid" element={<ViewNetworkRoute />} />
 | 
					          <Route path="net/:uuid" element={<ViewNetworkRoute />} />
 | 
				
			||||||
          <Route path="net/:uuid/edit" element={<EditNetworkRoute />} />
 | 
					          <Route path="net/:uuid/edit" element={<EditNetworkRoute />} />
 | 
				
			||||||
          <Route path="net/:uuid/xml" element={<NetXMLRoute />} />
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
          <Route path="sysinfo" element={<SysInfoRoute />} />
 | 
					          <Route path="sysinfo" element={<SysInfoRoute />} />
 | 
				
			||||||
          <Route path="*" element={<NotFoundRoute />} />
 | 
					          <Route path="*" element={<NotFoundRoute />} />
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,50 +0,0 @@
 | 
				
			|||||||
import ArrowBackIcon from "@mui/icons-material/ArrowBack";
 | 
					 | 
				
			||||||
import { IconButton } from "@mui/material";
 | 
					 | 
				
			||||||
import React from "react";
 | 
					 | 
				
			||||||
import { useParams } from "react-router-dom";
 | 
					 | 
				
			||||||
import { NetworkApi, NetworkInfo, NetworkURL } from "../api/NetworksApi";
 | 
					 | 
				
			||||||
import { AsyncWidget } from "../widgets/AsyncWidget";
 | 
					 | 
				
			||||||
import { RouterLink } from "../widgets/RouterLink";
 | 
					 | 
				
			||||||
import { VirtWebRouteContainer } from "../widgets/VirtWebRouteContainer";
 | 
					 | 
				
			||||||
import { XMLWidget } from "../widgets/XMLWidget";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export function NetXMLRoute(): React.ReactElement {
 | 
					 | 
				
			||||||
  const { uuid } = useParams();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const [net, setNet] = React.useState<NetworkInfo | undefined>();
 | 
					 | 
				
			||||||
  const [src, setSrc] = React.useState<string | undefined>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const load = async () => {
 | 
					 | 
				
			||||||
    setNet(await NetworkApi.GetSingle(uuid!));
 | 
					 | 
				
			||||||
    setSrc(await NetworkApi.GetSingleXML(uuid!));
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return (
 | 
					 | 
				
			||||||
    <AsyncWidget
 | 
					 | 
				
			||||||
      loadKey={uuid}
 | 
					 | 
				
			||||||
      load={load}
 | 
					 | 
				
			||||||
      errMsg="Failed to load network information!"
 | 
					 | 
				
			||||||
      build={() => <XMLRouteInner net={net!} src={src!} />}
 | 
					 | 
				
			||||||
    />
 | 
					 | 
				
			||||||
  );
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function XMLRouteInner(p: {
 | 
					 | 
				
			||||||
  net: NetworkInfo;
 | 
					 | 
				
			||||||
  src: string;
 | 
					 | 
				
			||||||
}): React.ReactElement {
 | 
					 | 
				
			||||||
  return (
 | 
					 | 
				
			||||||
    <VirtWebRouteContainer
 | 
					 | 
				
			||||||
      label={`XML definition of ${p.net.name}`}
 | 
					 | 
				
			||||||
      actions={
 | 
					 | 
				
			||||||
        <RouterLink to={NetworkURL(p.net)}>
 | 
					 | 
				
			||||||
          <IconButton>
 | 
					 | 
				
			||||||
            <ArrowBackIcon />
 | 
					 | 
				
			||||||
          </IconButton>
 | 
					 | 
				
			||||||
        </RouterLink>
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    >
 | 
					 | 
				
			||||||
      <XMLWidget src={p.src} />
 | 
					 | 
				
			||||||
    </VirtWebRouteContainer>
 | 
					 | 
				
			||||||
  );
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -42,14 +42,6 @@ function VMRouteBody(p: { vm: VMInfo }): React.ReactElement {
 | 
				
			|||||||
        <span style={{ display: "inline-flex", alignItems: "center" }}>
 | 
					        <span style={{ display: "inline-flex", alignItems: "center" }}>
 | 
				
			||||||
          <VMStatusWidget vm={p.vm} onChange={setState} />
 | 
					          <VMStatusWidget vm={p.vm} onChange={setState} />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          <RouterLink to={p.vm.XMLURL}>
 | 
					 | 
				
			||||||
            <Tooltip title="View domain definition">
 | 
					 | 
				
			||||||
              <IconButton size="small">
 | 
					 | 
				
			||||||
                <Icon path={mdiXml} style={{ width: "1em" }} />
 | 
					 | 
				
			||||||
              </IconButton>
 | 
					 | 
				
			||||||
            </Tooltip>
 | 
					 | 
				
			||||||
          </RouterLink>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          <ConfigImportExportButtons
 | 
					          <ConfigImportExportButtons
 | 
				
			||||||
            filename={`vm-${p.vm.name}.json`}
 | 
					            filename={`vm-${p.vm.name}.json`}
 | 
				
			||||||
            currentConf={p.vm}
 | 
					            currentConf={p.vm}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,47 +0,0 @@
 | 
				
			|||||||
import React from "react";
 | 
					 | 
				
			||||||
import { useParams } from "react-router-dom";
 | 
					 | 
				
			||||||
import { VMApi, VMInfo } from "../api/VMApi";
 | 
					 | 
				
			||||||
import { AsyncWidget } from "../widgets/AsyncWidget";
 | 
					 | 
				
			||||||
import { VirtWebRouteContainer } from "../widgets/VirtWebRouteContainer";
 | 
					 | 
				
			||||||
import { IconButton } from "@mui/material";
 | 
					 | 
				
			||||||
import { RouterLink } from "../widgets/RouterLink";
 | 
					 | 
				
			||||||
import ArrowBackIcon from "@mui/icons-material/ArrowBack";
 | 
					 | 
				
			||||||
import { XMLWidget } from "../widgets/XMLWidget";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export function VMXMLRoute(): React.ReactElement {
 | 
					 | 
				
			||||||
  const { uuid } = useParams();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const [vm, setVM] = React.useState<VMInfo | undefined>();
 | 
					 | 
				
			||||||
  const [src, setSrc] = React.useState<string | undefined>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const load = async () => {
 | 
					 | 
				
			||||||
    setVM(await VMApi.GetSingle(uuid!));
 | 
					 | 
				
			||||||
    setSrc(await VMApi.GetSingleXML(uuid!));
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return (
 | 
					 | 
				
			||||||
    <AsyncWidget
 | 
					 | 
				
			||||||
      loadKey={uuid}
 | 
					 | 
				
			||||||
      load={load}
 | 
					 | 
				
			||||||
      errMsg="Failed to load VM information!"
 | 
					 | 
				
			||||||
      build={() => <XMLRouteInner vm={vm!} src={src!} />}
 | 
					 | 
				
			||||||
    />
 | 
					 | 
				
			||||||
  );
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function XMLRouteInner(p: { vm: VMInfo; src: string }): React.ReactElement {
 | 
					 | 
				
			||||||
  return (
 | 
					 | 
				
			||||||
    <VirtWebRouteContainer
 | 
					 | 
				
			||||||
      label={`XML definition of ${p.vm.name}`}
 | 
					 | 
				
			||||||
      actions={
 | 
					 | 
				
			||||||
        <RouterLink to={p.vm.ViewURL}>
 | 
					 | 
				
			||||||
          <IconButton>
 | 
					 | 
				
			||||||
            <ArrowBackIcon />
 | 
					 | 
				
			||||||
          </IconButton>
 | 
					 | 
				
			||||||
        </RouterLink>
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    >
 | 
					 | 
				
			||||||
      <XMLWidget src={p.src} />
 | 
					 | 
				
			||||||
    </VirtWebRouteContainer>
 | 
					 | 
				
			||||||
  );
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -51,14 +51,6 @@ function ViewNetworkRouteInner(p: {
 | 
				
			|||||||
        <span style={{ display: "flex", alignItems: "center" }}>
 | 
					        <span style={{ display: "flex", alignItems: "center" }}>
 | 
				
			||||||
          <NetworkStatusWidget net={p.network} onChange={setNetStatus} />
 | 
					          <NetworkStatusWidget net={p.network} onChange={setNetStatus} />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          <RouterLink to={NetworkXMLURL(p.network)}>
 | 
					 | 
				
			||||||
            <Tooltip title="View network definition">
 | 
					 | 
				
			||||||
              <IconButton size="small">
 | 
					 | 
				
			||||||
                <Icon path={mdiXml} style={{ width: "1em" }} />
 | 
					 | 
				
			||||||
              </IconButton>
 | 
					 | 
				
			||||||
            </Tooltip>
 | 
					 | 
				
			||||||
          </RouterLink>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          <ConfigImportExportButtons
 | 
					          <ConfigImportExportButtons
 | 
				
			||||||
            filename={`net-${p.network.name}.json`}
 | 
					            filename={`net-${p.network.name}.json`}
 | 
				
			||||||
            currentConf={p.network}
 | 
					            currentConf={p.network}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,8 @@ import { dracula } from "react-syntax-highlighter/dist/esm/styles/hljs";
 | 
				
			|||||||
import xmlFormat from "xml-formatter";
 | 
					import xmlFormat from "xml-formatter";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Light as SyntaxHighlighter } from "react-syntax-highlighter";
 | 
					import { Light as SyntaxHighlighter } from "react-syntax-highlighter";
 | 
				
			||||||
 | 
					import { AsyncWidget } from "./AsyncWidget";
 | 
				
			||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SyntaxHighlighter.registerLanguage("xml", xml);
 | 
					SyntaxHighlighter.registerLanguage("xml", xml);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -19,3 +21,24 @@ export function XMLWidget(p: { src: string }): React.ReactElement {
 | 
				
			|||||||
    </SyntaxHighlighter>
 | 
					    </SyntaxHighlighter>
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function XMLAsyncWidget(p: {
 | 
				
			||||||
 | 
					  identifier: string;
 | 
				
			||||||
 | 
					  load: () => Promise<string>;
 | 
				
			||||||
 | 
					  errMsg: string;
 | 
				
			||||||
 | 
					}): React.ReactElement {
 | 
				
			||||||
 | 
					  const [src, setSrc] = React.useState<string | undefined>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const load = async () => {
 | 
				
			||||||
 | 
					    setSrc(await p.load());
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <AsyncWidget
 | 
				
			||||||
 | 
					      errMsg={p.errMsg}
 | 
				
			||||||
 | 
					      load={load}
 | 
				
			||||||
 | 
					      loadKey={p.identifier}
 | 
				
			||||||
 | 
					      build={() => <XMLWidget src={src!} />}
 | 
				
			||||||
 | 
					    />
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,6 +14,7 @@ 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 { DHCPHostReservations } from "./DHCPHostReservations";
 | 
					import { DHCPHostReservations } from "./DHCPHostReservations";
 | 
				
			||||||
 | 
					import { XMLAsyncWidget } from "../XMLWidget";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface DetailsProps {
 | 
					interface DetailsProps {
 | 
				
			||||||
  net: NetworkInfo;
 | 
					  net: NetworkInfo;
 | 
				
			||||||
@@ -42,6 +43,7 @@ enum NetTab {
 | 
				
			|||||||
  General = 0,
 | 
					  General = 0,
 | 
				
			||||||
  IPv4,
 | 
					  IPv4,
 | 
				
			||||||
  IPv6,
 | 
					  IPv6,
 | 
				
			||||||
 | 
					  XML,
 | 
				
			||||||
  Danger,
 | 
					  Danger,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -67,6 +69,11 @@ function NetworkDetailsInner(p: DetailsInnerProps): React.ReactElement {
 | 
				
			|||||||
            value: NetTab.IPv6,
 | 
					            value: NetTab.IPv6,
 | 
				
			||||||
            visible: p.editable || !!p.net.ip_v6,
 | 
					            visible: p.editable || !!p.net.ip_v6,
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            label: "XML",
 | 
				
			||||||
 | 
					            value: NetTab.XML,
 | 
				
			||||||
 | 
					            visible: !p.editable,
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
          {
 | 
					          {
 | 
				
			||||||
            label: "Danger zone",
 | 
					            label: "Danger zone",
 | 
				
			||||||
            value: NetTab.Danger,
 | 
					            value: NetTab.Danger,
 | 
				
			||||||
@@ -79,6 +86,7 @@ function NetworkDetailsInner(p: DetailsInnerProps): React.ReactElement {
 | 
				
			|||||||
      {currTab === NetTab.General && <NetworkDetailsTabGeneral {...p} />}
 | 
					      {currTab === NetTab.General && <NetworkDetailsTabGeneral {...p} />}
 | 
				
			||||||
      {currTab === NetTab.IPv4 && <NetworkDetailsTabIPv4 {...p} />}
 | 
					      {currTab === NetTab.IPv4 && <NetworkDetailsTabIPv4 {...p} />}
 | 
				
			||||||
      {currTab === NetTab.IPv6 && <NetworkDetailsTabIPv6 {...p} />}
 | 
					      {currTab === NetTab.IPv6 && <NetworkDetailsTabIPv6 {...p} />}
 | 
				
			||||||
 | 
					      {currTab === NetTab.XML && <NetworkDetailsTabXML {...p} />}
 | 
				
			||||||
      {currTab === NetTab.Danger && <NetworkDetailsTabDanger {...p} />}
 | 
					      {currTab === NetTab.Danger && <NetworkDetailsTabDanger {...p} />}
 | 
				
			||||||
    </>
 | 
					    </>
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
@@ -380,6 +388,16 @@ function IPSection(p: {
 | 
				
			|||||||
  );
 | 
					  );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function NetworkDetailsTabXML(p: DetailsInnerProps): React.ReactElement {
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <XMLAsyncWidget
 | 
				
			||||||
 | 
					      errMsg="Failed to load network XML definition!"
 | 
				
			||||||
 | 
					      identifier={p.net.uuid!}
 | 
				
			||||||
 | 
					      load={() => NetworkApi.GetSingleXML(p.net.uuid!)}
 | 
				
			||||||
 | 
					    />
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function NetworkDetailsTabDanger(p: DetailsInnerProps): React.ReactElement {
 | 
					function NetworkDetailsTabDanger(p: DetailsInnerProps): React.ReactElement {
 | 
				
			||||||
  const confirm = useConfirm();
 | 
					  const confirm = useConfirm();
 | 
				
			||||||
  const snackbar = useSnackbar();
 | 
					  const snackbar = useSnackbar();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,6 +21,7 @@ import { VMDisksList } from "../forms/VMDisksList";
 | 
				
			|||||||
import { VMNetworksList } from "../forms/VMNetworksList";
 | 
					import { VMNetworksList } from "../forms/VMNetworksList";
 | 
				
			||||||
import { VMSelectIsoInput } from "../forms/VMSelectIsoInput";
 | 
					import { VMSelectIsoInput } from "../forms/VMSelectIsoInput";
 | 
				
			||||||
import { VMScreenshot } from "./VMScreenshot";
 | 
					import { VMScreenshot } from "./VMScreenshot";
 | 
				
			||||||
 | 
					import { XMLAsyncWidget } from "../XMLWidget";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface DetailsProps {
 | 
					interface DetailsProps {
 | 
				
			||||||
  vm: VMInfo;
 | 
					  vm: VMInfo;
 | 
				
			||||||
@@ -68,6 +69,7 @@ enum VMTab {
 | 
				
			|||||||
  General = 0,
 | 
					  General = 0,
 | 
				
			||||||
  Storage,
 | 
					  Storage,
 | 
				
			||||||
  Network,
 | 
					  Network,
 | 
				
			||||||
 | 
					  XML,
 | 
				
			||||||
  Danger,
 | 
					  Danger,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -90,6 +92,11 @@ function VMDetailsInner(p: DetailsInnerProps): React.ReactElement {
 | 
				
			|||||||
          { label: "General", value: VMTab.General, visible: true },
 | 
					          { label: "General", value: VMTab.General, visible: true },
 | 
				
			||||||
          { label: "Storage", value: VMTab.Storage, visible: true },
 | 
					          { label: "Storage", value: VMTab.Storage, visible: true },
 | 
				
			||||||
          { label: "Network", value: VMTab.Network, visible: true },
 | 
					          { label: "Network", value: VMTab.Network, visible: true },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            label: "XML",
 | 
				
			||||||
 | 
					            value: VMTab.XML,
 | 
				
			||||||
 | 
					            visible: !p.editable,
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
          {
 | 
					          {
 | 
				
			||||||
            label: "Danger zone",
 | 
					            label: "Danger zone",
 | 
				
			||||||
            value: VMTab.Danger,
 | 
					            value: VMTab.Danger,
 | 
				
			||||||
@@ -102,6 +109,7 @@ function VMDetailsInner(p: DetailsInnerProps): React.ReactElement {
 | 
				
			|||||||
      {currTab === VMTab.General && <VMDetailsTabGeneral {...p} />}
 | 
					      {currTab === VMTab.General && <VMDetailsTabGeneral {...p} />}
 | 
				
			||||||
      {currTab === VMTab.Storage && <VMDetailsTabStorage {...p} />}
 | 
					      {currTab === VMTab.Storage && <VMDetailsTabStorage {...p} />}
 | 
				
			||||||
      {currTab === VMTab.Network && <VMDetailsTabNetwork {...p} />}
 | 
					      {currTab === VMTab.Network && <VMDetailsTabNetwork {...p} />}
 | 
				
			||||||
 | 
					      {currTab === VMTab.XML && <VMDetailsTabXML {...p} />}
 | 
				
			||||||
      {currTab === VMTab.Danger && <VMDetailsTabDanger {...p} />}
 | 
					      {currTab === VMTab.Danger && <VMDetailsTabDanger {...p} />}
 | 
				
			||||||
    </>
 | 
					    </>
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
@@ -293,6 +301,16 @@ function VMDetailsTabNetwork(p: DetailsInnerProps): React.ReactElement {
 | 
				
			|||||||
  return <VMNetworksList {...p} />;
 | 
					  return <VMNetworksList {...p} />;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function VMDetailsTabXML(p: DetailsInnerProps): React.ReactElement {
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <XMLAsyncWidget
 | 
				
			||||||
 | 
					      errMsg="Failed to load VM XML source definition!"
 | 
				
			||||||
 | 
					      identifier={p.vm.uuid!}
 | 
				
			||||||
 | 
					      load={() => VMApi.GetSingleXML(p.vm.uuid!)}
 | 
				
			||||||
 | 
					    />
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function VMDetailsTabDanger(p: DetailsInnerProps): React.ReactElement {
 | 
					function VMDetailsTabDanger(p: DetailsInnerProps): React.ReactElement {
 | 
				
			||||||
  const confirm = useConfirm();
 | 
					  const confirm = useConfirm();
 | 
				
			||||||
  const alert = useAlert();
 | 
					  const alert = useAlert();
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user