Can define OEMStrings from webui
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Pierre HUBERT 2025-05-22 22:03:57 +02:00
parent dcb0743cbe
commit dce17062a3
3 changed files with 104 additions and 1 deletions

View File

@ -317,7 +317,7 @@ pub struct DomainCPUXML {
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename = "entry")]
pub struct OEMStringEntryXML {
#[serde(rename = "$text")]
#[serde(rename = "$text", default)]
pub content: String,
}

View File

@ -0,0 +1,89 @@
/* eslint-disable react-x/no-array-index-key */
import AddIcon from "@mui/icons-material/Add";
import ClearIcon from "@mui/icons-material/Clear";
import {
Alert,
IconButton,
InputAdornment,
TextField,
Tooltip,
} from "@mui/material";
import { VMInfo } from "../../api/VMApi";
import { useConfirm } from "../../hooks/providers/ConfirmDialogProvider";
import { EditSection } from "./EditSection";
export function OEMStringFormWidget(p: {
vm: VMInfo;
editable: boolean;
onChange?: () => void;
}): React.ReactElement {
const confirm = useConfirm();
const handleDeleteOEMString = async (num: number) => {
if (!(await confirm("Do you really want to delete this entry?"))) return;
p.vm.oem_strings.splice(num, 1);
p.onChange?.();
};
return (
<EditSection
title="SMBIOS OEM Strings"
actions={
p.editable ? (
<Tooltip title="Add a new string entry">
<IconButton
onClick={() => {
p.vm.oem_strings.push("");
p.onChange?.();
}}
>
<AddIcon />
</IconButton>
</Tooltip>
) : (
<></>
)
}
>
<Alert severity="info">
You can use the{" "}
<a
href="https://www.nongnu.org/dmidecode/"
target="_blank"
rel="noreferrer noopener"
style={{ color: "inherit" }}
>
<i>dmidecode</i>
</a>{" "}
tool on Linux to extract these strings on the guest.
</Alert>
{p.vm.oem_strings.map((s, num) => (
<TextField
key={num}
fullWidth
disabled={!p.editable}
value={s}
onChange={(e) => {
p.vm.oem_strings[num] = e.target.value;
p.onChange?.();
}}
style={{ marginTop: "5px" }}
slotProps={{
input: {
endAdornment: p.editable ? (
<InputAdornment position="end">
<Tooltip title="Remove entry">
<IconButton onClick={() => handleDeleteOEMString(num)}>
<ClearIcon />
</IconButton>
</Tooltip>
</InputAdornment>
) : undefined,
},
}}
/>
))}
</EditSection>
);
}

View File

@ -19,6 +19,7 @@ import { TabsWidget } from "../TabsWidget";
import { XMLAsyncWidget } from "../XMLWidget";
import { CheckboxInput } from "../forms/CheckboxInput";
import { EditSection } from "../forms/EditSection";
import { OEMStringFormWidget } from "../forms/OEMStringFormWidget";
import { ResAutostartInput } from "../forms/ResAutostartInput";
import { SelectInput } from "../forms/SelectInput";
import { TextInput } from "../forms/TextInput";
@ -78,6 +79,7 @@ enum VMTab {
General = 0,
Storage,
Network,
Advanced,
XML,
Danger,
}
@ -102,6 +104,8 @@ function VMDetailsInner(p: DetailsInnerProps): React.ReactElement {
{ label: "General", value: VMTab.General, visible: true },
{ label: "Storage", value: VMTab.Storage, visible: true },
{ label: "Network", value: VMTab.Network, visible: true },
{ label: "Avanced", value: VMTab.Advanced, visible: true },
{
label: "XML",
value: VMTab.XML,
@ -119,6 +123,7 @@ function VMDetailsInner(p: DetailsInnerProps): React.ReactElement {
{currTab === VMTab.General && <VMDetailsTabGeneral {...p} />}
{currTab === VMTab.Storage && <VMDetailsTabStorage {...p} />}
{currTab === VMTab.Network && <VMDetailsTabNetwork {...p} />}
{currTab === VMTab.Advanced && <VMDetailsTabAdvanced {...p} />}
{currTab === VMTab.XML && <VMDetailsTabXML {...p} />}
{currTab === VMTab.Danger && <VMDetailsTabDanger {...p} />}
</>
@ -361,6 +366,15 @@ function VMDetailsTabNetwork(p: DetailsInnerProps): React.ReactElement {
return <VMNetworksList {...p} />;
}
function VMDetailsTabAdvanced(p: DetailsInnerProps): React.ReactElement {
return (
<Grid container spacing={2}>
{/* OEM strings */}
<OEMStringFormWidget {...p} />
</Grid>
);
}
function VMDetailsTabXML(p: DetailsInnerProps): React.ReactElement {
return (
<XMLAsyncWidget