@iobroker/dm-gui-components 10.0.22 → 10.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -0
- package/build/AnimatedIcons.d.ts +37 -0
- package/build/AnimatedIcons.js +108 -0
- package/build/AnimatedIcons.js.map +1 -0
- package/build/Communication.d.ts +7 -0
- package/build/Communication.js +43 -11
- package/build/Communication.js.map +1 -1
- package/build/DeviceCard.d.ts +25 -13
- package/build/DeviceCard.js +177 -282
- package/build/DeviceCard.js.map +1 -1
- package/build/DeviceControl.js +38 -26
- package/build/DeviceControl.js.map +1 -1
- package/build/DeviceImageUpload.d.ts +5 -1
- package/build/DeviceImageUpload.js +79 -62
- package/build/DeviceImageUpload.js.map +1 -1
- package/build/DeviceList.d.ts +8 -0
- package/build/DeviceList.js +74 -59
- package/build/DeviceList.js.map +1 -1
- package/build/DeviceStatus.d.ts +20 -4
- package/build/DeviceStatus.js +146 -191
- package/build/DeviceStatus.js.map +1 -1
- package/build/StatusIndicator.js +9 -37
- package/build/StatusIndicator.js.map +1 -1
- package/build/StatusPill.d.ts +18 -0
- package/build/StatusPill.js +30 -0
- package/build/StatusPill.js.map +1 -0
- package/build/Switch.d.ts +3 -0
- package/build/Switch.js +36 -26
- package/build/Switch.js.map +1 -1
- package/build/Utils.js +92 -60
- package/build/Utils.js.map +1 -1
- package/build/i18n/de.json +3 -0
- package/build/i18n/en.json +3 -0
- package/build/i18n/es.json +3 -0
- package/build/i18n/fr.json +3 -0
- package/build/i18n/it.json +3 -0
- package/build/i18n/nl.json +3 -0
- package/build/i18n/pl.json +3 -0
- package/build/i18n/pt.json +3 -0
- package/build/i18n/ru.json +3 -0
- package/build/i18n/uk.json +3 -0
- package/build/i18n/zh-cn.json +3 -0
- package/build/styles.d.ts +17 -0
- package/build/styles.js +226 -0
- package/build/styles.js.map +1 -0
- package/package.json +10 -10
package/build/DeviceList.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { IconButton, InputAdornment, TextField, Toolbar, Tooltip, LinearProgress, Select, MenuItem,
|
|
3
|
-
import { ArrowBack, Clear,
|
|
4
|
-
import { I18n, DeviceTypeIcon, Icon, InfoBox } from '@iobroker/gui-components';
|
|
2
|
+
import { Button, ButtonBase, IconButton, InputAdornment, TextField, Toolbar, Tooltip, LinearProgress, Select, MenuItem, Typography, Menu, Checkbox, ListSubheader, } from '@mui/material';
|
|
3
|
+
import { ArrowBack, Clear, DevicesOther, QuestionMark, FilterAltOff, Tune } from '@mui/icons-material';
|
|
4
|
+
import { I18n, DeviceTypeIcon, Icon, IconConnectionState, IconFilter, IconRefresh, InfoBox, } from '@iobroker/gui-components';
|
|
5
5
|
import DeviceCard, { DeviceCardSkeleton, CARD_WIDTH, CARD_MIN_HEIGHT, CARD_MARGIN, SMALL_CARD_WIDTH, SMALL_CARD_MIN_HEIGHT, SMALL_CARD_MARGIN, } from './DeviceCard';
|
|
6
6
|
import { getTranslation, renderIcon } from './Utils';
|
|
7
7
|
import Communication from './Communication';
|
|
@@ -10,6 +10,8 @@ import { StatusIndicators } from './StatusIndicator';
|
|
|
10
10
|
import { StateOrObjectHandler } from './StateOrObjectHandler';
|
|
11
11
|
import { DeviceFieldsResolver } from './DeviceFields';
|
|
12
12
|
import { LazyRender, LazyRenderObserver } from './LazyRender';
|
|
13
|
+
import { IconBattery, IconUpdate } from './AnimatedIcons';
|
|
14
|
+
import { ensureDmStyles, getThemeVars } from './styles';
|
|
13
15
|
import de from './i18n/de.json';
|
|
14
16
|
import en from './i18n/en.json';
|
|
15
17
|
import ru from './i18n/ru.json';
|
|
@@ -107,6 +109,7 @@ export default class DeviceList extends Communication {
|
|
|
107
109
|
hiddenIndicatorsCache = null;
|
|
108
110
|
constructor(props) {
|
|
109
111
|
super(props);
|
|
112
|
+
ensureDmStyles();
|
|
110
113
|
this.stateOrObjectHandler = new StateOrObjectHandler(this.props.socket);
|
|
111
114
|
this.fieldsResolver = new DeviceFieldsResolver(this.stateOrObjectHandler, this.onFieldsChanged);
|
|
112
115
|
if (!DeviceList.i18nInitialized) {
|
|
@@ -518,46 +521,60 @@ export default class DeviceList extends Communication {
|
|
|
518
521
|
}
|
|
519
522
|
const instanceIds = Object.keys(this.state.dmInstances);
|
|
520
523
|
if (!instanceIds.length) {
|
|
521
|
-
return [
|
|
522
|
-
React.createElement("div", { style: { padding: 25 }, key: "noInstances" },
|
|
523
|
-
React.createElement("span", null, getTranslation('noInstancesFoundText'))),
|
|
524
|
-
];
|
|
525
|
-
}
|
|
526
|
-
const backgroundColor = this.props.theme.palette.mode === 'dark' ? '#0b0b0b' : '#d5d5d5';
|
|
527
|
-
if (this.props.smallCards) {
|
|
528
|
-
return instanceIds.map(id => {
|
|
529
|
-
const info = this.state.dmInstances[id];
|
|
530
|
-
return (React.createElement(Card, { key: id, sx: { width: 200, margin: '5px', backgroundColor } },
|
|
531
|
-
React.createElement(CardActionArea, { onClick: () => this.selectInstance(id), style: { height: '100%' } },
|
|
532
|
-
React.createElement(CardContent, { style: {
|
|
533
|
-
height: '100%',
|
|
534
|
-
display: 'flex',
|
|
535
|
-
alignItems: 'center',
|
|
536
|
-
gap: 8,
|
|
537
|
-
padding: 8,
|
|
538
|
-
} },
|
|
539
|
-
info.icon ? (React.createElement(Icon, { src: info.icon, style: { width: 32, height: 32, flexShrink: 0 } })) : (React.createElement(QuestionMark, { style: { width: 32, height: 32, flexShrink: 0 } })),
|
|
540
|
-
React.createElement("div", { style: { overflow: 'hidden' } },
|
|
541
|
-
React.createElement(Typography, { variant: "body1", noWrap: true, style: { fontSize: 14, fontWeight: 'bold' } }, id),
|
|
542
|
-
info.title ? (React.createElement(Typography, { variant: "caption", color: "textSecondary", noWrap: true, component: "div" }, info.title)) : null)))));
|
|
543
|
-
});
|
|
524
|
+
return [this.renderEmpty('noInstances', getTranslation('noInstancesFoundText'))];
|
|
544
525
|
}
|
|
526
|
+
const small = !!this.props.smallCards;
|
|
545
527
|
return instanceIds.map(id => {
|
|
546
528
|
const info = this.state.dmInstances[id];
|
|
547
|
-
return (React.createElement(
|
|
548
|
-
React.createElement(
|
|
549
|
-
React.createElement(
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
alignItems: 'center',
|
|
554
|
-
gap: 8,
|
|
555
|
-
} },
|
|
556
|
-
info.icon ? (React.createElement(Icon, { src: info.icon, style: { width: 64, height: 64 } })) : (React.createElement(QuestionMark, { style: { width: 64, height: 64 } })),
|
|
557
|
-
React.createElement(Typography, { variant: "h6", style: { textAlign: 'center', wordBreak: 'break-all' } }, id),
|
|
558
|
-
info.title ? (React.createElement(Typography, { variant: "body2", color: "textSecondary", style: { textAlign: 'center' } }, info.title)) : null))));
|
|
529
|
+
return (React.createElement("div", { key: id, className: small ? 'dm-card dm-inst dm-inst-small' : 'dm-card dm-inst' },
|
|
530
|
+
React.createElement(ButtonBase, { className: "dm-inst-area", onClick: () => this.selectInstance(id) },
|
|
531
|
+
React.createElement("div", { className: "dm-avatar" }, info.icon ? (React.createElement(Icon, { src: info.icon, style: { width: '100%', height: '100%', objectFit: 'contain' } })) : (React.createElement(QuestionMark, { style: { width: '70%', height: '70%' } }))),
|
|
532
|
+
React.createElement("div", { className: "dm-inst-text" },
|
|
533
|
+
React.createElement("div", { className: "dm-inst-id" }, id),
|
|
534
|
+
info.title ? React.createElement("div", { className: "dm-inst-title" }, info.title) : null))));
|
|
559
535
|
});
|
|
560
536
|
}
|
|
537
|
+
/** True if any filter hides devices: the text, the group or one of the toggles */
|
|
538
|
+
hasActiveFilter() {
|
|
539
|
+
return (!!this.state.filterText ||
|
|
540
|
+
this.state.onlyUpdatable ||
|
|
541
|
+
this.state.onlyBatteryProblem ||
|
|
542
|
+
(!!this.state.groupKey && this.state.groupKey !== '_'));
|
|
543
|
+
}
|
|
544
|
+
/** Removes all filters at once */
|
|
545
|
+
resetFilters() {
|
|
546
|
+
if (this.filterTimeout) {
|
|
547
|
+
clearTimeout(this.filterTimeout);
|
|
548
|
+
this.filterTimeout = null;
|
|
549
|
+
}
|
|
550
|
+
window.localStorage.setItem('dm_onlyUpdatable', 'false');
|
|
551
|
+
window.localStorage.setItem('dm_onlyBatteryProblem', 'false');
|
|
552
|
+
window.localStorage.removeItem(`dm_group_${this.state.selectedInstance}`);
|
|
553
|
+
this.setState({
|
|
554
|
+
filter: '',
|
|
555
|
+
filterText: '',
|
|
556
|
+
onlyUpdatable: false,
|
|
557
|
+
onlyBatteryProblem: false,
|
|
558
|
+
groupKey: '',
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
/** An empty list says what happened and, if possible, what to do */
|
|
562
|
+
renderEmpty(key, text, icon, action) {
|
|
563
|
+
return (React.createElement("div", { key: key, className: "dm-empty", style: getThemeVars(this.props.theme) },
|
|
564
|
+
icon,
|
|
565
|
+
React.createElement("span", null, text),
|
|
566
|
+
action));
|
|
567
|
+
}
|
|
568
|
+
/** The filter symbol in the toolbar. While a filter is set, a red cross shows that a click removes all filters */
|
|
569
|
+
renderFilterButton() {
|
|
570
|
+
const active = this.hasActiveFilter();
|
|
571
|
+
if (!active) {
|
|
572
|
+
return React.createElement(IconFilter, { active: false });
|
|
573
|
+
}
|
|
574
|
+
return (React.createElement(Tooltip, { title: getTranslation('resetFiltersTooltip'), slotProps: { popper: { sx: { pointerEvents: 'none' } } } },
|
|
575
|
+
React.createElement(IconButton, { color: "inherit", size: "small", onClick: () => this.resetFilters(), style: { margin: -5 } },
|
|
576
|
+
React.createElement(IconFilter, { active: true }))));
|
|
577
|
+
}
|
|
561
578
|
/**
|
|
562
579
|
* Apply the text filter and the "only updatable" / "only battery problem" filters.
|
|
563
580
|
*
|
|
@@ -770,9 +787,6 @@ export default class DeviceList extends Communication {
|
|
|
770
787
|
return (React.createElement("div", { style: { marginLeft: 20 } }, actions.map(action => (React.createElement(InstanceActionButton, { key: action.id, action: action, instanceHandler: this.instanceHandler })))));
|
|
771
788
|
}
|
|
772
789
|
renderContent() {
|
|
773
|
-
const emptyStyle = {
|
|
774
|
-
padding: 25,
|
|
775
|
-
};
|
|
776
790
|
const deviceGroups = [];
|
|
777
791
|
const showRootPage = !this.props.embedded && this.props.selectedInstance === undefined && !this.state.selectedInstance;
|
|
778
792
|
let list;
|
|
@@ -782,15 +796,13 @@ export default class DeviceList extends Communication {
|
|
|
782
796
|
}
|
|
783
797
|
else if (!this.props.embedded && !this.state.alive) {
|
|
784
798
|
list = [
|
|
785
|
-
|
|
786
|
-
|
|
799
|
+
this.renderEmpty('notAlive', getTranslation('instanceNotAlive'),
|
|
800
|
+
// `null` while the state is still unknown: nothing is known yet, so no symbol
|
|
801
|
+
this.state.alive === false ? React.createElement(IconConnectionState, { state: "disconnected" }) : null),
|
|
787
802
|
];
|
|
788
803
|
}
|
|
789
804
|
else if (!this.state.devices.length && this.state.selectedInstance && !this.state.loading) {
|
|
790
|
-
list = [
|
|
791
|
-
React.createElement("div", { style: emptyStyle, key: "notFound" },
|
|
792
|
-
React.createElement("span", null, getTranslation('noDevicesFoundText'))),
|
|
793
|
-
];
|
|
805
|
+
list = [this.renderEmpty('notFound', getTranslation('noDevicesFoundText'), React.createElement(DevicesOther, null))];
|
|
794
806
|
}
|
|
795
807
|
else {
|
|
796
808
|
// build a device types list
|
|
@@ -869,15 +881,11 @@ export default class DeviceList extends Communication {
|
|
|
869
881
|
else if (!visibleDevices.length && this.state.devices.length > 0) {
|
|
870
882
|
// The filter is applied here now, so the list knows that nothing is left instead
|
|
871
883
|
// of having to hide the message with a CSS rule
|
|
872
|
-
list.push(React.createElement(
|
|
873
|
-
React.createElement("span", null, getTranslation('allDevicesFilteredOut'))));
|
|
884
|
+
list.push(this.renderEmpty('filtered', getTranslation('allDevicesFilteredOut'), React.createElement(IconFilter, { active: !this.props.embedded }), this.props.embedded ? null : (React.createElement(Button, { variant: "outlined", color: "primary", onClick: () => this.resetFilters() }, getTranslation('resetFilters')))));
|
|
874
885
|
}
|
|
875
886
|
}
|
|
876
887
|
else {
|
|
877
|
-
list = [
|
|
878
|
-
React.createElement("div", { style: emptyStyle, key: "selectInstance" },
|
|
879
|
-
React.createElement("span", null, getTranslation('selectInstanceText'))),
|
|
880
|
-
];
|
|
888
|
+
list = [this.renderEmpty('selectInstance', getTranslation('selectInstanceText'))];
|
|
881
889
|
}
|
|
882
890
|
}
|
|
883
891
|
if (this.props.embedded) {
|
|
@@ -885,7 +893,14 @@ export default class DeviceList extends Communication {
|
|
|
885
893
|
this.state.loading ? React.createElement(LinearProgress, { style: { width: '100%' } }) : null,
|
|
886
894
|
this.state.apiVersionError ? React.createElement("div", null, I18n.t('apiVersionError')) : list));
|
|
887
895
|
}
|
|
888
|
-
return (React.createElement("div", { style: {
|
|
896
|
+
return (React.createElement("div", { style: {
|
|
897
|
+
...getThemeVars(this.props.theme),
|
|
898
|
+
width: '100%',
|
|
899
|
+
height: '100%',
|
|
900
|
+
overflow: 'hidden',
|
|
901
|
+
display: 'flex',
|
|
902
|
+
flexDirection: 'column',
|
|
903
|
+
} },
|
|
889
904
|
React.createElement(Toolbar, { variant: "dense", sx: TOOLBAR_SX, style: {
|
|
890
905
|
display: 'flex',
|
|
891
906
|
flexWrap: 'wrap',
|
|
@@ -905,11 +920,11 @@ export default class DeviceList extends Communication {
|
|
|
905
920
|
this.props.selectedInstance === undefined && !this.state.selectedInstance ? (React.createElement(Tooltip, { title: getTranslation('refreshInstanceList'), slotProps: { popper: { sx: { pointerEvents: 'none' } } } },
|
|
906
921
|
React.createElement("span", null,
|
|
907
922
|
React.createElement(IconButton, { onClick: () => this.refreshInstanceList(), disabled: !this.state.dmInstances, color: "inherit", size: "small" },
|
|
908
|
-
React.createElement(
|
|
923
|
+
React.createElement(IconRefresh, { loading: !this.state.dmInstances }))))) : null,
|
|
909
924
|
this.state.selectedInstance ? (React.createElement(Tooltip, { title: getTranslation('refreshTooltip'), slotProps: { popper: { sx: { pointerEvents: 'none' } } } },
|
|
910
925
|
React.createElement("span", null,
|
|
911
926
|
React.createElement(IconButton, { onClick: () => this.loadAllData(), disabled: !this.state.alive || this.state.apiVersionError, color: "inherit", size: "small" },
|
|
912
|
-
React.createElement(
|
|
927
|
+
React.createElement(IconRefresh, { loading: !!this.state.loading }))))) : null,
|
|
913
928
|
!this.state.apiVersionError && this.state.alive && this.renderInstanceActions(),
|
|
914
929
|
!this.state.apiVersionError && this.state.alive && this.state.instanceInfo?.indicators?.length ? (React.createElement(StatusIndicators, { indicators: this.state.instanceInfo.indicators.filter(indicator => this.isIndicatorVisible(indicator)), theme: this.props.theme, stateOrObjectHandler: this.stateOrObjectHandler, resolveAction: this.resolveInstanceIndicatorAction, defaultColor: "#fff", style: { marginLeft: 20 } })) : null,
|
|
915
930
|
React.createElement("div", { style: { flexGrow: 1 } }),
|
|
@@ -922,7 +937,7 @@ export default class DeviceList extends Communication {
|
|
|
922
937
|
this.setState({ onlyUpdatable });
|
|
923
938
|
window.localStorage.setItem('dm_onlyUpdatable', onlyUpdatable ? 'true' : 'false');
|
|
924
939
|
}, size: "small" },
|
|
925
|
-
React.createElement(
|
|
940
|
+
React.createElement(IconUpdate, null)))) : null,
|
|
926
941
|
!this.state.apiVersionError &&
|
|
927
942
|
this.state.alive &&
|
|
928
943
|
this.state.devices.some(device => hasBatteryStatus(device.status)) ? (React.createElement(Tooltip, { title: getTranslation('onlyBatteryProblemTooltip'), slotProps: { popper: { sx: { pointerEvents: 'none' } } } },
|
|
@@ -931,10 +946,10 @@ export default class DeviceList extends Communication {
|
|
|
931
946
|
this.setState({ onlyBatteryProblem });
|
|
932
947
|
window.localStorage.setItem('dm_onlyBatteryProblem', onlyBatteryProblem ? 'true' : 'false');
|
|
933
948
|
}, size: "small" },
|
|
934
|
-
React.createElement(
|
|
949
|
+
React.createElement(IconBattery, { level: 10 })))) : null,
|
|
935
950
|
!this.state.apiVersionError && this.state.alive ? this.renderIndicatorSettings() : null,
|
|
936
951
|
!this.state.apiVersionError && this.state.alive ? (React.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' } },
|
|
937
|
-
|
|
952
|
+
this.renderFilterButton(),
|
|
938
953
|
this.renderFilterFields(),
|
|
939
954
|
this.renderFilterValue())) : null,
|
|
940
955
|
React.createElement(Typography, { sx: { display: { xs: 'none', md: 'block' } }, style: {
|