mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2026-10-28 11:14:58 +00:00
This commit is contained in:
@@ -11,6 +11,7 @@ import WarningIcon from '@mui/icons-material/Warning';
|
|||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Button,
|
Button,
|
||||||
|
Checkbox,
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogActions,
|
DialogActions,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
@@ -91,6 +92,8 @@ const Customizations = () => {
|
|||||||
const [deviceEntities, setDeviceEntities] = useState<DeviceEntity[]>([]);
|
const [deviceEntities, setDeviceEntities] = useState<DeviceEntity[]>([]);
|
||||||
const [confirmReset, setConfirmReset] = useState<boolean>(false);
|
const [confirmReset, setConfirmReset] = useState<boolean>(false);
|
||||||
const [selectedFilters, setSelectedFilters] = useState<number>(0);
|
const [selectedFilters, setSelectedFilters] = useState<number>(0);
|
||||||
|
const [modifiedOnly, setModifiedOnly] = useState<boolean>(false);
|
||||||
|
const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set());
|
||||||
const [search, setSearch] = useState('');
|
const [search, setSearch] = useState('');
|
||||||
const [selectedDeviceEntity, setSelectedDeviceEntity] = useState<DeviceEntity>();
|
const [selectedDeviceEntity, setSelectedDeviceEntity] = useState<DeviceEntity>();
|
||||||
const [dialogOpen, setDialogOpen] = useState<boolean>(false);
|
const [dialogOpen, setDialogOpen] = useState<boolean>(false);
|
||||||
@@ -173,7 +176,7 @@ const Customizations = () => {
|
|||||||
|
|
||||||
const entities_theme = useTheme({
|
const entities_theme = useTheme({
|
||||||
Table: `
|
Table: `
|
||||||
--data-table-library_grid-template-columns: 156px repeat(1, minmax(80px, 1fr)) 45px minmax(45px, auto) minmax(120px, auto);
|
--data-table-library_grid-template-columns: 32px 156px repeat(1, minmax(80px, 1fr)) 45px minmax(45px, auto) minmax(120px, auto);
|
||||||
`,
|
`,
|
||||||
BaseRow: `
|
BaseRow: `
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
@@ -182,10 +185,10 @@ const Customizations = () => {
|
|||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
BaseCell: `
|
BaseCell: `
|
||||||
&:nth-of-type(3) {
|
&:nth-of-type(4) {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
&:nth-of-type(4) {
|
&:nth-of-type(5) {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
&:last-of-type {
|
&:last-of-type {
|
||||||
@@ -221,13 +224,13 @@ const Customizations = () => {
|
|||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
Cell: `
|
Cell: `
|
||||||
&:nth-of-type(2) {
|
&:nth-of-type(3) {
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
}
|
}
|
||||||
&:nth-of-type(3) {
|
&:nth-of-type(4) {
|
||||||
padding-right: 4px;
|
padding-right: 4px;
|
||||||
}
|
}
|
||||||
&:nth-of-type(4) {
|
&:nth-of-type(5) {
|
||||||
padding-right: 4px;
|
padding-right: 4px;
|
||||||
}
|
}
|
||||||
&:last-of-type {
|
&:last-of-type {
|
||||||
@@ -245,6 +248,11 @@ const Customizations = () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Saved customization (c), or an edit that is not applied yet.
|
||||||
|
function isModified(de: DeviceEntity) {
|
||||||
|
return !!de.c || hasEntityChanged(de);
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (deviceEntities.length) {
|
if (deviceEntities.length) {
|
||||||
const changedEntities = deviceEntities.filter((de) => hasEntityChanged(de));
|
const changedEntities = deviceEntities.filter((de) => hasEntityChanged(de));
|
||||||
@@ -267,6 +275,7 @@ const Customizations = () => {
|
|||||||
setSelectedDeviceBrand(device.b);
|
setSelectedDeviceBrand(device.b);
|
||||||
}
|
}
|
||||||
setNumChanges(0);
|
setNumChanges(0);
|
||||||
|
setSelectedIds(new Set());
|
||||||
setRestartNeeded(false);
|
setRestartNeeded(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -331,24 +340,61 @@ const Customizations = () => {
|
|||||||
|
|
||||||
const filter_entity = (de: DeviceEntity) =>
|
const filter_entity = (de: DeviceEntity) =>
|
||||||
(de.m & selectedFilters || !selectedFilters) &&
|
(de.m & selectedFilters || !selectedFilters) &&
|
||||||
|
(!modifiedOnly || isModified(de)) &&
|
||||||
formatName(de, true).toLowerCase().includes(search.toLowerCase());
|
formatName(de, true).toLowerCase().includes(search.toLowerCase());
|
||||||
|
|
||||||
|
// Checked rows when any are checked, otherwise every row the filter is showing.
|
||||||
|
const inBulkTarget = (de: DeviceEntity) =>
|
||||||
|
selectedIds.size > 0 ? selectedIds.has(de.id) : filter_entity(de);
|
||||||
|
|
||||||
const maskDisabled = (set: boolean) => {
|
const maskDisabled = (set: boolean) => {
|
||||||
|
const excludeMask =
|
||||||
|
DeviceEntityMask.DV_API_MQTT_EXCLUDE | DeviceEntityMask.DV_WEB_EXCLUDE;
|
||||||
setDeviceEntities((prev) =>
|
setDeviceEntities((prev) =>
|
||||||
prev.map((de) => {
|
prev.map((de) => {
|
||||||
if (filter_entity(de)) {
|
if (!inBulkTarget(de)) {
|
||||||
const excludeMask =
|
return de;
|
||||||
DeviceEntityMask.DV_API_MQTT_EXCLUDE | DeviceEntityMask.DV_WEB_EXCLUDE;
|
|
||||||
return {
|
|
||||||
...de,
|
|
||||||
m: set ? de.m | excludeMask : de.m & ~excludeMask
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
return de;
|
return {
|
||||||
|
...de,
|
||||||
|
m: set ? de.m | excludeMask : de.m & ~excludeMask
|
||||||
|
};
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const maskReadonly = (set: boolean) => {
|
||||||
|
setDeviceEntities((prev) =>
|
||||||
|
prev.map((de) => {
|
||||||
|
if (!inBulkTarget(de) || !de.w) {
|
||||||
|
return de;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...de,
|
||||||
|
m: set
|
||||||
|
? de.m | DeviceEntityMask.DV_READONLY
|
||||||
|
: de.m & ~DeviceEntityMask.DV_READONLY
|
||||||
|
};
|
||||||
|
})
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const resetSelected = () => {
|
||||||
|
setDeviceEntities((prev) =>
|
||||||
|
prev.map((de) => {
|
||||||
|
if (!selectedIds.has(de.id)) {
|
||||||
|
return de;
|
||||||
|
}
|
||||||
|
const next: DeviceEntity = { ...de, m: 0, c: false };
|
||||||
|
delete next.cn;
|
||||||
|
delete next.mi;
|
||||||
|
delete next.ma;
|
||||||
|
return next;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
setSelectedIds(new Set());
|
||||||
|
};
|
||||||
|
|
||||||
const resetCustomization = async () => {
|
const resetCustomization = async () => {
|
||||||
try {
|
try {
|
||||||
await sendResetCustomizations();
|
await sendResetCustomizations();
|
||||||
@@ -414,6 +460,8 @@ const Customizations = () => {
|
|||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
toast.success(LL.CUSTOMIZATIONS_SAVED());
|
toast.success(LL.CUSTOMIZATIONS_SAVED());
|
||||||
|
// Reload so cleared min/max fall back to the built-in limits and the modified flag matches the file.
|
||||||
|
void sendDeviceEntities(selectedDevice);
|
||||||
})
|
})
|
||||||
.catch((error: Error) => {
|
.catch((error: Error) => {
|
||||||
if (error.message === 'Reboot required') {
|
if (error.message === 'Reboot required') {
|
||||||
@@ -541,6 +589,34 @@ const Customizations = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const filteredEntities = deviceEntities.filter((de) => filter_entity(de));
|
const filteredEntities = deviceEntities.filter((de) => filter_entity(de));
|
||||||
|
const allFilteredSelected =
|
||||||
|
filteredEntities.length > 0 &&
|
||||||
|
filteredEntities.every((de) => selectedIds.has(de.id));
|
||||||
|
const someFilteredSelected = filteredEntities.some((de) => selectedIds.has(de.id));
|
||||||
|
|
||||||
|
const toggleSelected = (id: string) => {
|
||||||
|
setSelectedIds((prev) => {
|
||||||
|
const next = new Set(prev);
|
||||||
|
if (next.has(id)) {
|
||||||
|
next.delete(id);
|
||||||
|
} else {
|
||||||
|
next.add(id);
|
||||||
|
}
|
||||||
|
return next;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const toggleSelectFiltered = () => {
|
||||||
|
setSelectedIds((prev) => {
|
||||||
|
const next = new Set(prev);
|
||||||
|
if (allFilteredSelected) {
|
||||||
|
filteredEntities.forEach((de) => next.delete(de.id));
|
||||||
|
} else {
|
||||||
|
filteredEntities.forEach((de) => next.add(de.id));
|
||||||
|
}
|
||||||
|
return next;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const renderDeviceData = () => {
|
const renderDeviceData = () => {
|
||||||
return (
|
return (
|
||||||
@@ -608,6 +684,17 @@ const Customizations = () => {
|
|||||||
</ToggleButton>
|
</ToggleButton>
|
||||||
</ToggleButtonGroup>
|
</ToggleButtonGroup>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<Grid>
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
sx={{ fontSize: 10 }}
|
||||||
|
variant="outlined"
|
||||||
|
color={modifiedOnly ? 'secondary' : 'inherit'}
|
||||||
|
onClick={() => setModifiedOnly((current) => !current)}
|
||||||
|
>
|
||||||
|
{LL.MODIFIED()}
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
<Grid>
|
<Grid>
|
||||||
<Button
|
<Button
|
||||||
size="small"
|
size="small"
|
||||||
@@ -634,6 +721,43 @@ const Customizations = () => {
|
|||||||
<OptionIcon type="web_exclude" isSet={true} />
|
<OptionIcon type="web_exclude" isSet={true} />
|
||||||
</Button>
|
</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<Grid>
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
sx={{ fontSize: 10 }}
|
||||||
|
variant="outlined"
|
||||||
|
color="inherit"
|
||||||
|
onClick={() => maskReadonly(false)}
|
||||||
|
>
|
||||||
|
{LL.SET_ALL()}
|
||||||
|
<OptionIcon type="readonly" isSet={false} />
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
<Grid>
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
sx={{ fontSize: 10 }}
|
||||||
|
variant="outlined"
|
||||||
|
color="inherit"
|
||||||
|
onClick={() => maskReadonly(true)}
|
||||||
|
>
|
||||||
|
{LL.SET_ALL()}
|
||||||
|
<OptionIcon type="readonly" isSet={true} />
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
{selectedIds.size > 0 && (
|
||||||
|
<Grid>
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
sx={{ fontSize: 10 }}
|
||||||
|
variant="outlined"
|
||||||
|
color="error"
|
||||||
|
onClick={resetSelected}
|
||||||
|
>
|
||||||
|
{LL.RESET_SELECTED()} ({selectedIds.size})
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
<Grid>
|
<Grid>
|
||||||
<Typography variant="subtitle2" color="grey">
|
<Typography variant="subtitle2" color="grey">
|
||||||
{LL.SHOWING()} {filteredEntities.length}/{deviceEntities.length}
|
{LL.SHOWING()} {filteredEntities.length}/{deviceEntities.length}
|
||||||
@@ -650,6 +774,16 @@ const Customizations = () => {
|
|||||||
<>
|
<>
|
||||||
<Header>
|
<Header>
|
||||||
<HeaderRow>
|
<HeaderRow>
|
||||||
|
<HeaderCell stiff>
|
||||||
|
<Checkbox
|
||||||
|
size="small"
|
||||||
|
sx={{ p: 0, color: 'inherit' }}
|
||||||
|
checked={allFilteredSelected}
|
||||||
|
indeterminate={!allFilteredSelected && someFilteredSelected}
|
||||||
|
disabled={filteredEntities.length === 0}
|
||||||
|
onChange={toggleSelectFiltered}
|
||||||
|
/>
|
||||||
|
</HeaderCell>
|
||||||
<HeaderCell stiff>{LL.OPTIONS()}</HeaderCell>
|
<HeaderCell stiff>{LL.OPTIONS()}</HeaderCell>
|
||||||
<HeaderCell resize>{LL.NAME(1)}</HeaderCell>
|
<HeaderCell resize>{LL.NAME(1)}</HeaderCell>
|
||||||
<HeaderCell stiff>{LL.MIN()}</HeaderCell>
|
<HeaderCell stiff>{LL.MIN()}</HeaderCell>
|
||||||
@@ -660,6 +794,14 @@ const Customizations = () => {
|
|||||||
<Body>
|
<Body>
|
||||||
{tableList.map((de: DeviceEntity) => (
|
{tableList.map((de: DeviceEntity) => (
|
||||||
<Row key={de.id} item={de} onClick={() => editDeviceEntity(de)}>
|
<Row key={de.id} item={de} onClick={() => editDeviceEntity(de)}>
|
||||||
|
<Cell stiff onClick={(event) => event.stopPropagation()}>
|
||||||
|
<Checkbox
|
||||||
|
size="small"
|
||||||
|
sx={{ p: 0 }}
|
||||||
|
checked={selectedIds.has(de.id)}
|
||||||
|
onChange={() => toggleSelected(de.id)}
|
||||||
|
/>
|
||||||
|
</Cell>
|
||||||
<Cell stiff>
|
<Cell stiff>
|
||||||
<EntityMaskToggle onUpdate={updateDeviceEntity} de={de} />
|
<EntityMaskToggle onUpdate={updateDeviceEntity} de={de} />
|
||||||
</Cell>
|
</Cell>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { memo, useEffect, useState } from 'react';
|
|||||||
import CancelIcon from '@mui/icons-material/Cancel';
|
import CancelIcon from '@mui/icons-material/Cancel';
|
||||||
import CloseIcon from '@mui/icons-material/Close';
|
import CloseIcon from '@mui/icons-material/Close';
|
||||||
import DoneIcon from '@mui/icons-material/Done';
|
import DoneIcon from '@mui/icons-material/Done';
|
||||||
|
import SettingsBackupRestoreIcon from '@mui/icons-material/SettingsBackupRestore';
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Button,
|
Button,
|
||||||
@@ -101,6 +102,14 @@ const CustomizationsDialog = ({
|
|||||||
setEditItem((prev) => ({ ...prev, m: updatedItem.m }));
|
setEditItem((prev) => ({ ...prev, m: updatedItem.m }));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const remove = () => {
|
||||||
|
const next: DeviceEntity = { ...editItem, m: 0, c: false };
|
||||||
|
delete next.cn;
|
||||||
|
delete next.mi;
|
||||||
|
delete next.ma;
|
||||||
|
onSave(next);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog sx={dialogStyle} open={open} onClose={handleClose}>
|
<Dialog sx={dialogStyle} open={open} onClose={handleClose}>
|
||||||
<DialogTitle>{`${LL.EDIT()} ${LL.ENTITY()}`}</DialogTitle>
|
<DialogTitle>{`${LL.EDIT()} ${LL.ENTITY()}`}</DialogTitle>
|
||||||
@@ -169,6 +178,15 @@ const CustomizationsDialog = ({
|
|||||||
</DialogContent>
|
</DialogContent>
|
||||||
|
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
|
<Button
|
||||||
|
startIcon={<SettingsBackupRestoreIcon />}
|
||||||
|
variant="outlined"
|
||||||
|
onClick={remove}
|
||||||
|
color="error"
|
||||||
|
>
|
||||||
|
{LL.REMOVE()}
|
||||||
|
</Button>
|
||||||
|
<Box sx={{ flexGrow: 1 }} />
|
||||||
<Button
|
<Button
|
||||||
startIcon={<CancelIcon />}
|
startIcon={<CancelIcon />}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
|
|||||||
@@ -174,6 +174,7 @@ export interface DeviceEntity {
|
|||||||
w: boolean; // writeable
|
w: boolean; // writeable
|
||||||
mi?: number; // min value
|
mi?: number; // min value
|
||||||
ma?: number; // max value
|
ma?: number; // max value
|
||||||
|
c?: boolean; // true when a customization is saved (mask, name, or min/max)
|
||||||
o_m?: number; // original mask before edits
|
o_m?: number; // original mask before edits
|
||||||
o_cn?: string; // original cn before edits
|
o_cn?: string; // original cn before edits
|
||||||
o_mi?: number; // original min value
|
o_mi?: number; // original min value
|
||||||
|
|||||||
@@ -141,6 +141,8 @@ const cs: Translation = {
|
|||||||
CUSTOMIZATIONS_HELP_6: 'odstranit z paměti',
|
CUSTOMIZATIONS_HELP_6: 'odstranit z paměti',
|
||||||
SELECT_DEVICE: 'Vyberte zařízení',
|
SELECT_DEVICE: 'Vyberte zařízení',
|
||||||
SET_ALL: 'nastavit vše',
|
SET_ALL: 'nastavit vše',
|
||||||
|
MODIFIED: 'upravené',
|
||||||
|
RESET_SELECTED: 'Obnovit vybrané',
|
||||||
OPTIONS: 'Možnosti',
|
OPTIONS: 'Možnosti',
|
||||||
NAME: 'Název',
|
NAME: 'Název',
|
||||||
CUSTOMIZATIONS_RESET: 'Opravdu chcete odstranit všechna přizpůsobení?',
|
CUSTOMIZATIONS_RESET: 'Opravdu chcete odstranit všechna přizpůsobení?',
|
||||||
|
|||||||
@@ -141,6 +141,8 @@ const de: Translation = {
|
|||||||
CUSTOMIZATIONS_HELP_6: 'Aus dem Speicher entfernen',
|
CUSTOMIZATIONS_HELP_6: 'Aus dem Speicher entfernen',
|
||||||
SELECT_DEVICE: 'Wählen Sie ein Gerät aus',
|
SELECT_DEVICE: 'Wählen Sie ein Gerät aus',
|
||||||
SET_ALL: 'Setzen Sie alle',
|
SET_ALL: 'Setzen Sie alle',
|
||||||
|
MODIFIED: 'geändert',
|
||||||
|
RESET_SELECTED: 'Auswahl zurücksetzen',
|
||||||
OPTIONS: 'Optionen',
|
OPTIONS: 'Optionen',
|
||||||
NAME: 'Name',
|
NAME: 'Name',
|
||||||
CUSTOMIZATIONS_RESET: 'Möchten Sie wirklich alle Anpassungen entfernen?',
|
CUSTOMIZATIONS_RESET: 'Möchten Sie wirklich alle Anpassungen entfernen?',
|
||||||
|
|||||||
@@ -141,6 +141,8 @@ const en: Translation = {
|
|||||||
CUSTOMIZATIONS_HELP_6: 'remove from memory',
|
CUSTOMIZATIONS_HELP_6: 'remove from memory',
|
||||||
SELECT_DEVICE: 'Select a device',
|
SELECT_DEVICE: 'Select a device',
|
||||||
SET_ALL: 'set all',
|
SET_ALL: 'set all',
|
||||||
|
MODIFIED: 'modified',
|
||||||
|
RESET_SELECTED: 'Reset selected',
|
||||||
OPTIONS: 'Options',
|
OPTIONS: 'Options',
|
||||||
NAME: 'Name',
|
NAME: 'Name',
|
||||||
CUSTOMIZATIONS_RESET: 'Are you sure you want remove all the customizations?',
|
CUSTOMIZATIONS_RESET: 'Are you sure you want remove all the customizations?',
|
||||||
|
|||||||
@@ -141,6 +141,8 @@ const fr: Translation = {
|
|||||||
CUSTOMIZATIONS_HELP_6: 'supprimer de la mémoire',
|
CUSTOMIZATIONS_HELP_6: 'supprimer de la mémoire',
|
||||||
SELECT_DEVICE: 'Sélectionnez un appareil',
|
SELECT_DEVICE: 'Sélectionnez un appareil',
|
||||||
SET_ALL: 'tout régler',
|
SET_ALL: 'tout régler',
|
||||||
|
MODIFIED: 'modifié',
|
||||||
|
RESET_SELECTED: 'Réinitialiser la sélection',
|
||||||
OPTIONS: 'Options',
|
OPTIONS: 'Options',
|
||||||
NAME: 'Nom',
|
NAME: 'Nom',
|
||||||
CUSTOMIZATIONS_RESET: 'Êtes-vous sûr de vouloir supprimer toutes les personnalisations?',
|
CUSTOMIZATIONS_RESET: 'Êtes-vous sûr de vouloir supprimer toutes les personnalisations?',
|
||||||
|
|||||||
@@ -141,6 +141,8 @@ const it: Translation = {
|
|||||||
CUSTOMIZATIONS_HELP_6: 'rimuovi dalla memoria',
|
CUSTOMIZATIONS_HELP_6: 'rimuovi dalla memoria',
|
||||||
SELECT_DEVICE: 'Seleziona un dispositivo',
|
SELECT_DEVICE: 'Seleziona un dispositivo',
|
||||||
SET_ALL: 'imposta tutto',
|
SET_ALL: 'imposta tutto',
|
||||||
|
MODIFIED: 'modificato',
|
||||||
|
RESET_SELECTED: 'Reimposta selezionati',
|
||||||
OPTIONS: 'Opzioni',
|
OPTIONS: 'Opzioni',
|
||||||
NAME: 'Nome',
|
NAME: 'Nome',
|
||||||
CUSTOMIZATIONS_RESET: 'Sei sicuro di voler rimuovere tutte le personalizzazioni?',
|
CUSTOMIZATIONS_RESET: 'Sei sicuro di voler rimuovere tutte le personalizzazioni?',
|
||||||
|
|||||||
@@ -141,6 +141,8 @@ const nl: Translation = {
|
|||||||
CUSTOMIZATIONS_HELP_6: 'verwijderen van memory',
|
CUSTOMIZATIONS_HELP_6: 'verwijderen van memory',
|
||||||
SELECT_DEVICE: 'Selecteer een apparaat',
|
SELECT_DEVICE: 'Selecteer een apparaat',
|
||||||
SET_ALL: 'Alles aanzetten',
|
SET_ALL: 'Alles aanzetten',
|
||||||
|
MODIFIED: 'gewijzigd',
|
||||||
|
RESET_SELECTED: 'Selectie resetten',
|
||||||
OPTIONS: 'Opties',
|
OPTIONS: 'Opties',
|
||||||
NAME: 'Naam',
|
NAME: 'Naam',
|
||||||
CUSTOMIZATIONS_RESET: 'Weet je zeker dat je alle custom aanpassingen wilt verwijderen?',
|
CUSTOMIZATIONS_RESET: 'Weet je zeker dat je alle custom aanpassingen wilt verwijderen?',
|
||||||
|
|||||||
@@ -141,6 +141,8 @@ const no: Translation = {
|
|||||||
CUSTOMIZATIONS_HELP_6: 'fjern fra minnet',
|
CUSTOMIZATIONS_HELP_6: 'fjern fra minnet',
|
||||||
SELECT_DEVICE: 'Velg en enhet',
|
SELECT_DEVICE: 'Velg en enhet',
|
||||||
SET_ALL: 'sett alle',
|
SET_ALL: 'sett alle',
|
||||||
|
MODIFIED: 'endret',
|
||||||
|
RESET_SELECTED: 'Tilbakestill valgte',
|
||||||
OPTIONS: 'Alternativ',
|
OPTIONS: 'Alternativ',
|
||||||
NAME: 'Navn',
|
NAME: 'Navn',
|
||||||
CUSTOMIZATIONS_RESET: 'Er du sikker på att du vil fjerne tilpassninger?',
|
CUSTOMIZATIONS_RESET: 'Er du sikker på att du vil fjerne tilpassninger?',
|
||||||
|
|||||||
@@ -141,6 +141,8 @@ const pl: BaseTranslation = {
|
|||||||
CUSTOMIZATIONS_HELP_6: 'usuń z pamięci',
|
CUSTOMIZATIONS_HELP_6: 'usuń z pamięci',
|
||||||
SELECT_DEVICE: 'wybierz urządzenie',
|
SELECT_DEVICE: 'wybierz urządzenie',
|
||||||
SET_ALL: 'Ustaw wszystko jako',
|
SET_ALL: 'Ustaw wszystko jako',
|
||||||
|
MODIFIED: 'zmienione',
|
||||||
|
RESET_SELECTED: 'Resetuj zaznaczone',
|
||||||
OPTIONS: 'Opcje',
|
OPTIONS: 'Opcje',
|
||||||
NAME: '{{Nazwa|nazwa|}}',
|
NAME: '{{Nazwa|nazwa|}}',
|
||||||
CUSTOMIZATIONS_RESET: 'Na pewno chcesz usunąć wszystkie personalizacje?',
|
CUSTOMIZATIONS_RESET: 'Na pewno chcesz usunąć wszystkie personalizacje?',
|
||||||
|
|||||||
@@ -141,6 +141,8 @@ const sk: Translation = {
|
|||||||
CUSTOMIZATIONS_HELP_6: 'odstrániť z pamäte',
|
CUSTOMIZATIONS_HELP_6: 'odstrániť z pamäte',
|
||||||
SELECT_DEVICE: 'Zvoliť zariadenie',
|
SELECT_DEVICE: 'Zvoliť zariadenie',
|
||||||
SET_ALL: 'nastaviť všetko',
|
SET_ALL: 'nastaviť všetko',
|
||||||
|
MODIFIED: 'upravené',
|
||||||
|
RESET_SELECTED: 'Obnoviť vybrané',
|
||||||
OPTIONS: 'Možnosti',
|
OPTIONS: 'Možnosti',
|
||||||
NAME: 'Názov',
|
NAME: 'Názov',
|
||||||
CUSTOMIZATIONS_RESET: 'Naozaj chcete odstrániť všetky prispôsobenia?',
|
CUSTOMIZATIONS_RESET: 'Naozaj chcete odstrániť všetky prispôsobenia?',
|
||||||
|
|||||||
@@ -141,6 +141,8 @@ const sv: Translation = {
|
|||||||
CUSTOMIZATIONS_HELP_6: 'Ta bort',
|
CUSTOMIZATIONS_HELP_6: 'Ta bort',
|
||||||
SELECT_DEVICE: 'Välj en enhet',
|
SELECT_DEVICE: 'Välj en enhet',
|
||||||
SET_ALL: 'ställ in alla',
|
SET_ALL: 'ställ in alla',
|
||||||
|
MODIFIED: 'ändrade',
|
||||||
|
RESET_SELECTED: 'Återställ markerade',
|
||||||
OPTIONS: 'Alternativ',
|
OPTIONS: 'Alternativ',
|
||||||
NAME: 'Namn',
|
NAME: 'Namn',
|
||||||
CUSTOMIZATIONS_RESET: 'Är du säker på att du vill ta bort alla anpassningar?',
|
CUSTOMIZATIONS_RESET: 'Är du säker på att du vill ta bort alla anpassningar?',
|
||||||
|
|||||||
@@ -141,6 +141,8 @@ const tr: Translation = {
|
|||||||
CUSTOMIZATIONS_HELP_6: 'remove from memory',
|
CUSTOMIZATIONS_HELP_6: 'remove from memory',
|
||||||
SELECT_DEVICE: 'Bir cihaz seç',
|
SELECT_DEVICE: 'Bir cihaz seç',
|
||||||
SET_ALL: 'hepsini ayarla',
|
SET_ALL: 'hepsini ayarla',
|
||||||
|
MODIFIED: 'değiştirilmiş',
|
||||||
|
RESET_SELECTED: 'Seçilenleri sıfırla',
|
||||||
OPTIONS: 'Seçenekler',
|
OPTIONS: 'Seçenekler',
|
||||||
NAME: 'İsim',
|
NAME: 'İsim',
|
||||||
CUSTOMIZATIONS_RESET: 'Bütün özelleştirmeleri kaldırmak istediğinizden emin misiniz?',
|
CUSTOMIZATIONS_RESET: 'Bütün özelleştirmeleri kaldırmak istediğinizden emin misiniz?',
|
||||||
|
|||||||
@@ -1193,6 +1193,12 @@ void EMSdevice::generate_values_web_customization(JsonArray output) {
|
|||||||
// 0x10 = 16 = DV_WEB_EXCLUDE
|
// 0x10 = 16 = DV_WEB_EXCLUDE
|
||||||
obj["m"] = dv.state >> 4;
|
obj["m"] = dv.state >> 4;
|
||||||
|
|
||||||
|
// Saved customization: mask bits, or a custom name/min/max stored in custom_fullname.
|
||||||
|
// Min/max in "mi"/"ma" are the effective limits, so they alone do not show a customization.
|
||||||
|
if (dv.has_custom_fullname() || (dv.state >> 4) != 0) {
|
||||||
|
obj["c"] = true;
|
||||||
|
}
|
||||||
|
|
||||||
obj["w"] = dv.has_cmd; // if writable
|
obj["w"] = dv.has_cmd; // if writable
|
||||||
|
|
||||||
if (dv.has_cmd && (obj["v"].is<float>() || obj["v"].is<int>())) {
|
if (dv.has_cmd && (obj["v"].is<float>() || obj["v"].is<int>())) {
|
||||||
@@ -1219,6 +1225,7 @@ void EMSdevice::generate_values_web_customization(JsonArray output) {
|
|||||||
JsonObject obj = output.add<JsonObject>();
|
JsonObject obj = output.add<JsonObject>();
|
||||||
obj["id"] = DeviceValue::get_name(entity_id); // set the name, it could be custom following a '|'
|
obj["id"] = DeviceValue::get_name(entity_id); // set the name, it could be custom following a '|'
|
||||||
obj["m"] = mask; // update the mask
|
obj["m"] = mask; // update the mask
|
||||||
|
obj["c"] = true;
|
||||||
obj["w"] = false; // not writeable as it won't be shown
|
obj["w"] = false; // not writeable as it won't be shown
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user