sync with dev

This commit is contained in:
proddy
2026-04-15 09:25:38 +02:00
parent 16c0370443
commit 4d3b31e5a1
67 changed files with 1747 additions and 1125 deletions

View File

@@ -343,9 +343,9 @@ const CustomEntities = () => {
return (
<SectionContent>
{blocker ? <BlockNavigation blocker={blocker} /> : null}
<Box mb={2} color="warning.main">
<Typography variant="body1">{LL.ENTITIES_HELP_1()}.</Typography>
</Box>
<Typography sx={{ mb: 2 }} color="warning" variant="body1">
{LL.ENTITIES_HELP_1()}.
</Typography>
{renderEntity()}
@@ -361,8 +361,8 @@ const CustomEntities = () => {
/>
)}
<Box mt={2} display="flex" flexWrap="wrap">
<Box flexGrow={1}>
<Box sx={{ mt: 2, display: 'flex', flexWrap: 'wrap' }}>
<Box sx={{ flexGrow: 1 }}>
{numChanges > 0 && (
<ButtonRow>
<Button
@@ -384,7 +384,7 @@ const CustomEntities = () => {
</ButtonRow>
)}
</Box>
<Box flexWrap="nowrap" whiteSpace="nowrap">
<Box sx={{ flexWrap: 'nowrap', whiteSpace: 'nowrap' }}>
<Button
startIcon={<AddIcon />}
variant="outlined"

View File

@@ -7,7 +7,7 @@ import DoneIcon from '@mui/icons-material/Done';
import EditOffOutlinedIcon from '@mui/icons-material/EditOffOutlined';
import EditOutlinedIcon from '@mui/icons-material/EditOutlined';
import InsertCommentOutlinedIcon from '@mui/icons-material/InsertCommentOutlined';
import RemoveIcon from '@mui/icons-material/RemoveCircleOutline';
import RemoveIcon from '@mui/icons-material/RemoveCircleOutlined';
import {
Box,
Button,
@@ -178,7 +178,7 @@ const CustomEntitiesDialog = ({
onChange={updateFormValue}
/>
</Grid>
<Grid mt={3}>
<Grid sx={{ mt: 3 }}>
<BlockFormControlLabel
control={
<Checkbox
@@ -238,7 +238,7 @@ const CustomEntitiesDialog = ({
)}
{editItem.ram === 0 && (
<>
<Grid mt={3}>
<Grid sx={{ mt: 3 }}>
<BlockFormControlLabel
control={
<Checkbox
@@ -404,7 +404,7 @@ const CustomEntitiesDialog = ({
</DialogContent>
<DialogActions>
{!creating && (
<Box flexGrow={1}>
<Box sx={{ flexGrow: 1 }}>
<Button
startIcon={<RemoveIcon />}
variant="outlined"

View File

@@ -470,10 +470,10 @@ const Customizations = () => {
const renderDeviceList = () => (
<>
<Box mb={1} color="warning.main">
<Typography variant="body1">{LL.CUSTOMIZATIONS_HELP_1()}.</Typography>
</Box>
<Box display="flex" flexWrap="wrap" alignItems="center" gap={2}>
<Typography sx={{ mb: 1 }} color="warning" variant="body1">
{LL.CUSTOMIZATIONS_HELP_1()}.
</Typography>
<Box sx={{ display: 'flex', flexWrap: 'wrap', alignItems: 'center', gap: 2 }}>
{rename ? (
<>
<TextField
@@ -570,27 +570,22 @@ const Customizations = () => {
const renderDeviceData = () => {
return (
<>
<Box color="warning.main">
<Typography variant="body2" mt={1} mb={1}>
<OptionIcon type="favorite" isSet={true} />={LL.CUSTOMIZATIONS_HELP_2()}
&nbsp;&nbsp;
<OptionIcon type="readonly" isSet={true} />={LL.CUSTOMIZATIONS_HELP_3()}
&nbsp;&nbsp;
<OptionIcon type="api_mqtt_exclude" isSet={true} />=
{LL.CUSTOMIZATIONS_HELP_4()}&nbsp;&nbsp;
<OptionIcon type="web_exclude" isSet={true} />=
{LL.CUSTOMIZATIONS_HELP_5()}&nbsp;&nbsp;
<OptionIcon type="deleted" isSet={true} />={LL.CUSTOMIZATIONS_HELP_6()}
</Typography>
</Box>
<Typography sx={{ mt: 1, mb: 1 }} color="warning" variant="body2">
<OptionIcon type="favorite" isSet={true} />={LL.CUSTOMIZATIONS_HELP_2()}
&nbsp;&nbsp;
<OptionIcon type="readonly" isSet={true} />={LL.CUSTOMIZATIONS_HELP_3()}
&nbsp;&nbsp;
<OptionIcon type="api_mqtt_exclude" isSet={true} />=
{LL.CUSTOMIZATIONS_HELP_4()}&nbsp;&nbsp;
<OptionIcon type="web_exclude" isSet={true} />={LL.CUSTOMIZATIONS_HELP_5()}
&nbsp;&nbsp;
<OptionIcon type="deleted" isSet={true} />={LL.CUSTOMIZATIONS_HELP_6()}
</Typography>
<Grid
container
mb={1}
mt={0}
spacing={2}
direction="row"
justifyContent="flex-start"
alignItems="center"
sx={{ mb: 1, mt: 0, justifyContent: 'flex-start', alignItems: 'center' }}
>
<Grid>
<TextField
@@ -779,8 +774,8 @@ const Customizations = () => {
</Button>
</MessageBox>
) : (
<Box display="flex" flexWrap="wrap">
<Box flexGrow={1}>
<Box sx={{ display: 'flex', flexWrap: 'wrap' }}>
<Box sx={{ flexGrow: 1 }}>
{numChanges !== 0 && (
<ButtonRow>
<Button

View File

@@ -37,7 +37,7 @@ interface LabelValueProps {
const LabelValue = memo(({ label, value }: LabelValueProps) => (
<Grid container direction="row">
<Typography variant="body2" color="warning.main">
<Typography variant="body2" color="warning">
{label}:&nbsp;
</Typography>
<Typography variant="body2">{value}</Typography>
@@ -131,7 +131,7 @@ const CustomizationsDialog = ({
/>
<LabelValue label={LL.WRITEABLE()} value={writeableIcon} />
<Box mt={1} mb={2}>
<Box sx={{ mt: 1, mb: 2 }}>
<EntityMaskToggle onUpdate={updateDeviceEntity} de={editItem} />
</Box>
@@ -172,7 +172,7 @@ const CustomizationsDialog = ({
</Grid>
{error && (
<Typography variant="body2" color="error" mt={2}>
<Typography sx={{ mt: 2 }} variant="body2" color="error">
Error: Check min and max values
</Typography>
)}

View File

@@ -6,7 +6,7 @@ import { toast } from 'react-toastify';
import ChevronRightIcon from '@mui/icons-material/ChevronRight';
import EditIcon from '@mui/icons-material/Edit';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import HelpOutlineIcon from '@mui/icons-material/HelpOutline';
import HelpOutlineIcon from '@mui/icons-material/HelpOutlined';
import UnfoldLessIcon from '@mui/icons-material/UnfoldLess';
import UnfoldMoreIcon from '@mui/icons-material/UnfoldMore';
import {
@@ -263,7 +263,7 @@ const Dashboard = memo(() => {
return (
<>
{data.connected && data.nodes.length > 0 && !hasFavEntities && (
<MessageBox mb={2} level="warning">
<MessageBox sx={{ mb: 2 }} level="warning">
<Typography>
{LL.NO_DATA_1()}&nbsp;
<Link to="/customizations" style={{ color: 'white' }}>
@@ -280,10 +280,12 @@ const Dashboard = memo(() => {
)}
<Box
display="flex"
justifyContent="flex-end"
flexWrap="nowrap"
whiteSpace="nowrap"
sx={{
display: 'flex',
justifyContent: 'flex-end',
flexWrap: 'nowrap',
whiteSpace: 'nowrap'
}}
>
<ToggleButtonGroup
size="small"
@@ -306,7 +308,7 @@ const Dashboard = memo(() => {
</Box>
{data.nodes.length > 0 ? (
<Box mt={1} justifyContent="center" flexDirection="column">
<Box sx={{ mt: 1, justifyContent: 'center', flexDirection: 'column' }}>
<IconContext.Provider
value={{
color: 'lightblue',
@@ -373,13 +375,8 @@ const Dashboard = memo(() => {
</IconContext.Provider>
</Box>
) : (
<Box
display="flex"
// justifyContent="flex-end"
// flexWrap="nowrap"
// whiteSpace="nowrap"
>
<Typography mt={1} color="warning.main" variant="body1">
<Box sx={{ display: 'flex' }}>
<Typography sx={{ mt: 1 }} color="warning" variant="body1">
no data
</Typography>
<Tooltip title={LL.DASHBOARD_1()}>

View File

@@ -1,4 +1,5 @@
import { memo } from 'react';
import type { IconType } from 'react-icons';
import { AiOutlineAlert, AiOutlineControl, AiOutlineGateway } from 'react-icons/ai';
import { CgSmartHomeBoiler } from 'react-icons/cg';
import { FaSolarPanel } from 'react-icons/fa';
@@ -15,14 +16,9 @@ import { PiFan, PiGauge } from 'react-icons/pi';
import { TiFlowSwitch, TiThermometer } from 'react-icons/ti';
import { VscVmConnect } from 'react-icons/vsc';
import type { SvgIconProps } from '@mui/material';
import { DeviceType } from './types';
const deviceIconLookup: Record<
DeviceType,
React.ComponentType<SvgIconProps> | null
> = {
const deviceIconLookup: Record<DeviceType, IconType | null> = {
[DeviceType.TEMPERATURESENSOR]: TiThermometer,
[DeviceType.ANALOGSENSOR]: PiGauge,
[DeviceType.BOILER]: CgSmartHomeBoiler,

View File

@@ -546,7 +546,7 @@ const Devices = memo(() => {
)
</MessageBox>
) : (
<Box justifyContent="center" flexDirection="column">
<Box sx={{ justifyContent: 'center', flexDirection: 'column' }}>
<IconContext.Provider
value={{
color: 'lightblue',
@@ -670,12 +670,12 @@ const Devices = memo(() => {
}}
>
<Box sx={{ p: 1 }}>
<Grid container justifyContent="space-between">
<Typography noWrap variant="subtitle1" color="warning.main">
<Grid container sx={{ justifyContent: 'space-between' }}>
<Typography noWrap variant="subtitle1" color="warning">
{deviceInfo.n}&nbsp;(
{deviceInfo.tn})
</Typography>
<Grid justifyContent="flex-end">
<Grid sx={{ justifyContent: 'flex-end' }}>
<ButtonTooltip title={LL.CLOSE()}>
<IconButton onClick={resetDeviceSelect} aria-label={LL.CLOSE()}>
<HighlightOffIcon color="primary" sx={{ fontSize: 18 }} />

View File

@@ -128,9 +128,9 @@ const DevicesDialog = ({
<Dialog sx={dialogStyle} open={open} onClose={onClose}>
<DialogTitle>{dialogTitle}</DialogTitle>
<DialogContent dividers>
<Box color="warning.main" mb={2}>
<Typography variant="body2">{editItem.id.slice(2)}</Typography>
</Box>
<Typography sx={{ mb: 2 }} color="warning" variant="body2">
{editItem.id.slice(2)}
</Typography>
<Grid container>
<Grid size={12}>
{editItem.l ? (

View File

@@ -11,6 +11,7 @@ import {
Box,
Button,
Divider,
Grid,
Link,
List,
ListItem,
@@ -42,7 +43,7 @@ interface CustomSupport {
html: string | null;
}
const DEFAULT_IMAGE_URL = 'https://emsesp.org/_media/images/installer.jpeg';
const DEFAULT_IMAGE_URL = 'https://emsesp.org/media/images/installer.jpeg';
const SUPPORT_BOX_STYLES: SxProps<Theme> = {
borderRadius: 3,
@@ -71,7 +72,6 @@ const HelpComponent = () => {
});
const [imgError, setImgError] = useState<boolean>(false);
// Memoize the request method to prevent re-creation on every render
const getCustomSupportMethod = useMemo(
() => callAction({ action: 'getCustomSupport' }),
[]
@@ -146,11 +146,9 @@ const HelpComponent = () => {
<SectionContent>
{customSupport.html && (
<Stack
padding={1}
mb={2}
direction="row"
divider={<Divider orientation="vertical" flexItem />}
sx={SUPPORT_BOX_STYLES}
sx={{ padding: 1, mb: 2, ...SUPPORT_BOX_STYLES }}
>
<Typography variant="subtitle1">
<div dangerouslySetInnerHTML={{ __html: customSupport.html }} />
@@ -185,9 +183,9 @@ const HelpComponent = () => {
</List>
)}
<Box p={2} color="warning.main">
<Typography mb={1} variant="body1">
{LL.HELP_INFORMATION_4()}.
<Grid container spacing={2} sx={{ mt: 2, alignItems: 'center' }}>
<Typography sx={{ mb: 1 }} color="warning" variant="body1">
{LL.HELP_INFORMATION_4()}:
</Typography>
<Button
startIcon={<DownloadIcon />}
@@ -197,11 +195,11 @@ const HelpComponent = () => {
>
{LL.SUPPORT_INFORMATION(0)}
</Button>
</Box>
</Grid>
<Divider sx={{ mt: 4 }} />
<Typography color="white" variant="subtitle1" align="center" mt={1}>
<Typography color="white" variant="subtitle1" align="center" sx={{ mt: 1 }}>
&copy;&nbsp;
<Link
target="_blank"

View File

@@ -186,9 +186,9 @@ const Modules = () => {
return (
<>
<Box mb={2} color="warning.main">
<Typography variant="body1">{LL.MODULES_DESCRIPTION()}.</Typography>
</Box>
<Typography sx={{ mb: 2 }} color="warning" variant="body1">
{LL.MODULES_DESCRIPTION()}.
</Typography>
<Table
data={{ nodes: modules }}
theme={modules_theme}
@@ -236,8 +236,8 @@ const Modules = () => {
)}
</Table>
<Box mt={1} display="flex" flexWrap="wrap">
<Box flexGrow={1}>
<Box sx={{ mt: 1, display: 'flex', flexWrap: 'wrap' }}>
<Box sx={{ flexGrow: 1 }}>
{numChanges !== 0 && (
<ButtonRow>
<Button

View File

@@ -79,7 +79,7 @@ const ModulesDialog = ({
label="Enabled"
/>
</Grid>
<Box mt={2} mb={1}>
<Box sx={{ mt: 2, mb: 1 }}>
<TextField
name="license"
label="License Key"

View File

@@ -2,12 +2,12 @@ import { memo } from 'react';
import CommentsDisabledOutlinedIcon from '@mui/icons-material/CommentsDisabledOutlined';
import DeleteForeverIcon from '@mui/icons-material/DeleteForever';
import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline';
import DeleteOutlineIcon from '@mui/icons-material/DeleteOutlined';
import EditOffOutlinedIcon from '@mui/icons-material/EditOffOutlined';
import EditOutlinedIcon from '@mui/icons-material/EditOutlined';
import InsertCommentOutlinedIcon from '@mui/icons-material/InsertCommentOutlined';
import StarIcon from '@mui/icons-material/Star';
import StarOutlineIcon from '@mui/icons-material/StarOutline';
import StarOutlineIcon from '@mui/icons-material/StarOutlined';
import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined';
import VisibilityOutlinedIcon from '@mui/icons-material/VisibilityOutlined';
import type { SvgIconProps } from '@mui/material';

View File

@@ -358,9 +358,9 @@ const Scheduler = () => {
return (
<SectionContent>
{blocker ? <BlockNavigation blocker={blocker} /> : null}
<Box mb={2} color="warning.main">
<Typography variant="body1">{LL.SCHEDULER_HELP_1()}.</Typography>
</Box>
<Typography sx={{ mb: 2 }} color="warning" variant="body1">
{LL.SCHEDULER_HELP_1()}.
</Typography>
{renderSchedule()}
{selectedScheduleItem && (
@@ -375,8 +375,8 @@ const Scheduler = () => {
/>
)}
<Box display="flex" flexWrap="wrap">
<Box flexGrow={1}>
<Box sx={{ display: 'flex', flexWrap: 'wrap' }}>
<Box sx={{ flexGrow: 1 }}>
{numChanges !== 0 && (
<ButtonRow>
<Button
@@ -398,7 +398,7 @@ const Scheduler = () => {
</ButtonRow>
)}
</Box>
<Box flexWrap="nowrap" whiteSpace="nowrap">
<Box sx={{ flexWrap: 'nowrap', whiteSpace: 'nowrap' }}>
<ButtonRow>
<Button
startIcon={<AddIcon />}

View File

@@ -4,7 +4,7 @@ import AddIcon from '@mui/icons-material/Add';
import CancelIcon from '@mui/icons-material/Cancel';
import DoneIcon from '@mui/icons-material/Done';
import PlayArrowIcon from '@mui/icons-material/PlayArrow';
import RemoveIcon from '@mui/icons-material/RemoveCircleOutline';
import RemoveIcon from '@mui/icons-material/RemoveCircleOutlined';
import {
Box,
Button,
@@ -338,11 +338,13 @@ const SchedulerDialog = ({
onChange={updateFormValue}
/>
{isTimerSchedule && (
<Box color="warning.main" ml={2} mt={4}>
<Typography variant="body2">
{LL.SCHEDULER_HELP_2()}
</Typography>
</Box>
<Typography
sx={{ ml: 2, mt: 4 }}
color="warning"
variant="body2"
>
{LL.SCHEDULER_HELP_2()}
</Typography>
)}
</>
) : (
@@ -391,7 +393,7 @@ const SchedulerDialog = ({
<DialogActions>
{!creating && (
<Box flexGrow={1}>
<Box sx={{ flexGrow: 1 }}>
<Button
startIcon={<RemoveIcon />}
variant="outlined"

View File

@@ -591,7 +591,14 @@ const Sensors = () => {
/>
)}
{sensorData?.analog_enabled === true && me.admin && (
<Box mt={2} display="flex" flexWrap="wrap" justifyContent="flex-end">
<Box
sx={{
mt: 2,
display: 'flex',
flexWrap: 'wrap',
justifyContent: 'flex-end'
}}
>
<Button
variant="outlined"
color="primary"

View File

@@ -2,7 +2,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react';
import CancelIcon from '@mui/icons-material/Cancel';
import DoneIcon from '@mui/icons-material/Done';
import RemoveIcon from '@mui/icons-material/RemoveCircleOutline';
import RemoveIcon from '@mui/icons-material/RemoveCircleOutlined';
import WarningIcon from '@mui/icons-material/Warning';
import {
Box,
@@ -479,7 +479,7 @@ const SensorsAnalogDialog = ({
)}
</Grid>
{fieldErrors && Object.keys(fieldErrors).length > 0 && (
<Box mt={1}>
<Box sx={{ mt: 1 }}>
{Object.values(fieldErrors).map((errArr, idx) =>
Array.isArray(errArr)
? errArr.map((err, j) => (
@@ -487,7 +487,7 @@ const SensorsAnalogDialog = ({
key={`${idx}-${j}`}
color="error"
variant="caption"
display="block"
sx={{ display: 'block' }}
>
{err.message}
</Typography>
@@ -498,7 +498,7 @@ const SensorsAnalogDialog = ({
)}
{editItem.s && (
<Grid>
<Typography mt={1} color="warning.main" variant="body2">
<Typography sx={{ mt: 1 }} color="warning" variant="body2">
<WarningIcon
fontSize="small"
sx={{ mr: 1, verticalAlign: 'middle' }}
@@ -511,7 +511,7 @@ const SensorsAnalogDialog = ({
</DialogContent>
<DialogActions>
{!creating && (
<Box flexGrow={1} sx={{ '& button': { mt: 0 } }}>
<Box sx={{ flexGrow: 1, '& button': { mt: 0 } }}>
<Button
startIcon={<RemoveIcon />}
disabled={editItem.s}

View File

@@ -4,7 +4,6 @@ import CancelIcon from '@mui/icons-material/Cancel';
import DoneIcon from '@mui/icons-material/Done';
import WarningIcon from '@mui/icons-material/Warning';
import {
Box,
Button,
Dialog,
DialogActions,
@@ -111,11 +110,9 @@ const SensorsTemperatureDialog = ({
<Dialog sx={dialogStyle} open={open} onClose={handleClose}>
<DialogTitle>{dialogTitle}</DialogTitle>
<DialogContent dividers>
<Box color="warning.main" mb={2}>
<Typography variant="body2">
{LL.ID_OF(LL.SENSOR(0))}: {editItem.id}
</Typography>
</Box>
<Typography sx={{ mb: 2 }} color="warning" variant="body2">
{LL.ID_OF(LL.SENSOR(0))}: {editItem.id}
</Typography>
<Grid container spacing={2}>
<Grid>
<ValidatedTextField
@@ -142,7 +139,7 @@ const SensorsTemperatureDialog = ({
</Grid>
{editItem.s && (
<Grid>
<Typography mt={1} color="warning.main" variant="body2">
<Typography sx={{ mt: 1 }} color="warning" variant="body2">
<WarningIcon
fontSize="small"
sx={{ mr: 1, verticalAlign: 'middle' }}

View File

@@ -41,8 +41,12 @@ const UserProfileComponent = () => {
/>
</ListItem>
</List>
<Box mt={2} mb={2} display="flex" alignItems="center">
<Typography mr={2} variant="body1" align="center">
<Box sx={{ mt: 2, mb: 2, display: 'flex', alignItems: 'center' }}>
<Typography
sx={{ mr: 2, textAlign: 'center' }}
color="warning"
variant="body1"
>
{LL.LANGUAGE()}:
</Typography>
<LanguageSelector />

View File

@@ -43,16 +43,6 @@ export interface Settings {
modbus_port: number;
modbus_max_clients: number;
modbus_timeout: number;
email_enabled: boolean;
email_ssl?: boolean;
email_starttls?: boolean;
email_server: string;
email_port: number;
email_login: string;
email_pass: string;
email_sender: string;
email_recp: string;
email_subject: string;
developer_mode: boolean;
}