Can configure all network settings
This commit is contained in:
parent
b7d44f3091
commit
23f2029deb
@ -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 {
|
||||
|
@ -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>
|
||||
|
60
virtweb_frontend/src/widgets/forms/TextMaskInput.tsx
Normal file
60
virtweb_frontend/src/widgets/forms/TextMaskInput.tsx
Normal 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>
|
||||
);
|
||||
}
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user