updates to web pages

This commit is contained in:
proddy
2024-03-17 23:23:09 +01:00
parent 20ddbeb709
commit 1af103d5ee
22 changed files with 121 additions and 142 deletions

View File

@@ -84,5 +84,8 @@
"**/*.map",
"**/ArduinoJson/**"
],
"cSpell.enableFiletypes": ["!cpp"]
"cSpell.enableFiletypes": [
"!cpp",
"!typescript"
]
}

View File

@@ -1,7 +1,8 @@
import { useContext, type FC } from 'react';
import { Navigate, Routes, Route } from 'react-router-dom';
import Help from './project/Help';
import type { FC } from 'react';
import { Layout, RequireAdmin } from 'components';
import { Layout } from 'components';
import { AuthenticatedContext } from 'contexts/authentication';
import Settings from 'framework/Settings';
import AccessPoint from 'framework/ap/AccessPoint';
import Mqtt from 'framework/mqtt/Mqtt';
@@ -18,49 +19,35 @@ import Devices from 'project/Devices';
import Scheduler from 'project/Scheduler';
import Sensors from 'project/Sensors';
const AuthenticatedRouting: FC = () => (
<Layout>
<Routes>
<Route path="/devices/*" element={<Devices />} />
<Route path="/sensors/*" element={<Sensors />} />
<Route path="/customizations/*" element={<Customization />} />
<Route path="/scheduler/*" element={<Scheduler />} />
<Route path="/customentities/*" element={<CustomEntities />} />
{/* TODO only show the rest here if admin */}
<Route path="/status/*" element={<Status />} />
<Route
path="settings/*"
element={
<RequireAdmin>
<Settings />
</RequireAdmin>
}
/>
<Route path="/settings/network/*" element={<NetworkConnection />} />
<Route path="/settings/ems-esp/*" element={<ApplicationSettings />} />
<Route path="/settings/ap/*" element={<AccessPoint />} />
<Route path="/settings/ntp/*" element={<NetworkTime />} />
<Route path="/settings/mqtt/*" element={<Mqtt />} />
<Route path="/settings/ota/*" element={<OTASettingsForm />} />
<Route
path="/settings/security/*"
element={
<RequireAdmin>
<Security />
</RequireAdmin>
}
/>
<Route path="/settings/upload/*" element={<UploadDownload />} />
<Route path="/help/*" element={<Help />} />
<Route path="/*" element={<Navigate to="/" />} />
</Routes>
</Layout>
);
const AuthenticatedRouting: FC = () => {
const { me } = useContext(AuthenticatedContext);
return (
<Layout>
<Routes>
<Route path="/devices/*" element={<Devices />} />
<Route path="/sensors/*" element={<Sensors />} />
<Route path="/status/*" element={<Status />} />
<Route path="/help/*" element={<Help />} />
<Route path="/*" element={<Navigate to="/" />} />
{me.admin && (
<>
<Route path="/customizations/*" element={<Customization />} />
<Route path="/scheduler/*" element={<Scheduler />} />
<Route path="/customentities/*" element={<CustomEntities />} />
<Route path="/settings/*" element={<Settings />} />
<Route path="/settings/network/*" element={<NetworkConnection />} />
<Route path="/settings/ems-esp/*" element={<ApplicationSettings />} />
<Route path="/settings/ap/*" element={<AccessPoint />} />
<Route path="/settings/ntp/*" element={<NetworkTime />} />
<Route path="/settings/mqtt/*" element={<Mqtt />} />
<Route path="/settings/ota/*" element={<OTASettingsForm />} />
<Route path="/settings/security/*" element={<Security />} />
<Route path="/settings/upload/*" element={<UploadDownload />} />
</>
)}
</Routes>
</Layout>
);
};
export default AuthenticatedRouting;

View File

