import { useState } from 'react'; import { toast } from 'react-toastify'; import CancelIcon from '@mui/icons-material/Cancel'; import PowerSettingsNewIcon from '@mui/icons-material/PowerSettingsNew'; import WarningIcon from '@mui/icons-material/Warning'; import { Box, Button, Checkbox, Divider, Grid, InputAdornment, MenuItem, TextField, Typography } from '@mui/material'; import { readHardwareStatus, restart } from 'api/system'; import { useRequest } from 'alova/client'; import RestartMonitor from 'app/status/RestartMonitor'; import type { ValidateFieldsError } from 'async-validator'; import { BlockFormControlLabel, BlockNavigation, ButtonRow, FormLoader, MessageBox, SectionContent, ValidatedTextField, useLayoutTitle } from 'components'; import { useI18nContext } from 'i18n/i18n-react'; import { numberValue, updateValueDirty, useRest } from 'utils'; import { validate } from 'validators'; import { getBoardProfile, readSettings, writeSettings } from '../../api/app'; import { BOARD_PROFILES } from '../main/types'; import type { Settings } from '../main/types'; import { createSettingsValidator } from '../main/validators'; export function boardProfileSelectItems() { return Object.keys(BOARD_PROFILES).map((code) => ( {BOARD_PROFILES[code]} )); } const ApplicationSettings = () => { const { data: hardwareData } = useRequest(readHardwareStatus); const { loadData, saveData, updateDataValue, data, origData, dirtyFlags, setDirtyFlags, blocker, errorMessage, restartNeeded } = useRest({ read: readSettings, update: writeSettings }); const [restarting, setRestarting] = useState(); const { LL } = useI18nContext(); const updateFormValue = updateValueDirty( origData, dirtyFlags, setDirtyFlags, updateDataValue ); const [fieldErrors, setFieldErrors] = useState(); const { loading: processingBoard, send: readBoardProfile } = useRequest( (boardProfile: string) => getBoardProfile(boardProfile), { immediate: false } ).onSuccess((event) => { const response = event.data as Settings; updateDataValue({ ...data, board_profile: response.board_profile, led_gpio: response.led_gpio, dallas_gpio: response.dallas_gpio, rx_gpio: response.rx_gpio, tx_gpio: response.tx_gpio, pbutton_gpio: response.pbutton_gpio, phy_type: response.phy_type, eth_power: response.eth_power, eth_phy_addr: response.eth_phy_addr, eth_clock_mode: response.eth_clock_mode }); }); const { send: restartCommand } = useRequest(restart(), { immediate: false }); const updateBoardProfile = async (board_profile: string) => { await readBoardProfile(board_profile).catch((error: Error) => { toast.error(error.message); }); }; useLayoutTitle(LL.SETTINGS_OF(LL.APPLICATION())); const content = () => { if (!data || !hardwareData) { return ; } const validateAndSubmit = async () => { try { setFieldErrors(undefined); await validate(createSettingsValidator(data), data); } catch (error) { setFieldErrors(error as ValidateFieldsError); } finally { await saveData(); } }; const changeBoardProfile = (event: React.ChangeEvent) => { const boardProfile = event.target.value; updateFormValue(event); if (boardProfile === 'CUSTOM') { updateDataValue({ ...data, board_profile: boardProfile }); } else { void updateBoardProfile(boardProfile); } }; const restart = async () => { await validateAndSubmit(); await restartCommand().catch((error: Error) => { toast.error(error.message); }); setRestarting(true); }; return ( <> {LL.SERVICES()} API } label={LL.BYPASS_TOKEN()} /> Console } label={LL.ENABLE_TELNET()} /> Modbus } label={LL.ENABLE_MODBUS()} /> {data.modbus_enabled && ( ms }} fullWidth variant="outlined" value={numberValue(data.modbus_timeout)} type="number" onChange={updateFormValue} margin="normal" /> )} Syslog } label={LL.ENABLE_SYSLOG()} /> {data.syslog_enabled && ( OFF ERR NOTICE INFO DEBUG ALL {LL.SECONDS()} ) }} fullWidth variant="outlined" value={numberValue(data.syslog_mark_interval)} type="number" onChange={updateFormValue} margin="normal" /> )} {LL.SENSORS()} Analog } label={LL.ENABLE_ANALOG()} /> {data.dallas_gpio !== 0 && ( <> {LL.TEMPERATURE()} } label={LL.ENABLE_PARASITE()} /> )} {LL.FORMATTING_OPTIONS()} Deutsch (DE) English (EN) Français (FR) Italiano (IT) Nederlands (NL) Norsk (NO) Polski (PL) Slovenčina (SK) Svenska (SV) Türk (TR) {LL.ONOFF()} {LL.ONOFF_CAP()} true/false 1/0 {LL.ONOFF()} {LL.ONOFF_CAP()} "true"/"false" true/false "1"/"0" 1/0 {LL.VALUE(5)} {LL.INDEX()} } label={LL.CONVERT_FAHRENHEIT()} /> } label={LL.LOG_HEX()} /> {LL.SETTINGS_OF(LL.HARDWARE())} {boardProfileSelectItems()} {LL.CUSTOM()}… {data.board_profile === 'CUSTOM' && ( <> {LL.DISABLED(1)} LAN8720 TLK110 {data.phy_type !== 0 && ( GPIO0_IN GPIO0_OUT GPIO16_OUT GPIO17_OUT )} )} EMS EMS+ HT3 {LL.HARDWARE()} Terminal (0x0A) Service Key (0x0B) Modem (0x0D) Converter (0x0E) Time Module (0x0F) Gateway 1 (0x48) Gateway 2 (0x49) Gateway 3 (0x4A) Gateway 4 (0x4B) Gateway 5 (0x4C) Gateway 7 (0x4D) } label={LL.READONLY()} /> {data.led_gpio !== 0 && ( } label={LL.HIDE_LED()} /> )} } label={LL.UNDERCLOCK_CPU()} /> {LL.GENERAL_OPTIONS()} } label={LL.HEATINGOFF()} /> } label={LL.REMOTE_TIMEOUT_EN()} /> {data.remote_timeout_en && ( {LL.HOURS()} ) }} variant="outlined" value={numberValue(data.remote_timeout)} type="number" onChange={updateFormValue} /> )} } label={LL.ENABLE_SHOWER_TIMER()} /> } label={LL.ENABLE_SHOWER_ALERT()} disabled={!data.shower_timer} /> {data.shower_timer && ( {LL.SECONDS()} ) }} variant="outlined" value={numberValue(data.shower_min_duration)} fullWidth type="number" onChange={updateFormValue} /> )} {data.shower_alert && ( <> {LL.MINUTES()} ) }} variant="outlined" value={numberValue(data.shower_alert_trigger)} fullWidth type="number" onChange={updateFormValue} disabled={!data.shower_timer} /> {LL.SECONDS()} ) }} variant="outlined" value={numberValue(data.shower_alert_coldshot)} fullWidth type="number" onChange={updateFormValue} disabled={!data.shower_timer} /> )} {restartNeeded && ( )} {!restartNeeded && dirtyFlags && dirtyFlags.length !== 0 && ( )} ); }; return ( {blocker ? : null} {restarting ? : content()} ); }; export default ApplicationSettings;