This commit is contained in:
Proddy
2023-02-04 14:25:29 +01:00
parent 6dc63907f1
commit 6c46770330
25 changed files with 506 additions and 410 deletions

View File

@@ -25,14 +25,16 @@ import { useSnackbar } from 'notistack';
import WarningIcon from '@mui/icons-material/Warning';
import CancelIcon from '@mui/icons-material/Cancel';
import DoneIcon from '@mui/icons-material/Done';
import SettingsBackupRestoreIcon from '@mui/icons-material/SettingsBackupRestore';
import SearchIcon from '@mui/icons-material/Search';
import FilterListIcon from '@mui/icons-material/FilterList';
import PowerSettingsNewIcon from '@mui/icons-material/PowerSettingsNew';
import OptionIcon from './OptionIcon';
import { ButtonRow, FormLoader, ValidatedTextField, SectionContent } from '../components';
import { ButtonRow, FormLoader, ValidatedTextField, SectionContent, MessageBox } from '../components';
import * as EMSESP from './api';
@@ -42,15 +44,18 @@ import { DeviceShort, Devices, DeviceEntity, DeviceEntityMask } from './types';
import { useI18nContext } from '../i18n/i18n-react';
import RestartMonitor from '../framework/system/RestartMonitor';
export const APIURL = window.location.origin + '/api/';
const SettingsCustomization: FC = () => {
const { LL } = useI18nContext();
const { enqueueSnackbar } = useSnackbar();
const emptyDeviceEntity = { id: '', v: 0, n: '', cn: '', m: 0, w: false };
const [restarting, setRestarting] = useState<boolean>(false);
const [restartNeeded, setRestartNeeded] = useState<boolean>(false);
const [deviceEntities, setDeviceEntities] = useState<DeviceEntity[]>([emptyDeviceEntity]);
const [devices, setDevices] = useState<Devices>();
const [errorMessage, setErrorMessage] = useState<string>();
@@ -58,15 +63,13 @@ const SettingsCustomization: FC = () => {
const [confirmReset, setConfirmReset] = useState<boolean>(false);
const [selectedFilters, setSelectedFilters] = useState<number>(0);
const [search, setSearch] = useState('');
const [deviceEntity, setDeviceEntity] = useState<DeviceEntity>();
// eslint-disable-next-line
const [masks, setMasks] = useState(() => ['']);
const entities_theme = useTheme({
Table: `
--data-table-library_grid-template-columns: 120px repeat(1, minmax(80px, 1fr)) 45px 45px 120px;
--data-table-library_grid-template-columns: 150px repeat(1, minmax(80px, 1fr)) 45px 45px 120px;
`,
BaseRow: `
font-size: 14px;
@@ -210,6 +213,9 @@ const SettingsCustomization: FC = () => {
if ((m & 8) === 8) {
new_masks.push('8');
}
if ((m & 128) === 128) {
new_masks.push('128');
}
return new_masks;
};
@@ -235,6 +241,7 @@ const SettingsCustomization: FC = () => {
const selected_device = parseInt(event.target.value, 10);
setSelectedDevice(selected_device);
fetchDeviceEntities(devices?.devices[selected_device].i);
setRestartNeeded(false);
}
};
@@ -271,6 +278,15 @@ const SettingsCustomization: FC = () => {
);
};
const restart = async () => {
try {
await EMSESP.restart();
setRestarting(true);
} catch (error) {
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
}
};
const saveCustomization = async () => {
if (devices && deviceEntities && selectedDevice !== -1) {
const masked_entities = getChanges();
@@ -289,6 +305,8 @@ const SettingsCustomization: FC = () => {
});
if (response.status === 200) {
enqueueSnackbar(LL.CUSTOMIZATIONS_SAVED(), { variant: 'success' });
} else if (response.status === 201) {
setRestartNeeded(true);
} else {
enqueueSnackbar(LL.PROBLEM_UPDATING(), { variant: 'error' });
}
@@ -312,7 +330,8 @@ const SettingsCustomization: FC = () => {
<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()}
<OptionIcon type="web_exclude" isSet={true} />={LL.CUSTOMIZATIONS_HELP_5()}&nbsp;&nbsp;
<OptionIcon type="deleted" isSet={true} />={LL.CUSTOMIZATIONS_HELP_6()}
</Typography>
</Box>
<ValidatedTextField
@@ -425,6 +444,9 @@ const SettingsCustomization: FC = () => {
<ToggleButton value="1">
<OptionIcon type="web_exclude" isSet={true} />
</ToggleButton>
<ToggleButton value="128">
<OptionIcon type="deleted" isSet={true} />
</ToggleButton>
</ToggleButtonGroup>
</Grid>
@@ -479,53 +501,63 @@ const SettingsCustomization: FC = () => {
{tableList.map((de: DeviceEntity) => (
<Row key={de.id} item={de} onClick={() => editEntity(de)}>
<Cell stiff>
<ToggleButtonGroup
size="small"
color="secondary"
value={getMaskString(de.m)}
onChange={(event, mask) => {
de.m = getMaskNumber(mask);
if (de.n === '' && de.m & DeviceEntityMask.DV_READONLY) {
de.m = de.m | DeviceEntityMask.DV_WEB_EXCLUDE;
}
if (de.m & DeviceEntityMask.DV_WEB_EXCLUDE) {
de.m = de.m & ~DeviceEntityMask.DV_FAVORITE;
}
setMasks(['']);
}}
>
<ToggleButton value="8" disabled={(de.m & 1) !== 0 || de.n === undefined}>
<OptionIcon
type="favorite"
isSet={(de.m & DeviceEntityMask.DV_FAVORITE) === DeviceEntityMask.DV_FAVORITE}
/>
</ToggleButton>
<ToggleButton value="4" disabled={!de.w || (de.m & 3) === 3}>
<OptionIcon
type="readonly"
isSet={(de.m & DeviceEntityMask.DV_READONLY) === DeviceEntityMask.DV_READONLY}
/>
</ToggleButton>
<ToggleButton value="2" disabled={de.n === ''}>
<OptionIcon
type="api_mqtt_exclude"
isSet={
(de.m & DeviceEntityMask.DV_API_MQTT_EXCLUDE) === DeviceEntityMask.DV_API_MQTT_EXCLUDE
{!deviceEntity && (
<ToggleButtonGroup
size="small"
color="secondary"
value={getMaskString(de.m)}
onChange={(event, mask) => {
de.m = getMaskNumber(mask);
if (de.n === '' && de.m & DeviceEntityMask.DV_READONLY) {
de.m = de.m | DeviceEntityMask.DV_WEB_EXCLUDE;
}
/>
</ToggleButton>
<ToggleButton value="1" disabled={de.n === undefined}>
<OptionIcon
type="web_exclude"
isSet={(de.m & DeviceEntityMask.DV_WEB_EXCLUDE) === DeviceEntityMask.DV_WEB_EXCLUDE}
/>
</ToggleButton>
</ToggleButtonGroup>
if (de.m & DeviceEntityMask.DV_WEB_EXCLUDE) {
de.m = de.m & ~DeviceEntityMask.DV_FAVORITE;
}
setMasks(['']);
}}
>
<ToggleButton value="8" disabled={(de.m & 0x81) !== 0 || de.n === undefined}>
<OptionIcon
type="favorite"
isSet={(de.m & DeviceEntityMask.DV_FAVORITE) === DeviceEntityMask.DV_FAVORITE}
/>
</ToggleButton>
<ToggleButton value="4" disabled={!de.w || (de.m & 0x83) >= 3}>
<OptionIcon
type="readonly"
isSet={(de.m & DeviceEntityMask.DV_READONLY) === DeviceEntityMask.DV_READONLY}
/>
</ToggleButton>
<ToggleButton value="2" disabled={de.n === '' || (de.m & 0x80) !== 0}>
<OptionIcon
type="api_mqtt_exclude"
isSet={
(de.m & DeviceEntityMask.DV_API_MQTT_EXCLUDE) === DeviceEntityMask.DV_API_MQTT_EXCLUDE
}
/>
</ToggleButton>
<ToggleButton value="1" disabled={de.n === undefined || (de.m & 0x80) !== 0}>
<OptionIcon
type="web_exclude"
isSet={(de.m & DeviceEntityMask.DV_WEB_EXCLUDE) === DeviceEntityMask.DV_WEB_EXCLUDE}
/>
</ToggleButton>
<ToggleButton value="128">
<OptionIcon
type="deleted"
isSet={(de.m & DeviceEntityMask.DV_DELETED) === DeviceEntityMask.DV_DELETED}
/>
</ToggleButton>
</ToggleButtonGroup>
)}
</Cell>
<Cell>{formatName(de)}</Cell>
<Cell>{!(de.m & DeviceEntityMask.DV_READONLY) && formatValue(de.mi)}</Cell>
<Cell>{!(de.m & DeviceEntityMask.DV_READONLY) && formatValue(de.ma)}</Cell>
<Cell>{formatValue(de.v)}</Cell>
<Cell>{!deviceEntity && formatName(de)}</Cell>
<Cell>{!deviceEntity && !(de.m & DeviceEntityMask.DV_READONLY) && formatValue(de.mi)}</Cell>
<Cell>{!deviceEntity && !(de.m & DeviceEntityMask.DV_READONLY) && formatValue(de.ma)}</Cell>
<Cell>{!deviceEntity && formatValue(de.v)}</Cell>
</Row>
))}
</Body>
@@ -567,32 +599,41 @@ const SettingsCustomization: FC = () => {
</Typography>
{renderDeviceList()}
{renderDeviceData()}
<Box display="flex" flexWrap="wrap">
<Box flexGrow={1}>
<ButtonRow>
{restartNeeded && (
<MessageBox my={2} level="warning" message={LL.RESTART_TEXT()}>
<Button startIcon={<PowerSettingsNewIcon />} variant="contained" color="error" onClick={restart}>
{LL.RESTART()}
</Button>
</MessageBox>
)}
{!restartNeeded && (
<Box display="flex" flexWrap="wrap">
<Box flexGrow={1}>
{num_changes !== 0 && (
<Button
startIcon={<WarningIcon color="warning" />}
variant="contained"
color="info"
onClick={() => saveCustomization()}
>
{LL.APPLY_CHANGES(num_changes)}
</Button>
<ButtonRow>
<Button
startIcon={<WarningIcon color="warning" />}
variant="contained"
color="info"
onClick={() => saveCustomization()}
>
{LL.APPLY_CHANGES(num_changes)}
</Button>
</ButtonRow>
)}
</Box>
<ButtonRow>
<Button
startIcon={<SettingsBackupRestoreIcon />}
variant="outlined"
color="error"
onClick={() => setConfirmReset(true)}
>
{LL.RESET(0)}
</Button>
</ButtonRow>
</Box>
<ButtonRow>
<Button
startIcon={<SettingsBackupRestoreIcon />}
variant="outlined"
color="error"
onClick={() => setConfirmReset(true)}
>
{LL.RESET(0)}
</Button>
</ButtonRow>
</Box>
)}
{renderResetDialog()}
</>
);
@@ -655,11 +696,11 @@ const SettingsCustomization: FC = () => {
{LL.CANCEL()}
</Button>
<Button
startIcon={<WarningIcon color="warning" />}
variant="contained"
startIcon={<DoneIcon />}
variant="outlined"
type="submit"
onClick={() => updateEntity()}
color="info"
color="primary"
>
{LL.UPDATE()}
</Button>
@@ -671,7 +712,7 @@ const SettingsCustomization: FC = () => {
return (
<SectionContent title={LL.CUSTOMIZATIONS()} titleGutter>
{renderContent()}
{restarting ? <RestartMonitor /> : renderContent()}
{renderEditDialog()}
</SectionContent>
);