mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-07 00:09:51 +03:00
translate NTP, AP, MQTT and User
This commit is contained in:
@@ -32,8 +32,8 @@ const LayoutMenu: FC = () => {
|
|||||||
)}
|
)}
|
||||||
<List disablePadding component="nav">
|
<List disablePadding component="nav">
|
||||||
<LayoutMenuItem icon={SettingsEthernetIcon} label={LL.NETWORK_CONNECTION()} to="/network" />
|
<LayoutMenuItem icon={SettingsEthernetIcon} label={LL.NETWORK_CONNECTION()} to="/network" />
|
||||||
<LayoutMenuItem icon={SettingsInputAntennaIcon} label="Access Point" to="/ap" />
|
<LayoutMenuItem icon={SettingsInputAntennaIcon} label={LL.ACCESS_POINT()} to="/ap" />
|
||||||
{features.ntp && <LayoutMenuItem icon={AccessTimeIcon} label={LL.NETWORK_TIME()} to="/ntp" />}
|
{features.ntp && <LayoutMenuItem icon={AccessTimeIcon} label="NTP" to="/ntp" />}
|
||||||
{features.mqtt && <LayoutMenuItem icon={DeviceHubIcon} label="MQTT" to="/mqtt" />}
|
{features.mqtt && <LayoutMenuItem icon={DeviceHubIcon} label="MQTT" to="/mqtt" />}
|
||||||
<LayoutMenuItem
|
<LayoutMenuItem
|
||||||
icon={LockIcon}
|
icon={LockIcon}
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ import { APProvisionMode, APSettings } from '../../types';
|
|||||||
import { numberValue, updateValue, useRest } from '../../utils';
|
import { numberValue, updateValue, useRest } from '../../utils';
|
||||||
import * as APApi from '../../api/ap';
|
import * as APApi from '../../api/ap';
|
||||||
|
|
||||||
|
import { useI18nContext } from '../../i18n/i18n-react';
|
||||||
|
|
||||||
export const isAPEnabled = ({ provision_mode }: APSettings) => {
|
export const isAPEnabled = ({ provision_mode }: APSettings) => {
|
||||||
return provision_mode === APProvisionMode.AP_MODE_ALWAYS || provision_mode === APProvisionMode.AP_MODE_DISCONNECTED;
|
return provision_mode === APProvisionMode.AP_MODE_ALWAYS || provision_mode === APProvisionMode.AP_MODE_DISCONNECTED;
|
||||||
};
|
};
|
||||||
@@ -29,6 +31,8 @@ const APSettingsForm: FC = () => {
|
|||||||
update: APApi.updateAPSettings
|
update: APApi.updateAPSettings
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { LL } = useI18nContext();
|
||||||
|
|
||||||
const [fieldErrors, setFieldErrors] = useState<ValidateFieldsError>();
|
const [fieldErrors, setFieldErrors] = useState<ValidateFieldsError>();
|
||||||
|
|
||||||
const updateFormValue = updateValue(setData);
|
const updateFormValue = updateValue(setData);
|
||||||
@@ -53,7 +57,7 @@ const APSettingsForm: FC = () => {
|
|||||||
<ValidatedTextField
|
<ValidatedTextField
|
||||||
fieldErrors={fieldErrors}
|
fieldErrors={fieldErrors}
|
||||||
name="provision_mode"
|
name="provision_mode"
|
||||||
label="Provide Access Point…"
|
label={LL.AP_PROVIDE() + '...'}
|
||||||
value={data.provision_mode}
|
value={data.provision_mode}
|
||||||
fullWidth
|
fullWidth
|
||||||
select
|
select
|
||||||
@@ -61,16 +65,16 @@ const APSettingsForm: FC = () => {
|
|||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
margin="normal"
|
margin="normal"
|
||||||
>
|
>
|
||||||
<MenuItem value={APProvisionMode.AP_MODE_ALWAYS}>Always</MenuItem>
|
<MenuItem value={APProvisionMode.AP_MODE_ALWAYS}>{LL.AP_PROVIDE_TEXT_1()}</MenuItem>
|
||||||
<MenuItem value={APProvisionMode.AP_MODE_DISCONNECTED}>When WiFi Disconnected</MenuItem>
|
<MenuItem value={APProvisionMode.AP_MODE_DISCONNECTED}>{LL.AP_PROVIDE_TEXT_2()}</MenuItem>
|
||||||
<MenuItem value={APProvisionMode.AP_NEVER}>Never</MenuItem>
|
<MenuItem value={APProvisionMode.AP_NEVER}>{LL.AP_PROVIDE_TEXT_3()}</MenuItem>
|
||||||
</ValidatedTextField>
|
</ValidatedTextField>
|
||||||
{isAPEnabled(data) && (
|
{isAPEnabled(data) && (
|
||||||
<>
|
<>
|
||||||
<ValidatedTextField
|
<ValidatedTextField
|
||||||
fieldErrors={fieldErrors}
|
fieldErrors={fieldErrors}
|
||||||
name="ssid"
|
name="ssid"
|
||||||
label="Access Point SSID"
|
label={LL.ACCESS_POINT() + ' SSID'}
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={data.ssid}
|
value={data.ssid}
|
||||||
@@ -80,7 +84,7 @@ const APSettingsForm: FC = () => {
|
|||||||
<ValidatedPasswordField
|
<ValidatedPasswordField
|
||||||
fieldErrors={fieldErrors}
|
fieldErrors={fieldErrors}
|
||||||
name="password"
|
name="password"
|
||||||
label="Access Point Password"
|
label={LL.ACCESS_POINT() + ' ' + LL.PASSWORD()}
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={data.password}
|
value={data.password}
|
||||||
@@ -90,7 +94,7 @@ const APSettingsForm: FC = () => {
|
|||||||
<ValidatedTextField
|
<ValidatedTextField
|
||||||
fieldErrors={fieldErrors}
|
fieldErrors={fieldErrors}
|
||||||
name="channel"
|
name="channel"
|
||||||
label="Preferred Channel"
|
label={LL.AP_PREFERRED_CHANNEL()}
|
||||||
value={numberValue(data.channel)}
|
value={numberValue(data.channel)}
|
||||||
fullWidth
|
fullWidth
|
||||||
select
|
select
|
||||||
@@ -107,7 +111,7 @@ const APSettingsForm: FC = () => {
|
|||||||
</ValidatedTextField>
|
</ValidatedTextField>
|
||||||
<BlockFormControlLabel
|
<BlockFormControlLabel
|
||||||
control={<Checkbox name="ssid_hidden" checked={data.ssid_hidden} onChange={updateFormValue} />}
|
control={<Checkbox name="ssid_hidden" checked={data.ssid_hidden} onChange={updateFormValue} />}
|
||||||
label="Hide SSID"
|
label={LL.AP_HIDE_SSID()}
|
||||||
/>
|
/>
|
||||||
<ValidatedTextField
|
<ValidatedTextField
|
||||||
fieldErrors={fieldErrors}
|
fieldErrors={fieldErrors}
|
||||||
@@ -168,7 +172,7 @@ const APSettingsForm: FC = () => {
|
|||||||
type="submit"
|
type="submit"
|
||||||
onClick={validateAndSubmit}
|
onClick={validateAndSubmit}
|
||||||
>
|
>
|
||||||
Save
|
{LL.SAVE()}
|
||||||
</Button>
|
</Button>
|
||||||
</ButtonRow>
|
</ButtonRow>
|
||||||
</>
|
</>
|
||||||
@@ -176,7 +180,7 @@ const APSettingsForm: FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SectionContent title="Access Point Settings" titleGutter>
|
<SectionContent title={LL.ACCESS_POINT() + ' ' + LL.SETTINGS()} titleGutter>
|
||||||
{content()}
|
{content()}
|
||||||
</SectionContent>
|
</SectionContent>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import { APNetworkStatus, APStatus } from '../../types';
|
|||||||
import { ButtonRow, FormLoader, SectionContent } from '../../components';
|
import { ButtonRow, FormLoader, SectionContent } from '../../components';
|
||||||
import { useRest } from '../../utils';
|
import { useRest } from '../../utils';
|
||||||
|
|
||||||
|
import { useI18nContext } from '../../i18n/i18n-react';
|
||||||
|
|
||||||
export const apStatusHighlight = ({ status }: APStatus, theme: Theme) => {
|
export const apStatusHighlight = ({ status }: APStatus, theme: Theme) => {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case APNetworkStatus.ACTIVE:
|
case APNetworkStatus.ACTIVE:
|
||||||
@@ -24,24 +26,26 @@ export const apStatusHighlight = ({ status }: APStatus, theme: Theme) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const apStatus = ({ status }: APStatus) => {
|
|
||||||
switch (status) {
|
|
||||||
case APNetworkStatus.ACTIVE:
|
|
||||||
return 'Active';
|
|
||||||
case APNetworkStatus.INACTIVE:
|
|
||||||
return 'Inactive';
|
|
||||||
case APNetworkStatus.LINGERING:
|
|
||||||
return 'Lingering until idle';
|
|
||||||
default:
|
|
||||||
return 'Unknown';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const APStatusForm: FC = () => {
|
const APStatusForm: FC = () => {
|
||||||
const { loadData, data, errorMessage } = useRest<APStatus>({ read: APApi.readAPStatus });
|
const { loadData, data, errorMessage } = useRest<APStatus>({ read: APApi.readAPStatus });
|
||||||
|
|
||||||
|
const { LL } = useI18nContext();
|
||||||
|
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
|
const apStatus = ({ status }: APStatus) => {
|
||||||
|
switch (status) {
|
||||||
|
case APNetworkStatus.ACTIVE:
|
||||||
|
return LL.ACTIVE();
|
||||||
|
case APNetworkStatus.INACTIVE:
|
||||||
|
return LL.INACTIVE();
|
||||||
|
case APNetworkStatus.LINGERING:
|
||||||
|
return 'Lingering until idle';
|
||||||
|
default:
|
||||||
|
return LL.UNKNOWN();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const content = () => {
|
const content = () => {
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return <FormLoader onRetry={loadData} errorMessage={errorMessage} />;
|
return <FormLoader onRetry={loadData} errorMessage={errorMessage} />;
|
||||||
@@ -56,7 +60,7 @@ const APStatusForm: FC = () => {
|
|||||||
<SettingsInputAntennaIcon />
|
<SettingsInputAntennaIcon />
|
||||||
</Avatar>
|
</Avatar>
|
||||||
</ListItemAvatar>
|
</ListItemAvatar>
|
||||||
<ListItemText primary="Status" secondary={apStatus(data)} />
|
<ListItemText primary={LL.STATUS()} secondary={apStatus(data)} />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<Divider variant="inset" component="li" />
|
<Divider variant="inset" component="li" />
|
||||||
<ListItem>
|
<ListItem>
|
||||||
@@ -87,7 +91,7 @@ const APStatusForm: FC = () => {
|
|||||||
</List>
|
</List>
|
||||||
<ButtonRow>
|
<ButtonRow>
|
||||||
<Button startIcon={<RefreshIcon />} variant="outlined" color="secondary" onClick={loadData}>
|
<Button startIcon={<RefreshIcon />} variant="outlined" color="secondary" onClick={loadData}>
|
||||||
Refresh
|
{LL.REFRESH()}
|
||||||
</Button>
|
</Button>
|
||||||
</ButtonRow>
|
</ButtonRow>
|
||||||
</>
|
</>
|
||||||
@@ -95,7 +99,7 @@ const APStatusForm: FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SectionContent title="Access Point Status" titleGutter>
|
<SectionContent title={LL.ACCESS_POINT() + ' ' + LL.STATUS()} titleGutter>
|
||||||
{content()}
|
{content()}
|
||||||
</SectionContent>
|
</SectionContent>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -8,8 +8,12 @@ import APStatusForm from './APStatusForm';
|
|||||||
import APSettingsForm from './APSettingsForm';
|
import APSettingsForm from './APSettingsForm';
|
||||||
import { RequireAdmin, RouterTabs, useLayoutTitle, useRouterTab } from '../../components';
|
import { RequireAdmin, RouterTabs, useLayoutTitle, useRouterTab } from '../../components';
|
||||||
|
|
||||||
|
import { useI18nContext } from '../../i18n/i18n-react';
|
||||||
|
|
||||||
const AccessPoint: FC = () => {
|
const AccessPoint: FC = () => {
|
||||||
useLayoutTitle('Access Point');
|
const { LL } = useI18nContext();
|
||||||
|
|
||||||
|
useLayoutTitle(LL.ACCESS_POINT());
|
||||||
|
|
||||||
const authenticatedContext = useContext(AuthenticatedContext);
|
const authenticatedContext = useContext(AuthenticatedContext);
|
||||||
|
|
||||||
@@ -18,8 +22,12 @@ const AccessPoint: FC = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<RouterTabs value={routerTab}>
|
<RouterTabs value={routerTab}>
|
||||||
<Tab value="status" label="Access Point Status" />
|
<Tab value="status" label={LL.ACCESS_POINT() + ' ' + LL.STATUS()} />
|
||||||
<Tab value="settings" label="Access Point Settings" disabled={!authenticatedContext.me.admin} />
|
<Tab
|
||||||
|
value="settings"
|
||||||
|
label={LL.ACCESS_POINT() + ' ' + LL.SETTINGS()}
|
||||||
|
disabled={!authenticatedContext.me.admin}
|
||||||
|
/>
|
||||||
</RouterTabs>
|
</RouterTabs>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="status" element={<APStatusForm />} />
|
<Route path="status" element={<APStatusForm />} />
|
||||||
|
|||||||
@@ -9,7 +9,11 @@ import { AuthenticatedContext } from '../../contexts/authentication';
|
|||||||
import MqttStatusForm from './MqttStatusForm';
|
import MqttStatusForm from './MqttStatusForm';
|
||||||
import MqttSettingsForm from './MqttSettingsForm';
|
import MqttSettingsForm from './MqttSettingsForm';
|
||||||
|
|
||||||
|
import { useI18nContext } from '../../i18n/i18n-react';
|
||||||
|
|
||||||
const Mqtt: FC = () => {
|
const Mqtt: FC = () => {
|
||||||
|
const { LL } = useI18nContext();
|
||||||
|
|
||||||
useLayoutTitle('MQTT');
|
useLayoutTitle('MQTT');
|
||||||
|
|
||||||
const authenticatedContext = useContext(AuthenticatedContext);
|
const authenticatedContext = useContext(AuthenticatedContext);
|
||||||
@@ -18,8 +22,8 @@ const Mqtt: FC = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<RouterTabs value={routerTab}>
|
<RouterTabs value={routerTab}>
|
||||||
<Tab value="status" label="MQTT Status" />
|
<Tab value="status" label={'MQTT ' + LL.STATUS()} />
|
||||||
<Tab value="settings" label="MQTT Settings" disabled={!authenticatedContext.me.admin} />
|
<Tab value="settings" label={'MQTT ' + LL.SETTINGS()} disabled={!authenticatedContext.me.admin} />
|
||||||
</RouterTabs>
|
</RouterTabs>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="status" element={<MqttStatusForm />} />
|
<Route path="status" element={<MqttStatusForm />} />
|
||||||
|
|||||||
@@ -17,12 +17,16 @@ import { MqttSettings } from '../../types';
|
|||||||
import { numberValue, updateValue, useRest } from '../../utils';
|
import { numberValue, updateValue, useRest } from '../../utils';
|
||||||
import * as MqttApi from '../../api/mqtt';
|
import * as MqttApi from '../../api/mqtt';
|
||||||
|
|
||||||
|
import { useI18nContext } from '../../i18n/i18n-react';
|
||||||
|
|
||||||
const MqttSettingsForm: FC = () => {
|
const MqttSettingsForm: FC = () => {
|
||||||
const { loadData, saving, data, setData, saveData, errorMessage } = useRest<MqttSettings>({
|
const { loadData, saving, data, setData, saveData, errorMessage } = useRest<MqttSettings>({
|
||||||
read: MqttApi.readMqttSettings,
|
read: MqttApi.readMqttSettings,
|
||||||
update: MqttApi.updateMqttSettings
|
update: MqttApi.updateMqttSettings
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { LL } = useI18nContext();
|
||||||
|
|
||||||
const [fieldErrors, setFieldErrors] = useState<ValidateFieldsError>();
|
const [fieldErrors, setFieldErrors] = useState<ValidateFieldsError>();
|
||||||
|
|
||||||
const updateFormValue = updateValue(setData);
|
const updateFormValue = updateValue(setData);
|
||||||
@@ -46,7 +50,7 @@ const MqttSettingsForm: FC = () => {
|
|||||||
<>
|
<>
|
||||||
<BlockFormControlLabel
|
<BlockFormControlLabel
|
||||||
control={<Checkbox name="enabled" checked={data.enabled} onChange={updateFormValue} />}
|
control={<Checkbox name="enabled" checked={data.enabled} onChange={updateFormValue} />}
|
||||||
label="Enable MQTT"
|
label={LL.ENABLE_MQTT()}
|
||||||
/>
|
/>
|
||||||
<Grid container spacing={1} direction="row" justifyContent="flex-start" alignItems="flex-start">
|
<Grid container spacing={1} direction="row" justifyContent="flex-start" alignItems="flex-start">
|
||||||
<Grid item xs={6}>
|
<Grid item xs={6}>
|
||||||
@@ -91,7 +95,7 @@ const MqttSettingsForm: FC = () => {
|
|||||||
<Grid item xs={6}>
|
<Grid item xs={6}>
|
||||||
<ValidatedTextField
|
<ValidatedTextField
|
||||||
name="client_id"
|
name="client_id"
|
||||||
label="Client ID (optional)"
|
label={'Client ID (' + LL.OPTIONAL() + ')'}
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={data.client_id}
|
value={data.client_id}
|
||||||
@@ -104,7 +108,7 @@ const MqttSettingsForm: FC = () => {
|
|||||||
<Grid item xs={6}>
|
<Grid item xs={6}>
|
||||||
<ValidatedTextField
|
<ValidatedTextField
|
||||||
name="username"
|
name="username"
|
||||||
label="Username"
|
label={LL.USERNAME()}
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={data.username}
|
value={data.username}
|
||||||
@@ -115,7 +119,7 @@ const MqttSettingsForm: FC = () => {
|
|||||||
<Grid item xs={6}>
|
<Grid item xs={6}>
|
||||||
<ValidatedPasswordField
|
<ValidatedPasswordField
|
||||||
name="password"
|
name="password"
|
||||||
label="Password"
|
label={LL.PASSWORD()}
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={data.password}
|
value={data.password}
|
||||||
@@ -160,18 +164,18 @@ const MqttSettingsForm: FC = () => {
|
|||||||
</Grid>
|
</Grid>
|
||||||
<BlockFormControlLabel
|
<BlockFormControlLabel
|
||||||
control={<Checkbox name="clean_session" checked={data.clean_session} onChange={updateFormValue} />}
|
control={<Checkbox name="clean_session" checked={data.clean_session} onChange={updateFormValue} />}
|
||||||
label="Set Clean Session"
|
label={LL.MQTT_CLEAN_SESSION()}
|
||||||
/>
|
/>
|
||||||
<BlockFormControlLabel
|
<BlockFormControlLabel
|
||||||
control={<Checkbox name="mqtt_retain" checked={data.mqtt_retain} onChange={updateFormValue} />}
|
control={<Checkbox name="mqtt_retain" checked={data.mqtt_retain} onChange={updateFormValue} />}
|
||||||
label="Always use Retain Flag"
|
label={LL.MQTT_RETAIN_FLAG()}
|
||||||
/>
|
/>
|
||||||
<Typography sx={{ pt: 2 }} variant="h6" color="primary">
|
<Typography sx={{ pt: 2 }} variant="h6" color="primary">
|
||||||
Formatting
|
{LL.FORMATTING()}
|
||||||
</Typography>
|
</Typography>
|
||||||
<ValidatedTextField
|
<ValidatedTextField
|
||||||
name="nested_format"
|
name="nested_format"
|
||||||
label="Topic/Payload Format"
|
label={'Topic/Payload ' + LL.FORMAT()}
|
||||||
value={data.nested_format}
|
value={data.nested_format}
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
@@ -179,19 +183,19 @@ const MqttSettingsForm: FC = () => {
|
|||||||
margin="normal"
|
margin="normal"
|
||||||
select
|
select
|
||||||
>
|
>
|
||||||
<MenuItem value={1}>Nested in a single topic</MenuItem>
|
<MenuItem value={1}>{LL.MQTT_NEST_1()}</MenuItem>
|
||||||
<MenuItem value={2}>As individual topics</MenuItem>
|
<MenuItem value={2}>{LL.MQTT_NEST_2()}</MenuItem>
|
||||||
</ValidatedTextField>
|
</ValidatedTextField>
|
||||||
<BlockFormControlLabel
|
<BlockFormControlLabel
|
||||||
control={<Checkbox name="send_response" checked={data.send_response} onChange={updateFormValue} />}
|
control={<Checkbox name="send_response" checked={data.send_response} onChange={updateFormValue} />}
|
||||||
label="Publish command output to a 'response' topic"
|
label={LL.MQTT_RESPONSE()}
|
||||||
/>
|
/>
|
||||||
{!data.ha_enabled && (
|
{!data.ha_enabled && (
|
||||||
<Grid container spacing={1} direction="row" justifyContent="flex-start" alignItems="flex-start">
|
<Grid container spacing={1} direction="row" justifyContent="flex-start" alignItems="flex-start">
|
||||||
<Grid item>
|
<Grid item>
|
||||||
<BlockFormControlLabel
|
<BlockFormControlLabel
|
||||||
control={<Checkbox name="publish_single" checked={data.publish_single} onChange={updateFormValue} />}
|
control={<Checkbox name="publish_single" checked={data.publish_single} onChange={updateFormValue} />}
|
||||||
label="Publish single value topics on change"
|
label={LL.MQTT_PUBLISH_TEXT_1()}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
{data.publish_single && (
|
{data.publish_single && (
|
||||||
@@ -200,7 +204,7 @@ const MqttSettingsForm: FC = () => {
|
|||||||
control={
|
control={
|
||||||
<Checkbox name="publish_single2cmd" checked={data.publish_single2cmd} onChange={updateFormValue} />
|
<Checkbox name="publish_single2cmd" checked={data.publish_single2cmd} onChange={updateFormValue} />
|
||||||
}
|
}
|
||||||
label="Publish to command topics (ioBroker)"
|
label={LL.MQTT_PUBLISH_TEXT_2()}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
)}
|
)}
|
||||||
@@ -211,14 +215,14 @@ const MqttSettingsForm: FC = () => {
|
|||||||
<Grid item>
|
<Grid item>
|
||||||
<BlockFormControlLabel
|
<BlockFormControlLabel
|
||||||
control={<Checkbox name="ha_enabled" checked={data.ha_enabled} onChange={updateFormValue} />}
|
control={<Checkbox name="ha_enabled" checked={data.ha_enabled} onChange={updateFormValue} />}
|
||||||
label="Enable MQTT Discovery (Home Assistant, Domoticz)"
|
label={LL.MQTT_PUBLISH_TEXT_3()}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
{data.ha_enabled && (
|
{data.ha_enabled && (
|
||||||
<Grid item xs={6}>
|
<Grid item xs={6}>
|
||||||
<ValidatedTextField
|
<ValidatedTextField
|
||||||
name="discovery_prefix"
|
name="discovery_prefix"
|
||||||
label="Prefix for the Discovery topics"
|
label={LL.MQTT_PUBLISH_TEXT_4()}
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={data.discovery_prefix}
|
value={data.discovery_prefix}
|
||||||
@@ -230,14 +234,14 @@ const MqttSettingsForm: FC = () => {
|
|||||||
</Grid>
|
</Grid>
|
||||||
)}
|
)}
|
||||||
<Typography sx={{ pt: 2 }} variant="h6" color="primary">
|
<Typography sx={{ pt: 2 }} variant="h6" color="primary">
|
||||||
Publish Intervals (0=auto)
|
{LL.MQTT_PUBLISH_INTERVALS()} (0=auto)
|
||||||
</Typography>
|
</Typography>
|
||||||
<Grid container spacing={1} direction="row" justifyContent="flex-start" alignItems="flex-start">
|
<Grid container spacing={1} direction="row" justifyContent="flex-start" alignItems="flex-start">
|
||||||
<Grid item xs={4}>
|
<Grid item xs={4}>
|
||||||
<ValidatedTextField
|
<ValidatedTextField
|
||||||
fieldErrors={fieldErrors}
|
fieldErrors={fieldErrors}
|
||||||
name="publish_time_boiler"
|
name="publish_time_boiler"
|
||||||
label="Boilers and Heat Pumps"
|
label={LL.MQTT_INT_BOILER()}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
endAdornment: <InputAdornment position="end">seconds</InputAdornment>
|
endAdornment: <InputAdornment position="end">seconds</InputAdornment>
|
||||||
}}
|
}}
|
||||||
@@ -253,7 +257,7 @@ const MqttSettingsForm: FC = () => {
|
|||||||
<ValidatedTextField
|
<ValidatedTextField
|
||||||
fieldErrors={fieldErrors}
|
fieldErrors={fieldErrors}
|
||||||
name="publish_time_thermostat"
|
name="publish_time_thermostat"
|
||||||
label="Thermostats"
|
label={LL.MQTT_INT_THERMOSTATS()}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
endAdornment: <InputAdornment position="end">seconds</InputAdornment>
|
endAdornment: <InputAdornment position="end">seconds</InputAdornment>
|
||||||
}}
|
}}
|
||||||
@@ -269,7 +273,7 @@ const MqttSettingsForm: FC = () => {
|
|||||||
<ValidatedTextField
|
<ValidatedTextField
|
||||||
fieldErrors={fieldErrors}
|
fieldErrors={fieldErrors}
|
||||||
name="publish_time_solar"
|
name="publish_time_solar"
|
||||||
label="Solar Modules"
|
label={LL.MQTT_INT_SOLAR()}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
endAdornment: <InputAdornment position="end">seconds</InputAdornment>
|
endAdornment: <InputAdornment position="end">seconds</InputAdornment>
|
||||||
}}
|
}}
|
||||||
@@ -285,7 +289,7 @@ const MqttSettingsForm: FC = () => {
|
|||||||
<ValidatedTextField
|
<ValidatedTextField
|
||||||
fieldErrors={fieldErrors}
|
fieldErrors={fieldErrors}
|
||||||
name="publish_time_mixer"
|
name="publish_time_mixer"
|
||||||
label="Mixer Modules"
|
label={LL.MQTT_INT_MIXER()}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
endAdornment: <InputAdornment position="end">seconds</InputAdornment>
|
endAdornment: <InputAdornment position="end">seconds</InputAdornment>
|
||||||
}}
|
}}
|
||||||
@@ -301,7 +305,7 @@ const MqttSettingsForm: FC = () => {
|
|||||||
<ValidatedTextField
|
<ValidatedTextField
|
||||||
fieldErrors={fieldErrors}
|
fieldErrors={fieldErrors}
|
||||||
name="publish_time_sensor"
|
name="publish_time_sensor"
|
||||||
label="Temperature Sensors"
|
label={LL.TEMP_SENSORS()}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
endAdornment: <InputAdornment position="end">seconds</InputAdornment>
|
endAdornment: <InputAdornment position="end">seconds</InputAdornment>
|
||||||
}}
|
}}
|
||||||
@@ -320,7 +324,7 @@ const MqttSettingsForm: FC = () => {
|
|||||||
InputProps={{
|
InputProps={{
|
||||||
endAdornment: <InputAdornment position="end">seconds</InputAdornment>
|
endAdornment: <InputAdornment position="end">seconds</InputAdornment>
|
||||||
}}
|
}}
|
||||||
label="Default"
|
label={LL.DEFAULT()}
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={numberValue(data.publish_time_other)}
|
value={numberValue(data.publish_time_other)}
|
||||||
@@ -339,7 +343,7 @@ const MqttSettingsForm: FC = () => {
|
|||||||
type="submit"
|
type="submit"
|
||||||
onClick={validateAndSubmit}
|
onClick={validateAndSubmit}
|
||||||
>
|
>
|
||||||
Save
|
{LL.SAVE()}
|
||||||
</Button>
|
</Button>
|
||||||
</ButtonRow>
|
</ButtonRow>
|
||||||
</>
|
</>
|
||||||
@@ -347,7 +351,7 @@ const MqttSettingsForm: FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SectionContent title="MQTT Settings" titleGutter>
|
<SectionContent title={'MQTT ' + LL.SETTINGS()} titleGutter>
|
||||||
{content()}
|
{content()}
|
||||||
</SectionContent>
|
</SectionContent>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import { MqttStatus, MqttDisconnectReason } from '../../types';
|
|||||||
import * as MqttApi from '../../api/mqtt';
|
import * as MqttApi from '../../api/mqtt';
|
||||||
import { useRest } from '../../utils';
|
import { useRest } from '../../utils';
|
||||||
|
|
||||||
|
import { useI18nContext } from '../../i18n/i18n-react';
|
||||||
|
|
||||||
export const mqttStatusHighlight = ({ enabled, connected }: MqttStatus, theme: Theme) => {
|
export const mqttStatusHighlight = ({ enabled, connected }: MqttStatus, theme: Theme) => {
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
return theme.palette.info.main;
|
return theme.palette.info.main;
|
||||||
@@ -29,17 +31,24 @@ export const mqttPublishHighlight = ({ mqtt_fails }: MqttStatus, theme: Theme) =
|
|||||||
return theme.palette.error.main;
|
return theme.palette.error.main;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const mqttStatus = ({ enabled, connected }: MqttStatus) => {
|
const MqttStatusForm: FC = () => {
|
||||||
|
const { loadData, data, errorMessage } = useRest<MqttStatus>({ read: MqttApi.readMqttStatus });
|
||||||
|
|
||||||
|
const { LL } = useI18nContext();
|
||||||
|
|
||||||
|
const theme = useTheme();
|
||||||
|
|
||||||
|
const mqttStatus = ({ enabled, connected }: MqttStatus) => {
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
return 'Not enabled';
|
return LL.NOT_ENABLED();
|
||||||
}
|
}
|
||||||
if (connected) {
|
if (connected) {
|
||||||
return 'Connected';
|
return LL.CONNECTED();
|
||||||
}
|
}
|
||||||
return 'Disconnected';
|
return LL.DISCONNECTED();
|
||||||
};
|
};
|
||||||
|
|
||||||
export const disconnectReason = ({ disconnect_reason }: MqttStatus) => {
|
const disconnectReason = ({ disconnect_reason }: MqttStatus) => {
|
||||||
switch (disconnect_reason) {
|
switch (disconnect_reason) {
|
||||||
case MqttDisconnectReason.TCP_DISCONNECTED:
|
case MqttDisconnectReason.TCP_DISCONNECTED:
|
||||||
return 'TCP disconnected';
|
return 'TCP disconnected';
|
||||||
@@ -60,12 +69,7 @@ export const disconnectReason = ({ disconnect_reason }: MqttStatus) => {
|
|||||||
default:
|
default:
|
||||||
return 'Unknown';
|
return 'Unknown';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const MqttStatusForm: FC = () => {
|
|
||||||
const { loadData, data, errorMessage } = useRest<MqttStatus>({ read: MqttApi.readMqttStatus });
|
|
||||||
|
|
||||||
const theme = useTheme();
|
|
||||||
|
|
||||||
const content = () => {
|
const content = () => {
|
||||||
if (!data) {
|
if (!data) {
|
||||||
@@ -89,7 +93,7 @@ const MqttStatusForm: FC = () => {
|
|||||||
<SpeakerNotesOffIcon />
|
<SpeakerNotesOffIcon />
|
||||||
</Avatar>
|
</Avatar>
|
||||||
</ListItemAvatar>
|
</ListItemAvatar>
|
||||||
<ListItemText primary="MQTT Publish Errors" secondary={data.mqtt_fails} />
|
<ListItemText primary={'MQTT Publish ' + LL.ERRORS()} secondary={data.mqtt_fails} />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
@@ -102,7 +106,7 @@ const MqttStatusForm: FC = () => {
|
|||||||
<ReportIcon />
|
<ReportIcon />
|
||||||
</Avatar>
|
</Avatar>
|
||||||
</ListItemAvatar>
|
</ListItemAvatar>
|
||||||
<ListItemText primary="Disconnect Reason" secondary={disconnectReason(data)} />
|
<ListItemText primary={LL.DISCONNECT_REASON()} secondary={disconnectReason(data)} />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<Divider variant="inset" component="li" />
|
<Divider variant="inset" component="li" />
|
||||||
</>
|
</>
|
||||||
@@ -118,14 +122,14 @@ const MqttStatusForm: FC = () => {
|
|||||||
<DeviceHubIcon />
|
<DeviceHubIcon />
|
||||||
</Avatar>
|
</Avatar>
|
||||||
</ListItemAvatar>
|
</ListItemAvatar>
|
||||||
<ListItemText primary="Status" secondary={mqttStatus(data)} />
|
<ListItemText primary={LL.STATUS()} secondary={mqttStatus(data)} />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<Divider variant="inset" component="li" />
|
<Divider variant="inset" component="li" />
|
||||||
{data.enabled && renderConnectionStatus()}
|
{data.enabled && renderConnectionStatus()}
|
||||||
</List>
|
</List>
|
||||||
<ButtonRow>
|
<ButtonRow>
|
||||||
<Button startIcon={<RefreshIcon />} variant="outlined" color="secondary" onClick={loadData}>
|
<Button startIcon={<RefreshIcon />} variant="outlined" color="secondary" onClick={loadData}>
|
||||||
Refresh
|
{LL.REFRESH()}
|
||||||
</Button>
|
</Button>
|
||||||
</ButtonRow>
|
</ButtonRow>
|
||||||
</>
|
</>
|
||||||
@@ -133,7 +137,7 @@ const MqttStatusForm: FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SectionContent title="MQTT Status" titleGutter>
|
<SectionContent title={'MQTT ' + LL.STATUS()} titleGutter>
|
||||||
{content()}
|
{content()}
|
||||||
</SectionContent>
|
</SectionContent>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -12,12 +12,16 @@ import * as NTPApi from '../../api/ntp';
|
|||||||
import { selectedTimeZone, timeZoneSelectItems, TIME_ZONES } from './TZ';
|
import { selectedTimeZone, timeZoneSelectItems, TIME_ZONES } from './TZ';
|
||||||
import { NTP_SETTINGS_VALIDATOR } from '../../validators/ntp';
|
import { NTP_SETTINGS_VALIDATOR } from '../../validators/ntp';
|
||||||
|
|
||||||
|
import { useI18nContext } from '../../i18n/i18n-react';
|
||||||
|
|
||||||
const NTPSettingsForm: FC = () => {
|
const NTPSettingsForm: FC = () => {
|
||||||
const { loadData, saving, data, setData, saveData, errorMessage } = useRest<NTPSettings>({
|
const { loadData, saving, data, setData, saveData, errorMessage } = useRest<NTPSettings>({
|
||||||
read: NTPApi.readNTPSettings,
|
read: NTPApi.readNTPSettings,
|
||||||
update: NTPApi.updateNTPSettings
|
update: NTPApi.updateNTPSettings
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { LL } = useI18nContext();
|
||||||
|
|
||||||
const updateFormValue = updateValue(setData);
|
const updateFormValue = updateValue(setData);
|
||||||
|
|
||||||
const [fieldErrors, setFieldErrors] = useState<ValidateFieldsError>();
|
const [fieldErrors, setFieldErrors] = useState<ValidateFieldsError>();
|
||||||
@@ -49,7 +53,7 @@ const NTPSettingsForm: FC = () => {
|
|||||||
<>
|
<>
|
||||||
<BlockFormControlLabel
|
<BlockFormControlLabel
|
||||||
control={<Checkbox name="enabled" checked={data.enabled} onChange={updateFormValue} />}
|
control={<Checkbox name="enabled" checked={data.enabled} onChange={updateFormValue} />}
|
||||||
label="Enable NTP"
|
label={LL.ENABLE_NTP()}
|
||||||
/>
|
/>
|
||||||
<ValidatedTextField
|
<ValidatedTextField
|
||||||
fieldErrors={fieldErrors}
|
fieldErrors={fieldErrors}
|
||||||
@@ -64,7 +68,7 @@ const NTPSettingsForm: FC = () => {
|
|||||||
<ValidatedTextField
|
<ValidatedTextField
|
||||||
fieldErrors={fieldErrors}
|
fieldErrors={fieldErrors}
|
||||||
name="tz_label"
|
name="tz_label"
|
||||||
label="Time zone"
|
label={LL.TIME_ZONE()}
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={selectedTimeZone(data.tz_label, data.tz_format)}
|
value={selectedTimeZone(data.tz_label, data.tz_format)}
|
||||||
@@ -72,7 +76,7 @@ const NTPSettingsForm: FC = () => {
|
|||||||
margin="normal"
|
margin="normal"
|
||||||
select
|
select
|
||||||
>
|
>
|
||||||
<MenuItem disabled>Time zone...</MenuItem>
|
<MenuItem disabled>{LL.TIME_ZONE()}...</MenuItem>
|
||||||
{timeZoneSelectItems()}
|
{timeZoneSelectItems()}
|
||||||
</ValidatedTextField>
|
</ValidatedTextField>
|
||||||
<ButtonRow>
|
<ButtonRow>
|
||||||
@@ -84,7 +88,7 @@ const NTPSettingsForm: FC = () => {
|
|||||||
type="submit"
|
type="submit"
|
||||||
onClick={validateAndSubmit}
|
onClick={validateAndSubmit}
|
||||||
>
|
>
|
||||||
Save
|
{LL.SAVE()}
|
||||||
</Button>
|
</Button>
|
||||||
</ButtonRow>
|
</ButtonRow>
|
||||||
</>
|
</>
|
||||||
@@ -92,7 +96,7 @@ const NTPSettingsForm: FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SectionContent title="NTP Settings" titleGutter>
|
<SectionContent title={'NTP ' + LL.SETTINGS()} titleGutter>
|
||||||
{content()}
|
{content()}
|
||||||
</SectionContent>
|
</SectionContent>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -49,19 +49,6 @@ export const ntpStatusHighlight = ({ status }: NTPStatus, theme: Theme) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ntpStatus = ({ status }: NTPStatus) => {
|
|
||||||
switch (status) {
|
|
||||||
case NTPSyncStatus.NTP_DISABLED:
|
|
||||||
return 'Disabled';
|
|
||||||
case NTPSyncStatus.NTP_INACTIVE:
|
|
||||||
return 'Inactive';
|
|
||||||
case NTPSyncStatus.NTP_ACTIVE:
|
|
||||||
return 'Active';
|
|
||||||
default:
|
|
||||||
return 'Unknown';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const NTPStatusForm: FC = () => {
|
const NTPStatusForm: FC = () => {
|
||||||
const { loadData, data, errorMessage } = useRest<NTPStatus>({ read: NTPApi.readNTPStatus });
|
const { loadData, data, errorMessage } = useRest<NTPStatus>({ read: NTPApi.readNTPStatus });
|
||||||
const [localTime, setLocalTime] = useState<string>('');
|
const [localTime, setLocalTime] = useState<string>('');
|
||||||
@@ -81,6 +68,19 @@ const NTPStatusForm: FC = () => {
|
|||||||
|
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
|
const ntpStatus = ({ status }: NTPStatus) => {
|
||||||
|
switch (status) {
|
||||||
|
case NTPSyncStatus.NTP_DISABLED:
|
||||||
|
return LL.DISABLED();
|
||||||
|
case NTPSyncStatus.NTP_INACTIVE:
|
||||||
|
return LL.INACTIVE();
|
||||||
|
case NTPSyncStatus.NTP_ACTIVE:
|
||||||
|
return LL.ACTIVE();
|
||||||
|
default:
|
||||||
|
return LL.UNKNOWN();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const configureTime = async () => {
|
const configureTime = async () => {
|
||||||
setProcessing(true);
|
setProcessing(true);
|
||||||
try {
|
try {
|
||||||
@@ -100,11 +100,11 @@ const NTPStatusForm: FC = () => {
|
|||||||
const renderSetTimeDialog = () => {
|
const renderSetTimeDialog = () => {
|
||||||
return (
|
return (
|
||||||
<Dialog open={settingTime} onClose={() => setSettingTime(false)}>
|
<Dialog open={settingTime} onClose={() => setSettingTime(false)}>
|
||||||
<DialogTitle>Set Time</DialogTitle>
|
<DialogTitle>{LL.SET_TIME()}</DialogTitle>
|
||||||
<DialogContent dividers>
|
<DialogContent dividers>
|
||||||
<Box mb={2}>Enter local date and time below to set the device's time.</Box>
|
<Box mb={2}>{LL.SET_TIME_TEXT()}</Box>
|
||||||
<TextField
|
<TextField
|
||||||
label="Local Time"
|
label={LL.LOCAL_TIME()}
|
||||||
type="datetime-local"
|
type="datetime-local"
|
||||||
value={localTime}
|
value={localTime}
|
||||||
onChange={updateLocalTime}
|
onChange={updateLocalTime}
|
||||||
@@ -118,7 +118,7 @@ const NTPStatusForm: FC = () => {
|
|||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<Button startIcon={<CancelIcon />} variant="outlined" onClick={() => setSettingTime(false)} color="secondary">
|
<Button startIcon={<CancelIcon />} variant="outlined" onClick={() => setSettingTime(false)} color="secondary">
|
||||||
Cancel
|
{LL.CANCEL()}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
startIcon={<AccessTimeIcon />}
|
startIcon={<AccessTimeIcon />}
|
||||||
@@ -128,7 +128,7 @@ const NTPStatusForm: FC = () => {
|
|||||||
color="primary"
|
color="primary"
|
||||||
autoFocus
|
autoFocus
|
||||||
>
|
>
|
||||||
Set Time
|
{LL.SET_TIME()}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
@@ -149,7 +149,7 @@ const NTPStatusForm: FC = () => {
|
|||||||
<UpdateIcon />
|
<UpdateIcon />
|
||||||
</Avatar>
|
</Avatar>
|
||||||
</ListItemAvatar>
|
</ListItemAvatar>
|
||||||
<ListItemText primary="Status" secondary={ntpStatus(data)} />
|
<ListItemText primary={LL.STATUS()} secondary={ntpStatus(data)} />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<Divider variant="inset" component="li" />
|
<Divider variant="inset" component="li" />
|
||||||
{isNtpEnabled(data) && (
|
{isNtpEnabled(data) && (
|
||||||
@@ -171,7 +171,7 @@ const NTPStatusForm: FC = () => {
|
|||||||
<AccessTimeIcon />
|
<AccessTimeIcon />
|
||||||
</Avatar>
|
</Avatar>
|
||||||
</ListItemAvatar>
|
</ListItemAvatar>
|
||||||
<ListItemText primary="Local Time" secondary={formatDateTime(data.local_time)} />
|
<ListItemText primary={LL.LOCAL_TIME()} secondary={formatDateTime(data.local_time)} />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<Divider variant="inset" component="li" />
|
<Divider variant="inset" component="li" />
|
||||||
<ListItem>
|
<ListItem>
|
||||||
@@ -180,7 +180,7 @@ const NTPStatusForm: FC = () => {
|
|||||||
<SwapVerticalCircleIcon />
|
<SwapVerticalCircleIcon />
|
||||||
</Avatar>
|
</Avatar>
|
||||||
</ListItemAvatar>
|
</ListItemAvatar>
|
||||||
<ListItemText primary="UTC Time" secondary={formatDateTime(data.utc_time)} />
|
<ListItemText primary={LL.UTC_TIME()} secondary={formatDateTime(data.utc_time)} />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<Divider variant="inset" component="li" />
|
<Divider variant="inset" component="li" />
|
||||||
</List>
|
</List>
|
||||||
@@ -188,7 +188,7 @@ const NTPStatusForm: FC = () => {
|
|||||||
<Box flexGrow={1}>
|
<Box flexGrow={1}>
|
||||||
<ButtonRow>
|
<ButtonRow>
|
||||||
<Button startIcon={<RefreshIcon />} variant="outlined" color="secondary" onClick={loadData}>
|
<Button startIcon={<RefreshIcon />} variant="outlined" color="secondary" onClick={loadData}>
|
||||||
Refresh
|
{LL.REFRESH()}
|
||||||
</Button>
|
</Button>
|
||||||
</ButtonRow>
|
</ButtonRow>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -196,7 +196,7 @@ const NTPStatusForm: FC = () => {
|
|||||||
<Box flexWrap="nowrap" whiteSpace="nowrap">
|
<Box flexWrap="nowrap" whiteSpace="nowrap">
|
||||||
<ButtonRow>
|
<ButtonRow>
|
||||||
<Button onClick={openSetTime} variant="outlined" color="primary" startIcon={<AccessTimeIcon />}>
|
<Button onClick={openSetTime} variant="outlined" color="primary" startIcon={<AccessTimeIcon />}>
|
||||||
Set Time
|
{LL.SET_TIME()}
|
||||||
</Button>
|
</Button>
|
||||||
</ButtonRow>
|
</ButtonRow>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -208,7 +208,7 @@ const NTPStatusForm: FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SectionContent title="NTP Status" titleGutter>
|
<SectionContent title={'NTP ' + LL.STATUS()} titleGutter>
|
||||||
{content()}
|
{content()}
|
||||||
</SectionContent>
|
</SectionContent>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import { useI18nContext } from '../../i18n/i18n-react';
|
|||||||
|
|
||||||
const NetworkTime: FC = () => {
|
const NetworkTime: FC = () => {
|
||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
useLayoutTitle(LL.NETWORK_TIME());
|
useLayoutTitle("NTP");
|
||||||
|
|
||||||
const authenticatedContext = useContext(AuthenticatedContext);
|
const authenticatedContext = useContext(AuthenticatedContext);
|
||||||
const { routerTab } = useRouterTab();
|
const { routerTab } = useRouterTab();
|
||||||
@@ -21,8 +21,8 @@ const NetworkTime: FC = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<RouterTabs value={routerTab}>
|
<RouterTabs value={routerTab}>
|
||||||
<Tab value="status" label="NTP Status" />
|
<Tab value="status" label={'NTP ' + LL.STATUS()} />
|
||||||
<Tab value="settings" label="NTP Settings" disabled={!authenticatedContext.me.admin} />
|
<Tab value="settings" label={'NTP ' + LL.SETTINGS()} disabled={!authenticatedContext.me.admin} />
|
||||||
</RouterTabs>
|
</RouterTabs>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="status" element={<NTPStatusForm />} />
|
<Route path="status" element={<NTPStatusForm />} />
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ import { MessageBox } from '../../components';
|
|||||||
import * as SecurityApi from '../../api/security';
|
import * as SecurityApi from '../../api/security';
|
||||||
import { Token } from '../../types';
|
import { Token } from '../../types';
|
||||||
|
|
||||||
|
import { useI18nContext } from '../../i18n/i18n-react';
|
||||||
|
|
||||||
interface GenerateTokenProps {
|
interface GenerateTokenProps {
|
||||||
username?: string;
|
username?: string;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
@@ -28,15 +30,17 @@ const GenerateToken: FC<GenerateTokenProps> = ({ username, onClose }) => {
|
|||||||
const [token, setToken] = useState<Token>();
|
const [token, setToken] = useState<Token>();
|
||||||
const open = !!username;
|
const open = !!username;
|
||||||
|
|
||||||
|
const { LL } = useI18nContext();
|
||||||
|
|
||||||
const { enqueueSnackbar } = useSnackbar();
|
const { enqueueSnackbar } = useSnackbar();
|
||||||
|
|
||||||
const getToken = useCallback(async () => {
|
const getToken = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
setToken((await SecurityApi.generateToken(username)).data);
|
setToken((await SecurityApi.generateToken(username)).data);
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, 'Problem generating token'), { variant: 'error' });
|
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
||||||
}
|
}
|
||||||
}, [username, enqueueSnackbar]);
|
}, [username, enqueueSnackbar, LL]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (open) {
|
if (open) {
|
||||||
@@ -46,16 +50,11 @@ const GenerateToken: FC<GenerateTokenProps> = ({ username, onClose }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog onClose={onClose} aria-labelledby="generate-token-dialog-title" open={!!username} fullWidth maxWidth="sm">
|
<Dialog onClose={onClose} aria-labelledby="generate-token-dialog-title" open={!!username} fullWidth maxWidth="sm">
|
||||||
<DialogTitle id="generate-token-dialog-title">Access Token for {username}</DialogTitle>
|
<DialogTitle id="generate-token-dialog-title">{LL.ACCESS_TOKEN_FOR() + ' ' + username}</DialogTitle>
|
||||||
<DialogContent dividers>
|
<DialogContent dividers>
|
||||||
{token ? (
|
{token ? (
|
||||||
<>
|
<>
|
||||||
<MessageBox
|
<MessageBox message={LL.ACCESS_TOKEN_TEXT()} level="info" my={2} />
|
||||||
message="The token below is used with REST API calls that require authorization. It can be passed either as a Bearer token in the
|
|
||||||
'Authorization' header or in the 'access_token' URL query parameter."
|
|
||||||
level="info"
|
|
||||||
my={2}
|
|
||||||
/>
|
|
||||||
<Box mt={2} mb={2}>
|
<Box mt={2} mb={2}>
|
||||||
<TextField label="Token" multiline value={token.token} fullWidth contentEditable={false} />
|
<TextField label="Token" multiline value={token.token} fullWidth contentEditable={false} />
|
||||||
</Box>
|
</Box>
|
||||||
@@ -63,13 +62,13 @@ const GenerateToken: FC<GenerateTokenProps> = ({ username, onClose }) => {
|
|||||||
) : (
|
) : (
|
||||||
<Box m={4} textAlign="center">
|
<Box m={4} textAlign="center">
|
||||||
<LinearProgress />
|
<LinearProgress />
|
||||||
<Typography variant="h6">Generating token…</Typography>
|
<Typography variant="h6">{LL.GENERATING_TOKEN()}…</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<Button startIcon={<CloseIcon />} variant="outlined" onClick={onClose} color="secondary">
|
<Button startIcon={<CloseIcon />} variant="outlined" onClick={onClose} color="secondary">
|
||||||
Close
|
{LL.CLOSE()}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ import { createUserValidator } from '../../validators';
|
|||||||
import { useRest } from '../../utils';
|
import { useRest } from '../../utils';
|
||||||
import { AuthenticatedContext } from '../../contexts/authentication';
|
import { AuthenticatedContext } from '../../contexts/authentication';
|
||||||
|
|
||||||
|
import { useI18nContext } from '../../i18n/i18n-react';
|
||||||
|
|
||||||
import GenerateToken from './GenerateToken';
|
import GenerateToken from './GenerateToken';
|
||||||
import UserForm from './UserForm';
|
import UserForm from './UserForm';
|
||||||
|
|
||||||
@@ -34,9 +36,11 @@ const ManageUsersForm: FC = () => {
|
|||||||
const [generatingToken, setGeneratingToken] = useState<string>();
|
const [generatingToken, setGeneratingToken] = useState<string>();
|
||||||
const authenticatedContext = useContext(AuthenticatedContext);
|
const authenticatedContext = useContext(AuthenticatedContext);
|
||||||
|
|
||||||
|
const { LL } = useI18nContext();
|
||||||
|
|
||||||
const table_theme = useTheme({
|
const table_theme = useTheme({
|
||||||
Table: `
|
Table: `
|
||||||
--data-table-library_grid-template-columns: repeat(1, minmax(0, 1fr)) 90px 120px;
|
--data-table-library_grid-template-columns: repeat(1, minmax(0, 1fr)) 120px 120px;
|
||||||
`,
|
`,
|
||||||
BaseRow: `
|
BaseRow: `
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
@@ -136,8 +140,8 @@ const ManageUsersForm: FC = () => {
|
|||||||
<>
|
<>
|
||||||
<Header>
|
<Header>
|
||||||
<HeaderRow>
|
<HeaderRow>
|
||||||
<HeaderCell resize>USERNAME</HeaderCell>
|
<HeaderCell resize>{LL.USERNAME()}</HeaderCell>
|
||||||
<HeaderCell stiff>IS ADMIN</HeaderCell>
|
<HeaderCell stiff>{LL.IS_ADMIN()}</HeaderCell>
|
||||||
<HeaderCell stiff />
|
<HeaderCell stiff />
|
||||||
</HeaderRow>
|
</HeaderRow>
|
||||||
</Header>
|
</Header>
|
||||||
@@ -169,9 +173,7 @@ const ManageUsersForm: FC = () => {
|
|||||||
)}
|
)}
|
||||||
</Table>
|
</Table>
|
||||||
|
|
||||||
{noAdminConfigured() && (
|
{noAdminConfigured() && <MessageBox level="warning" message={LL.USER_WARNING()} my={2} />}
|
||||||
<MessageBox level="warning" message="You must have at least one admin user configured" my={2} />
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Box display="flex" flexWrap="wrap">
|
<Box display="flex" flexWrap="wrap">
|
||||||
<Box flexGrow={1} sx={{ '& button': { mt: 2 } }}>
|
<Box flexGrow={1} sx={{ '& button': { mt: 2 } }}>
|
||||||
@@ -183,14 +185,14 @@ const ManageUsersForm: FC = () => {
|
|||||||
type="submit"
|
type="submit"
|
||||||
onClick={onSubmit}
|
onClick={onSubmit}
|
||||||
>
|
>
|
||||||
Save
|
{LL.SAVE()}
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box flexWrap="nowrap" whiteSpace="nowrap">
|
<Box flexWrap="nowrap" whiteSpace="nowrap">
|
||||||
<ButtonRow>
|
<ButtonRow>
|
||||||
<Button startIcon={<PersonAddIcon />} variant="outlined" color="secondary" onClick={createUser}>
|
<Button startIcon={<PersonAddIcon />} variant="outlined" color="secondary" onClick={createUser}>
|
||||||
Add
|
{LL.ADD()}
|
||||||
</Button>
|
</Button>
|
||||||
</ButtonRow>
|
</ButtonRow>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -210,7 +212,7 @@ const ManageUsersForm: FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SectionContent title="Manage Users" titleGutter>
|
<SectionContent title={LL.MANAGE_USERS()} titleGutter>
|
||||||
{content()}
|
{content()}
|
||||||
</SectionContent>
|
</SectionContent>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ const Security: FC = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<RouterTabs value={routerTab}>
|
<RouterTabs value={routerTab}>
|
||||||
<Tab value="users" label="Manage Users" />
|
<Tab value="users" label={LL.MANAGE_USERS()} />
|
||||||
<Tab value="settings" label="Security Settings" />
|
<Tab value="settings" label={LL.SECURITY() + ' ' + LL.SETTINGS()} />
|
||||||
</RouterTabs>
|
</RouterTabs>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="users" element={<ManageUsersForm />} />
|
<Route path="users" element={<ManageUsersForm />} />
|
||||||
|
|||||||
@@ -11,7 +11,11 @@ import { SECURITY_SETTINGS_VALIDATOR, validate } from '../../validators';
|
|||||||
import { updateValue, useRest } from '../../utils';
|
import { updateValue, useRest } from '../../utils';
|
||||||
import { AuthenticatedContext } from '../../contexts/authentication';
|
import { AuthenticatedContext } from '../../contexts/authentication';
|
||||||
|
|
||||||
|
import { useI18nContext } from '../../i18n/i18n-react';
|
||||||
|
|
||||||
const SecuritySettingsForm: FC = () => {
|
const SecuritySettingsForm: FC = () => {
|
||||||
|
const { LL } = useI18nContext();
|
||||||
|
|
||||||
const [fieldErrors, setFieldErrors] = useState<ValidateFieldsError>();
|
const [fieldErrors, setFieldErrors] = useState<ValidateFieldsError>();
|
||||||
const { loadData, saving, data, setData, saveData, errorMessage } = useRest<SecuritySettings>({
|
const { loadData, saving, data, setData, saveData, errorMessage } = useRest<SecuritySettings>({
|
||||||
read: SecurityApi.readSecuritySettings,
|
read: SecurityApi.readSecuritySettings,
|
||||||
@@ -42,7 +46,7 @@ const SecuritySettingsForm: FC = () => {
|
|||||||
<ValidatedPasswordField
|
<ValidatedPasswordField
|
||||||
fieldErrors={fieldErrors}
|
fieldErrors={fieldErrors}
|
||||||
name="jwt_secret"
|
name="jwt_secret"
|
||||||
label="su Password"
|
label={"su " + LL.PASSWORD()}
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={data.jwt_secret}
|
value={data.jwt_secret}
|
||||||
@@ -51,7 +55,7 @@ const SecuritySettingsForm: FC = () => {
|
|||||||
/>
|
/>
|
||||||
<MessageBox
|
<MessageBox
|
||||||
level="info"
|
level="info"
|
||||||
message="The su (super user) password is used to sign authentication tokens and also enable admin privileges within the Console."
|
message={LL.SU_TEXT()}
|
||||||
mt={1}
|
mt={1}
|
||||||
/>
|
/>
|
||||||
<ButtonRow>
|
<ButtonRow>
|
||||||
@@ -63,7 +67,7 @@ const SecuritySettingsForm: FC = () => {
|
|||||||
type="submit"
|
type="submit"
|
||||||
onClick={validateAndSubmit}
|
onClick={validateAndSubmit}
|
||||||
>
|
>
|
||||||
Save
|
{LL.SAVE()}
|
||||||
</Button>
|
</Button>
|
||||||
</ButtonRow>
|
</ButtonRow>
|
||||||
</>
|
</>
|
||||||
@@ -71,7 +75,7 @@ const SecuritySettingsForm: FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SectionContent title="Security Settings" titleGutter>
|
<SectionContent title={LL.SECURITY() + " " + LL.SETTINGS()} titleGutter>
|
||||||
{content()}
|
{content()}
|
||||||
</SectionContent>
|
</SectionContent>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import { User } from '../../types';
|
|||||||
import { updateValue } from '../../utils';
|
import { updateValue } from '../../utils';
|
||||||
import { validate } from '../../validators';
|
import { validate } from '../../validators';
|
||||||
|
|
||||||
|
import { useI18nContext } from '../../i18n/i18n-react';
|
||||||
|
|
||||||
interface UserFormProps {
|
interface UserFormProps {
|
||||||
creating: boolean;
|
creating: boolean;
|
||||||
validator: Schema;
|
validator: Schema;
|
||||||
@@ -23,6 +25,8 @@ interface UserFormProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const UserForm: FC<UserFormProps> = ({ creating, validator, user, setUser, onDoneEditing, onCancelEditing }) => {
|
const UserForm: FC<UserFormProps> = ({ creating, validator, user, setUser, onDoneEditing, onCancelEditing }) => {
|
||||||
|
const { LL } = useI18nContext();
|
||||||
|
|
||||||
const updateFormValue = updateValue(setUser);
|
const updateFormValue = updateValue(setUser);
|
||||||
const [fieldErrors, setFieldErrors] = useState<ValidateFieldsError>();
|
const [fieldErrors, setFieldErrors] = useState<ValidateFieldsError>();
|
||||||
const open = !!user;
|
const open = !!user;
|
||||||
@@ -49,12 +53,14 @@ const UserForm: FC<UserFormProps> = ({ creating, validator, user, setUser, onDon
|
|||||||
<Dialog onClose={onCancelEditing} open={!!user} fullWidth maxWidth="sm">
|
<Dialog onClose={onCancelEditing} open={!!user} fullWidth maxWidth="sm">
|
||||||
{user && (
|
{user && (
|
||||||
<>
|
<>
|
||||||
<DialogTitle id="user-form-dialog-title">{creating ? 'Add' : 'Modify'} User</DialogTitle>
|
<DialogTitle id="user-form-dialog-title">
|
||||||
|
{creating ? LL.ADD() : LL.MODIFY()} {LL.USER()}
|
||||||
|
</DialogTitle>
|
||||||
<DialogContent dividers>
|
<DialogContent dividers>
|
||||||
<ValidatedTextField
|
<ValidatedTextField
|
||||||
fieldErrors={fieldErrors}
|
fieldErrors={fieldErrors}
|
||||||
name="username"
|
name="username"
|
||||||
label="Username"
|
label={LL.USERNAME()}
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={user.username}
|
value={user.username}
|
||||||
@@ -65,7 +71,7 @@ const UserForm: FC<UserFormProps> = ({ creating, validator, user, setUser, onDon
|
|||||||
<ValidatedPasswordField
|
<ValidatedPasswordField
|
||||||
fieldErrors={fieldErrors}
|
fieldErrors={fieldErrors}
|
||||||
name="password"
|
name="password"
|
||||||
label="Password"
|
label={LL.PASSWORD()}
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={user.password}
|
value={user.password}
|
||||||
@@ -74,12 +80,12 @@ const UserForm: FC<UserFormProps> = ({ creating, validator, user, setUser, onDon
|
|||||||
/>
|
/>
|
||||||
<BlockFormControlLabel
|
<BlockFormControlLabel
|
||||||
control={<Checkbox name="admin" checked={user.admin} onChange={updateFormValue} />}
|
control={<Checkbox name="admin" checked={user.admin} onChange={updateFormValue} />}
|
||||||
label="is Admin?"
|
label={LL.IS_ADMIN()}
|
||||||
/>
|
/>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<Button startIcon={<CancelIcon />} variant="outlined" onClick={onCancelEditing} color="secondary">
|
<Button startIcon={<CancelIcon />} variant="outlined" onClick={onCancelEditing} color="secondary">
|
||||||
Cancel
|
{LL.CANCEL()}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
startIcon={<PersonAddIcon />}
|
startIcon={<PersonAddIcon />}
|
||||||
@@ -88,7 +94,7 @@ const UserForm: FC<UserFormProps> = ({ creating, validator, user, setUser, onDon
|
|||||||
color="primary"
|
color="primary"
|
||||||
autoFocus
|
autoFocus
|
||||||
>
|
>
|
||||||
Add
|
{LL.ADD()}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ const de: Translation = {
|
|||||||
INVALID_LOGIN: 'Ungültige Login Daten',
|
INVALID_LOGIN: 'Ungültige Login Daten',
|
||||||
NETWORK_CONNECTION: 'Netzwerkverbindung',
|
NETWORK_CONNECTION: 'Netzwerkverbindung',
|
||||||
SECURITY: 'Sicherheit',
|
SECURITY: 'Sicherheit',
|
||||||
NETWORK_TIME: 'Netzwerkzeit',
|
|
||||||
ONOFF_CAP: 'AN/AUS',
|
ONOFF_CAP: 'AN/AUS',
|
||||||
ONOFF: 'an/aus',
|
ONOFF: 'an/aus',
|
||||||
TYPE: 'Typ',
|
TYPE: 'Typ',
|
||||||
@@ -173,7 +172,58 @@ const de: Translation = {
|
|||||||
UPLOADING: 'DE_Uploading',
|
UPLOADING: 'DE_Uploading',
|
||||||
UPLOAD_DROP_TEXT: 'DE_Drop file or click here',
|
UPLOAD_DROP_TEXT: 'DE_Drop file or click here',
|
||||||
ERROR: 'DE_Unexpected Error, please try again',
|
ERROR: 'DE_Unexpected Error, please try again',
|
||||||
TIME_SET: 'DE_Time set'
|
TIME_SET: 'DE_Time set',
|
||||||
|
MANAGE_USERS: 'DE_Manage Users',
|
||||||
|
IS_ADMIN: 'DE_is Admin',
|
||||||
|
USER_WARNING: 'DE_You must have at least one admin user configured',
|
||||||
|
ADD: 'DE_Add',
|
||||||
|
ACCESS_TOKEN_FOR: 'DE_Access Token for',
|
||||||
|
ACCESS_TOKEN_TEXT:
|
||||||
|
'DE_The token below is used with REST API calls that require authorization. It can be passed either as a Bearer token in the Authorization header or in the access_token URL query parameter.',
|
||||||
|
GENERATING_TOKEN: 'DE_Generating token',
|
||||||
|
USER: 'DE_User',
|
||||||
|
MODIFY: 'DE_Modify',
|
||||||
|
SU_TEXT:
|
||||||
|
'DE_The su (super user) password is used to sign authentication tokens and also enable admin privileges within the Console.',
|
||||||
|
NOT_ENABLED: 'DE_Not enabled',
|
||||||
|
ERRORS: 'DE_Errors',
|
||||||
|
DISCONNECT_REASON: 'DE_Disconnect Reason',
|
||||||
|
ENABLE_MQTT: 'DE_Enable MQTT',
|
||||||
|
OPTIONAL: 'DE_Optional',
|
||||||
|
FORMATTING: 'DE_Formatting',
|
||||||
|
FORMAT: 'DE_Format',
|
||||||
|
MQTT_NEST_1: 'DE_Nested in a single topic',
|
||||||
|
MQTT_NEST_2: 'DE_As individual topics',
|
||||||
|
MQTT_RESPONSE: 'DE_Publish command output to a `response` topic',
|
||||||
|
MQTT_PUBLISH_TEXT_1: 'DE_Publish single value topics on change',
|
||||||
|
MQTT_PUBLISH_TEXT_2: 'DE_Publish to command topics (ioBroker)',
|
||||||
|
MQTT_PUBLISH_TEXT_3: 'DE_Enable MQTT Discovery (Home Assistant, Domoticz)',
|
||||||
|
MQTT_PUBLISH_TEXT_4: 'DE_Prefix for the Discovery topics',
|
||||||
|
MQTT_PUBLISH_INTERVALS: 'DE_Publish Intervals',
|
||||||
|
MQTT_INT_BOILER: 'DE_Boilers and Heat Pumps',
|
||||||
|
MQTT_INT_THERMOSTATS: 'DE_Thermostats',
|
||||||
|
MQTT_INT_SOLAR: 'DE_Solar Modules',
|
||||||
|
MQTT_INT_MIXER: 'DE_Mixer Modules',
|
||||||
|
DEFAULT: 'DE_Default',
|
||||||
|
MQTT_CLEAN_SESSION: 'DE_Set Clean Session',
|
||||||
|
MQTT_RETAIN_FLAG: 'DE_Always set Retain flag',
|
||||||
|
INACTIVE: 'DE_Inactive',
|
||||||
|
ACTIVE: 'DE_Active',
|
||||||
|
UNKNOWN: 'DE_Unknown',
|
||||||
|
SET_TIME: 'DE_Set Time',
|
||||||
|
SET_TIME_TEXT: 'DE_Enter local date and time below to set the time.',
|
||||||
|
LOCAL_TIME: 'DE_Local Time',
|
||||||
|
UTC_TIME: 'DE_UTC Time',
|
||||||
|
ENABLE_NTP: 'DE_Enable NTP',
|
||||||
|
TIME_ZONE: 'DE_Time Zone',
|
||||||
|
ACCESS_POINT: 'DE_Access Point',
|
||||||
|
AP_PROVIDE: 'DE_Enable Access Point',
|
||||||
|
AP_PROVIDE_TEXT_1: 'DE_always',
|
||||||
|
AP_PROVIDE_TEXT_2: 'DE_when WiFi is disconnected',
|
||||||
|
AP_PROVIDE_TEXT_3: 'DE_never',
|
||||||
|
AP_PREFERRED_CHANNEL: 'DE_Preferred Channel',
|
||||||
|
AP_HIDE_SSID: 'DE_Hide SSID'
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default de;
|
export default de;
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ const en: BaseTranslation = {
|
|||||||
INVALID_LOGIN: 'Invalid login details',
|
INVALID_LOGIN: 'Invalid login details',
|
||||||
NETWORK_CONNECTION: 'Network Connection',
|
NETWORK_CONNECTION: 'Network Connection',
|
||||||
SECURITY: 'Security',
|
SECURITY: 'Security',
|
||||||
NETWORK_TIME: 'Network Time',
|
|
||||||
ONOFF_CAP: 'ON/OFF',
|
ONOFF_CAP: 'ON/OFF',
|
||||||
ONOFF: 'on/off',
|
ONOFF: 'on/off',
|
||||||
TYPE: 'Type',
|
TYPE: 'Type',
|
||||||
@@ -173,7 +172,57 @@ const en: BaseTranslation = {
|
|||||||
UPLOADING: 'Uploading',
|
UPLOADING: 'Uploading',
|
||||||
UPLOAD_DROP_TEXT: 'Drop file or click here',
|
UPLOAD_DROP_TEXT: 'Drop file or click here',
|
||||||
ERROR: 'Unexpected Error, please try again',
|
ERROR: 'Unexpected Error, please try again',
|
||||||
TIME_SET: 'Time set'
|
TIME_SET: 'Time set',
|
||||||
|
MANAGE_USERS: 'Manage Users',
|
||||||
|
IS_ADMIN: 'is Admin',
|
||||||
|
USER_WARNING: 'You must have at least one admin user configured',
|
||||||
|
ADD: 'Add',
|
||||||
|
ACCESS_TOKEN_FOR: 'Access Token for',
|
||||||
|
ACCESS_TOKEN_TEXT:
|
||||||
|
'The token below is used with REST API calls that require authorization. It can be passed either as a Bearer token in the Authorization header or in the access_token URL query parameter.',
|
||||||
|
GENERATING_TOKEN: 'Generating token',
|
||||||
|
USER: 'User',
|
||||||
|
MODIFY: 'Modify',
|
||||||
|
SU_TEXT:
|
||||||
|
'The su (super user) password is used to sign authentication tokens and also enable admin privileges within the Console.',
|
||||||
|
NOT_ENABLED: 'Not enabled',
|
||||||
|
ERRORS: 'Errors',
|
||||||
|
DISCONNECT_REASON: 'Disconnect Reason',
|
||||||
|
ENABLE_MQTT: 'Enable MQTT',
|
||||||
|
OPTIONAL: 'Optional',
|
||||||
|
FORMATTING: 'Formatting',
|
||||||
|
FORMAT: 'Format',
|
||||||
|
MQTT_NEST_1: 'Nested in a single topic',
|
||||||
|
MQTT_NEST_2: 'As individual topics',
|
||||||
|
MQTT_RESPONSE: 'Publish command output to a `response` topic',
|
||||||
|
MQTT_PUBLISH_TEXT_1: 'Publish single value topics on change',
|
||||||
|
MQTT_PUBLISH_TEXT_2: 'Publish to command topics (ioBroker)',
|
||||||
|
MQTT_PUBLISH_TEXT_3: 'Enable MQTT Discovery (Home Assistant, Domoticz)',
|
||||||
|
MQTT_PUBLISH_TEXT_4: 'Prefix for the Discovery topics',
|
||||||
|
MQTT_PUBLISH_INTERVALS: 'Publish Intervals',
|
||||||
|
MQTT_INT_BOILER: 'Boilers and Heat Pumps',
|
||||||
|
MQTT_INT_THERMOSTATS: 'Thermostats',
|
||||||
|
MQTT_INT_SOLAR: 'Solar Modules',
|
||||||
|
MQTT_INT_MIXER: 'Mixer Modules',
|
||||||
|
DEFAULT: 'Default',
|
||||||
|
MQTT_CLEAN_SESSION: 'Set Clean Session',
|
||||||
|
MQTT_RETAIN_FLAG: 'Always set Retain flag',
|
||||||
|
INACTIVE: 'Inactive',
|
||||||
|
ACTIVE: 'Active',
|
||||||
|
UNKNOWN: 'Unknown',
|
||||||
|
SET_TIME: 'Set Time',
|
||||||
|
SET_TIME_TEXT: 'Enter local date and time below to set the time.',
|
||||||
|
LOCAL_TIME: 'Local Time',
|
||||||
|
UTC_TIME: 'UTC Time',
|
||||||
|
ENABLE_NTP: 'Enable NTP',
|
||||||
|
TIME_ZONE: 'Time Zone',
|
||||||
|
ACCESS_POINT: 'Access Point',
|
||||||
|
AP_PROVIDE: 'Enable Access Point',
|
||||||
|
AP_PROVIDE_TEXT_1: 'always',
|
||||||
|
AP_PROVIDE_TEXT_2: 'when WiFi is disconnected',
|
||||||
|
AP_PROVIDE_TEXT_3: 'never',
|
||||||
|
AP_PREFERRED_CHANNEL: 'Preferred Channel',
|
||||||
|
AP_HIDE_SSID: 'Hide SSID'
|
||||||
};
|
};
|
||||||
|
|
||||||
export default en;
|
export default en;
|
||||||
|
|||||||
@@ -83,10 +83,6 @@ type RootTranslation = {
|
|||||||
* Security
|
* Security
|
||||||
*/
|
*/
|
||||||
SECURITY: string
|
SECURITY: string
|
||||||
/**
|
|
||||||
* Network Time
|
|
||||||
*/
|
|
||||||
NETWORK_TIME: string
|
|
||||||
/**
|
/**
|
||||||
* ON/OFF
|
* ON/OFF
|
||||||
*/
|
*/
|
||||||
@@ -695,6 +691,198 @@ type RootTranslation = {
|
|||||||
* Time set
|
* Time set
|
||||||
*/
|
*/
|
||||||
TIME_SET: string
|
TIME_SET: string
|
||||||
|
/**
|
||||||
|
* Manage Users
|
||||||
|
*/
|
||||||
|
MANAGE_USERS: string
|
||||||
|
/**
|
||||||
|
* is Admin
|
||||||
|
*/
|
||||||
|
IS_ADMIN: string
|
||||||
|
/**
|
||||||
|
* You must have at least one admin user configured
|
||||||
|
*/
|
||||||
|
USER_WARNING: string
|
||||||
|
/**
|
||||||
|
* Add
|
||||||
|
*/
|
||||||
|
ADD: string
|
||||||
|
/**
|
||||||
|
* Access Token for
|
||||||
|
*/
|
||||||
|
ACCESS_TOKEN_FOR: string
|
||||||
|
/**
|
||||||
|
* The token below is used with REST API calls that require authorization. It can be passed either as a Bearer token in the Authorization header or in the access_token URL query parameter.
|
||||||
|
*/
|
||||||
|
ACCESS_TOKEN_TEXT: string
|
||||||
|
/**
|
||||||
|
* Generating token
|
||||||
|
*/
|
||||||
|
GENERATING_TOKEN: string
|
||||||
|
/**
|
||||||
|
* User
|
||||||
|
*/
|
||||||
|
USER: string
|
||||||
|
/**
|
||||||
|
* Modify
|
||||||
|
*/
|
||||||
|
MODIFY: string
|
||||||
|
/**
|
||||||
|
* The su (super user) password is used to sign authentication tokens and also enable admin privileges within the Console.
|
||||||
|
*/
|
||||||
|
SU_TEXT: string
|
||||||
|
/**
|
||||||
|
* Not enabled
|
||||||
|
*/
|
||||||
|
NOT_ENABLED: string
|
||||||
|
/**
|
||||||
|
* Errors
|
||||||
|
*/
|
||||||
|
ERRORS: string
|
||||||
|
/**
|
||||||
|
* Disconnect Reason
|
||||||
|
*/
|
||||||
|
DISCONNECT_REASON: string
|
||||||
|
/**
|
||||||
|
* Enable MQTT
|
||||||
|
*/
|
||||||
|
ENABLE_MQTT: string
|
||||||
|
/**
|
||||||
|
* Optional
|
||||||
|
*/
|
||||||
|
OPTIONAL: string
|
||||||
|
/**
|
||||||
|
* Formatting
|
||||||
|
*/
|
||||||
|
FORMATTING: string
|
||||||
|
/**
|
||||||
|
* Format
|
||||||
|
*/
|
||||||
|
FORMAT: string
|
||||||
|
/**
|
||||||
|
* Nested in a single topic
|
||||||
|
*/
|
||||||
|
MQTT_NEST_1: string
|
||||||
|
/**
|
||||||
|
* As individual topics
|
||||||
|
*/
|
||||||
|
MQTT_NEST_2: string
|
||||||
|
/**
|
||||||
|
* Publish command output to a `response` topic
|
||||||
|
*/
|
||||||
|
MQTT_RESPONSE: string
|
||||||
|
/**
|
||||||
|
* Publish single value topics on change
|
||||||
|
*/
|
||||||
|
MQTT_PUBLISH_TEXT_1: string
|
||||||
|
/**
|
||||||
|
* Publish to command topics (ioBroker)
|
||||||
|
*/
|
||||||
|
MQTT_PUBLISH_TEXT_2: string
|
||||||
|
/**
|
||||||
|
* Enable MQTT Discovery (Home Assistant, Domoticz)
|
||||||
|
*/
|
||||||
|
MQTT_PUBLISH_TEXT_3: string
|
||||||
|
/**
|
||||||
|
* Prefix for the Discovery topics
|
||||||
|
*/
|
||||||
|
MQTT_PUBLISH_TEXT_4: string
|
||||||
|
/**
|
||||||
|
* Publish Intervals
|
||||||
|
*/
|
||||||
|
MQTT_PUBLISH_INTERVALS: string
|
||||||
|
/**
|
||||||
|
* Boilers and Heat Pumps
|
||||||
|
*/
|
||||||
|
MQTT_INT_BOILER: string
|
||||||
|
/**
|
||||||
|
* Thermostats
|
||||||
|
*/
|
||||||
|
MQTT_INT_THERMOSTATS: string
|
||||||
|
/**
|
||||||
|
* Solar Modules
|
||||||
|
*/
|
||||||
|
MQTT_INT_SOLAR: string
|
||||||
|
/**
|
||||||
|
* Mixer Modules
|
||||||
|
*/
|
||||||
|
MQTT_INT_MIXER: string
|
||||||
|
/**
|
||||||
|
* Default
|
||||||
|
*/
|
||||||
|
DEFAULT: string
|
||||||
|
/**
|
||||||
|
* Set Clean Session
|
||||||
|
*/
|
||||||
|
MQTT_CLEAN_SESSION: string
|
||||||
|
/**
|
||||||
|
* Always set Retain flag
|
||||||
|
*/
|
||||||
|
MQTT_RETAIN_FLAG: string
|
||||||
|
/**
|
||||||
|
* Inactive
|
||||||
|
*/
|
||||||
|
INACTIVE: string
|
||||||
|
/**
|
||||||
|
* Active
|
||||||
|
*/
|
||||||
|
ACTIVE: string
|
||||||
|
/**
|
||||||
|
* Unknown
|
||||||
|
*/
|
||||||
|
UNKNOWN: string
|
||||||
|
/**
|
||||||
|
* Set Time
|
||||||
|
*/
|
||||||
|
SET_TIME: string
|
||||||
|
/**
|
||||||
|
* Enter local date and time below to set the time.
|
||||||
|
*/
|
||||||
|
SET_TIME_TEXT: string
|
||||||
|
/**
|
||||||
|
* Local Time
|
||||||
|
*/
|
||||||
|
LOCAL_TIME: string
|
||||||
|
/**
|
||||||
|
* UTC Time
|
||||||
|
*/
|
||||||
|
UTC_TIME: string
|
||||||
|
/**
|
||||||
|
* Enable NTP
|
||||||
|
*/
|
||||||
|
ENABLE_NTP: string
|
||||||
|
/**
|
||||||
|
* Time Zone
|
||||||
|
*/
|
||||||
|
TIME_ZONE: string
|
||||||
|
/**
|
||||||
|
* Access Point
|
||||||
|
*/
|
||||||
|
ACCESS_POINT: string
|
||||||
|
/**
|
||||||
|
* Enable Access Point
|
||||||
|
*/
|
||||||
|
AP_PROVIDE: string
|
||||||
|
/**
|
||||||
|
* always
|
||||||
|
*/
|
||||||
|
AP_PROVIDE_TEXT_1: string
|
||||||
|
/**
|
||||||
|
* when WiFi is disconnected
|
||||||
|
*/
|
||||||
|
AP_PROVIDE_TEXT_2: string
|
||||||
|
/**
|
||||||
|
* never
|
||||||
|
*/
|
||||||
|
AP_PROVIDE_TEXT_3: string
|
||||||
|
/**
|
||||||
|
* Preferred Channel
|
||||||
|
*/
|
||||||
|
AP_PREFERRED_CHANNEL: string
|
||||||
|
/**
|
||||||
|
* Hide SSID
|
||||||
|
*/
|
||||||
|
AP_HIDE_SSID: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TranslationFunctions = {
|
export type TranslationFunctions = {
|
||||||
@@ -766,10 +954,6 @@ export type TranslationFunctions = {
|
|||||||
* Security
|
* Security
|
||||||
*/
|
*/
|
||||||
SECURITY: () => LocalizedString
|
SECURITY: () => LocalizedString
|
||||||
/**
|
|
||||||
* Network Time
|
|
||||||
*/
|
|
||||||
NETWORK_TIME: () => LocalizedString
|
|
||||||
/**
|
/**
|
||||||
* ON/OFF
|
* ON/OFF
|
||||||
*/
|
*/
|
||||||
@@ -1368,6 +1552,198 @@ export type TranslationFunctions = {
|
|||||||
* Time set
|
* Time set
|
||||||
*/
|
*/
|
||||||
TIME_SET: () => LocalizedString
|
TIME_SET: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Manage Users
|
||||||
|
*/
|
||||||
|
MANAGE_USERS: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* is Admin
|
||||||
|
*/
|
||||||
|
IS_ADMIN: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* You must have at least one admin user configured
|
||||||
|
*/
|
||||||
|
USER_WARNING: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Add
|
||||||
|
*/
|
||||||
|
ADD: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Access Token for
|
||||||
|
*/
|
||||||
|
ACCESS_TOKEN_FOR: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* The token below is used with REST API calls that require authorization. It can be passed either as a Bearer token in the Authorization header or in the access_token URL query parameter.
|
||||||
|
*/
|
||||||
|
ACCESS_TOKEN_TEXT: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Generating token
|
||||||
|
*/
|
||||||
|
GENERATING_TOKEN: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* User
|
||||||
|
*/
|
||||||
|
USER: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Modify
|
||||||
|
*/
|
||||||
|
MODIFY: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* The su (super user) password is used to sign authentication tokens and also enable admin privileges within the Console.
|
||||||
|
*/
|
||||||
|
SU_TEXT: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Not enabled
|
||||||
|
*/
|
||||||
|
NOT_ENABLED: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Errors
|
||||||
|
*/
|
||||||
|
ERRORS: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Disconnect Reason
|
||||||
|
*/
|
||||||
|
DISCONNECT_REASON: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Enable MQTT
|
||||||
|
*/
|
||||||
|
ENABLE_MQTT: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Optional
|
||||||
|
*/
|
||||||
|
OPTIONAL: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Formatting
|
||||||
|
*/
|
||||||
|
FORMATTING: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Format
|
||||||
|
*/
|
||||||
|
FORMAT: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Nested in a single topic
|
||||||
|
*/
|
||||||
|
MQTT_NEST_1: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* As individual topics
|
||||||
|
*/
|
||||||
|
MQTT_NEST_2: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Publish command output to a `response` topic
|
||||||
|
*/
|
||||||
|
MQTT_RESPONSE: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Publish single value topics on change
|
||||||
|
*/
|
||||||
|
MQTT_PUBLISH_TEXT_1: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Publish to command topics (ioBroker)
|
||||||
|
*/
|
||||||
|
MQTT_PUBLISH_TEXT_2: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Enable MQTT Discovery (Home Assistant, Domoticz)
|
||||||
|
*/
|
||||||
|
MQTT_PUBLISH_TEXT_3: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Prefix for the Discovery topics
|
||||||
|
*/
|
||||||
|
MQTT_PUBLISH_TEXT_4: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Publish Intervals
|
||||||
|
*/
|
||||||
|
MQTT_PUBLISH_INTERVALS: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Boilers and Heat Pumps
|
||||||
|
*/
|
||||||
|
MQTT_INT_BOILER: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Thermostats
|
||||||
|
*/
|
||||||
|
MQTT_INT_THERMOSTATS: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Solar Modules
|
||||||
|
*/
|
||||||
|
MQTT_INT_SOLAR: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Mixer Modules
|
||||||
|
*/
|
||||||
|
MQTT_INT_MIXER: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Default
|
||||||
|
*/
|
||||||
|
DEFAULT: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Set Clean Session
|
||||||
|
*/
|
||||||
|
MQTT_CLEAN_SESSION: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Always set Retain flag
|
||||||
|
*/
|
||||||
|
MQTT_RETAIN_FLAG: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Inactive
|
||||||
|
*/
|
||||||
|
INACTIVE: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Active
|
||||||
|
*/
|
||||||
|
ACTIVE: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Unknown
|
||||||
|
*/
|
||||||
|
UNKNOWN: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Set Time
|
||||||
|
*/
|
||||||
|
SET_TIME: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Enter local date and time below to set the time.
|
||||||
|
*/
|
||||||
|
SET_TIME_TEXT: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Local Time
|
||||||
|
*/
|
||||||
|
LOCAL_TIME: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* UTC Time
|
||||||
|
*/
|
||||||
|
UTC_TIME: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Enable NTP
|
||||||
|
*/
|
||||||
|
ENABLE_NTP: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Time Zone
|
||||||
|
*/
|
||||||
|
TIME_ZONE: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Access Point
|
||||||
|
*/
|
||||||
|
ACCESS_POINT: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Enable Access Point
|
||||||
|
*/
|
||||||
|
AP_PROVIDE: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* always
|
||||||
|
*/
|
||||||
|
AP_PROVIDE_TEXT_1: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* when WiFi is disconnected
|
||||||
|
*/
|
||||||
|
AP_PROVIDE_TEXT_2: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* never
|
||||||
|
*/
|
||||||
|
AP_PROVIDE_TEXT_3: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Preferred Channel
|
||||||
|
*/
|
||||||
|
AP_PREFERRED_CHANNEL: () => LocalizedString
|
||||||
|
/**
|
||||||
|
* Hide SSID
|
||||||
|
*/
|
||||||
|
AP_HIDE_SSID: () => LocalizedString
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Formatters = {}
|
export type Formatters = {}
|
||||||
|
|||||||
Reference in New Issue
Block a user