@iobroker/adapter-react-v5 4.7.15 → 4.8.1

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.
Files changed (127) hide show
  1. package/Components/JsonConfigComponent/ConfigAccordion.d.ts +1 -1
  2. package/Components/JsonConfigComponent/ConfigAccordion.js +4 -6
  3. package/Components/JsonConfigComponent/ConfigAccordion.js.map +1 -1
  4. package/Components/JsonConfigComponent/ConfigAlive.d.ts +2 -2
  5. package/Components/JsonConfigComponent/ConfigAutocomplete.d.ts +36 -13
  6. package/Components/JsonConfigComponent/ConfigAutocomplete.js +66 -164
  7. package/Components/JsonConfigComponent/ConfigAutocompleteSendTo.d.ts +16 -13
  8. package/Components/JsonConfigComponent/ConfigAutocompleteSendTo.js +119 -251
  9. package/Components/JsonConfigComponent/ConfigCRON.d.ts +2 -2
  10. package/Components/JsonConfigComponent/ConfigCertCollection.d.ts +2 -2
  11. package/Components/JsonConfigComponent/ConfigCertificateSelect.d.ts +2 -2
  12. package/Components/JsonConfigComponent/ConfigCertificates.d.ts +2 -2
  13. package/Components/JsonConfigComponent/ConfigCheckbox.d.ts +14 -13
  14. package/Components/JsonConfigComponent/ConfigCheckbox.js +37 -79
  15. package/Components/JsonConfigComponent/ConfigChip.d.ts +2 -2
  16. package/Components/JsonConfigComponent/ConfigColor.d.ts +2 -2
  17. package/Components/JsonConfigComponent/ConfigCoordinates.d.ts +2 -2
  18. package/Components/JsonConfigComponent/ConfigDatePicker.d.ts +2 -2
  19. package/Components/JsonConfigComponent/ConfigDeviceManager.d.ts +6 -0
  20. package/Components/JsonConfigComponent/ConfigDeviceManager.js +18 -0
  21. package/Components/JsonConfigComponent/ConfigFile.d.ts +2 -2
  22. package/Components/JsonConfigComponent/ConfigFile.js +2 -2
  23. package/Components/JsonConfigComponent/ConfigFile.js.map +1 -1
  24. package/Components/JsonConfigComponent/ConfigFileSelector.js +8 -5
  25. package/Components/JsonConfigComponent/ConfigFileSelector.js.map +1 -1
  26. package/Components/JsonConfigComponent/ConfigFunc.d.ts +2 -2
  27. package/Components/JsonConfigComponent/ConfigGeneric.d.ts +12 -4
  28. package/Components/JsonConfigComponent/ConfigGeneric.js +11 -2
  29. package/Components/JsonConfigComponent/ConfigIP.d.ts +2 -2
  30. package/Components/JsonConfigComponent/ConfigImageSendTo.d.ts +2 -2
  31. package/Components/JsonConfigComponent/ConfigImageUpload.js +38 -44
  32. package/Components/JsonConfigComponent/ConfigImageUpload.js.map +1 -1
  33. package/Components/JsonConfigComponent/ConfigInstanceSelect.d.ts +2 -2
  34. package/Components/JsonConfigComponent/ConfigInterface.d.ts +2 -2
  35. package/Components/JsonConfigComponent/ConfigInterface.js +1 -1
  36. package/Components/JsonConfigComponent/ConfigInterface.js.map +1 -1
  37. package/Components/JsonConfigComponent/ConfigJsonEditor.d.ts +2 -2
  38. package/Components/JsonConfigComponent/ConfigJsonEditor.js +0 -1
  39. package/Components/JsonConfigComponent/ConfigJsonEditor.js.map +1 -1
  40. package/Components/JsonConfigComponent/ConfigLanguage.d.ts +6 -13
  41. package/Components/JsonConfigComponent/ConfigLanguage.js +105 -154
  42. package/Components/JsonConfigComponent/ConfigLicense.d.ts +1 -1
  43. package/Components/JsonConfigComponent/ConfigNumber.d.ts +1 -1
  44. package/Components/JsonConfigComponent/ConfigObjectId.d.ts +2 -2
  45. package/Components/JsonConfigComponent/ConfigPanel.js +8 -1
  46. package/Components/JsonConfigComponent/ConfigPanel.js.map +1 -1
  47. package/Components/JsonConfigComponent/ConfigPassword.d.ts +2 -2
  48. package/Components/JsonConfigComponent/ConfigPattern.d.ts +2 -2
  49. package/Components/JsonConfigComponent/ConfigRoom.d.ts +2 -2
  50. package/Components/JsonConfigComponent/ConfigSelect.d.ts +2 -2
  51. package/Components/JsonConfigComponent/ConfigSelectSendTo.d.ts +2 -2
  52. package/Components/JsonConfigComponent/ConfigSendto.d.ts +23 -17
  53. package/Components/JsonConfigComponent/ConfigSendto.js +259 -399
  54. package/Components/JsonConfigComponent/ConfigSetState.d.ts +2 -2
  55. package/Components/JsonConfigComponent/ConfigSlider.d.ts +2 -2
  56. package/Components/JsonConfigComponent/ConfigStaticDivider.d.ts +2 -2
  57. package/Components/JsonConfigComponent/ConfigStaticHeader.d.ts +2 -2
  58. package/Components/JsonConfigComponent/ConfigStaticImage.d.ts +2 -2
  59. package/Components/JsonConfigComponent/ConfigStaticText.d.ts +2 -2
  60. package/Components/JsonConfigComponent/ConfigText.d.ts +2 -2
  61. package/Components/JsonConfigComponent/ConfigText.js +18 -0
  62. package/Components/JsonConfigComponent/ConfigText.js.map +1 -1
  63. package/Components/JsonConfigComponent/ConfigTextSendTo.d.ts +2 -2
  64. package/Components/JsonConfigComponent/ConfigTimePicker.d.ts +2 -2
  65. package/Components/JsonConfigComponent/ConfigTopic.d.ts +2 -2
  66. package/Components/JsonConfigComponent/ConfigUUID.d.ts +2 -2
  67. package/Components/JsonConfigComponent/ConfigUser.d.ts +2 -2
  68. package/Components/JsonConfigComponent/DeviceManager/Communication.d.ts +63 -0
  69. package/Components/JsonConfigComponent/DeviceManager/Communication.js +268 -0
  70. package/Components/JsonConfigComponent/DeviceManager/DeviceActionButton.d.ts +11 -0
  71. package/Components/JsonConfigComponent/DeviceManager/DeviceActionButton.js +15 -0
  72. package/Components/JsonConfigComponent/DeviceManager/DeviceCard.d.ts +53 -0
  73. package/Components/JsonConfigComponent/DeviceManager/DeviceCard.js +340 -0
  74. package/Components/JsonConfigComponent/DeviceManager/DeviceControl.d.ts +45 -0
  75. package/Components/JsonConfigComponent/DeviceManager/DeviceControl.js +146 -0
  76. package/Components/JsonConfigComponent/DeviceManager/DeviceImageUpload.d.ts +12 -0
  77. package/Components/JsonConfigComponent/DeviceManager/DeviceImageUpload.js +69 -0
  78. package/Components/JsonConfigComponent/DeviceManager/DeviceList.d.ts +51 -0
  79. package/Components/JsonConfigComponent/DeviceManager/DeviceList.js +226 -0
  80. package/Components/JsonConfigComponent/DeviceManager/DeviceStatus.d.ts +13 -0
  81. package/Components/JsonConfigComponent/DeviceManager/DeviceStatus.js +111 -0
  82. package/Components/JsonConfigComponent/DeviceManager/InstanceActionButton.d.ts +7 -0
  83. package/Components/JsonConfigComponent/DeviceManager/InstanceActionButton.js +16 -0
  84. package/Components/JsonConfigComponent/DeviceManager/JsonConfig.d.ts +11 -0
  85. package/Components/JsonConfigComponent/DeviceManager/JsonConfig.js +94 -0
  86. package/Components/JsonConfigComponent/DeviceManager/TooltipButton.d.ts +10 -0
  87. package/Components/JsonConfigComponent/DeviceManager/TooltipButton.js +22 -0
  88. package/Components/JsonConfigComponent/DeviceManager/Utils.d.ts +12 -0
  89. package/Components/JsonConfigComponent/DeviceManager/Utils.js +158 -0
  90. package/Components/JsonConfigComponent/DeviceManager/i18n/de.json +21 -0
  91. package/Components/JsonConfigComponent/DeviceManager/i18n/en.json +21 -0
  92. package/Components/JsonConfigComponent/DeviceManager/i18n/es.json +21 -0
  93. package/Components/JsonConfigComponent/DeviceManager/i18n/fr.json +21 -0
  94. package/Components/JsonConfigComponent/DeviceManager/i18n/i18n.d.ts +26 -0
  95. package/Components/JsonConfigComponent/DeviceManager/i18n/it.json +21 -0
  96. package/Components/JsonConfigComponent/DeviceManager/i18n/nl.json +21 -0
  97. package/Components/JsonConfigComponent/DeviceManager/i18n/pl.json +21 -0
  98. package/Components/JsonConfigComponent/DeviceManager/i18n/pt.json +21 -0
  99. package/Components/JsonConfigComponent/DeviceManager/i18n/ru.json +21 -0
  100. package/Components/JsonConfigComponent/DeviceManager/i18n/uk.json +21 -0
  101. package/Components/JsonConfigComponent/DeviceManager/i18n/zh-cn.json +21 -0
  102. package/Components/JsonConfigComponent/DeviceManager/index.d.ts +2 -0
  103. package/Components/JsonConfigComponent/DeviceManager/index.js +10 -0
  104. package/Components/JsonConfigComponent/DeviceManager/index.js.map +1 -0
  105. package/Components/JsonConfigComponent/index.js +2 -7
  106. package/Components/JsonConfigComponent/index.js.map +1 -1
  107. package/Components/TextWithIcon.d.ts +1 -1
  108. package/Dialogs/ComplexCron.js +15 -17
  109. package/Dialogs/ComplexCron.js.map +1 -1
  110. package/Dialogs/Confirm.d.ts +20 -44
  111. package/Dialogs/Confirm.js +102 -158
  112. package/Dialogs/Error.d.ts +20 -39
  113. package/Dialogs/Error.js +50 -76
  114. package/Dialogs/Message.d.ts +22 -32
  115. package/Dialogs/Message.js +51 -83
  116. package/LegacyConnection.d.ts +3 -3
  117. package/README.md +7 -4
  118. package/i18n.d.ts +6 -6
  119. package/package.json +7 -6
  120. package/Components/JsonConfigComponent/ConfigAutocomplete.js.map +0 -1
  121. package/Components/JsonConfigComponent/ConfigAutocompleteSendTo.js.map +0 -1
  122. package/Components/JsonConfigComponent/ConfigCheckbox.js.map +0 -1
  123. package/Components/JsonConfigComponent/ConfigLanguage.js.map +0 -1
  124. package/Components/JsonConfigComponent/ConfigSendto.js.map +0 -1
  125. package/Dialogs/Confirm.js.map +0 -1
  126. package/Dialogs/Error.js.map +0 -1
  127. package/Dialogs/Message.js.map +0 -1
