Can configure all network settings

This commit is contained in:
Pierre HUBERT 2023-12-06 18:48:07 +01:00
parent b7d44f3091
commit 23f2029deb
4 changed files with 232 additions and 13 deletions

View File

@ -371,6 +371,12 @@ impl NetworkInfo {
}
}
if let Some(domain) = &self.domain {
if !regex!("^[a-zA-Z0-9.]+$").is_match(domain) {
return Err(StructureExtraction("Domain name is invalid!").into());
}
}
let mut ips = Vec::with_capacity(2);
if let Some(ipv4) = self.ip_v4 {

View File

@ -1,15 +1,24 @@
import { Grid, Paper, Typography } from "@mui/material";
import { PropsWithChildren } from "react";
import React, { PropsWithChildren } from "react";
export function EditSection(
p: { title: string } & PropsWithChildren
p: { title: string; actions?: React.ReactElement } & PropsWithChildren
): React.ReactElement {
return (
<Grid item sm={12} md={6}>
<Paper style={{ margin: "10px", padding: "10px" }}>
<Typography variant="h5" style={{ marginBottom: "15px" }}>
{p.title}
</Typography>
<span
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
}}
>
<Typography variant="h5" style={{ marginBottom: "15px" }}>
{p.title}
</Typography>
{p.actions}
</span>
{p.children}
</Paper>
</Grid>

View File

@ -0,0 +1,60 @@
import { FormControl, Input, InputLabel } from "@mui/material";
import { TextInput } from "./TextInput";
import { IMaskInput } from "react-imask";
import React from "react";
interface CustomProps {
onChange: (event: { target: { name: string; value: string } }) => void;
name: string;
placeholder: string;
}
const TextMaskCustom = React.forwardRef<HTMLInputElement, CustomProps>(
function TextMaskCustom(props, ref) {
const { onChange, placeholder, ...other } = props;
return (
<IMaskInput
{...other}
mask={placeholder}
definitions={{
"#": /[1-9]/,
}}
inputRef={ref}
onAccept={(value: any) =>
onChange({ target: { name: props.name, value } })
}
overwrite
/>
);
}
);
export function TextMaskInput(p: {
label: string;
editable: boolean;
value?: string;
onValueChange?: (newVal: string | undefined) => void;
mask: string;
}): React.ReactElement {
const id = React.useRef(Math.random());
if (!p.editable) return <TextInput {...p} />;
return (
<FormControl variant="standard" fullWidth>
<InputLabel htmlFor={`mi-${id.current}`}>{p.label}</InputLabel>
<Input
fullWidth
value={p.value ?? ""}
onChange={(c) =>
p.onValueChange?.(
c.target.value.length === 0 ? undefined : c.target.value
)
}
id={`mi-${id.current}`}
inputComponent={TextMaskCustom as any}
placeholder={p.mask}
/>
</FormControl>
);
}

View File

@ -1,12 +1,14 @@
import { Grid } from "@mui/material";
import { NetworkInfo } from "../../api/NetworksApi";
import { ServerApi } from "../../api/ServerApi";
import { EditSection } from "../forms/EditSection";
import { TextInput } from "../forms/TextInput";
import { SelectInput } from "../forms/SelectInput";
import { Checkbox, Grid } from "@mui/material";
import React from "react";
import { IpConfig, NetworkInfo } from "../../api/NetworksApi";
import { ServerApi } from "../../api/ServerApi";
import { AsyncWidget } from "../AsyncWidget";
import { IPv4Input } from "../forms/IPv4Input";
import { EditSection } from "../forms/EditSection";
import { IPInput } from "../forms/IPInput";
import { SelectInput } from "../forms/SelectInput";
import { TextInput } from "../forms/TextInput";
import { useConfirm } from "../../hooks/providers/ConfirmDialogProvider";
import { CheckboxInput } from "../forms/CheckboxInput";
interface DetailsProps {
net: NetworkInfo;
@ -116,7 +118,7 @@ function NetworkDetailsInner(
/>
)}
<IPv4Input
<IPInput
editable={p.editable}
label="DNS server to use"
value={p.net.dns_server}
@ -124,8 +126,150 @@ function NetworkDetailsInner(
p.net.dns_server = v;
p.onChange?.();
}}
version={4}
/>
<TextInput
label="Domain"
editable={p.editable}
value={p.net.domain}
onValueChange={(v) => {
p.net.domain = v;
p.onChange?.();
}}
multiline={true}
/>
</EditSection>
<IPSection
editable={p.editable}
config={p.net.ip_v4}
onChange={(c) => {
p.net.ip_v4 = c;
p.onChange?.();
}}
version={4}
/>
<IPSection
editable={p.editable}
config={p.net.ip_v6}
onChange={(c) => {
p.net.ip_v6 = c;
p.onChange?.();
}}
version={6}
/>
</Grid>
);
}
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,
});
};
if (!p.config && !p.editable) return <></>;
return (
<EditSection
title={`IPv${p.version} network`}
actions={
<Checkbox
disabled={!p.editable}
checked={!!p.config}
onChange={toggleNetwork}
/>
}
>
{p.config && (
<>
<IPInput
editable={p.editable}
label="Bridge address"
version={p.version}
value={p.config?.bridge_address}
onValueChange={(v) => {
p.config!.bridge_address = v ?? "";
p.onChange?.(p.config);
}}
/>
<TextInput
label="Prefix"
editable={p.editable}
value={p.config.prefix.toString()}
type="number"
onValueChange={(v) => {
p.config!.prefix = Number(v);
p.onChange?.(p.config);
}}
size={p.version === 4 ? { min: 0, max: 32 } : { min: 0, max: 128 }}
/>
<CheckboxInput
checked={!!p.config.dhcp_range}
editable={p.editable}
label="Enable DHCP"
onValueChange={(v) => {
if (v)
p.config!.dhcp_range =
p.version === 4
? ["192.168.1.100", "192.168.1.200"]
: ["fd00::100", "fd00::f00"];
else p.config!.dhcp_range = undefined;
p.onChange?.(p.config);
}}
/>
</>
)}
{p.config?.dhcp_range && (
<>
<IPInput
label="DHCP allocation start"
editable={p.editable}
version={p.version}
value={p.config.dhcp_range[0]}
onValueChange={(v) => {
p.config!.dhcp_range![0] = v!;
p.onChange(p.config);
}}
/>
<IPInput
label="DHCP allocation end"
editable={p.editable}
version={p.version}
value={p.config.dhcp_range[1]}
onValueChange={(v) => {
p.config!.dhcp_range![1] = v!;
p.onChange(p.config);
}}
/>
</>
)}
</EditSection>
);
}