From aa3acae3524579505fc4a223879d6326d6266570 Mon Sep 17 00:00:00 2001 From: Sacha Weatherstone Date: Thu, 27 Oct 2022 20:03:57 +1000 Subject: [PATCH] Add form sections --- src/components/PageComponents/Config/LoRa.tsx | 192 +++++++++--------- .../PageComponents/Config/Network.tsx | 169 +++++++-------- .../PageComponents/Config/Position.tsx | 66 +++++- .../PageComponents/Config/Power.tsx | 67 +++--- .../PageComponents/Messages/Message.tsx | 2 +- src/components/form/FormSection.tsx | 22 ++ src/pages/Messages.tsx | 2 +- src/validation/config/network.ts | 6 +- src/validation/config/position.ts | 10 + 9 files changed, 320 insertions(+), 216 deletions(-) create mode 100644 src/components/form/FormSection.tsx diff --git a/src/components/PageComponents/Config/LoRa.tsx b/src/components/PageComponents/Config/LoRa.tsx index edd7f604..e31ac8f7 100644 --- a/src/components/PageComponents/Config/LoRa.tsx +++ b/src/components/PageComponents/Config/LoRa.tsx @@ -4,6 +4,7 @@ import { useEffect } from "react"; import { Controller, useForm, useWatch } from "react-hook-form"; import { toast } from "react-hot-toast"; +import { FormSection } from "@app/components/form/FormSection.js"; import { Input } from "@app/components/form/Input.js"; import { Select } from "@app/components/form/Select.js"; import { Toggle } from "@app/components/form/Toggle.js"; @@ -70,74 +71,103 @@ export const LoRa = (): JSX.Element => { dirty={isDirty} onSubmit={onSubmit} > - ( - - )} - /> - - - - - - - + + ( + + )} + /> + + + + + + + ( + + )} + /> + + + + + { error={errors.hopLimit?.message} {...register("hopLimit", { valueAsNumber: true })} /> - ( - - )} - /> - - ); }; diff --git a/src/components/PageComponents/Config/Network.tsx b/src/components/PageComponents/Config/Network.tsx index 1c11d533..9d899619 100644 --- a/src/components/PageComponents/Config/Network.tsx +++ b/src/components/PageComponents/Config/Network.tsx @@ -4,6 +4,7 @@ import { useEffect } from "react"; import { Controller, useForm, useWatch } from "react-hook-form"; import { toast } from "react-hot-toast"; +import { FormSection } from "@app/components/form/FormSection.js"; import { Input } from "@app/components/form/Input.js"; import { Select } from "@app/components/form/Select.js"; import { Toggle } from "@app/components/form/Toggle.js"; @@ -75,41 +76,91 @@ export const Network = (): JSX.Element => { dirty={isDirty} onSubmit={onSubmit} > - ( - - )} - /> - - - + + ( + + )} + /> + + + + + + ( + + )} + /> + + + + + + + + { disabled={!wifiEnabled && !ethEnabled} {...register("ntpServer")} /> - ( - - )} - /> - - - - - ); }; diff --git a/src/components/PageComponents/Config/Position.tsx b/src/components/PageComponents/Config/Position.tsx index 54774aea..4413f9de 100644 --- a/src/components/PageComponents/Config/Position.tsx +++ b/src/components/PageComponents/Config/Position.tsx @@ -1,15 +1,17 @@ import type React from "react"; import { useEffect } from "react"; -import { Controller, useForm } from "react-hook-form"; +import { Controller, useForm, useWatch } from "react-hook-form"; import { toast } from "react-hot-toast"; +import { FormSection } from "@app/components/form/FormSection.js"; import { Input } from "@app/components/form/Input.js"; import { Toggle } from "@app/components/form/Toggle.js"; import { PositionValidation } from "@app/validation/config/position.js"; import { Form } from "@components/form/Form"; import { useDevice } from "@core/providers/useDevice.js"; import { classValidatorResolver } from "@hookform/resolvers/class-validator"; +import { Protobuf } from "@meshtastic/meshtasticjs"; export const Position = (): JSX.Element => { const { config, connection } = useDevice(); @@ -24,18 +26,52 @@ export const Position = (): JSX.Element => { resolver: classValidatorResolver(PositionValidation), }); + const fixedPositionEnabled = useWatch({ + control, + name: "fixedPosition", + defaultValue: false, + }); + useEffect(() => { reset(config.position); }, [reset, config.position]); const onSubmit = handleSubmit((data) => { + const { fixedAlt, fixedLat, fixedLng, ...rest } = data; + if (connection) { + void toast.promise( + connection.sendPacket( + Protobuf.Position.toBinary( + Protobuf.Position.create({ + altitude: fixedAlt, + latitudeI: fixedLat * 1e7, + longitudeI: fixedLng * 1e7, + }) + ), + Protobuf.PortNum.POSITION_APP, + undefined, + true, + undefined, + true, + false, + async () => { + reset({ ...data }); + await Promise.resolve(); + } + ), + { + loading: "Saving...", + success: "Saved Channel", + error: "No response received", + } + ); void toast.promise( connection.setConfig( { payloadVariant: { oneofKind: "position", - position: data, + position: rest, }, }, async () => { @@ -92,6 +128,32 @@ export const Position = (): JSX.Element => { /> )} /> + + + + + { error={errors.adcMultiplierOverride?.message} {...register("adcMultiplierOverride", { valueAsNumber: true })} /> - - - - + + + + + + { - const { setPeerInfoOpen, setActivePeer } = useDevice(); + const { setPeerInfoOpen, setActivePeer, connection } = useDevice(); const openPeer = (): void => { setActivePeer(message.packet.from); diff --git a/src/components/form/FormSection.tsx b/src/components/form/FormSection.tsx new file mode 100644 index 00000000..ea47a835 --- /dev/null +++ b/src/components/form/FormSection.tsx @@ -0,0 +1,22 @@ +import type React from "react"; + +export interface FormSectionProps { + title: string; + children: React.ReactNode; +} + +export const FormSection = ({ + title, + children, +}: FormSectionProps): JSX.Element => { + return ( +
+

+ {title} +

+
+ {children} +
+
+ ); +}; diff --git a/src/pages/Messages.tsx b/src/pages/Messages.tsx index 9a5c5d19..b1a964ab 100644 --- a/src/pages/Messages.tsx +++ b/src/pages/Messages.tsx @@ -26,7 +26,7 @@ export const MessagesPage = (): JSX.Element => { }); return ( -
+