diff --git a/src/components/Form/FormSelect.tsx b/src/components/Form/FormSelect.tsx index 414ce12c..42be6c11 100644 --- a/src/components/Form/FormSelect.tsx +++ b/src/components/Form/FormSelect.tsx @@ -39,15 +39,11 @@ export function SelectInput({ disabled, field, }: GenericFormElementProps>) { - // Get default value and set it - const defaultValue = field.properties.defaultValue ?? field.defaultValue; - const { field: { value, onChange, ...rest }, } = useController({ name: field.name, control, - defaultValue: defaultValue ? defaultValue.toString() : undefined, }); const { enumValue, formatEnumName, ...remainingProperties } = field.properties; @@ -80,7 +76,6 @@ export function SelectInput({ onValueChange={handleValueChange} disabled={disabled} value={value?.toString()} - defaultValue={defaultValue?.toString()} {...remainingProperties} {...rest} > diff --git a/src/components/PageComponents/Config/Network.tsx b/src/components/PageComponents/Config/Network.tsx index a5c99a67..a52e74bd 100644 --- a/src/components/PageComponents/Config/Network.tsx +++ b/src/components/PageComponents/Config/Network.tsx @@ -1,4 +1,4 @@ -import type { NetworkValidation } from "@app/validation/config/network.ts"; +import { NetworkValidationSchema, type NetworkValidation } from "@app/validation/config/network.ts"; import { create } from "@bufbuild/protobuf"; import { DynamicForm } from "@components/Form/DynamicForm.tsx"; import { useDevice } from "@core/stores/deviceStore.ts"; @@ -7,13 +7,19 @@ import { convertIpAddressToInt, } from "@core/utils/ip.ts"; import { Protobuf } from "@meshtastic/core"; +import { validateSchema } from "@app/validation/validate.ts"; export const Network = () => { const { config, setWorkingConfig } = useDevice(); + console.log(config.network); + const onSubmit = (data: NetworkValidation) => { + const result = validateSchema(NetworkValidationSchema, data); - console.log("Network data", data); + if (!result.success) { + console.error("Validation errors:", result.errors); + } setWorkingConfig( create(Protobuf.Config.ConfigSchema, { @@ -24,10 +30,10 @@ export const Network = () => { ipv4Config: create( Protobuf.Config.Config_NetworkConfig_IpV4ConfigSchema, { - ip: convertIpAddressToInt(data?.ipv4Config?.ip) ?? 0, - gateway: convertIpAddressToInt(data.ipv4Config.gateway) ?? 0, - subnet: convertIpAddressToInt(data.ipv4Config.subnet) ?? 0, - dns: convertIpAddressToInt(data.ipv4Config.dns) ?? 0, + ip: convertIpAddressToInt(data.ipv4Config?.ip ?? ""), + gateway: convertIpAddressToInt(data.ipv4Config?.gateway ?? ""), + subnet: convertIpAddressToInt(data.ipv4Config?.subnet ?? ""), + dns: convertIpAddressToInt(data.ipv4Config?.dns ?? ""), }, ), }, @@ -51,6 +57,8 @@ export const Network = () => { ), dns: convertIntToIpAddress(config.network?.ipv4Config?.dns ?? 0), }, + enabledProtocols: config.network?.enabledProtocols ?? Protobuf.Config.Config_NetworkConfig_ProtocolFlags.NO_BROADCAST + }} fieldGroups={[ { @@ -175,7 +183,7 @@ export const Network = () => { { type: "select", name: "enabledProtocols", - label: "Mesh via UDP enabled", + label: "Mesh via UDP", properties: { enumValue: Protobuf.Config.Config_NetworkConfig_ProtocolFlags, diff --git a/src/pages/Config/DeviceConfig.tsx b/src/pages/Config/DeviceConfig.tsx index 45ae5f19..697b80b9 100644 --- a/src/pages/Config/DeviceConfig.tsx +++ b/src/pages/Config/DeviceConfig.tsx @@ -31,7 +31,6 @@ export const DeviceConfig = () => { { label: "Network", element: Network, - // disabled: !metadata.get(0)?.hasWifi, }, { label: "Display", diff --git a/src/validation/config/network.ts b/src/validation/config/network.ts index 6b2d8a06..9268128b 100644 --- a/src/validation/config/network.ts +++ b/src/validation/config/network.ts @@ -1,64 +1,27 @@ -import type { Message } from "@bufbuild/protobuf"; +import { z } from "zod"; import { Protobuf } from "@meshtastic/core"; -import { - IsBoolean, - IsEnum, - IsIP, - IsOptional, - IsString, - Length, -} from "class-validator"; -export class NetworkValidation - implements - Omit { - @IsBoolean() - wifiEnabled: boolean; +const AddressModeEnum = z.nativeEnum(Protobuf.Config.Config_NetworkConfig_AddressMode); +const ProtocolFlagsEnum = z.nativeEnum(Protobuf.Config.Config_NetworkConfig_ProtocolFlags); + +export const NetworkValidationIpV4ConfigSchema = z.object({ + ip: z.string().ip(), + gateway: z.string().ip(), + subnet: z.string().ip(), + dns: z.string().ip(), +}); + +export const NetworkValidationSchema = z.object({ + wifiEnabled: z.boolean(), + wifiSsid: z.string().min(0).max(33).optional(), + wifiPsk: z.string().min(0).max(64).optional(), + ntpServer: z.string().min(2).max(30), + ethEnabled: z.boolean(), + addressMode: AddressModeEnum, + ipv4Config: NetworkValidationIpV4ConfigSchema.optional(), + enabledProtocols: ProtocolFlagsEnum, + rsyslogServer: z.string(), +}); + +export type NetworkValidation = z.infer; - @Length(1, 33) - @IsOptional({}) - wifiSsid: string; - - @Length(8, 64) - @IsOptional() - wifiPsk: string; - - @Length(2, 30) - ntpServer: string; - - @IsBoolean() - ethEnabled: boolean; - - @IsEnum(Protobuf.Config.Config_NetworkConfig_AddressMode) - addressMode: Protobuf.Config.Config_NetworkConfig_AddressMode; - - ipv4Config: NetworkValidationIpV4Config; - - @IsEnum(Protobuf.Config.Config_NetworkConfig_EnabledProtocols) - enabledProtocols: Protobuf.Config.Config_NetworkConfig_ProtocolFlags; - - @IsString() - rsyslogServer: string; -} - -export class NetworkValidationIpV4Config implements - Omit< - Protobuf.Config.Config_NetworkConfig_IpV4Config, - keyof Message | "ip" | "gateway" | "subnet" | "dns" - > { - @IsIP() - @IsOptional() - ip: string; - - @IsIP() - @IsOptional() - gateway: string; - - @IsIP() - @IsOptional() - subnet: string; - - @IsIP() - @IsOptional() - dns: string; -} diff --git a/src/validation/validate.ts b/src/validation/validate.ts new file mode 100644 index 00000000..0969a1de --- /dev/null +++ b/src/validation/validate.ts @@ -0,0 +1,13 @@ +import { ZodError, ZodSchema } from "zod"; + +export function validateSchema( + schema: ZodSchema, + data: unknown +): { success: true; data: T } | { success: false; errors: ZodError["issues"] } { + const result = schema.safeParse(data); + if (result.success) { + return { success: true, data: result.data }; + } else { + return { success: false, errors: result.error.issues }; + } +} \ No newline at end of file