Turn XML routes into tabs
This commit is contained in:
parent
f890cba5a4
commit
ffac6991c4
@ -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();
|
||||||
|
Loading…
Reference in New Issue
Block a user