From a1c900228273aa12cc950151a2516f0f4ac9a43b Mon Sep 17 00:00:00 2001 From: selankon Date: Thu, 24 Oct 2024 15:43:29 +0200 Subject: [PATCH] chore(meshconfig): refactor rest of modal api --- .../src/components/modals.tsx | 192 ++++++---- .../src/components/nextStepFooter.tsx | 201 ++++++++++- .../src/hooks/useStepper.tsx | 327 ++++++++---------- .../components/FeatureDetail/LinkDetail.tsx | 43 +-- .../components/FeatureDetail/NodeDetail.tsx | 40 ++- .../FeatureDetail/RebootNodeBtn.tsx | 126 +++---- .../src/components/modals.tsx | 148 ++++---- src/components/Modal/Modal.tsx | 2 +- 8 files changed, 638 insertions(+), 441 deletions(-) diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx index 3357844d0..229dca899 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx @@ -1,61 +1,108 @@ import { Trans } from "@lingui/macro"; -import { VNode } from "preact"; +import { ComponentChildren, VNode } from "preact"; import { useCallback } from "react"; -import { useModal } from "components/Modal/Modal"; +import { + CallbackFn, + Modal, + ModalProps, + useModal, +} from "components/Modal/Modal"; -interface IUseParallelQueriesModalProps { - useSuccessBtn?: boolean; - cb?: (e) => void; - title?: VNode; - content?: VNode; - btnTxt?: VNode; -} +import { useMeshUpgrade } from "plugins/lime-plugin-mesh-wide-upgrade/src/hooks/meshWideUpgradeProvider"; +import { + useParallelConfirmUpgrade, + useParallelScheduleUpgrade, +} from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueries"; -const useParallelQueriesModal = ({ - useSuccessBtn, - cb, - title, - content, - btnTxt = Schedule, -}: IUseParallelQueriesModalProps) => { - const { toggleModal, setModalState } = useModal(); - const runAndClose = useCallback(() => { - cb(null); - toggleModal(); - }, [cb, toggleModal]); +// interface IUseParallelQueriesModalProps { +// useSuccessBtn?: boolean; +// cb?: (e) => void; +// title?: VNode; +// content?: VNode; +// btnTxt?: VNode; +// } - const showModal = useCallback(() => { - setModalState({ - content, - title, - successCb: useSuccessBtn ? runAndClose : undefined, - deleteCb: !useSuccessBtn ? runAndClose : undefined, - successBtnText: btnTxt, - deleteBtnText: btnTxt, - }); - toggleModal(); - }, [ - setModalState, - content, - title, - useSuccessBtn, - runAndClose, - btnTxt, - toggleModal, - ]); - return { showModal, toggleModal }; -}; +// const useParallelQueriesModal = ({ +// useSuccessBtn, +// cb, +// title, +// content, +// btnTxt = Schedule, +// }: IUseParallelQueriesModalProps) => { +// const { toggleModal, setModalState } = useModal(); +// const runAndClose = useCallback(() => { +// cb(null); +// toggleModal(); +// }, [cb, toggleModal]); +// +// const showModal = useCallback(() => { +// setModalState({ +// content, +// title, +// successCb: useSuccessBtn ? runAndClose : undefined, +// deleteCb: !useSuccessBtn ? runAndClose : undefined, +// successBtnText: btnTxt, +// deleteBtnText: btnTxt, +// }); +// toggleModal(); +// }, [ +// setModalState, +// content, +// title, +// useSuccessBtn, +// runAndClose, +// btnTxt, +// toggleModal, +// ]); +// return { showModal, toggleModal }; +// }; -export const useScheduleUpgradeModal = ({ - useSuccessBtn, +type IUseParallelQueriesModalProps = { + isSuccess: boolean; +} & Pick; + +export const ParallelQueriesModal = ({ + children, + isSuccess, cb, -}: IUseParallelQueriesModalProps) => { + ...rest +}: { + cb: CallbackFn; + children: ComponentChildren; +} & IUseParallelQueriesModalProps & + Pick) => { + let props: Partial< + Pick< + ModalProps, + "onSuccess" | "onDelete" | "successBtnText" | "deleteBtnText" + > + > = { + onSuccess: cb, + successBtnText: Schedule, + }; + if (!isSuccess) { + props = { + onDelete: cb, + deleteBtnText: Schedule, + }; + } + return ( + + {children} + + ); +}; + +export const ScheduleUpgradeModal = (props: IUseParallelQueriesModalProps) => { + const { callMutations: startScheduleMeshUpgrade } = + useParallelScheduleUpgrade(); + let title = All nodes are ready; let content = ( Schedule a firmware upgrade for all nodes on the network ); - if (!useSuccessBtn) { + if (!props.isSuccess) { title = Some nodes are not ready; content = ( @@ -65,23 +112,25 @@ export const useScheduleUpgradeModal = ({ ); } - return useParallelQueriesModal({ - useSuccessBtn, - cb, - title, - content, - }); + return ( + + {content} + + ); }; -export const useConfirmModal = ({ - useSuccessBtn, - cb, -}: IUseParallelQueriesModalProps) => { +export const ConfirmModal = (props: IUseParallelQueriesModalProps) => { + const { callMutations: confirmMeshUpgrade } = useParallelConfirmUpgrade(); + let title = All nodes are upgraded successfully; let content = ( Confirm mesh wide upgrade for all nodes on the network ); - if (!useSuccessBtn) { + if (!props.isSuccess) { title = Some nodes don't upgraded properly; content = ( @@ -90,15 +139,18 @@ export const useConfirmModal = ({ ); } - return useParallelQueriesModal({ - useSuccessBtn, - cb, - title, - content, - }); + return ( + + {content} + + ); }; -export const useAbortModal = ({ cb }: IUseParallelQueriesModalProps) => { +export const AbortModal = ({ + ...props +}: Omit) => { + const { abort } = useMeshUpgrade(); + const title = Abort current mesh wide upgrade?; const content = ( @@ -107,11 +159,9 @@ export const useAbortModal = ({ cb }: IUseParallelQueriesModalProps) => { ); const btnTxt = Abort; - return useParallelQueriesModal({ - useSuccessBtn: false, - cb, - title, - content, - btnTxt, - }); + return ( + + {content} + + ); }; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/nextStepFooter.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/nextStepFooter.tsx index e2c82d4e8..a1b988ebb 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/components/nextStepFooter.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/nextStepFooter.tsx @@ -1,11 +1,206 @@ +import { Trans } from "@lingui/macro"; +import { useMemo } from "react"; + +import { useDisclosure } from "components/Modal/useDisclosure"; import { FooterStatus } from "components/status/footer"; +import { IStatusAndButton } from "components/status/statusAndButton"; + +import { + AbortModal, + ConfirmModal, + ScheduleUpgradeModal, +} from "plugins/lime-plugin-mesh-wide-upgrade/src/components/modals"; +import { useMeshUpgrade } from "plugins/lime-plugin-mesh-wide-upgrade/src/hooks/meshWideUpgradeProvider"; +import { + useParallelConfirmUpgrade, + useParallelScheduleUpgrade, +} from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueries"; +import { StepperState } from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeTypes"; + +export type ShowFooterStepperState = Extract< + StepperState, + | "UPDATE_AVAILABLE" + | "DOWNLOADED_MAIN" + | "TRANSACTION_STARTED" + | "UPGRADE_SCHEDULED" + | "CONFIRMATION_PENDING" + | "ERROR" +>; -import { useStep } from "plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper"; +export function isShowFooterStepperState( + value: string +): value is ShowFooterStepperState { + return [ + "UPDATE_AVAILABLE", + "DOWNLOADED_MAIN", + "TRANSACTION_STARTED", + "UPGRADE_SCHEDULED", + "CONFIRMATION_PENDING", + "ERROR", + ].includes(value); +} + +function isShowAbortButtonState( + value: string +): value is ShowFooterStepperState { + return [ + "TRANSACTION_STARTED", + "UPGRADE_SCHEDULED", + "CONFIRMATION_PENDING", + "ERROR", + ].includes(value); +} const NextStepFooter = () => { - const { step, showFooter } = useStep(); + const { + stepperState, + becomeMainNode, + startFwUpgradeTransaction, + allNodesReadyForUpgrade, + abort, + } = useMeshUpgrade(); + + const { errors: scheduleErrors } = useParallelScheduleUpgrade(); + + const { + open: showScheduleModal, + onOpen: openScheduleModal, + onClose: closeScheduleModal, + } = useDisclosure(); + + const { + open: showConfirmationModal, + onOpen: openConfirmationModal, + onClose: closeConfirmationModal, + } = useDisclosure(); + + const { + open: showAbort, + onOpen: openAbort, + onClose: closeAbort, + } = useDisclosure(); + + const showFooter = isShowFooterStepperState(stepperState); + + const step: IStatusAndButton | null = useMemo(() => { + if (!showFooter) return null; + + let step: IStatusAndButton; + switch (stepperState as ShowFooterStepperState) { + case "UPDATE_AVAILABLE": + step = { + status: "success", + onClick: () => becomeMainNode(), + children: ( + + Download remote firmware +
+ to start mesh upgrade +
+ ), + btn: Start mesh upgrade, + }; + break; + case "DOWNLOADED_MAIN": + step = { + status: "success", + onClick: startFwUpgradeTransaction, + children: Ready to start mesh wide upgrade, + btn: Start, + }; + break; + case "TRANSACTION_STARTED": + step = { + status: allNodesReadyForUpgrade ? "success" : "warning", + onClick: openScheduleModal, + children: allNodesReadyForUpgrade ? ( + Ready to start mesh wide upgrade + ) : ( + + Some nodes are not ready for upgrade
+ Check node details for more info +
+ ), + btn: Schedule upgrade, + }; + break; + case "UPGRADE_SCHEDULED": { + const data: Omit = { + onClick: openScheduleModal, + btn: Schedule again, + }; + if (scheduleErrors?.length) { + step = { + ...data, + status: "warning", + children: Some nodes have errors, + }; + } + step = { + ...data, + status: "success", + children: All nodes scheduled successful, + }; + break; + } + case "CONFIRMATION_PENDING": + step = { + status: "success", + onClick: openConfirmationModal, + children: Confirm upgrade on all nodes, + btn: Confirm, + }; + break; + case "ERROR": + default: + step = { + status: "warning", + children: Try last step again, + }; + } + if (isShowAbortButtonState(stepperState)) { + const showAbort: Pick< + IStatusAndButton, + "btnCancel" | "onClickCancel" + > = { + btnCancel: Abort, + onClickCancel: openAbort, + }; + step = { ...step, ...showAbort }; + } + return step; + }, [ + abort, + allNodesReadyForUpgrade, + becomeMainNode, + scheduleErrors?.length, + showConfirmationModal, + showFooter, + showScheduleModal, + startFwUpgradeTransaction, + stepperState, + ]); - return <>{showFooter && }; + return ( + <> + {showFooter && ( + <> + + + + + + )} + + ); }; export default NextStepFooter; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx index 65e376640..d4ebf4ebd 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx @@ -1,12 +1,13 @@ import { Trans } from "@lingui/macro"; import { useMemo } from "react"; +import { useDisclosure } from "components/Modal/useDisclosure"; import { IStatusAndButton } from "components/status/statusAndButton"; import { - useAbortModal, - useConfirmModal, - useScheduleUpgradeModal, + AbortModal, + ConfirmModal, + ScheduleUpgradeModal, } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/modals"; import { useMeshUpgrade } from "plugins/lime-plugin-mesh-wide-upgrade/src/hooks/meshWideUpgradeProvider"; import { @@ -99,179 +100,147 @@ export const getStepperStatus = ( return "INITIAL"; }; -export type ShowFooterStepperState = Extract< - StepperState, - | "UPDATE_AVAILABLE" - | "DOWNLOADED_MAIN" - | "TRANSACTION_STARTED" - | "UPGRADE_SCHEDULED" - | "CONFIRMATION_PENDING" - | "ERROR" ->; - -export function isShowFooterStepperState( - value: string -): value is ShowFooterStepperState { - return [ - "UPDATE_AVAILABLE", - "DOWNLOADED_MAIN", - "TRANSACTION_STARTED", - "UPGRADE_SCHEDULED", - "CONFIRMATION_PENDING", - "ERROR", - ].includes(value); -} - -function isShowAbortButtonState( - value: string -): value is ShowFooterStepperState { - return [ - "TRANSACTION_STARTED", - "UPGRADE_SCHEDULED", - "CONFIRMATION_PENDING", - "ERROR", - ].includes(value); -} - -export const useStep = () => { - const { - stepperState, - becomeMainNode, - startFwUpgradeTransaction, - allNodesReadyForUpgrade, - abort, - } = useMeshUpgrade(); - - const { callMutations: startScheduleMeshUpgrade, errors: scheduleErrors } = - useParallelScheduleUpgrade(); - - const { callMutations: confirmMeshUpgrade } = useParallelConfirmUpgrade(); - - const { showModal: showScheduleModal } = useScheduleUpgradeModal({ - useSuccessBtn: allNodesReadyForUpgrade, - cb: () => { - return startScheduleMeshUpgrade(); - }, - }); - - const { showModal: showConfirmationModal } = useConfirmModal({ - // Ideally we have to implement some kind of state before run the upgrade to check if all nodes are up again. - useSuccessBtn: true, - cb: () => { - return confirmMeshUpgrade(); - }, - }); - - const { showModal: showAbortModal } = useAbortModal({ - cb: () => { - return abort(); - }, - }); - - const showFooter = isShowFooterStepperState(stepperState); - - const step: IStatusAndButton | null = useMemo(() => { - if (!showFooter) return null; - - let step: IStatusAndButton; - switch (stepperState as ShowFooterStepperState) { - case "UPDATE_AVAILABLE": - step = { - status: "success", - onClick: () => becomeMainNode(), - children: ( - - Download remote firmware -
- to start mesh upgrade -
- ), - btn: Start mesh upgrade, - }; - break; - case "DOWNLOADED_MAIN": - step = { - status: "success", - onClick: startFwUpgradeTransaction, - children: Ready to start mesh wide upgrade, - btn: Start, - }; - break; - case "TRANSACTION_STARTED": - step = { - status: allNodesReadyForUpgrade ? "success" : "warning", - onClick: () => { - showScheduleModal(); - }, - children: allNodesReadyForUpgrade ? ( - Ready to start mesh wide upgrade - ) : ( - - Some nodes are not ready for upgrade
- Check node details for more info -
- ), - btn: Schedule upgrade, - }; - break; - case "UPGRADE_SCHEDULED": { - const data: Omit = { - onClick: showScheduleModal, - btn: Schedule again, - }; - if (scheduleErrors?.length) { - step = { - ...data, - status: "warning", - children: Some nodes have errors, - }; - } - step = { - ...data, - status: "success", - children: All nodes scheduled successful, - }; - break; - } - case "CONFIRMATION_PENDING": - step = { - status: "success", - onClick: showConfirmationModal, - children: Confirm upgrade on all nodes, - btn: Confirm, - }; - break; - case "ERROR": - default: - step = { - status: "warning", - children: Try last step again, - }; - } - if (isShowAbortButtonState(stepperState)) { - const showAbort: Pick< - IStatusAndButton, - "btnCancel" | "onClickCancel" - > = { - btnCancel: Abort, - onClickCancel: async () => { - showAbortModal(); - }, - }; - step = { ...step, ...showAbort }; - } - return step; - }, [ - abort, - allNodesReadyForUpgrade, - becomeMainNode, - scheduleErrors?.length, - showConfirmationModal, - showFooter, - showScheduleModal, - startFwUpgradeTransaction, - stepperState, - ]); - - return { step, showFooter }; -}; +// export const useStep = () => { +// const { +// stepperState, +// becomeMainNode, +// startFwUpgradeTransaction, +// allNodesReadyForUpgrade, +// abort, +// } = useMeshUpgrade(); +// +// const { callMutations: startScheduleMeshUpgrade, errors: scheduleErrors } = +// useParallelScheduleUpgrade(); +// +// const { callMutations: confirmMeshUpgrade } = useParallelConfirmUpgrade(); +// +// const { open, onOpen, onClose } = useDisclosure(); +// +// const { showModal: showScheduleModal } = useScheduleUpgradeModal({ +// useSuccessBtn: allNodesReadyForUpgrade, +// cb: () => { +// return startScheduleMeshUpgrade(); +// }, +// }); +// +// const { showModal: showConfirmationModal } = useConfirmModal({ +// // Ideally we have to implement some kind of state before run the upgrade to check if all nodes are up again. +// useSuccessBtn: true, +// cb: () => { +// return confirmMeshUpgrade(); +// }, +// }); +// +// const { showModal: showAbortModal } = useAbortModal({ +// cb: () => { +// return abort(); +// }, +// }); +// +// const showFooter = isShowFooterStepperState(stepperState); +// +// const step: IStatusAndButton | null = useMemo(() => { +// if (!showFooter) return null; +// +// let step: IStatusAndButton; +// switch (stepperState as ShowFooterStepperState) { +// case "UPDATE_AVAILABLE": +// step = { +// status: "success", +// onClick: () => becomeMainNode(), +// children: ( +// +// Download remote firmware +//
+// to start mesh upgrade +//
+// ), +// btn: Start mesh upgrade, +// }; +// break; +// case "DOWNLOADED_MAIN": +// step = { +// status: "success", +// onClick: startFwUpgradeTransaction, +// children: Ready to start mesh wide upgrade, +// btn: Start, +// }; +// break; +// case "TRANSACTION_STARTED": +// step = { +// status: allNodesReadyForUpgrade ? "success" : "warning", +// onClick: () => { +// showScheduleModal(); +// }, +// children: allNodesReadyForUpgrade ? ( +// Ready to start mesh wide upgrade +// ) : ( +// +// Some nodes are not ready for upgrade
+// Check node details for more info +//
+// ), +// btn: Schedule upgrade, +// }; +// break; +// case "UPGRADE_SCHEDULED": { +// const data: Omit = { +// onClick: showScheduleModal, +// btn: Schedule again, +// }; +// if (scheduleErrors?.length) { +// step = { +// ...data, +// status: "warning", +// children: Some nodes have errors, +// }; +// } +// step = { +// ...data, +// status: "success", +// children: All nodes scheduled successful, +// }; +// break; +// } +// case "CONFIRMATION_PENDING": +// step = { +// status: "success", +// onClick: showConfirmationModal, +// children: Confirm upgrade on all nodes, +// btn: Confirm, +// }; +// break; +// case "ERROR": +// default: +// step = { +// status: "warning", +// children: Try last step again, +// }; +// } +// if (isShowAbortButtonState(stepperState)) { +// const showAbort: Pick< +// IStatusAndButton, +// "btnCancel" | "onClickCancel" +// > = { +// btnCancel: Abort, +// onClickCancel: async () => { +// showAbortModal(); +// }, +// }; +// step = { ...step, ...showAbort }; +// } +// return step; +// }, [ +// abort, +// allNodesReadyForUpgrade, +// becomeMainNode, +// scheduleErrors?.length, +// showConfirmationModal, +// showFooter, +// showScheduleModal, +// startFwUpgradeTransaction, +// stepperState, +// ]); +// +// return { step, showFooter }; +// }; diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx index 44e07459e..c22a6a373 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx @@ -3,12 +3,13 @@ import { useMemo } from "preact/compat"; import { useState } from "preact/hooks"; import { useCallback } from "react"; +import { useDisclosure } from "components/Modal/useDisclosure"; import { Warning } from "components/icons/status"; import Tabs from "components/tabs"; import { useToast } from "components/toast/toastProvider"; import { StatusAndButton } from "plugins/lime-plugin-mesh-wide/src/components/Components"; -import { useSetLinkReferenceStateModal } from "plugins/lime-plugin-mesh-wide/src/components/modals"; +import { SetLinkReferenceStateModal } from "plugins/lime-plugin-mesh-wide/src/components/modals"; import { getQueryByLinkType, usePointToPointErrors, @@ -283,6 +284,8 @@ export const LinkReferenceStatus = ({ linkToShow, reference, }: LinkMapFeature) => { + const { open, onOpen, onClose } = useDisclosure(); + const isNewLink = !reference; const { errors } = usePointToPointErrors({ @@ -307,9 +310,6 @@ export const LinkReferenceStatus = ({ referenceError = true; } - // Modal to set ref state - const { closeModal, confirmModal, isModalOpen } = - useSetLinkReferenceStateModal(); const { showToast } = useToast(); // Get nodes to update @@ -355,9 +355,9 @@ export const LinkReferenceStatus = ({ text: Error setting new reference state!, }); } finally { - closeModal(); + onClose(); } - }, [callMutations, closeModal, showToast]); + }, [callMutations, onClose, showToast]); let btnText = ( @@ -394,20 +394,23 @@ export const LinkReferenceStatus = ({ errors?.hasErrors || isDown || isNewLink || referenceError; return ( - - confirmModal({ - dataType: linkToShow.type, - nodes: Object.values(nodesToUpdate), - isDown, - cb: setReferenceState, - }) - } - > - {errorMessage} - + <> + + {errorMessage} + + + ); }; diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx index 3208f9b98..f8a26a66f 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx @@ -1,6 +1,8 @@ import { Trans } from "@lingui/macro"; +import { DomEvent } from "leaflet"; import { useCallback } from "react"; +import { useDisclosure } from "components/Modal/useDisclosure"; import UpdateSharedStateBtn from "components/shared-state/UpdateSharedStateBtn"; import useSharedStateSync from "components/shared-state/useSharedStateSync"; import { useToast } from "components/toast/toastProvider"; @@ -11,7 +13,7 @@ import { Row, TitleAndText, } from "plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/index"; -import { useSetNodeInfoReferenceStateModal } from "plugins/lime-plugin-mesh-wide/src/components/modals"; +import { SetNodeInfoReferenceStateModal } from "plugins/lime-plugin-mesh-wide/src/components/modals"; import { useSingleNodeErrors } from "plugins/lime-plugin-mesh-wide/src/hooks/useSingleNodeErrors"; import { getArrayDifference } from "plugins/lime-plugin-mesh-wide/src/lib/utils"; import { @@ -146,6 +148,7 @@ const NodeDetails = ({ actual, reference, name }: NodeMapFeature) => { }; export const NodeReferenceStatus = ({ actual, reference }: NodeMapFeature) => { + const { open, onOpen, onClose } = useDisclosure(); const { hasErrors: hasNodeErrors, isDown, @@ -162,8 +165,6 @@ export const NodeReferenceStatus = ({ actual, reference }: NodeMapFeature) => { const { data: meshWideNodesReference, isError: isReferenceError } = useMeshWideNodesReference({}); - const { toggleModal, confirmModal, isModalOpen } = - useSetNodeInfoReferenceStateModal(); const { showToast } = useToast(); const { syncNode } = useSharedStateSync({ @@ -190,17 +191,11 @@ export const NodeReferenceStatus = ({ actual, reference }: NodeMapFeature) => { }); }, onSettled: () => { - if (isModalOpen) toggleModal(); + if (open) onClose(); }, }, }); - const setReferenceState = useCallback(async () => { - confirmModal(hostname, isDown, async () => { - await mutateAsync(); - }); - }, [confirmModal, hostname, isDown, mutateAsync]); - let btnText = Set reference state for this node; if (isDown) { btnText = Delete this this node from reference state; @@ -230,13 +225,24 @@ export const NodeReferenceStatus = ({ actual, reference }: NodeMapFeature) => { const showSetReferenceButton = hasNodeErrors || isNewNode || referenceError; return ( - - {errorMessage} - + <> + + {errorMessage} + + { + await mutateAsync(); + }} + onClose={onClose} + isOpen={open} + /> + ); }; diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx index 131be722e..a8dec3224 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx @@ -1,9 +1,9 @@ import { Trans } from "@lingui/macro"; import { useMutation } from "@tanstack/react-query"; -import { useEffect, useState } from "preact/hooks"; -import { useCallback } from "react"; +import { useCallback, useState } from "preact/hooks"; -import { useModal } from "components/Modal/Modal"; +import { Modal, ModalProps } from "components/Modal/Modal"; +import { useDisclosure } from "components/Modal/useDisclosure"; import { Button } from "components/buttons/button"; import { ErrorMsg } from "components/form"; import Loading from "components/loading"; @@ -39,14 +39,15 @@ const useRemoteReboot = (opts?) => { }); }; -const useRebootNodeModal = ({ node }: { node: INodeInfo }) => { - const modalKey = "rebootNodeModal"; - const { toggleModal, setModalState, isModalOpen, openModalKey } = - useModal(); +const RebootNodeModal = ({ + node, + isOpen, + onClose, +}: { node: INodeInfo } & Pick) => { const [password, setPassword] = useState(""); const { mutate, isLoading, error } = useRemoteReboot({ onSuccess: () => { - toggleModal(modalKey); + onClose(); }, }); @@ -58,73 +59,58 @@ const useRebootNodeModal = ({ node }: { node: INodeInfo }) => { mutate({ ip: node.ipv4, password }); }, [mutate, node.ipv4, password]); - const updateModalState = useCallback(() => { - setModalState({ - title: Reboot node {node.hostname}, - content: ( -
- - Are you sure you want to reboot this node? This action - will disconnect the node from the network for a few - minutes.
- Add shared password or let it empty if no password is - set. -
- {isLoading && } - {!isLoading && ( -
- - - {error && ( - - - Error performing reboot: {error} - - - )} -
- )} -
- ), - successCb: doLogin, - successBtnText: Reboot, - }); - }, [doLogin, error, isLoading, node.hostname, password, setModalState]); - - const rebootModal = useCallback(() => { - updateModalState(); - toggleModal(modalKey); - }, [toggleModal, updateModalState]); - - // Update modal state with mutation result - useEffect(() => { - if (isModalOpen && openModalKey === modalKey) { - updateModalState(); - } - }, [isLoading, error, isModalOpen, updateModalState, openModalKey]); - - return { rebootModal, toggleModal, isModalOpen }; + return ( + Reboot node {node.hostname}
} + successBtnText={Reboot} + > +
+ + Are you sure you want to reboot this node? This action will + disconnect the node from the network for a few minutes.{" "} +
+ Add shared password or let it empty if no password is set. +
+ {isLoading && } + {!isLoading && ( +
+ + + {error && ( + + Error performing reboot: {error} + + )} +
+ )} +
+ + ); }; const RemoteRebootBtn = ({ node }: { node: INodeInfo }) => { - const { rebootModal, isModalOpen } = useRebootNodeModal({ - node, - }); + const { open, onOpen, onClose } = useDisclosure(); return ( - + <> + + + ); }; diff --git a/plugins/lime-plugin-mesh-wide/src/components/modals.tsx b/plugins/lime-plugin-mesh-wide/src/components/modals.tsx index ab7ce6a00..6a443fb23 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/modals.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/modals.tsx @@ -1,95 +1,83 @@ import { Trans } from "@lingui/macro"; -import { ComponentChildren } from "preact"; -import { useCallback } from "preact/compat"; -import { useForm } from "react-hook-form"; -import { ModalActions, useModal } from "components/Modal/Modal"; -import InputField from "components/inputs/InputField"; +import { Modal, ModalProps } from "components/Modal/Modal"; import { dataTypeNameMapping } from "plugins/lime-plugin-mesh-wide/src/lib/utils"; import { MeshWideMapDataTypeKeys } from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; -export const useSetNodeInfoReferenceStateModal = () => { - const { toggleModal, setModalState, isModalOpen } = useModal(); - - const confirmModal = useCallback( - (nodeName: string, isDown: boolean, cb: () => Promise) => { - let title = Set reference state for {nodeName}; - let content = Set the reference state for this node.; - if (isDown) { - title = ( - Remove {nodeName} from the reference state - ); - content = ( - - This node seems down, remove them from the reference - state? - - ); - } - setModalState({ - title, - content, - successCb: cb, - successBtnText: Continue, - }); - toggleModal(); - }, - [setModalState, toggleModal] +export const SetNodeInfoReferenceStateModal = ({ + nodeName, + isDown, + ...modalProps +}: { nodeName: string; isDown: boolean } & Pick< + ModalProps, + "onSuccess" | "isOpen" | "onClose" +>) => { + let title = Set reference state for {nodeName}; + let content = Set the reference state for this node.; + if (isDown) { + title = Remove {nodeName} from the reference state; + content = ( + + This node seems down, remove them from the reference state? + + ); + } + return ( + Continue
} + {...modalProps} + > + {content} + ); - return { confirmModal, toggleModal, isModalOpen }; }; -export const useSetLinkReferenceStateModal = () => { - const { toggleModal, setModalState, isModalOpen, closeModal } = useModal(); - - const confirmModal = ({ - dataType, - nodes, - isDown, - cb, - }: { - dataType: MeshWideMapDataTypeKeys; - nodes: string[]; - isDown: boolean; - cb: () => Promise; - }) => { - let title = ( +export const SetLinkReferenceStateModal = ({ + dataType, + nodes, + isDown, + ...modalProps +}: { + dataType: MeshWideMapDataTypeKeys; + nodes: string[]; + isDown: boolean; +} & Pick) => { + let title = ( + + Set reference state for this {dataTypeNameMapping(dataType)}? + + ); + let content = ( + This will set the reference state of this link: + ); + if (isDown) { + title = ( - Set reference state for this {dataTypeNameMapping(dataType)}? + Remove this {dataTypeNameMapping(dataType)} from the reference + state ); - let content = ( - This will set the reference state of this link: + content = ( + + This link seems down, remove them from the reference state? + ); - if (isDown) { - title = ( - - Remove this {dataTypeNameMapping(dataType)} from the - reference state - - ); - content = ( - - This link seems down, remove them from the reference state? - - ); - } - setModalState({ - title, - content: ( -
- {content} -
-
- {nodes.join(", ")} -
+ } + return ( + Continue} + {...modalProps} + > +
+ {content} +
+
+ {nodes.join(", ")}
- ), - successCb: cb, - successBtnText: Continue, - }); - toggleModal(); - }; - return { confirmModal, closeModal, isModalOpen }; +
+
+ ); }; diff --git a/src/components/Modal/Modal.tsx b/src/components/Modal/Modal.tsx index 7e498631e..d3a2f5740 100644 --- a/src/components/Modal/Modal.tsx +++ b/src/components/Modal/Modal.tsx @@ -25,7 +25,7 @@ type ModalContextProps = { isLoading: boolean; } & ModalProps; -type CallbackFn = () => void | Promise; +export type CallbackFn = () => void | Promise; const ModalContext = createContext(null);