Files
EMS-ESP32/interface/src/framework/mqtt/MqttSettingsForm.tsx
pswid 12da8f9b67 improve view of app and mqtt settings pages
The appearance of the configuration pages has been unified. Additionally on very narrow screens (e.g. smartphones) only one parameter per row is displayed (on wider screens up to three per row).
2023-03-22 13:31:53 +01:00

423 lines
14 KiB
TypeScript

import { FC, useState } from 'react';
import { ValidateFieldsError } from 'async-validator';
import { Button, Checkbox, MenuItem, Grid, Typography, InputAdornment } from '@mui/material';
import WarningIcon from '@mui/icons-material/Warning';
import CancelIcon from '@mui/icons-material/Cancel';
import { createMqttSettingsValidator, validate } from 'validators';
import {
BlockFormControlLabel,
ButtonRow,
FormLoader,
SectionContent,
ValidatedPasswordField,
ValidatedTextField,
BlockNavigation
} from 'components';
import { MqttSettings } from 'types';
import { numberValue, updateValueDirty, useRest } from 'utils';
import * as MqttApi from 'api/mqtt';
import { useI18nContext } from 'i18n/i18n-react';
const MqttSettingsForm: FC = () => {
const { loadData, saving, data, setData, origData, dirtyFlags, setDirtyFlags, blocker, saveData, errorMessage } =
useRest<MqttSettings>({
read: MqttApi.readMqttSettings,
update: MqttApi.updateMqttSettings
});
const { LL } = useI18nContext();
const [fieldErrors, setFieldErrors] = useState<ValidateFieldsError>();
const updateFormValue = updateValueDirty(origData, dirtyFlags, setDirtyFlags, setData);
const content = () => {
if (!data) {
return <FormLoader onRetry={loadData} errorMessage={errorMessage} />;
}
const validateAndSubmit = async () => {
try {
setFieldErrors(undefined);
await validate(createMqttSettingsValidator(data), data);
saveData();
} catch (errors: any) {
setFieldErrors(errors);
}
};
return (
<>
<BlockFormControlLabel
control={<Checkbox name="enabled" checked={data.enabled} onChange={updateFormValue} />}
label={LL.ENABLE_MQTT()}
/>
<Grid container spacing={1} direction="row" justifyContent="flex-start" alignItems="flex-start">
<Grid item xs={12} sm={6}>
<ValidatedTextField
fieldErrors={fieldErrors}
name="host"
label={LL.ADDRESS_OF(LL.BROKER())}
fullWidth
variant="outlined"
value={data.host}
onChange={updateFormValue}
margin="normal"
/>
</Grid>
<Grid item xs={12} sm={6}>
<ValidatedTextField
fieldErrors={fieldErrors}
name="port"
label="Port"
fullWidth
variant="outlined"
value={numberValue(data.port)}
type="number"
onChange={updateFormValue}
margin="normal"
/>
</Grid>
<Grid item xs={12} sm={6}>
<ValidatedTextField
fieldErrors={fieldErrors}
name="base"
label={LL.BASE_TOPIC()}
fullWidth
variant="outlined"
value={data.base}
onChange={updateFormValue}
margin="normal"
/>
</Grid>
<Grid item xs={12} sm={6}>
<ValidatedTextField
name="client_id"
label={LL.ID_OF(LL.CLIENT()) + ' (' + LL.OPTIONAL() + ')'}
fullWidth
variant="outlined"
value={data.client_id}
onChange={updateFormValue}
margin="normal"
/>
</Grid>
<Grid item xs={12} sm={6}>
<ValidatedTextField
name="username"
label={LL.USERNAME(0)}
fullWidth
variant="outlined"
value={data.username}
onChange={updateFormValue}
margin="normal"
/>
</Grid>
<Grid item xs={12} sm={6}>
<ValidatedPasswordField
name="password"
label={LL.PASSWORD()}
fullWidth
variant="outlined"
value={data.password}
onChange={updateFormValue}
margin="normal"
/>
</Grid>
<Grid item xs={12} sm={6}>
<ValidatedTextField
fieldErrors={fieldErrors}
name="keep_alive"
label="Keep Alive"
InputProps={{
endAdornment: <InputAdornment position="end">{LL.SECONDS()}</InputAdornment>
}}
fullWidth
variant="outlined"
value={numberValue(data.keep_alive)}
type="number"
onChange={updateFormValue}
margin="normal"
/>
</Grid>
<Grid item xs={12} sm={6}>
<ValidatedTextField
name="mqtt_qos"
label="QoS"
value={data.mqtt_qos}
fullWidth
variant="outlined"
onChange={updateFormValue}
margin="normal"
select
>
<MenuItem value={0}>0</MenuItem>
<MenuItem value={1}>1</MenuItem>
<MenuItem value={2}>2</MenuItem>
</ValidatedTextField>
</Grid>
</Grid>
<BlockFormControlLabel
control={<Checkbox name="clean_session" checked={data.clean_session} onChange={updateFormValue} />}
label={LL.MQTT_CLEAN_SESSION()}
/>
<BlockFormControlLabel
control={<Checkbox name="mqtt_retain" checked={data.mqtt_retain} onChange={updateFormValue} />}
label={LL.MQTT_RETAIN_FLAG()}
/>
<Typography sx={{ pt: 2 }} variant="h6" color="primary">
{LL.FORMATTING()}
</Typography>
<ValidatedTextField
name="nested_format"
label={LL.MQTT_FORMAT()}
value={data.nested_format}
fullWidth
variant="outlined"
onChange={updateFormValue}
margin="normal"
select
>
<MenuItem value={1}>{LL.MQTT_NEST_1()}</MenuItem>
<MenuItem value={2}>{LL.MQTT_NEST_2()}</MenuItem>
</ValidatedTextField>
<BlockFormControlLabel
control={<Checkbox name="send_response" checked={data.send_response} onChange={updateFormValue} />}
label={LL.MQTT_RESPONSE()}
/>
{!data.ha_enabled && (
<Grid container rowSpacing={-1} spacing={1} direction="row" justifyContent="flex-start" alignItems="flex-start">
<Grid item>
<BlockFormControlLabel
control={<Checkbox name="publish_single" checked={data.publish_single} onChange={updateFormValue} />}
label={LL.MQTT_PUBLISH_TEXT_1()}
/>
</Grid>
{data.publish_single && (
<Grid item>
<BlockFormControlLabel
control={
<Checkbox name="publish_single2cmd" checked={data.publish_single2cmd} onChange={updateFormValue} />
}
label={LL.MQTT_PUBLISH_TEXT_2()}
/>
</Grid>
)}
</Grid>
)}
{!data.publish_single && (
<Grid container spacing={1} direction="row" justifyContent="flex-start" alignItems="flex-start">
<Grid item>
<BlockFormControlLabel
control={<Checkbox name="ha_enabled" checked={data.ha_enabled} onChange={updateFormValue} />}
label={LL.MQTT_PUBLISH_TEXT_3()}
/>
</Grid>
{data.ha_enabled && (
<Grid container sx={{ pl: 1 }} spacing={1} direction="row" justifyContent="flex-start" alignItems="flex-start">
<Grid item xs={12} sm={6} md={4}>
<ValidatedTextField
name="discovery_type"
label={LL.MQTT_PUBLISH_TEXT_5()}
value={data.discovery_type}
fullWidth
variant="outlined"
onChange={updateFormValue}
margin="normal"
select
>
<MenuItem value={0}>Home Assistant</MenuItem>
<MenuItem value={1}>Domoticz</MenuItem>
</ValidatedTextField>
</Grid>
<Grid item xs={12} sm={6} md={4}>
<ValidatedTextField
name="discovery_prefix"
label={LL.MQTT_PUBLISH_TEXT_4()}
fullWidth
variant="outlined"
value={data.discovery_prefix}
onChange={updateFormValue}
margin="normal"
/>
</Grid>
<Grid item xs={12} sm={6} md={4}>
<ValidatedTextField
name="entity_format"
label={LL.MQTT_ENTITY_FORMAT()}
value={data.entity_format}
fullWidth
variant="outlined"
onChange={updateFormValue}
margin="normal"
select
>
<MenuItem value={0}>{LL.MQTT_ENTITY_FORMAT_0()}</MenuItem>
<MenuItem value={1}>{LL.MQTT_ENTITY_FORMAT_1()}</MenuItem>
<MenuItem value={2}>{LL.MQTT_ENTITY_FORMAT_2()}</MenuItem>
</ValidatedTextField>
</Grid>
</Grid>
)}
</Grid>
)}
<Typography sx={{ pt: 2 }} variant="h6" color="primary">
{LL.MQTT_PUBLISH_INTERVALS()}&nbsp;(0=auto)
</Typography>
<Grid container spacing={1} direction="row" justifyContent="flex-start" alignItems="flex-start">
<Grid item xs={12} sm={6} md={4}>
<ValidatedTextField
fieldErrors={fieldErrors}
name="publish_time_heartbeat"
label={LL.MQTT_INT_HEARTBEAT()}
InputProps={{
endAdornment: <InputAdornment position="end">{LL.SECONDS()}</InputAdornment>
}}
fullWidth
variant="outlined"
value={numberValue(data.publish_time_heartbeat)}
type="number"
onChange={updateFormValue}
margin="normal"
/>
</Grid>
<Grid item xs={12} sm={6} md={4}>
<ValidatedTextField
fieldErrors={fieldErrors}
name="publish_time_boiler"
label={LL.MQTT_INT_BOILER()}
InputProps={{
endAdornment: <InputAdornment position="end">{LL.SECONDS()}</InputAdornment>
}}
fullWidth
variant="outlined"
value={numberValue(data.publish_time_boiler)}
type="number"
onChange={updateFormValue}
margin="normal"
/>
</Grid>
<Grid item xs={12} sm={6} md={4}>
<ValidatedTextField
fieldErrors={fieldErrors}
name="publish_time_thermostat"
label={LL.MQTT_INT_THERMOSTATS()}
InputProps={{
endAdornment: <InputAdornment position="end">{LL.SECONDS()}</InputAdornment>
}}
fullWidth
variant="outlined"
value={numberValue(data.publish_time_thermostat)}
type="number"
onChange={updateFormValue}
margin="normal"
/>
</Grid>
<Grid item xs={12} sm={6} md={4}>
<ValidatedTextField
fieldErrors={fieldErrors}
name="publish_time_solar"
label={LL.MQTT_INT_SOLAR()}
InputProps={{
endAdornment: <InputAdornment position="end">{LL.SECONDS()}</InputAdornment>
}}
fullWidth
variant="outlined"
value={numberValue(data.publish_time_solar)}
type="number"
onChange={updateFormValue}
margin="normal"
/>
</Grid>
<Grid item xs={12} sm={6} md={4}>
<ValidatedTextField
fieldErrors={fieldErrors}
name="publish_time_mixer"
label={LL.MQTT_INT_MIXER()}
InputProps={{
endAdornment: <InputAdornment position="end">{LL.SECONDS()}</InputAdornment>
}}
fullWidth
variant="outlined"
value={numberValue(data.publish_time_mixer)}
type="number"
onChange={updateFormValue}
margin="normal"
/>
</Grid>
<Grid item xs={12} sm={6} md={4}>
<ValidatedTextField
fieldErrors={fieldErrors}
name="publish_time_sensor"
label={LL.TEMP_SENSORS()}
InputProps={{
endAdornment: <InputAdornment position="end">{LL.SECONDS()}</InputAdornment>
}}
fullWidth
variant="outlined"
value={numberValue(data.publish_time_sensor)}
type="number"
onChange={updateFormValue}
margin="normal"
/>
</Grid>
<Grid item xs={12} sm={6} md={4}>
<ValidatedTextField
fieldErrors={fieldErrors}
name="publish_time_other"
InputProps={{
endAdornment: <InputAdornment position="end">{LL.SECONDS()}</InputAdornment>
}}
label={LL.DEFAULT(0)}
fullWidth
variant="outlined"
value={numberValue(data.publish_time_other)}
type="number"
onChange={updateFormValue}
margin="normal"
/>
</Grid>
</Grid>
{dirtyFlags && dirtyFlags.length !== 0 && (
<ButtonRow>
<Button
startIcon={<CancelIcon />}
disabled={saving}
variant="outlined"
color="primary"
type="submit"
onClick={() => loadData()}
>
{LL.CANCEL()}
</Button>
<Button
startIcon={<WarningIcon color="warning" />}
disabled={saving}
variant="contained"
color="info"
type="submit"
onClick={validateAndSubmit}
>
{LL.APPLY_CHANGES(dirtyFlags.length)}
</Button>
</ButtonRow>
)}
</>
);
};
return (
<SectionContent title={LL.SETTINGS_OF('MQTT')} titleGutter>
{blocker ? <BlockNavigation blocker={blocker} /> : null}
{content()}
</SectionContent>
);
};
export default MqttSettingsForm;