@@ -0,0 +1,340 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ const react_1 = __importStar(require("react"));
30
+ const material_1 = require("@mui/material");
31
+ const icons_material_1 = require("@mui/icons-material");
32
+ const Icon_1 = __importDefault(require("../../Icon"));
33
+ const Utils_1 = __importDefault(require("../../Utils"));
34
+ const i18n_1 = __importDefault(require("../../../i18n"));
35
+ const DeviceActionButton_1 = __importDefault(require("./DeviceActionButton"));
36
+ const DeviceControl_1 = __importDefault(require("./DeviceControl"));
37
+ const DeviceStatus_1 = __importDefault(require("./DeviceStatus"));
38
+ const JsonConfig_1 = __importDefault(require("./JsonConfig"));
39
+ const DeviceImageUpload_1 = __importDefault(require("./DeviceImageUpload"));
40
+ const Utils_2 = require("./Utils");
41
+ const NoImageIcon = (props) => react_1.default.createElement("svg", { viewBox: "0 0 24 24", width: "24", height: "24", style: props.style, className: props.className },
42
+ react_1.default.createElement("path", { fill: "currentColor", d: "M21.9,21.9l-8.49-8.49l0,0L3.59,3.59l0,0L2.1,2.1L0.69,3.51L3,5.83V19c0,1.1,0.9,2,2,2h13.17l2.31,2.31L21.9,21.9z M5,18 l3.5-4.5l2.5,3.01L12.17,15l3,3H5z M21,18.17L5.83,3H19c1.1,0,2,0.9,2,2V18.17z" }));
43
+ function getText(text) {
44
+ if (typeof text === 'object') {
45
+ return text[i18n_1.default.getLanguage()] || text.en;
46
+ }
47
+ return text;
48
+ }
49
+ /**
50
+ * Device Card Component
51
+ */
52
+ class DeviceCard extends react_1.Component {
53
+ constructor(props) {
54
+ super(props);
55
+ /**
56
+ * Refresh the device details
57
+ */
58
+ this.refresh = () => {
59
+ this.setState({ details: null });
60
+ this.loadDetails().catch(console.error);
61
+ };
62
+ /**
63
+ * Copy the device ID to the clipboard
64
+ * @returns {void}
65
+ */
66
+ this.copyToClipboard = async () => {
67
+ const textToCopy = this.props.device.id;
68
+ Utils_1.default.copyToClipboard(textToCopy);
69
+ alert(`${(0, Utils_2.getTranslation)('copied')} ${textToCopy} ${(0, Utils_2.getTranslation)('toClipboard')}!`);
70
+ };
71
+ this.state = {
72
+ open: false,
73
+ details: null,
74
+ data: {},
75
+ icon: props.device.icon,
76
+ showControlDialog: false,
77
+ };
78
+ }
79
+ async fetchIcon() {
80
+ if (!this.props.device.icon) {
81
+ // try to load the icon from file storage
82
+ const fileName = `${this.props.device.manufacturer ? `${this.props.device.manufacturer}_` : ''}${this.props.device.model ? this.props.device.model : this.props.device.id}`;
83
+ try {
84
+ const file = await this.props.socket.readFile(this.props.instanceId.replace('system.adapter.', ''), `${fileName}.webp`, true);
85
+ this.setState({ icon: `data:image/${file.mimeType},${file}` });
86
+ // const response = await fetch(url);
87
+ // if (response.ok) {
88
+ // const blob = await response.blob();
89
+ // const reader = new FileReader();
90
+ // reader.onloadend = () => {
91
+ // setIcon(reader.result);
92
+ // };
93
+ // reader.readAsDataURL(blob);
94
+ // } else {
95
+ // throw new Error('Response not ok');
96
+ // }
97
+ }
98
+ catch (error) {
99
+ this.state.icon && this.setState({ icon: '' });
100
+ }
101
+ }
102
+ }
103
+ componentDidMount() {
104
+ this.fetchIcon()
105
+ .catch(e => console.error(e));
106
+ }
107
+ /**
108
+ * Load the device details
109
+ */
110
+ async loadDetails() {
111
+ console.log(`Loading device details for ${this.props.device.id}... from ${this.props.instanceId}`);
112
+ const details = await this.props.socket.sendTo(this.props.instanceId, 'dm:deviceDetails', this.props.device.id);
113
+ console.log(`Got device details for ${this.props.device.id}:`, details);
114
+ this.setState({ details, data: (details === null || details === void 0 ? void 0 : details.data) || {} });
115
+ }
116
+ ;
117
+ renderDialog() {
118
+ if (!this.state.open || !this.state.details) {
119
+ return null;
120
+ }
121
+ return react_1.default.createElement(material_1.Dialog, { open: !0, maxWidth: "md", onClose: () => this.setState({ open: false }) },
122
+ react_1.default.createElement(material_1.DialogContent, null,
123
+ react_1.default.createElement(JsonConfig_1.default, { instanceId: this.props.instanceId, socket: this.props.socket, schema: this.state.details.schema, data: this.state.data, onChange: (data) => this.setState({ data }) })),
124
+ react_1.default.createElement(material_1.DialogActions, null,
125
+ react_1.default.createElement(material_1.Button, { disabled: !this.props.alive, variant: "contained", color: "primary", onClick: () => this.setState({ open: false }), autoFocus: true }, (0, Utils_2.getTranslation)('closeButtonText'))));
126
+ }
127
+ renderControlDialog() {
128
+ var _a;
129
+ if (!this.state.showControlDialog || !this.props.alive) {
130
+ return null;
131
+ }
132
+ const colors = { primary: '#111', secondary: '#888' };
133
+ return react_1.default.createElement(material_1.Dialog, { open: !0, onClose: () => this.setState({ showControlDialog: false }) },
134
+ react_1.default.createElement(material_1.DialogTitle, null,
135
+ this.props.title,
136
+ react_1.default.createElement(material_1.IconButton, { style: {
137
+ position: 'absolute',
138
+ top: 5,
139
+ right: 5,
140
+ zIndex: 10,
141
+ }, onClick: () => this.setState({ showControlDialog: false }) },
142
+ react_1.default.createElement(icons_material_1.Close, null))),
143
+ react_1.default.createElement(material_1.DialogContent, { style: { display: 'flex', flexDirection: 'column' } }, (_a = this.props.device.controls) === null || _a === void 0 ? void 0 : _a.map(control => react_1.default.createElement(DeviceControl_1.default, { disabled: false, key: control.id, control: control, socket: this.props.socket, colors: colors, deviceId: this.props.device.id, controlHandler: this.props.controlHandler, controlStateHandler: this.props.controlStateHandler }))));
144
+ }
145
+ renderControls() {
146
+ var _a, _b, _c;
147
+ const colors = { primary: '#111', secondary: '#888' };
148
+ const firstControl = (_a = this.props.device.controls) === null || _a === void 0 ? void 0 : _a[0];
149
+ if (((_b = this.props.device.controls) === null || _b === void 0 ? void 0 : _b.length) === 1 && firstControl && ((firstControl.type === 'icon' || firstControl.type === 'switch') && !firstControl.label)) {
150
+ // control can be placed in button icon
151
+ return react_1.default.createElement(DeviceControl_1.default, { disabled: !this.props.alive, control: firstControl, colors: colors, socket: this.props.socket, deviceId: this.props.device.id, controlHandler: this.props.controlHandler, controlStateHandler: this.props.controlStateHandler });
152
+ }
153
+ if ((_c = this.props.device.controls) === null || _c === void 0 ? void 0 : _c.length) {
154
+ // place button and show controls dialog
155
+ return react_1.default.createElement(material_1.Fab, { size: "small", disabled: !this.props.alive, onClick: () => this.setState({ showControlDialog: true }) },
156
+ react_1.default.createElement(icons_material_1.VideogameAsset, null));
157
+ }
158
+ return null;
159
+ }
160
+ renderActions() {
161
+ var _a;
162
+ return ((_a = this.props.device.actions) === null || _a === void 0 ? void 0 : _a.length) ? this.props.device.actions.map(a => react_1.default.createElement(DeviceActionButton_1.default, { disabled: !this.props.alive, key: a.id, deviceId: this.props.device.id, action: a, deviceHandler: this.props.deviceHandler, refresh: this.refresh })) : null;
163
+ }
164
+ renderSmall() {
165
+ const hasDetails = this.props.device.hasDetails;
166
+ const status = !this.props.device.status ? [] : Array.isArray(this.props.device.status) ? this.props.device.status : [this.props.device.status];
167
+ return react_1.default.createElement(material_1.Card, { sx: {
168
+ maxWidth: 345,
169
+ minWidth: 200,
170
+ } },
171
+ react_1.default.createElement(material_1.CardHeader, { sx: theme => ({
172
+ backgroundColor: this.props.device.color || theme.palette.secondary.main,
173
+ color: this.props.device.color ? Utils_1.default.invertColor(this.props.device.color, true) : theme.palette.secondary.contrastText,
174
+ maxWidth: 345,
175
+ }), avatar: react_1.default.createElement("div", null,
176
+ this.props.uploadImagesToInstance ? react_1.default.createElement(DeviceImageUpload_1.default, { uploadImagesToInstance: this.props.uploadImagesToInstance, deviceId: this.props.device.id, manufacturer: getText(this.props.device.manufacturer), model: getText(this.props.device.model), onImageSelect: async (imageData) => imageData && this.setState({ icon: imageData }), socket: this.props.socket }) : null,
177
+ this.state.icon ? react_1.default.createElement(Icon_1.default, { src: this.state.icon }) : react_1.default.createElement(NoImageIcon, null)), action: hasDetails ? react_1.default.createElement(material_1.IconButton, { "aria-label": "settings", onClick: () => {
178
+ if (!this.state.open) {
179
+ this.loadDetails().catch(console.error);
180
+ this.setState({ open: true });
181
+ }
182
+ } },
183
+ react_1.default.createElement(icons_material_1.MoreVert, null)) : null, title: this.props.title, subheader: this.props.device.manufacturer ? react_1.default.createElement("span", null,
184
+ react_1.default.createElement("b", { style: { marginRight: 4 } },
185
+ (0, Utils_2.getTranslation)('manufacturer'),
186
+ ":"),
187
+ getText(this.props.device.manufacturer)) : null }),
188
+ react_1.default.createElement(material_1.CardContent, { style: { position: 'relative' } },
189
+ (status === null || status === void 0 ? void 0 : status.length) ? react_1.default.createElement("div", { style: {
190
+ display: 'flex',
191
+ position: 'absolute',
192
+ top: -11,
193
+ background: '#88888880',
194
+ padding: '0 8px',
195
+ borderRadius: 5,
196
+ width: 'calc(100% - 46px)',
197
+ } }, status.map((s, i) => react_1.default.createElement(DeviceStatus_1.default, { key: i, status: s }))) : null,
198
+ react_1.default.createElement("div", null,
199
+ react_1.default.createElement(material_1.Typography, { variant: "body1" },
200
+ react_1.default.createElement("div", { onClick: this.copyToClipboard },
201
+ react_1.default.createElement("b", null, "ID:"),
202
+ react_1.default.createElement("span", { style: { marginLeft: 4 } }, this.props.device.id.replace(/.*\.\d\./, ''))),
203
+ this.props.device.manufacturer ? react_1.default.createElement("div", null,
204
+ react_1.default.createElement("b", { style: { marginRight: 4 } },
205
+ (0, Utils_2.getTranslation)('manufacturer'),
206
+ ":"),
207
+ getText(this.props.device.manufacturer)) : null,
208
+ this.props.device.model ? react_1.default.createElement("div", null,
209
+ react_1.default.createElement("b", { style: { marginRight: 4 } },
210
+ (0, Utils_2.getTranslation)('model'),
211
+ ":"),
212
+ getText(this.props.device.model)) : null))),
213
+ react_1.default.createElement(material_1.CardActions, { disableSpacing: true },
214
+ this.renderActions(),
215
+ react_1.default.createElement("div", { style: { flexGrow: 1 } }),
216
+ this.renderControls()),
217
+ this.renderDialog(),
218
+ this.renderControlDialog());
219
+ }
220
+ renderBig() {
221
+ var _a;
222
+ const cardStyle = {
223
+ // backgroundColor: '#fafafa',
224
+ width: 300,
225
+ minHeight: 280,
226
+ margin: 10,
227
+ overflow: 'hidden',
228
+ display: 'inline-block',
229
+ };
230
+ /** @type {CSSProperties} */
231
+ const headerStyle = {
232
+ display: 'flex',
233
+ position: 'relative',
234
+ justifyContent: 'space-between',
235
+ minHeight: 60,
236
+ color: '#000',
237
+ padding: '0 10px 0 10px',
238
+ backgroundColor: '#77c7ff8c',
239
+ borderRadius: '4px 4px 0 0',
240
+ };
241
+ /** @type {CSSProperties} */
242
+ const imgAreaStyle = {
243
+ height: 45,
244
+ width: 45,
245
+ margin: 'auto',
246
+ justifyContent: 'center',
247
+ display: 'grid',
248
+ };
249
+ /** @type {CSSProperties} */
250
+ const imgStyle = {
251
+ zIndex: 2,
252
+ maxWidth: '100%',
253
+ maxHeight: '100%',
254
+ };
255
+ /** @type {CSSProperties} */
256
+ const titleStyle = {
257
+ color: '#333',
258
+ width: '100%',
259
+ fontSize: 16,
260
+ fontWeight: 'bold',
261
+ paddingTop: 16,
262
+ paddingLeft: 8,
263
+ whiteSpace: 'nowrap',
264
+ overflow: 'hidden',
265
+ textOverflow: 'ellipsis',
266
+ };
267
+ /** @type {CSSProperties} */
268
+ const detailsButtonStyle = {
269
+ right: 20,
270
+ bottom: -20,
271
+ position: 'absolute',
272
+ };
273
+ /** @type {CSSProperties} */
274
+ const bodyStyle = {
275
+ height: 'calc(100% - 116px)',
276
+ };
277
+ /** @type {CSSProperties} */
278
+ const deviceInfoStyle = {
279
+ padding: '20px 16px 0 16px',
280
+ height: 133,
281
+ };
282
+ /** @type {CSSProperties} */
283
+ const statusStyle = {
284
+ padding: '15px 15px 0 15px',
285
+ height: 41,
286
+ };
287
+ const status = !this.props.device.status ? [] : Array.isArray(this.props.device.status) ? this.props.device.status : [this.props.device.status];
288
+ return react_1.default.createElement(material_1.Paper, { style: cardStyle, key: this.props.id },
289
+ react_1.default.createElement("div", { style: headerStyle },
290
+ react_1.default.createElement("div", { style: imgAreaStyle },
291
+ this.props.uploadImagesToInstance ? react_1.default.createElement(DeviceImageUpload_1.default, { uploadImagesToInstance: this.props.uploadImagesToInstance, deviceId: this.props.device.id, manufacturer: getText(this.props.device.manufacturer), model: getText(this.props.device.model), onImageSelect: async (imageData) => imageData && this.setState({ icon: imageData }), socket: this.props.socket }) : null,
292
+ react_1.default.createElement(Icon_1.default, { src: this.state.icon, style: imgStyle })),
293
+ react_1.default.createElement("div", { style: titleStyle }, this.props.title),
294
+ this.props.device.hasDetails ? react_1.default.createElement(material_1.Fab, { disabled: !this.props.alive, size: "small", style: detailsButtonStyle, onClick: () => {
295
+ if (!this.state.open) {
296
+ this.loadDetails().catch(console.error);
297
+ this.setState({ open: true });
298
+ }
299
+ }, color: "primary" },
300
+ react_1.default.createElement(icons_material_1.MoreVert, null)) : null),
301
+ react_1.default.createElement("div", { style: statusStyle }, status.map((s, i) => react_1.default.createElement(DeviceStatus_1.default, { key: i, status: s }))),
302
+ react_1.default.createElement("div", { style: bodyStyle },
303
+ react_1.default.createElement(material_1.Typography, { variant: "body1", style: deviceInfoStyle },
304
+ react_1.default.createElement("div", { onClick: this.copyToClipboard },
305
+ react_1.default.createElement("b", { style: { marginRight: 4 } }, "ID:"),
306
+ this.props.device.id.replace(/.*\.\d\./, '')),
307
+ this.props.device.manufacturer ? react_1.default.createElement("div", null,
308
+ react_1.default.createElement("b", { style: { marginRight: 4 } },
309
+ (0, Utils_2.getTranslation)('manufacturer'),
310
+ ":"),
311
+ getText(this.props.device.manufacturer)) : null,
312
+ this.props.device.model ? react_1.default.createElement("div", null,
313
+ react_1.default.createElement("b", { style: { marginRight: 4 } },
314
+ (0, Utils_2.getTranslation)('model'),
315
+ ":"),
316
+ getText(this.props.device.model)) : null),
317
+ !!((_a = this.props.device.actions) === null || _a === void 0 ? void 0 : _a.length) && react_1.default.createElement("div", { style: {
318
+ flex: 1,
319
+ position: 'relative',
320
+ display: 'flex',
321
+ gap: 8,
322
+ paddingBottom: 5,
323
+ height: 34,
324
+ paddingLeft: 10,
325
+ paddingRight: 10,
326
+ } },
327
+ this.renderActions(),
328
+ react_1.default.createElement("div", { style: { flexGrow: 1 } }),
329
+ this.renderControls())),
330
+ this.renderDialog(),
331
+ this.renderControlDialog());
332
+ }
333
+ render() {
334
+ if (this.props.smallCards) {
335
+ return this.renderSmall();
336
+ }
337
+ return this.renderBig();
338
+ }
339
+ }
340
+ exports.default = DeviceCard;
@@ -0,0 +1,45 @@
1
+ import React, { Component } from 'react';
2
+ import { ControlBase, ControlState } from '@iobroker/dm-utils/build/types/base';
3
+ interface DeviceControlProps {
4
+ deviceId: string;
5
+ control: any;
6
+ socket: any;
7
+ controlHandler: (deviceId: string, control: ControlBase, state: ControlState) => () => Promise<ioBroker.State | null>;
8
+ controlStateHandler: (deviceId: string, control: ControlBase) => () => Promise<ioBroker.State | null>;
9
+ colors: any;
10
+ disabled?: boolean;
11
+ }
12
+ interface DeviceControlState {
13
+ value: any;
14
+ ts: number;
15
+ }
16
+ /**
17
+ * Device Control component
18
+ * @param {object} props - Parameters
19
+ * @param {object} props.control - Control object
20
+ * @param {object} props.socket - Socket object
21
+ * @param {object} props.controlHandler - Control handler to set the state
22
+ * @param {object} props.controlStateHandler - Control handler to read the state
23
+ * @returns {React.JSX.Element|null}
24
+ * @constructor
25
+ */
26
+ export default class DeviceControl extends Component<DeviceControlProps, DeviceControlState> {
27
+ constructor(props: DeviceControlProps);
28
+ componentDidMount(): void;
29
+ stateHandler: (id: string, state: ioBroker.State) => Promise<void>;
30
+ componentWillUnmount(): void;
31
+ static getDerivedStateFromProps(props: DeviceControlProps, state: DeviceControlState): {
32
+ value: any;
33
+ ts: any;
34
+ };
35
+ sendControl(deviceId: string, control: ControlBase, value: ControlState): Promise<void>;
36
+ renderButton(): React.JSX.Element;
37
+ renderSwitch(): React.JSX.Element;
38
+ getColor(): any;
39
+ renderSelect(): void;
40
+ renderSlider(): void;
41
+ renderColor(): void;
42
+ renderIcon(): React.JSX.Element;
43
+ render(): React.JSX.Element;
44
+ }
45
+ export {};
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ const react_1 = __importStar(require("react"));
27
+ const material_1 = require("@mui/material");
28
+ const Utils_1 = require("./Utils");
29
+ /**
30
+ * Device Control component
31
+ * @param {object} props - Parameters
32
+ * @param {object} props.control - Control object
33
+ * @param {object} props.socket - Socket object
34
+ * @param {object} props.controlHandler - Control handler to set the state
35
+ * @param {object} props.controlStateHandler - Control handler to read the state
36
+ * @returns {React.JSX.Element|null}
37
+ * @constructor
38
+ */
39
+ class DeviceControl extends react_1.Component {
40
+ constructor(props) {
41
+ var _a, _b;
42
+ super(props);
43
+ this.stateHandler = async (id, state) => {
44
+ if (id === this.props.control.stateId && state) {
45
+ // request new state
46
+ const newState = await (this.props.controlStateHandler(this.props.deviceId, this.props.control)());
47
+ if ((newState === null || newState === void 0 ? void 0 : newState.ts) && (!this.state.ts || newState.ts > this.state.ts)) {
48
+ this.setState({
49
+ value: newState.val,
50
+ ts: newState.ts,
51
+ });
52
+ }
53
+ }
54
+ };
55
+ this.state = {
56
+ value: (_a = props.control.state) === null || _a === void 0 ? void 0 : _a.val,
57
+ ts: (_b = props.control.state) === null || _b === void 0 ? void 0 : _b.ts,
58
+ };
59
+ }
60
+ componentDidMount() {
61
+ if (this.props.control.stateId) {
62
+ this.props.socket.subscribeState(this.props.control.stateId, this.stateHandler);
63
+ }
64
+ }
65
+ componentWillUnmount() {
66
+ if (this.props.control.stateId) {
67
+ this.props.socket.unsubscribeState(this.props.control.stateId, this.stateHandler);
68
+ }
69
+ }
70
+ static getDerivedStateFromProps(props, state) {
71
+ var _a, _b;
72
+ if (((_a = props.control.state) === null || _a === void 0 ? void 0 : _a.ts) && (!state.ts || ((_b = props.control.state) === null || _b === void 0 ? void 0 : _b.ts) > state.ts)) {
73
+ return {
74
+ value: props.control.state.val,
75
+ ts: props.control.state.ts,
76
+ };
77
+ }
78
+ return null;
79
+ }
80
+ async sendControl(deviceId, control, value) {
81
+ const result = await (this.props.controlHandler(deviceId, control, value)());
82
+ if ((result === null || result === void 0 ? void 0 : result.ts) && (!this.state.ts || (result === null || result === void 0 ? void 0 : result.ts) > this.state.ts)) {
83
+ this.setState({
84
+ value: result.val,
85
+ ts: result.ts,
86
+ });
87
+ }
88
+ }
89
+ renderButton() {
90
+ const tooltip = (0, Utils_1.getTranslation)(this.props.control.description);
91
+ const icon = (0, Utils_1.renderIcon)(this.props.control, this.props.colors, this.state.value);
92
+ if (!this.props.control.label) {
93
+ return react_1.default.createElement(material_1.Fab, { disabled: this.props.disabled, title: tooltip, onClick: () => this.sendControl(this.props.deviceId, this.props.control, true) }, icon);
94
+ }
95
+ return react_1.default.createElement(material_1.Button, { disabled: this.props.disabled, title: tooltip, onClick: () => this.sendControl(this.props.deviceId, this.props.control, true), startIcon: icon }, this.props.control.label);
96
+ }
97
+ renderSwitch() {
98
+ const tooltip = (0, Utils_1.getTranslation)(this.props.control.description);
99
+ // const icon = renderIcon(this.props.control, this.props.colors, this.state.value);
100
+ return react_1.default.createElement(material_1.Switch, { disabled: this.props.disabled, title: tooltip, checked: this.state.value, onChange: e => this.sendControl(this.props.deviceId, this.props.control, e.target.checked) });
101
+ }
102
+ getColor() {
103
+ let color;
104
+ if (this.state.value) {
105
+ color = this.props.control.colorOn || 'primary';
106
+ }
107
+ else if (this.props.control.type === 'switch') {
108
+ color = this.props.control.color;
109
+ }
110
+ if (color === 'primary') {
111
+ return this.props.colors.primary;
112
+ }
113
+ if (color === 'secondary') {
114
+ return this.props.colors.secondary;
115
+ }
116
+ return color;
117
+ }
118
+ renderSelect() {
119
+ }
120
+ renderSlider() {
121
+ }
122
+ renderColor() {
123
+ }
124
+ renderIcon() {
125
+ const tooltip = (0, Utils_1.getTranslation)(this.props.control.description);
126
+ const icon = (0, Utils_1.renderIcon)(this.props.control, this.props.colors, this.state.value);
127
+ const color = this.getColor();
128
+ if (!this.props.control.label) {
129
+ return react_1.default.createElement(material_1.Fab, { disabled: this.props.disabled, size: "small", title: tooltip, color: color === this.props.colors.primary ? 'primary' : (color === this.props.colors.secondary ? 'secondary' : undefined), style: color === this.props.colors.primary || color === this.props.colors.secondary ? undefined : { color }, onClick: () => this.sendControl(this.props.deviceId, this.props.control, !this.state.value) }, icon);
130
+ }
131
+ return react_1.default.createElement(material_1.Button, { disabled: this.props.disabled, title: tooltip, color: color === this.props.colors.primary ? 'primary' : (color === this.props.colors.secondary ? 'secondary' : undefined), style: color === this.props.colors.primary || color === this.props.colors.secondary ? undefined : { color }, onClick: () => this.sendControl(this.props.deviceId, this.props.control, !this.state.value), startIcon: icon }, this.props.control.label);
132
+ }
133
+ render() {
134
+ if (this.props.control.type === 'button') {
135
+ return this.renderButton();
136
+ }
137
+ if (this.props.control.type === 'icon') {
138
+ return this.renderIcon();
139
+ }
140
+ if (this.props.control.type === 'switch') {
141
+ return this.renderSwitch();
142
+ }
143
+ return react_1.default.createElement("div", { style: { color: 'red' } }, this.props.control.type);
144
+ }
145
+ }
146
+ exports.default = DeviceControl;
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import { Connection } from '@iobroker/socket-client';
3
+ interface DeviceImageUploadProps {
4
+ socket: Connection;
5
+ manufacturer?: string;
6
+ model?: string;
7
+ deviceId: string;
8
+ onImageSelect: (image: string) => void;
9
+ uploadImagesToInstance: string;
10
+ }
11
+ declare function DeviceImageUpload(params: DeviceImageUploadProps): React.JSX.Element | null;
12
+ export default DeviceImageUpload;
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const react_1 = __importDefault(require("react"));
7
+ function DeviceImageUpload(params) {
8
+ const { socket, manufacturer, model, deviceId, onImageSelect, uploadImagesToInstance, } = params;
9
+ const handleImageUpload = async (event) => {
10
+ const target = event.target;
11
+ const files = target.files;
12
+ if (!files || files.length === 0) {
13
+ return;
14
+ }
15
+ const file = files[0];
16
+ if (file) {
17
+ const reader = new FileReader();
18
+ reader.onload = async (e) => {
19
+ if (!e.target || !e.target.result) {
20
+ return;
21
+ }
22
+ const img = new Image();
23
+ img.src = e.target.result;
24
+ img.onload = async () => {
25
+ const maxWidth = 50;
26
+ const maxHeight = 50;
27
+ let width = img.width;
28
+ let height = img.height;
29
+ if (width > height) {
30
+ if (width > maxWidth) {
31
+ height *= maxWidth / width;
32
+ width = maxWidth;
33
+ }
34
+ }
35
+ else if (height > maxHeight) {
36
+ width *= maxHeight / height;
37
+ height = maxHeight;
38
+ }
39
+ const canvas = document.createElement('canvas');
40
+ const ctx = canvas.getContext('2d');
41
+ if (ctx) {
42
+ canvas.width = width;
43
+ canvas.height = height;
44
+ ctx.drawImage(img, 0, 0, width, height);
45
+ const resizedImage = canvas.toDataURL('image/webp');
46
+ // Build the file name from a manufacturer and model, if not available, use device id
47
+ const fileName = `${manufacturer ? `${manufacturer}_` : ''}${model || deviceId}`;
48
+ const base64Data = resizedImage.replace(/^data:image\/webp;base64,/, '');
49
+ const response = await socket.writeFile64(uploadImagesToInstance, fileName, base64Data);
50
+ console.log(`saveImage response: ${JSON.stringify(response)}`);
51
+ onImageSelect && onImageSelect(resizedImage);
52
+ }
53
+ };
54
+ };
55
+ reader.readAsDataURL(file);
56
+ }
57
+ };
58
+ const imageUploadButtonStyle = {
59
+ // make the button invisible but still clickable
60
+ opacity: 0,
61
+ position: 'absolute',
62
+ width: '45px',
63
+ height: '45px',
64
+ zIndex: 3,
65
+ };
66
+ return react_1.default.createElement("div", null,
67
+ react_1.default.createElement("input", { style: imageUploadButtonStyle, type: "file", accept: "image/*", onChange: handleImageUpload }));
68
+ }
69
+ exports.default = DeviceImageUpload;
@@ -0,0 +1,51 @@
1
+ import React from 'react';
2
+ import { DeviceInfo, InstanceDetails } from '@iobroker/dm-utils';
3
+ import Communication, { CommunicationProps, CommunicationState } from './Communication';
4
+ interface DeviceListProps extends CommunicationProps {
5
+ uploadImagesToInstance?: string;
6
+ filter?: string;
7
+ embedded?: boolean;
8
+ title?: string;
9
+ style?: React.CSSProperties;
10
+ smallCards?: boolean;
11
+ }
12
+ interface DeviceListState extends CommunicationState {
13
+ devices: DeviceInfo[];
14
+ filteredDevices: DeviceInfo[];
15
+ filter: string;
16
+ instanceInfo: InstanceDetails;
17
+ loading: boolean;
18
+ alive: boolean | null;
19
+ }
20
+ /**
21
+ * Device List Component
22
+ * @param {object} params - Component parameters
23
+ * @param {object} params.socket - socket object
24
+ * @param {string} params.selectedInstance - Selected instance
25
+ * @param {string} params.uploadImagesToInstance - Instance to upload images to
26
+ * @param {string} params.filter - Filter
27
+ * @param {string} params.empbedded - true if this list used with multiple instances and false if only with one
28
+ * @param {string} params.title - Title in appbar (only in non-embedded mode)
29
+ * @param {string} params.style - Style of devices list
30
+ * @returns {*[]} - Array of device cards
31
+ */
32
+ export default class DeviceList extends Communication<DeviceListProps, DeviceListState> {
33
+ static i18nInitialized: boolean;
34
+ private lastPropsFilter;
35
+ private lastInstance;
36
+ private filterTimeout;
37
+ private readonly language;
38
+ constructor(props: DeviceListProps);
39
+ componentDidMount(): Promise<void>;
40
+ componentWillUnmount(): void;
41
+ aliveHandler: ioBroker.StateChangeHandler;
42
+ /**
43
+ * Load devices
44
+ */
45
+ loadData(): void;
46
+ getText(text: ioBroker.StringOrTranslated): string;
47
+ applyFilter(): void;
48
+ handleFilterChange(filter: string): void;
49
+ renderContent(): React.JSX.Element | React.JSX.Element[] | null;
50
+ }
51
+ export {};