@@ -2,7 +2,7 @@ import AccountCircleIcon from '@mui/icons-material/AccountCircle';
import AssessmentIcon from '@mui/icons-material/Assessment';
import CategoryIcon from '@mui/icons-material/Category';
import ConstructionIcon from '@mui/icons-material/Construction';
import InfoIcon from '@mui/icons-material/Info';
import LiveHelpIcon from '@mui/icons-material/LiveHelp';
import MoreTimeIcon from '@mui/icons-material/MoreTime';
import PersonIcon from '@mui/icons-material/Person';
import PlaylistAddIcon from '@mui/icons-material/PlaylistAdd';
@@ -73,14 +73,24 @@ const LayoutMenu: FC = () => {
<LayoutMenuItem icon={CategoryIcon} label={LL.DEVICES()} to={`/devices`} />
<LayoutMenuItem icon={SensorsIcon} label={LL.SENSORS()} to={`/sensors`} />
<Divider />
<LayoutMenuItem icon={ConstructionIcon} label={LL.CUSTOMIZATIONS()} to={`/customizations`} />
<LayoutMenuItem icon={MoreTimeIcon} label={LL.SCHEDULER()} to={`/scheduler`} />
<LayoutMenuItem icon={PlaylistAddIcon} label={LL.CUSTOM_ENTITIES(0)} to={`/customentities`} />
<LayoutMenuItem
icon={ConstructionIcon}
label={LL.CUSTOMIZATIONS()}
disabled={!me.admin}
to={`/customizations`}
/>
<LayoutMenuItem icon={MoreTimeIcon} label={LL.SCHEDULER()} disabled={!me.admin} to={`/scheduler`} />
<LayoutMenuItem
icon={PlaylistAddIcon}
label={LL.CUSTOM_ENTITIES(0)}
disabled={!me.admin}
to={`/customentities`}
/>
</List>
<List style={{ marginTop: `auto` }}>
<LayoutMenuItem icon={AssessmentIcon} label={LL.STATUS_OF('')} to="/status" />
<LayoutMenuItem icon={SettingsIcon} label={LL.SETTINGS(0)} disabled={!me.admin} to="/settings" />
<LayoutMenuItem icon={InfoIcon} label={LL.HELP_OF('')} to={`/help`} />
<LayoutMenuItem icon={LiveHelpIcon} label={LL.HELP_OF('')} to={`/help`} />
</List>
<Divider />
<List>

View File

@@ -1,12 +1,10 @@
import { Tab } from '@mui/material';
import { useContext } from 'react';
import { Navigate, Routes, Route } from 'react-router-dom';
import APSettingsForm from './APSettingsForm';
import APStatusForm from './APStatusForm';
import type { FC } from 'react';
import { RequireAdmin, RouterTabs, useLayoutTitle, useRouterTab } from 'components';
import { AuthenticatedContext } from 'contexts/authentication';
import { useI18nContext } from 'i18n/i18n-react';
@@ -15,14 +13,12 @@ const AccessPoint: FC = () => {
useLayoutTitle(LL.ACCESS_POINT(0));
const authenticatedContext = useContext(AuthenticatedContext);
const { routerTab } = useRouterTab();
return (
<>
<RouterTabs value={routerTab}>
<Tab value="settings" label={LL.SETTINGS_OF(LL.ACCESS_POINT(1))} disabled={!authenticatedContext.me.admin} />
<Tab value="settings" label={LL.SETTINGS_OF(LL.ACCESS_POINT(1))} />
<Tab value="status" label={LL.STATUS_OF(LL.ACCESS_POINT(1))} />
</RouterTabs>
<Routes>

View File

@@ -1,12 +1,10 @@
import { Tab } from '@mui/material';
import { useContext } from 'react';
import { Navigate, Route, Routes } from 'react-router-dom';
import MqttSettingsForm from './MqttSettingsForm';
import MqttStatusForm from './MqttStatusForm';
import type { FC } from 'react';
import { RequireAdmin, RouterTabs, useLayoutTitle, useRouterTab } from 'components';
import { AuthenticatedContext } from 'contexts/authentication';
import { useI18nContext } from 'i18n/i18n-react';
@@ -15,13 +13,12 @@ const Mqtt: FC = () => {
useLayoutTitle('MQTT');
const authenticatedContext = useContext(AuthenticatedContext);
const { routerTab } = useRouterTab();
return (
<>
<RouterTabs value={routerTab}>
<Tab value="settings" label={LL.SETTINGS_OF('MQTT')} disabled={!authenticatedContext.me.admin} />
<Tab value="settings" label={LL.SETTINGS_OF('MQTT')} />
<Tab value="status" label={LL.STATUS_OF('MQTT')} />
</RouterTabs>
<Routes>

View File

@@ -1,5 +1,5 @@
import { Tab } from '@mui/material';
import { useCallback, useContext, useState } from 'react';
import { useCallback, useState } from 'react';
import { Navigate, Routes, Route, useNavigate } from 'react-router-dom';
import NetworkSettingsForm from './NetworkSettingsForm';
import NetworkStatusForm from './NetworkStatusForm';
@@ -9,7 +9,6 @@ import type { FC } from 'react';
import type { WiFiNetwork } from 'types';
import { RequireAdmin, RouterTabs, useLayoutTitle, useRouterTab } from 'components';
import { AuthenticatedContext } from 'contexts/authentication';
import { useI18nContext } from 'i18n/i18n-react';
const NetworkConnection: FC = () => {
@@ -18,7 +17,6 @@ const NetworkConnection: FC = () => {
const { routerTab } = useRouterTab();
const authenticatedContext = useContext(AuthenticatedContext);
const navigate = useNavigate();
const [selectedNetwork, setSelectedNetwork] = useState<WiFiNetwork>();
@@ -44,8 +42,8 @@ const NetworkConnection: FC = () => {
}}
>
<RouterTabs value={routerTab}>
<Tab value="settings" label={LL.SETTINGS_OF(LL.NETWORK(1))} disabled={!authenticatedContext.me.admin} />
<Tab value="scan" label={LL.NETWORK_SCAN()} disabled={!authenticatedContext.me.admin} />
<Tab value="settings" label={LL.SETTINGS_OF(LL.NETWORK(1))} />
<Tab value="scan" label={LL.NETWORK_SCAN()} />
<Tab value="status" label={LL.STATUS_OF(LL.NETWORK(1))} />
</RouterTabs>
<Routes>

View File

@@ -22,7 +22,7 @@ import {
Typography
} from '@mui/material';
import { useRequest } from 'alova';
import { useContext, useState } from 'react';
import { useState } from 'react';
import { toast } from 'react-toastify';
import type { Theme } from '@mui/material';
import type { FC } from 'react';
@@ -31,7 +31,6 @@ import type { NTPStatus } from 'types';
import { dialogStyle } from 'CustomTheme';
import * as NTPApi from 'api/ntp';
import { ButtonRow, FormLoader, SectionContent } from 'components';
import { AuthenticatedContext } from 'contexts/authentication';
import { useI18nContext } from 'i18n/i18n-react';
import { NTPSyncStatus } from 'types';
@@ -59,7 +58,6 @@ const NTPStatusForm: FC = () => {
const [localTime, setLocalTime] = useState<string>('');
const [settingTime, setSettingTime] = useState<boolean>(false);
const [processing, setProcessing] = useState<boolean>(false);
const { me } = useContext(AuthenticatedContext);
const { LL } = useI18nContext();
@@ -201,7 +199,7 @@ const NTPStatusForm: FC = () => {
</Button>
</ButtonRow>
</Box>
{me.admin && data && !isNtpActive(data) && (
{data && !isNtpActive(data) && (
<Box flexWrap="nowrap" whiteSpace="nowrap">
<ButtonRow>
<Button onClick={openSetTime} variant="outlined" color="primary" startIcon={<AccessTimeIcon />}>

View File

@@ -1,12 +1,10 @@
import { Tab } from '@mui/material';
import { useContext } from 'react';
import { Navigate, Route, Routes } from 'react-router-dom';
import NTPSettingsForm from './NTPSettingsForm';
import NTPStatusForm from './NTPStatusForm';
import type { FC } from 'react';
import { RequireAdmin, RouterTabs, useLayoutTitle, useRouterTab } from 'components';
import { AuthenticatedContext } from 'contexts/authentication';
import { useI18nContext } from 'i18n/i18n-react';
@@ -14,13 +12,12 @@ const NetworkTime: FC = () => {
const { LL } = useI18nContext();
useLayoutTitle('NTP');
const authenticatedContext = useContext(AuthenticatedContext);
const { routerTab } = useRouterTab();
return (
<>
<RouterTabs value={routerTab}>
<Tab value="settings" label={LL.SETTINGS_OF('NTP')} disabled={!authenticatedContext.me.admin} />
<Tab value="settings" label={LL.SETTINGS_OF('NTP')} />
<Tab value="status" label={LL.STATUS_OF('NTP')} />
</RouterTabs>
<Routes>

View File

@@ -8,8 +8,8 @@ import type { FC } from 'react';
import type { SecuritySettings } from 'types';
import * as SecurityApi from 'api/security';
import { ButtonRow, FormLoader, MessageBox, SectionContent, ValidatedPasswordField, BlockNavigation } from 'components';
import { AuthenticatedContext } from 'contexts/authentication';
import { AuthenticatedContext } from 'contexts/authentication';
import { useI18nContext } from 'i18n/i18n-react';
import { updateValueDirty, useRest } from 'utils';
import { SECURITY_SETTINGS_VALIDATOR, validate } from 'validators';

View File

@@ -232,7 +232,7 @@ const SystemLog: FC = () => {
};
return (
<SectionContent title={LL.LOG_OF(LL.SYSTEM(2))} titleGutter id="log-window">
<SectionContent title={LL.LOG_OF(LL.SYSTEM(2))} id="log-window">
{blocker ? <BlockNavigation blocker={blocker} /> : null}
{content()}
</SectionContent>

View File

@@ -46,13 +46,14 @@ function formatNumber(num: number) {
const SystemStatusForm: FC = () => {
const { LL } = useI18nContext();
const { me } = useContext(AuthenticatedContext);
const [confirmRestart, setConfirmRestart] = useState<boolean>(false);
const [confirmFactoryReset, setConfirmFactoryReset] = useState<boolean>(false);
const [processing, setProcessing] = useState<boolean>(false);
const [restarting, setRestarting] = useState<boolean>();
const [versionDialogOpen, setVersionDialogOpen] = useState<boolean>(false);
const { me } = useContext(AuthenticatedContext);
const { send: restartCommand } = useRequest(SystemApi.restart(), {
immediate: false
});
@@ -187,7 +188,7 @@ const SystemStatusForm: FC = () => {
<List>
<ListItem>
<ListItemAvatar>
<Avatar>
<Avatar sx={{ bgcolor: '#5f9a5f', color: 'white' }}>
<BuildIcon />
</Avatar>
</ListItemAvatar>
@@ -199,7 +200,7 @@ const SystemStatusForm: FC = () => {
<Divider variant="inset" component="li" />
<ListItem>
<ListItemAvatar>
<Avatar>
<Avatar sx={{ bgcolor: '#5f9a5f', color: 'white' }}>
<TimerIcon />
</Avatar>
</ListItemAvatar>
@@ -208,7 +209,7 @@ const SystemStatusForm: FC = () => {
<Divider variant="inset" component="li" />
<ListItem>
<ListItemAvatar>
<Avatar>
<Avatar sx={{ bgcolor: '#5f9a5f', color: 'white' }}>
<DevicesIcon />
</Avatar>
</ListItemAvatar>
@@ -217,7 +218,7 @@ const SystemStatusForm: FC = () => {
<Divider variant="inset" component="li" />
<ListItem>
<ListItemAvatar>
<Avatar>
<Avatar sx={{ bgcolor: '#5f9a5f', color: 'white' }}>
<DeveloperBoardIcon />
</Avatar>
</ListItemAvatar>
@@ -240,7 +241,7 @@ const SystemStatusForm: FC = () => {
<Divider variant="inset" component="li" />
<ListItem>
<ListItemAvatar>
<Avatar>
<Avatar sx={{ bgcolor: '#5f9a5f', color: 'white' }}>
<MemoryIcon />
</Avatar>
</ListItemAvatar>
@@ -254,7 +255,7 @@ const SystemStatusForm: FC = () => {
<Divider variant="inset" component="li" />
<ListItem>
<ListItemAvatar>
<Avatar>
<Avatar sx={{ bgcolor: '#5f9a5f', color: 'white' }}>
<AppsIcon />
</Avatar>
</ListItemAvatar>
@@ -268,7 +269,7 @@ const SystemStatusForm: FC = () => {
<Divider variant="inset" component="li" />
<ListItem>
<ListItemAvatar>
<Avatar>
<Avatar sx={{ bgcolor: '#5f9a5f', color: 'white' }}>
<SdStorageIcon />
</Avatar>
</ListItemAvatar>
@@ -282,7 +283,7 @@ const SystemStatusForm: FC = () => {
<Divider variant="inset" component="li" />
<ListItem>
<ListItemAvatar>
<Avatar>
<Avatar sx={{ bgcolor: '#5f9a5f', color: 'white' }}>
<SdCardAlertIcon />
</Avatar>
</ListItemAvatar>
@@ -296,7 +297,7 @@ const SystemStatusForm: FC = () => {
<Divider variant="inset" component="li" />
<ListItem>
<ListItemAvatar>
<Avatar>
<Avatar sx={{ bgcolor: '#5f9a5f', color: 'white' }}>
<FolderIcon />
</Avatar>
</ListItemAvatar>

View File

@@ -31,7 +31,7 @@ const SystemStatusVersionDialog = ({ open, onClose, version, platform }: SystemS
const STABLE_RELNOTES_URL = 'https://github.com/emsesp/EMS-ESP32/blob/main/CHANGELOG.md';
const DEV_RELNOTES_URL = 'https://github.com/emsesp/EMS-ESP32/blob/dev/CHANGELOG_LATEST.md';
const uploadURL = window.location.origin + '/system/upload';
const uploadURL = window.location.origin + '/settings/upload';
const connected = latestVersion && latestDevVersion;

View File

@@ -153,11 +153,6 @@ const UploadDownload: FC = () => {
<Typography sx={{ pt: 4, pb: 2 }} variant="h6" color="primary">
{LL.DOWNLOAD(0)}&nbsp;{LL.SUPPORT_INFORMATION(1)}
</Typography>
<Box color="warning.main">
<Typography mb={1} variant="body2">
{LL.HELP_INFORMATION_4()}
</Typography>
</Box>
<Button
startIcon={<DownloadIcon />}
variant="outlined"
@@ -216,7 +211,7 @@ const UploadDownload: FC = () => {
)}
</>
);
return <SectionContent title={LL.UPLOAD_DOWNLOAD()}>{restarting ? <RestartMonitor /> : content()}</SectionContent>;
return <SectionContent>{restarting ? <RestartMonitor /> : content()}</SectionContent>;
};
export default UploadDownload;

View File

@@ -155,7 +155,7 @@ const en: Translation = {
CUSTOMIZATIONS_HELP_4: 'exclude from MQTT and API',
CUSTOMIZATIONS_HELP_5: 'hide from Dashboard',
CUSTOMIZATIONS_HELP_6: 'remove from memory',
SELECT_DEVICE: 'Select a device',
SELECT_DEVICE: 'select a device',
SET_ALL: 'set all',
OPTIONS: 'Options',
NAME: 'Name',

View File

@@ -1,12 +1,13 @@
import PlaylistAddIcon from '@mui/icons-material/PlaylistAdd';
import { AiOutlineControl, AiOutlineGateway, AiOutlineAlert } from 'react-icons/ai';
import { CgSmartHomeBoiler } from 'react-icons/cg';
import { FaSolarPanel } from 'react-icons/fa';
import { GiHeatHaze } from 'react-icons/gi';
import { MdThermostatAuto, MdOutlineSensors, MdOutlineExtension, MdOutlineDevices } from 'react-icons/md';
import { MdThermostatAuto, MdOutlineSensors, MdOutlineDevices } from 'react-icons/md';
import { TiFlowSwitch } from 'react-icons/ti';
import { VscVmConnect } from 'react-icons/vsc';
import { DeviceType } from './types';
import type { FC } from 'react';
interface DeviceIconProps {
@@ -41,7 +42,7 @@ const DeviceIcon: FC<DeviceIconProps> = ({ type_id }) => {
case DeviceType.EXTENSION:
return <MdOutlineDevices />;
case DeviceType.CUSTOM:
return <MdOutlineExtension />;
return <PlaylistAddIcon sx={{ color: 'lightblue', fontSize: 24, verticalAlign: 'middle' }} />;
default:
return null;
}

View File

@@ -33,7 +33,7 @@ import { useSort, SortToggleType } from '@table-library/react-table-library/sort
import { Table, Header, HeaderRow, HeaderCell, Body, Row, Cell } from '@table-library/react-table-library/table';
import { useTheme } from '@table-library/react-table-library/theme';
import { useRequest } from 'alova';
import { useState, useContext, useEffect, useCallback, useLayoutEffect } from 'react';
import { useState, useEffect, useCallback, useLayoutEffect } from 'react';
import { IconContext } from 'react-icons';
import { useNavigate } from 'react-router-dom';
@@ -50,12 +50,10 @@ import type { Device, DeviceValue } from './types';
import type { FC } from 'react';
import { dialogStyle } from 'CustomTheme';
import { ButtonRow, SectionContent, MessageBox, useLayoutTitle } from 'components';
import { AuthenticatedContext } from 'contexts/authentication';
import { useI18nContext } from 'i18n/i18n-react';
const Devices: FC = () => {
const { me } = useContext(AuthenticatedContext);
const { LL } = useI18nContext();
const [size, setSize] = useState([0, 0]);
const [selectedDeviceValue, setSelectedDeviceValue] = useState<DeviceValue>();
@@ -422,11 +420,8 @@ const Devices: FC = () => {
};
const renderCoreData = () => (
<IconContext.Provider value={{ color: 'lightblue', size: '24', style: { verticalAlign: 'middle' } }}>
<IconContext.Provider value={{ color: 'lightblue', size: '18', style: { verticalAlign: 'middle' } }}>
{!coreData.connected && <MessageBox my={2} level="error" message={LL.EMS_BUS_WARNING()} />}
{/* {coreData.connected && coreData.devices.length === 0 && (
<MessageBox my={2} level="warning" message={LL.EMS_BUS_SCANNING()} />
)} */}
{coreData.connected && (
<Table data={{ nodes: coreData.devices }} select={device_select} theme={device_theme} layout={{ custom: true }}>
@@ -589,7 +584,7 @@ const Devices: FC = () => {
<Cell>{renderNameCell(dv)}</Cell>
<Cell>{formatValue(LL, dv.v, dv.u)}</Cell>
<Cell stiff>
{dv.c && me.admin && !hasMask(dv.id, DeviceEntityMask.DV_READONLY) && (
{dv.c && !hasMask(dv.id, DeviceEntityMask.DV_READONLY) && (
<IconButton size="small" onClick={() => showDeviceValue(dv)}>
{dv.v === '' && dv.c ? (
<PlayArrowIcon color="primary" sx={{ fontSize: 16 }} />
@@ -621,9 +616,7 @@ const Devices: FC = () => {
onSave={deviceValueDialogSave}
selectedItem={selectedDeviceValue}
writeable={
me.admin &&
selectedDeviceValue.c !== undefined &&
!hasMask(selectedDeviceValue.id, DeviceEntityMask.DV_READONLY)
selectedDeviceValue.c !== undefined && !hasMask(selectedDeviceValue.id, DeviceEntityMask.DV_READONLY)
}
validator={deviceValueItemValidation(selectedDeviceValue)}
progress={submitting}

View File

@@ -206,7 +206,7 @@ const EMSStatus: FC = () => {
</ListItem>
<ListItem>
<ListItemAvatar>
<Avatar>
<Avatar sx={{ bgcolor: theme.palette.success.main }}>
<DeviceHubIcon />
</Avatar>
</ListItemAvatar>
@@ -254,19 +254,20 @@ const EMSStatus: FC = () => {
{LL.REFRESH()}
</Button>
</Box>
<Box flexWrap="nowrap" whiteSpace="nowrap">
<ButtonRow>
<Button
startIcon={<PermScanWifiIcon />}
variant="outlined"
color="primary"
disabled={!me.admin}
onClick={() => setConfirmScan(true)}
>
{LL.SCAN_DEVICES()}
</Button>
</ButtonRow>
</Box>
{me.admin && (
<Box flexWrap="nowrap" whiteSpace="nowrap">
<ButtonRow>
<Button
startIcon={<PermScanWifiIcon />}
variant="outlined"
color="primary"
onClick={() => setConfirmScan(true)}
>
{LL.SCAN_DEVICES()}
</Button>
</ButtonRow>
</Box>
)}
</Box>
</>
);

View File

@@ -8,7 +8,7 @@ import { useSort, SortToggleType } from '@table-library/react-table-library/sort
import { Table, Header, HeaderRow, HeaderCell, Body, Row, Cell } from '@table-library/react-table-library/table';
import { useTheme } from '@table-library/react-table-library/theme';
import { useRequest } from 'alova';
import { useState, useContext, useEffect } from 'react';
import { useState, useEffect, useContext } from 'react';
import { toast } from 'react-toastify';
@@ -27,12 +27,12 @@ import { useI18nContext } from 'i18n/i18n-react';
const Sensors: FC = () => {
const { LL } = useI18nContext();
const { me } = useContext(AuthenticatedContext);
const [selectedTemperatureSensor, setSelectedTemperatureSensor] = useState<TemperatureSensor>();
const [selectedAnalogSensor, setSelectedAnalogSensor] = useState<AnalogSensor>();
const [temperatureDialogOpen, setTemperatureDialogOpen] = useState<boolean>(false);
const [analogDialogOpen, setAnalogDialogOpen] = useState<boolean>(false);
const [creating, setCreating] = useState<boolean>(false);
const { me } = useContext(AuthenticatedContext);
const { data: sensorData, send: fetchSensorData } = useRequest(() => EMSESP.readSensorData(), {
initialData: {
@@ -51,8 +51,6 @@ const Sensors: FC = () => {
immediate: false
});
const isAdmin = me.admin;
const common_theme = useTheme({
BaseRow: `
font-size: 14px;
@@ -222,10 +220,8 @@ const Sensors: FC = () => {
}
const updateTemperatureSensor = (ts: TemperatureSensor) => {
if (isAdmin) {
setSelectedTemperatureSensor(ts);
setTemperatureDialogOpen(true);
}
setSelectedTemperatureSensor(ts);
setTemperatureDialogOpen(true);
};
const onTemperatureDialogClose = () => {
@@ -248,11 +244,9 @@ const Sensors: FC = () => {
};
const updateAnalogSensor = (as: AnalogSensor) => {
if (isAdmin) {
setCreating(false);
setSelectedAnalogSensor(as);
setAnalogDialogOpen(true);
}
setCreating(false);
setSelectedAnalogSensor(as);
setAnalogDialogOpen(true);
};
const onAnalogDialogClose = () => {
@@ -453,7 +447,7 @@ const Sensors: FC = () => {
{LL.REFRESH()}
</Button>
</Box>
{sensorData?.analog_enabled === true && (
{sensorData?.analog_enabled === true && me.admin && (
<Button
variant="outlined"
color="primary"

View File

@@ -393,6 +393,7 @@ const system_status = {
uptime: '000+00:15:42.707',
arduino_version: 'ESP32 Arduino v2.0.14'
};
let security_settings = {
jwt_secret: 'naughty!',
users: [
@@ -402,10 +403,18 @@ let security_settings = {
};
const verify_authentication = { access_token: '1234' };
const signin = {
const admin_signin = {
access_token:
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiYWRtaW4iOnRydWUsInZlcnNpb24iOiIzLjAuMmIwIn0.MsHSgoJKI1lyYz77EiT5ZN3ECMrb4mPv9FNy3udq0TU'
};
const guest_signin = {
access_token:
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Imd1ZXN0IiwiYWRtaW4iOmZhbHNlfQ.E_lylR_vGIQFZUGNwcl5F6OkHoaELGsC5zqhi0pAiJE'
};
const signin = admin_signin;
// const signin = guest_signin;
const generate_token = { token: '1234' };
//
@@ -739,7 +748,7 @@ const emsesp_coredata = {
t: 17,
tn: 'Custom',
b: '',
n: 'Custom entities',
n: 'Custom Entities',
d: 1,
p: 1,
v: '',

View File

@@ -552,7 +552,7 @@ const emsesp_coredata = {
t: 17,
tn: 'Custom',
b: '',
n: 'Custom entities',
n: 'Custom Entities',
d: 1,
p: 1,
v: '',

View File

@@ -407,7 +407,7 @@ void EMSESP::show_device_values(uuid::console::Shell & shell) {
// show any custom entities
if (webCustomEntityService.count_entities() > 0) {
shell.printfln("Custom entities:");
shell.printfln("Custom Entities:");
JsonDocument custom_doc; // use max size
JsonObject custom_output = custom_doc.to<JsonObject>();
webCustomEntityService.show_values(custom_output);

View File

@@ -53,10 +53,9 @@ MAKE_WORD_TRANSLATION(heatsource_device, "Heatsource", "Heizquelle", "Heatsource
MAKE_WORD_TRANSLATION(sensors_device, "Sensors", "Sensoren", "Sensoren", "Sensorer", "Czujniki", "Sensorer", "Capteurs", "Sensör Cihazı", "Sensori", "Snímače")
MAKE_WORD_TRANSLATION(unknown_device, "Unknown", "Unbekannt", "Onbekend", "Okänt", "Nieznane urządzenie", "Ukjent", "Inconnu", "Bilinmeyen", "Sconosciuto", "Neznámy")
MAKE_WORD_TRANSLATION(custom_device, "Custom", "Nutzerdefiniert", "Aangepast", "", "Niestandardowe", "", "", "Özel", "Personalizzato", "Vlastné") // TODO translate
MAKE_WORD_TRANSLATION(custom_device_name, "Custom entities", "Nutzer deklarierte Entitäten", "Gebruiker gedefineerd", "", "Encje zdefiniowane przez użytkownika", "", "", "Kullanıcı tarafından tanımlanmış varlıklar", "Entità definita da utente", "Používateľom definované entity") // TODO translate
MAKE_WORD_TRANSLATION(custom_device_name, "Custom Entities", "Nutzer deklarierte Entitäten", "Gebruiker gedefineerd", "", "Encje zdefiniowane przez użytkownika", "", "", "Kullanıcı tarafından tanımlanmış varlıklar", "Entità definita da utente", "Používateľom definované entity") // TODO translate
MAKE_WORD_TRANSLATION(ventilation_device, "Ventilation", "Lüftung", "Ventilatie", "", "Wentylacja", "", "", "Havalandırma", "Ventilazione", "Vetranie") // TODO translate
// commands
MAKE_WORD_TRANSLATION(info_cmd, "lists all values", "Liste aller Werte", "lijst van alle waardes", "", "wyświetl wszystkie wartości", "Viser alle verdier", "", "Tüm değerleri listele", "elenca tutti i valori", "zobraziť všetky hodnoty") // TODO translate
MAKE_WORD_TRANSLATION(commands_cmd, "lists all commands", "Liste aller Kommandos", "lijst van alle commando's", "", "wyświetl wszystkie komendy", "Viser alle kommandoer", "", "Tüm komutları listele", "elencaa tutti i comandi", "zobraziť všetky príkazy") // TODO translate