diff --git a/src/components/Dialog/ManagedModeDialog.tsx b/src/components/Dialog/ManagedModeDialog.tsx new file mode 100644 index 00000000..e9831567 --- /dev/null +++ b/src/components/Dialog/ManagedModeDialog.tsx @@ -0,0 +1,70 @@ +import { Button } from "@components/UI/Button.tsx"; +import { + Dialog, + DialogClose, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@components/UI/Dialog.tsx"; +import { Trans, useTranslation } from "react-i18next"; +import { Checkbox } from "@components/UI/Checkbox/index.tsx"; +import { useState } from "react"; + +export interface ManagedModeDialogProps { + open: boolean; + onOpenChange: () => void; + onSubmit: () => void; +} + +export const ManagedModeDialog = ({ + open, + onOpenChange, + onSubmit, +}: ManagedModeDialogProps) => { + const { t } = useTranslation("dialog"); + const [confirmState, setConfirmState] = useState(false); + + return ( + + + + + {t("managedMode.title")} + + , + }} + /> + + + + setConfirmState(!confirmState)} + name="confirmUnderstanding" + > + {t("managedMode.confirmUnderstanding")} + + + + { + setConfirmState(false); + onSubmit(); + }} + > + {t("button.confirm")} + + + + + ); +}; diff --git a/src/components/PageComponents/Config/Security/Security.tsx b/src/components/PageComponents/Config/Security/Security.tsx index dfcc685e..911227b5 100644 --- a/src/components/PageComponents/Config/Security/Security.tsx +++ b/src/components/PageComponents/Config/Security/Security.tsx @@ -1,4 +1,5 @@ import { PkiRegenerateDialog } from "@components/Dialog/PkiRegenerateDialog.tsx"; +import { ManagedModeDialog } from "@components/Dialog/ManagedModeDialog.tsx"; import { DynamicForm, type DynamicFormFormInit, @@ -75,6 +76,9 @@ export const Security = ({ onFormInit }: SecurityConfigProps) => { const [privateKeyDialogOpen, setPrivateKeyDialogOpen] = useState( false, ); + const [managedModeDialogOpen, setManagedModeDialogOpen] = useState( + false, + ); const onSubmit = (data: RawSecurity) => { if (!formState.isReady) return; @@ -249,6 +253,13 @@ export const Security = ({ onFormInit }: SecurityConfigProps) => { name: "isManaged", label: t("security.managed.label"), description: t("security.managed.description"), + inputChange: (checked) => { + if (checked) { + setManagedModeDialogOpen(true); + } + + setValue("isManaged", false); + }, }, { type: "toggle", @@ -285,9 +296,18 @@ export const Security = ({ onFormInit }: SecurityConfigProps) => { description: t("pkiRegenerate.description"), }} open={privateKeyDialogOpen} - onOpenChange={() => setPrivateKeyDialogOpen(true)} + onOpenChange={() => setPrivateKeyDialogOpen((prev) => !prev)} onSubmit={pkiRegenerate} /> + + setManagedModeDialogOpen((prev) => !prev)} + onSubmit={() => { + setValue("isManaged", true); + setManagedModeDialogOpen(false); + }} + /> > ); }; diff --git a/src/core/stores/deviceStore.mock.ts b/src/core/stores/deviceStore.mock.ts index 2b463e6b..43af9a9e 100644 --- a/src/core/stores/deviceStore.mock.ts +++ b/src/core/stores/deviceStore.mock.ts @@ -44,6 +44,7 @@ export const mockDeviceStore: Device = { unsafeRoles: false, refreshKeys: false, deleteMessages: false, + managedMode: false, }, setStatus: vi.fn(), setConfig: vi.fn(), diff --git a/src/core/stores/deviceStore.ts b/src/core/stores/deviceStore.ts index 40905066..4ab3b4ce 100644 --- a/src/core/stores/deviceStore.ts +++ b/src/core/stores/deviceStore.ts @@ -62,6 +62,7 @@ export interface Device { unsafeRoles: boolean; refreshKeys: boolean; deleteMessages: boolean; + managedMode: boolean; }; setStatus: (status: Types.DeviceStatusEnum) => void; @@ -170,6 +171,7 @@ export const useDeviceStore = createStore((set, get) => ({ refreshKeys: false, rebootOTA: false, deleteMessages: false, + managedMode: false, }, pendingSettingsChanges: false, messageDraft: "", diff --git a/src/core/utils/eventBus.ts b/src/core/utils/eventBus.ts index 75c48d8c..e9eb264e 100644 --- a/src/core/utils/eventBus.ts +++ b/src/core/utils/eventBus.ts @@ -2,6 +2,9 @@ export type EventMap = { "dialog:unsafeRoles": { action: "confirm" | "dismiss"; }; + "dialog:managedMode": { + action: "confirm" | "dismiss"; + }; }; export type EventName = keyof EventMap; diff --git a/src/i18n/locales/en/dialog.json b/src/i18n/locales/en/dialog.json index 23393156..379e1e59 100644 --- a/src/i18n/locales/en/dialog.json +++ b/src/i18n/locales/en/dialog.json @@ -156,5 +156,10 @@ "choosingRightDeviceRole": "Choosing The Right Device Role", "deviceRoleDocumentation": "Device Role Documentation", "title": "Are you sure?" + }, + "managedMode": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "title": "Are you sure?", + "description": "Enabling Managed Mode blocks client applications (including the web client) from writing configurations to a radio. Once enabled, radio configurations can only be changed through Remote Admin messages. This setting is not required for remote node administration." } }