|
|
@ -27,6 +27,8 @@ const ConfigPage = () => { |
|
|
connection, |
|
|
connection, |
|
|
removeWorkingConfig, |
|
|
removeWorkingConfig, |
|
|
removeWorkingModuleConfig, |
|
|
removeWorkingModuleConfig, |
|
|
|
|
|
setConfig, |
|
|
|
|
|
setModuleConfig, |
|
|
} = useDevice(); |
|
|
} = useDevice(); |
|
|
const { hasErrors } = useAppStore(); |
|
|
const { hasErrors } = useAppStore(); |
|
|
|
|
|
|
|
|
@ -35,9 +37,7 @@ const ConfigPage = () => { |
|
|
>("device"); |
|
|
>("device"); |
|
|
const [isSaving, setIsSaving] = useState(false); |
|
|
const [isSaving, setIsSaving] = useState(false); |
|
|
const [formMethods, setFormMethods] = useState<UseFormReturn | null>(null); |
|
|
const [formMethods, setFormMethods] = useState<UseFormReturn | null>(null); |
|
|
|
|
|
|
|
|
const { toast } = useToast(); |
|
|
const { toast } = useToast(); |
|
|
const isError = hasErrors(); |
|
|
|
|
|
const { t } = useTranslation("deviceConfig"); |
|
|
const { t } = useTranslation("deviceConfig"); |
|
|
|
|
|
|
|
|
const onFormInit = (methods: UseFormReturn) => { |
|
|
const onFormInit = (methods: UseFormReturn) => { |
|
|
@ -51,33 +51,30 @@ const ConfigPage = () => { |
|
|
description: t("toast.validationError.description"), |
|
|
description: t("toast.validationError.description"), |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
if ( |
|
|
|
|
|
(activeConfigSection === "device" && workingConfig.length === 0) || |
|
|
|
|
|
(activeConfigSection === "module" && workingModuleConfig.length === 0) |
|
|
|
|
|
) return; |
|
|
|
|
|
|
|
|
|
|
|
setIsSaving(true); |
|
|
setIsSaving(true); |
|
|
|
|
|
|
|
|
try { |
|
|
try { |
|
|
await Promise.all( |
|
|
await Promise.all( |
|
|
workingConfig.map((config) => |
|
|
workingConfig.map((newConfig) => |
|
|
connection?.setConfig(config).then(() => |
|
|
connection?.setConfig(newConfig).then(() => { |
|
|
toast({ |
|
|
toast({ |
|
|
title: t("toast.saveSuccess.title"), |
|
|
title: t("toast.saveSuccess.title"), |
|
|
description: t("toast.saveSuccess.description", { |
|
|
description: t("toast.saveSuccess.description", { |
|
|
case: config.payloadVariant.case, |
|
|
case: newConfig.payloadVariant.case, |
|
|
}), |
|
|
}), |
|
|
}) |
|
|
}); |
|
|
) |
|
|
}) |
|
|
), |
|
|
), |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
await Promise.all( |
|
|
await Promise.all( |
|
|
workingModuleConfig.map((moduleConfig) => |
|
|
workingModuleConfig.map((newModuleConfig) => |
|
|
connection?.setModuleConfig(moduleConfig).then(() => |
|
|
connection?.setModuleConfig(newModuleConfig).then(() => |
|
|
toast({ |
|
|
toast({ |
|
|
title: t("toast.saveSuccess.title"), |
|
|
title: t("toast.saveSuccess.title"), |
|
|
description: t("toast.saveSuccess.description", { |
|
|
description: t("toast.saveSuccess.description", { |
|
|
case: moduleConfig.payloadVariant.case, |
|
|
case: newModuleConfig.payloadVariant.case, |
|
|
}), |
|
|
}), |
|
|
}) |
|
|
}) |
|
|
) |
|
|
) |
|
|
@ -85,16 +82,19 @@ const ConfigPage = () => { |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
await connection?.commitEditSettings().then(() => { |
|
|
await connection?.commitEditSettings().then(() => { |
|
|
removeWorkingConfig(); |
|
|
|
|
|
removeWorkingModuleConfig(); |
|
|
|
|
|
|
|
|
|
|
|
if (formMethods) { |
|
|
if (formMethods) { |
|
|
formMethods.reset({ |
|
|
formMethods.reset({}, { |
|
|
keepDefaultValues: true, |
|
|
keepValues: true, |
|
|
keepDirty: false, |
|
|
|
|
|
keepDirtyValues: true, |
|
|
|
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
workingConfig.map((newConfig) => setConfig(newConfig)); |
|
|
|
|
|
workingModuleConfig.map((newModuleConfig) => |
|
|
|
|
|
setModuleConfig(newModuleConfig) |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
removeWorkingConfig(); |
|
|
|
|
|
removeWorkingModuleConfig(); |
|
|
}); |
|
|
}); |
|
|
} catch (_error) { |
|
|
} catch (_error) { |
|
|
toast({ |
|
|
toast({ |
|
|
@ -145,13 +145,23 @@ const ConfigPage = () => { |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
const buttonOpacity = useMemo( |
|
|
const buttonOpacity = useMemo( |
|
|
() => (formMethods?.formState.isDirty || |
|
|
() => (formMethods?.formState.isDirty && |
|
|
|
|
|
Object.keys(formMethods?.formState.dirtyFields ?? {}).length > 0 || |
|
|
workingConfig.length > 0 || workingModuleConfig.length > 0 |
|
|
workingConfig.length > 0 || workingModuleConfig.length > 0 |
|
|
? "opacity-100" |
|
|
? "opacity-100" |
|
|
: "opacity-0"), |
|
|
: "opacity-0"), |
|
|
[formMethods?.formState.isDirty, workingConfig, workingModuleConfig], |
|
|
[ |
|
|
|
|
|
formMethods?.formState.isDirty, |
|
|
|
|
|
formMethods?.formState.dirtyFields, |
|
|
|
|
|
workingConfig, |
|
|
|
|
|
workingModuleConfig, |
|
|
|
|
|
], |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
const isValid = useMemo(() => { |
|
|
|
|
|
return Object.keys(formMethods?.formState.errors ?? {}).length === 0; |
|
|
|
|
|
}, [formMethods?.formState.errors]); |
|
|
|
|
|
|
|
|
const actions = useMemo(() => [ |
|
|
const actions = useMemo(() => [ |
|
|
{ |
|
|
{ |
|
|
key: "unsavedChanges", |
|
|
key: "unsavedChanges", |
|
|
@ -172,19 +182,22 @@ const ConfigPage = () => { |
|
|
}, |
|
|
}, |
|
|
{ |
|
|
{ |
|
|
key: "save", |
|
|
key: "save", |
|
|
icon: isError ? SaveOff : SaveIcon, |
|
|
icon: !isValid ? SaveOff : SaveIcon, |
|
|
isLoading: isSaving, |
|
|
isLoading: isSaving, |
|
|
disabled: isSaving || |
|
|
disabled: isSaving || |
|
|
|
|
|
!isValid || |
|
|
(workingConfig.length === 0 && workingModuleConfig.length === 0), |
|
|
(workingConfig.length === 0 && workingModuleConfig.length === 0), |
|
|
iconClasses: isError ? "text-red-400 cursor-not-allowed" : "", |
|
|
iconClasses: !isValid ? "text-red-400 cursor-not-allowed" : "", |
|
|
onClick: handleSave, |
|
|
onClick: handleSave, |
|
|
label: t("common:button.save"), |
|
|
label: t("common:button.save"), |
|
|
}, |
|
|
}, |
|
|
], [ |
|
|
], [ |
|
|
activeConfigSection, |
|
|
activeConfigSection, |
|
|
isError, |
|
|
|
|
|
isSaving, |
|
|
isSaving, |
|
|
|
|
|
isValid, |
|
|
buttonOpacity, |
|
|
buttonOpacity, |
|
|
|
|
|
workingConfig, |
|
|
|
|
|
workingModuleConfig, |
|
|
]); |
|
|
]); |
|
|
|
|
|
|
|
|
return ( |
|
|
return ( |
|
|
|