@iobroker/dm-gui-components 0.0.3 → 0.0.5
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/Communication.d.ts +3 -2
- package/Communication.js +12 -1
- package/DeviceActionButton.d.ts +1 -0
- package/DeviceActionButton.js +2 -2
- package/DeviceCard.d.ts +37 -4
- package/DeviceCard.js +270 -141
- package/DeviceControl.d.ts +1 -0
- package/DeviceControl.js +9 -9
- package/DeviceList.d.ts +2 -1
- package/DeviceList.js +30 -19
- package/README.md +6 -0
- package/package.json +3 -3
package/Communication.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { ActionBase, ControlBase, ControlState } from '@iobroker/dm-utils/build/
|
|
|
4
4
|
export type CommunicationProps = {
|
|
5
5
|
socket: Connection;
|
|
6
6
|
selectedInstance: string;
|
|
7
|
+
registerHandler?: (handler: null | ((command: string) => void)) => void;
|
|
7
8
|
};
|
|
8
9
|
interface CommunicationForm {
|
|
9
10
|
title?: string | null | undefined;
|
|
@@ -35,13 +36,13 @@ export type CommunicationState = {
|
|
|
35
36
|
* @param {string} params.selectedInstance - Selected instance
|
|
36
37
|
* @returns {*[]} - Array of device cards
|
|
37
38
|
*/
|
|
38
|
-
declare
|
|
39
|
+
declare class Communication<P extends CommunicationProps, S extends CommunicationState> extends Component<P, S> {
|
|
39
40
|
instanceHandler: (action: ActionBase<'api'>) => () => void;
|
|
40
41
|
deviceHandler: (deviceId: string, action: ActionBase<'api'>, refresh: () => void) => () => void;
|
|
41
42
|
controlHandler: (deviceId: string, control: ControlBase, state: ControlState) => () => Promise<ioBroker.State | null>;
|
|
42
43
|
controlStateHandler: (deviceId: string, control: ControlBase) => () => Promise<ioBroker.State | null>;
|
|
43
44
|
constructor(props: P);
|
|
44
|
-
|
|
45
|
+
loadData(): Promise<void>;
|
|
45
46
|
sendActionToInstance: (command: string, messageToSend: any, refresh?: () => void) => void;
|
|
46
47
|
sendControlToInstance: (command: string, messageToSend: {
|
|
47
48
|
deviceId: string;
|
package/Communication.js
CHANGED
|
@@ -162,14 +162,25 @@ class Communication extends react_1.Component {
|
|
|
162
162
|
form: null,
|
|
163
163
|
progress: null,
|
|
164
164
|
};
|
|
165
|
+
// eslint-disable-next-line react/no-unused-class-component-methods
|
|
165
166
|
this.instanceHandler = action => () => this.sendActionToInstance('dm:instanceAction', { actionId: action.id });
|
|
167
|
+
// eslint-disable-next-line react/no-unused-class-component-methods
|
|
166
168
|
this.deviceHandler = (deviceId, action, refresh) => () => this.sendActionToInstance('dm:deviceAction', { deviceId, actionId: action.id }, refresh);
|
|
169
|
+
// eslint-disable-next-line react/no-unused-class-component-methods
|
|
167
170
|
this.controlHandler = (deviceId, control, state) => () => this.sendControlToInstance('dm:deviceControl', { deviceId, controlId: control.id, state });
|
|
171
|
+
// eslint-disable-next-line react/no-unused-class-component-methods
|
|
168
172
|
this.controlStateHandler = (deviceId, control) => () => this.sendControlToInstance('dm:deviceControlState', { deviceId, controlId: control.id });
|
|
173
|
+
this.props.registerHandler && this.props.registerHandler(() => this.loadData());
|
|
169
174
|
}
|
|
175
|
+
// eslint-disable-next-line class-methods-use-this
|
|
176
|
+
loadData() {
|
|
177
|
+
return Promise.resolve();
|
|
178
|
+
}
|
|
179
|
+
// eslint-disable-next-line react/no-unused-class-component-methods
|
|
170
180
|
loadDevices() {
|
|
171
181
|
return this.props.socket.sendTo(this.props.selectedInstance, 'dm:listDevices');
|
|
172
182
|
}
|
|
183
|
+
// eslint-disable-next-line react/no-unused-class-component-methods
|
|
173
184
|
loadInstanceInfos() {
|
|
174
185
|
return this.props.socket.sendTo(this.props.selectedInstance, 'dm:instanceInfo');
|
|
175
186
|
}
|
|
@@ -189,7 +200,6 @@ class Communication extends react_1.Component {
|
|
|
189
200
|
if (!this.state.confirm) {
|
|
190
201
|
return null;
|
|
191
202
|
}
|
|
192
|
-
// @ts-ignore
|
|
193
203
|
return react_1.default.createElement(material_1.Dialog, { open: !0, onClose: () => { var _a; return (_a = this.state.confirm) === null || _a === void 0 ? void 0 : _a.handleClose(); }, hideBackdrop: true, "aria-describedby": "confirm-dialog-description" },
|
|
194
204
|
react_1.default.createElement(material_1.DialogContent, null,
|
|
195
205
|
react_1.default.createElement(material_1.DialogContentText, { id: "confirm-dialog-description" }, (0, Utils_1.getTranslation)((_a = this.state.confirm) === null || _a === void 0 ? void 0 : _a.message))),
|
|
@@ -232,6 +242,7 @@ class Communication extends react_1.Component {
|
|
|
232
242
|
return react_1.default.createElement(material_1.Dialog, { open: !0, onClose: () => { }, hideBackdrop: true },
|
|
233
243
|
react_1.default.createElement(material_1.LinearProgress, { variant: "determinate", value: ((_b = this.state.progress) === null || _b === void 0 ? void 0 : _b.progress) || 0 }));
|
|
234
244
|
}
|
|
245
|
+
// eslint-disable-next-line class-methods-use-this
|
|
235
246
|
renderContent() {
|
|
236
247
|
return null;
|
|
237
248
|
}
|
package/DeviceActionButton.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ interface DeviceActionButtonProps {
|
|
|
5
5
|
action: any;
|
|
6
6
|
refresh: () => void;
|
|
7
7
|
deviceHandler: (deviceId: string, action: ActionBase<'api'>, refresh: () => void) => () => void;
|
|
8
|
+
disabled?: boolean;
|
|
8
9
|
}
|
|
9
10
|
export default function DeviceActionButton(props: DeviceActionButtonProps): React.JSX.Element;
|
|
10
11
|
export {};
|
package/DeviceActionButton.js
CHANGED
|
@@ -7,9 +7,9 @@ const react_1 = __importDefault(require("react"));
|
|
|
7
7
|
const TooltipButton_js_1 = __importDefault(require("./TooltipButton.js"));
|
|
8
8
|
const Utils_js_1 = require("./Utils.js");
|
|
9
9
|
function DeviceActionButton(props) {
|
|
10
|
-
const { deviceId, action, refresh, deviceHandler, } = props;
|
|
10
|
+
const { deviceId, action, refresh, deviceHandler, disabled, } = props;
|
|
11
11
|
const tooltip = (0, Utils_js_1.getTranslation)(action.description);
|
|
12
12
|
const icon = (0, Utils_js_1.renderIcon)(action);
|
|
13
|
-
return react_1.default.createElement(TooltipButton_js_1.default, { label: action.label || (icon ? null : action.id), tooltip: tooltip, disabled: action.disabled, Icon: icon, onClick: deviceHandler(deviceId, action, refresh) });
|
|
13
|
+
return react_1.default.createElement(TooltipButton_js_1.default, { label: action.label || (icon ? null : action.id), tooltip: tooltip, disabled: disabled || action.disabled, Icon: icon, onClick: deviceHandler(deviceId, action, refresh) });
|
|
14
14
|
}
|
|
15
15
|
exports.default = DeviceActionButton;
|
package/DeviceCard.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { Component } from 'react';
|
|
2
2
|
import { Connection } from '@iobroker/adapter-react-v5';
|
|
3
|
-
import { DeviceInfo } from '@iobroker/dm-utils';
|
|
3
|
+
import { DeviceDetails, DeviceInfo } from '@iobroker/dm-utils';
|
|
4
4
|
import { ActionBase, ControlBase, ControlState } from '@iobroker/dm-utils/build/types/base';
|
|
5
5
|
interface DeviceCardProps {
|
|
6
6
|
title?: string;
|
|
@@ -12,9 +12,42 @@ interface DeviceCardProps {
|
|
|
12
12
|
deviceHandler: (deviceId: string, action: ActionBase<'api'>, refresh: () => void) => () => void;
|
|
13
13
|
controlHandler: (deviceId: string, control: ControlBase, state: ControlState) => () => Promise<ioBroker.State | null>;
|
|
14
14
|
controlStateHandler: (deviceId: string, control: ControlBase) => () => Promise<ioBroker.State | null>;
|
|
15
|
+
smallCards?: boolean;
|
|
16
|
+
alive: boolean;
|
|
17
|
+
}
|
|
18
|
+
interface DeviceCardState {
|
|
19
|
+
open: boolean;
|
|
20
|
+
details: DeviceDetails | null;
|
|
21
|
+
data: Record<string, any>;
|
|
22
|
+
icon: string | undefined;
|
|
23
|
+
showControlDialog: boolean;
|
|
15
24
|
}
|
|
16
25
|
/**
|
|
17
26
|
* Device Card Component
|
|
18
27
|
*/
|
|
19
|
-
|
|
20
|
-
|
|
28
|
+
declare class DeviceCard extends Component<DeviceCardProps, DeviceCardState> {
|
|
29
|
+
constructor(props: DeviceCardProps);
|
|
30
|
+
fetchIcon(): Promise<void>;
|
|
31
|
+
componentDidMount(): void;
|
|
32
|
+
/**
|
|
33
|
+
* Load the device details
|
|
34
|
+
*/
|
|
35
|
+
loadDetails(): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Refresh the device details
|
|
38
|
+
*/
|
|
39
|
+
refresh: () => void;
|
|
40
|
+
/**
|
|
41
|
+
* Copy the device ID to the clipboard
|
|
42
|
+
* @returns {void}
|
|
43
|
+
*/
|
|
44
|
+
copyToClipboard: () => Promise<void>;
|
|
45
|
+
renderDialog(): React.JSX.Element;
|
|
46
|
+
renderControlDialog(): React.JSX.Element;
|
|
47
|
+
renderControls(): React.JSX.Element;
|
|
48
|
+
renderActions(): React.JSX.Element[];
|
|
49
|
+
renderSmall(): React.JSX.Element;
|
|
50
|
+
renderBig(): React.JSX.Element;
|
|
51
|
+
render(): React.JSX.Element;
|
|
52
|
+
}
|
|
53
|
+
export default DeviceCard;
|
package/DeviceCard.js
CHANGED
|
@@ -47,162 +47,291 @@ function getText(text) {
|
|
|
47
47
|
/**
|
|
48
48
|
* Device Card Component
|
|
49
49
|
*/
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
50
|
+
class DeviceCard extends react_1.Component {
|
|
51
|
+
constructor(props) {
|
|
52
|
+
super(props);
|
|
53
|
+
/**
|
|
54
|
+
* Refresh the device details
|
|
55
|
+
*/
|
|
56
|
+
this.refresh = () => {
|
|
57
|
+
this.setState({ details: null });
|
|
58
|
+
this.loadDetails().catch(console.error);
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Copy the device ID to the clipboard
|
|
62
|
+
* @returns {void}
|
|
63
|
+
*/
|
|
64
|
+
this.copyToClipboard = async () => {
|
|
65
|
+
const textToCopy = this.props.device.id;
|
|
66
|
+
adapter_react_v5_1.Utils.copyToClipboard(textToCopy);
|
|
67
|
+
alert(`${(0, Utils_1.getTranslation)('copied')} ${textToCopy} ${(0, Utils_1.getTranslation)('toClipboard')}!`);
|
|
68
|
+
};
|
|
69
|
+
this.state = {
|
|
70
|
+
open: false,
|
|
71
|
+
details: null,
|
|
72
|
+
data: {},
|
|
73
|
+
icon: props.device.icon,
|
|
74
|
+
showControlDialog: false,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
async fetchIcon() {
|
|
78
|
+
if (!this.props.device.icon) {
|
|
79
|
+
// try to load the icon from file storage
|
|
80
|
+
const fileName = `${this.props.device.manufacturer ? `${this.props.device.manufacturer}_` : ''}${this.props.device.model ? this.props.device.model : this.props.device.id}`;
|
|
81
|
+
try {
|
|
82
|
+
const file = await this.props.socket.readFile(this.props.instanceId.replace('system.adapter.', ''), `${fileName}.webp`, true);
|
|
83
|
+
this.setState({ icon: `data:image/${file.mimeType},${file}` });
|
|
84
|
+
// const response = await fetch(url);
|
|
85
|
+
// if (response.ok) {
|
|
86
|
+
// const blob = await response.blob();
|
|
87
|
+
// const reader = new FileReader();
|
|
88
|
+
// reader.onloadend = () => {
|
|
89
|
+
// setIcon(reader.result);
|
|
90
|
+
// };
|
|
91
|
+
// reader.readAsDataURL(blob);
|
|
92
|
+
// } else {
|
|
93
|
+
// throw new Error('Response not ok');
|
|
94
|
+
// }
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
this.state.icon && this.setState({ icon: '' });
|
|
85
98
|
}
|
|
86
99
|
}
|
|
87
|
-
|
|
100
|
+
}
|
|
101
|
+
componentDidMount() {
|
|
102
|
+
this.fetchIcon()
|
|
88
103
|
.catch(e => console.error(e));
|
|
89
|
-
}
|
|
104
|
+
}
|
|
90
105
|
/**
|
|
91
106
|
* Load the device details
|
|
92
107
|
*/
|
|
93
|
-
|
|
94
|
-
console.log(`Loading device details for ${device.id}... from ${instanceId}`);
|
|
95
|
-
const
|
|
96
|
-
console.log(`Got device details for ${device.id}:`,
|
|
97
|
-
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
setDetails(null);
|
|
104
|
-
loadDetails().catch(console.error);
|
|
105
|
-
};
|
|
106
|
-
/**
|
|
107
|
-
* Open the modal
|
|
108
|
-
*/
|
|
109
|
-
const openModal = () => {
|
|
110
|
-
if (!open) {
|
|
111
|
-
loadDetails().catch(console.error);
|
|
112
|
-
setOpen(true);
|
|
108
|
+
async loadDetails() {
|
|
109
|
+
console.log(`Loading device details for ${this.props.device.id}... from ${this.props.instanceId}`);
|
|
110
|
+
const details = await this.props.socket.sendTo(this.props.instanceId, 'dm:deviceDetails', this.props.device.id);
|
|
111
|
+
console.log(`Got device details for ${this.props.device.id}:`, details);
|
|
112
|
+
this.setState({ details, data: (details === null || details === void 0 ? void 0 : details.data) || {} });
|
|
113
|
+
}
|
|
114
|
+
;
|
|
115
|
+
renderDialog() {
|
|
116
|
+
if (!this.state.open || !this.state.details) {
|
|
117
|
+
return null;
|
|
113
118
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
const handleImageClick = async (imageData) => imageData && setIcon(imageData);
|
|
120
|
-
/**
|
|
121
|
-
* Copy the device ID to the clipboard
|
|
122
|
-
* @returns {void}
|
|
123
|
-
*/
|
|
124
|
-
const copyToClipboard = async () => {
|
|
125
|
-
const textToCopy = device.id;
|
|
126
|
-
adapter_react_v5_1.Utils.copyToClipboard(textToCopy);
|
|
127
|
-
alert(`${(0, Utils_1.getTranslation)('copied')} ${textToCopy} ${(0, Utils_1.getTranslation)('toClipboard')}!`);
|
|
128
|
-
};
|
|
129
|
-
react_1.default.useEffect(() => setData((details === null || details === void 0 ? void 0 : details.data) || {}), [details]);
|
|
130
|
-
const renderedDialog = open && details ? react_1.default.createElement(material_1.Dialog, { open: !0, maxWidth: "md", onClose: handleClose },
|
|
131
|
-
react_1.default.createElement(material_1.DialogContent, null,
|
|
132
|
-
react_1.default.createElement(JsonConfig_1.default, { instanceId: instanceId, socket: socket, schema: details.schema, data: data, onChange: setData })),
|
|
133
|
-
react_1.default.createElement(material_1.DialogActions, null,
|
|
134
|
-
react_1.default.createElement(material_1.Button, { variant: "contained", color: "primary", onClick: handleClose, autoFocus: true }, (0, Utils_1.getTranslation)('closeButtonText')))) : null;
|
|
135
|
-
let renderedControls;
|
|
136
|
-
let controlDialog;
|
|
137
|
-
const firstControl = (_a = device.controls) === null || _a === void 0 ? void 0 : _a[0];
|
|
138
|
-
if (((_b = device.controls) === null || _b === void 0 ? void 0 : _b.length) === 1 && firstControl && ((firstControl.type === 'icon' || firstControl.type === 'switch') && !firstControl.label)) {
|
|
139
|
-
// control can be placed in button icon
|
|
140
|
-
renderedControls = react_1.default.createElement(DeviceControl_1.default, { control: firstControl, colors: colors, socket: socket, deviceId: device.id, controlHandler: controlHandler, controlStateHandler: controlStateHandler });
|
|
119
|
+
return react_1.default.createElement(material_1.Dialog, { open: !0, maxWidth: "md", onClose: () => this.setState({ open: false }) },
|
|
120
|
+
react_1.default.createElement(material_1.DialogContent, null,
|
|
121
|
+
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 }) })),
|
|
122
|
+
react_1.default.createElement(material_1.DialogActions, null,
|
|
123
|
+
react_1.default.createElement(material_1.Button, { disabled: !this.props.alive, variant: "contained", color: "primary", onClick: () => this.setState({ open: false }), autoFocus: true }, (0, Utils_1.getTranslation)('closeButtonText'))));
|
|
141
124
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
125
|
+
renderControlDialog() {
|
|
126
|
+
var _a;
|
|
127
|
+
if (!this.state.showControlDialog || !this.props.alive) {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
const colors = { primary: '#111', secondary: '#888' };
|
|
131
|
+
return react_1.default.createElement(material_1.Dialog, { open: !0, onClose: () => this.setState({ showControlDialog: false }) },
|
|
132
|
+
react_1.default.createElement(material_1.DialogTitle, null,
|
|
133
|
+
this.props.title,
|
|
134
|
+
react_1.default.createElement(material_1.IconButton, { style: {
|
|
135
|
+
position: 'absolute',
|
|
136
|
+
top: 5,
|
|
137
|
+
right: 5,
|
|
138
|
+
zIndex: 10,
|
|
139
|
+
}, onClick: () => this.setState({ showControlDialog: false }) },
|
|
140
|
+
react_1.default.createElement(icons_material_1.Close, null))),
|
|
141
|
+
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 }))));
|
|
142
|
+
}
|
|
143
|
+
renderControls() {
|
|
144
|
+
var _a, _b, _c;
|
|
145
|
+
const colors = { primary: '#111', secondary: '#888' };
|
|
146
|
+
const firstControl = (_a = this.props.device.controls) === null || _a === void 0 ? void 0 : _a[0];
|
|
147
|
+
if (((_b = this.props.device.controls) === null || _b === void 0 ? void 0 : _b.length) === 1 && firstControl && ((firstControl.type === 'icon' || firstControl.type === 'switch') && !firstControl.label)) {
|
|
148
|
+
// control can be placed in button icon
|
|
149
|
+
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 });
|
|
150
|
+
}
|
|
151
|
+
if ((_c = this.props.device.controls) === null || _c === void 0 ? void 0 : _c.length) {
|
|
152
|
+
// place button and show controls dialog
|
|
153
|
+
return react_1.default.createElement(material_1.Fab, { size: "small", disabled: !this.props.alive, onClick: () => this.setState({ showControlDialog: true }) },
|
|
154
|
+
react_1.default.createElement(icons_material_1.VideogameAsset, null));
|
|
158
155
|
}
|
|
156
|
+
return null;
|
|
159
157
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
(
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
158
|
+
renderActions() {
|
|
159
|
+
var _a;
|
|
160
|
+
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;
|
|
161
|
+
}
|
|
162
|
+
renderSmall() {
|
|
163
|
+
const hasDetails = this.props.device.hasDetails;
|
|
164
|
+
const status = !this.props.device.status ? [] : Array.isArray(this.props.device.status) ? this.props.device.status : [this.props.device.status];
|
|
165
|
+
return react_1.default.createElement(material_1.Card, { sx: {
|
|
166
|
+
maxWidth: 345,
|
|
167
|
+
minWidth: 200,
|
|
168
|
+
} },
|
|
169
|
+
react_1.default.createElement(material_1.CardHeader, { sx: theme => ({
|
|
170
|
+
backgroundColor: this.props.device.color || theme.palette.secondary.main,
|
|
171
|
+
color: this.props.device.color ? adapter_react_v5_1.Utils.invertColor(this.props.device.color, true) : theme.palette.secondary.contrastText,
|
|
172
|
+
maxWidth: 345,
|
|
173
|
+
}), avatar: react_1.default.createElement("div", null,
|
|
174
|
+
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,
|
|
175
|
+
this.state.icon ? react_1.default.createElement(adapter_react_v5_1.Icon, { src: this.state.icon }) : react_1.default.createElement(NoImageIcon, null)), action: hasDetails ? react_1.default.createElement(material_1.IconButton, { "aria-label": "settings", onClick: () => {
|
|
176
|
+
if (!this.state.open) {
|
|
177
|
+
this.loadDetails().catch(console.error);
|
|
178
|
+
this.setState({ open: true });
|
|
179
|
+
}
|
|
180
|
+
} },
|
|
181
|
+
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,
|
|
182
|
+
react_1.default.createElement("b", { style: { marginRight: 4 } },
|
|
183
|
+
(0, Utils_1.getTranslation)('manufacturer'),
|
|
184
|
+
":"),
|
|
185
|
+
getText(this.props.device.manufacturer)) : null }),
|
|
186
|
+
react_1.default.createElement(material_1.CardContent, { style: { position: 'relative' } },
|
|
187
|
+
(status === null || status === void 0 ? void 0 : status.length) ? react_1.default.createElement("div", { style: {
|
|
188
|
+
display: 'flex',
|
|
189
|
+
position: 'absolute',
|
|
190
|
+
top: -11,
|
|
191
|
+
background: '#88888880',
|
|
192
|
+
padding: '0 8px',
|
|
193
|
+
borderRadius: 5,
|
|
194
|
+
width: 'calc(100% - 46px)',
|
|
195
|
+
} }, status.map((s, i) => react_1.default.createElement(DeviceStatus_1.default, { key: i, status: s }))) : null,
|
|
196
|
+
react_1.default.createElement("div", null,
|
|
197
|
+
react_1.default.createElement(material_1.Typography, { variant: "body1" },
|
|
198
|
+
react_1.default.createElement("div", { onClick: this.copyToClipboard },
|
|
199
|
+
react_1.default.createElement("b", null, "ID:"),
|
|
200
|
+
react_1.default.createElement("span", { style: { marginLeft: 4 } }, this.props.device.id.replace(/.*\.\d\./, ''))),
|
|
201
|
+
this.props.device.manufacturer ? react_1.default.createElement("div", null,
|
|
202
|
+
react_1.default.createElement("b", { style: { marginRight: 4 } },
|
|
203
|
+
(0, Utils_1.getTranslation)('manufacturer'),
|
|
204
|
+
":"),
|
|
205
|
+
getText(this.props.device.manufacturer)) : null,
|
|
206
|
+
this.props.device.model ? react_1.default.createElement("div", null,
|
|
207
|
+
react_1.default.createElement("b", { style: { marginRight: 4 } },
|
|
208
|
+
(0, Utils_1.getTranslation)('model'),
|
|
209
|
+
":"),
|
|
210
|
+
getText(this.props.device.model)) : null))),
|
|
211
|
+
react_1.default.createElement(material_1.CardActions, { disableSpacing: true },
|
|
212
|
+
this.renderActions(),
|
|
213
|
+
react_1.default.createElement("div", { style: { flexGrow: 1 } }),
|
|
214
|
+
this.renderControls()),
|
|
215
|
+
this.renderDialog(),
|
|
216
|
+
this.renderControlDialog());
|
|
217
|
+
}
|
|
218
|
+
renderBig() {
|
|
219
|
+
var _a;
|
|
220
|
+
const cardStyle = {
|
|
221
|
+
// backgroundColor: '#fafafa',
|
|
222
|
+
width: 300,
|
|
223
|
+
minHeight: 280,
|
|
224
|
+
margin: 10,
|
|
225
|
+
overflow: 'hidden',
|
|
226
|
+
};
|
|
227
|
+
/** @type {CSSProperties} */
|
|
228
|
+
const headerStyle = {
|
|
229
|
+
display: 'flex',
|
|
230
|
+
position: 'relative',
|
|
231
|
+
justifyContent: 'space-between',
|
|
232
|
+
minHeight: 60,
|
|
233
|
+
color: '#000',
|
|
234
|
+
padding: '0 10px 0 10px',
|
|
235
|
+
backgroundColor: '#77c7ff8c',
|
|
236
|
+
borderRadius: '4px 4px 0 0',
|
|
237
|
+
};
|
|
238
|
+
/** @type {CSSProperties} */
|
|
239
|
+
const imgAreaStyle = {
|
|
240
|
+
height: 45,
|
|
241
|
+
width: 45,
|
|
242
|
+
margin: 'auto',
|
|
243
|
+
justifyContent: 'center',
|
|
244
|
+
display: 'grid',
|
|
245
|
+
};
|
|
246
|
+
/** @type {CSSProperties} */
|
|
247
|
+
const imgStyle = {
|
|
248
|
+
zIndex: 2,
|
|
249
|
+
maxWidth: '100%',
|
|
250
|
+
maxHeight: '100%',
|
|
251
|
+
};
|
|
252
|
+
/** @type {CSSProperties} */
|
|
253
|
+
const titleStyle = {
|
|
254
|
+
color: '#333',
|
|
255
|
+
width: '100%',
|
|
256
|
+
fontSize: 16,
|
|
257
|
+
fontWeight: 'bold',
|
|
258
|
+
paddingTop: 16,
|
|
259
|
+
paddingLeft: 8,
|
|
260
|
+
whiteSpace: 'nowrap',
|
|
261
|
+
overflow: 'hidden',
|
|
262
|
+
textOverflow: 'ellipsis',
|
|
263
|
+
};
|
|
264
|
+
/** @type {CSSProperties} */
|
|
265
|
+
const detailsButtonStyle = {
|
|
266
|
+
right: 20,
|
|
267
|
+
bottom: -20,
|
|
268
|
+
position: 'absolute',
|
|
269
|
+
};
|
|
270
|
+
/** @type {CSSProperties} */
|
|
271
|
+
const bodyStyle = {
|
|
272
|
+
height: 'calc(100% - 116px)',
|
|
273
|
+
};
|
|
274
|
+
/** @type {CSSProperties} */
|
|
275
|
+
const deviceInfoStyle = {
|
|
276
|
+
padding: '20px 16px 0 16px',
|
|
277
|
+
height: 133,
|
|
278
|
+
};
|
|
279
|
+
/** @type {CSSProperties} */
|
|
280
|
+
const statusStyle = {
|
|
281
|
+
padding: '15px 15px 0 15px',
|
|
282
|
+
height: 41,
|
|
283
|
+
};
|
|
284
|
+
const status = !this.props.device.status ? [] : Array.isArray(this.props.device.status) ? this.props.device.status : [this.props.device.status];
|
|
285
|
+
return react_1.default.createElement(material_1.Paper, { style: cardStyle, key: this.props.id },
|
|
286
|
+
react_1.default.createElement("div", { style: headerStyle },
|
|
287
|
+
react_1.default.createElement("div", { style: imgAreaStyle },
|
|
288
|
+
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,
|
|
289
|
+
react_1.default.createElement(adapter_react_v5_1.Icon, { src: this.state.icon, style: imgStyle })),
|
|
290
|
+
react_1.default.createElement("div", { style: titleStyle }, this.props.title),
|
|
291
|
+
this.props.device.hasDetails ? react_1.default.createElement(material_1.Fab, { disabled: !this.props.alive, size: "small", style: detailsButtonStyle, onClick: () => {
|
|
292
|
+
if (!this.state.open) {
|
|
293
|
+
this.loadDetails().catch(console.error);
|
|
294
|
+
this.setState({ open: true });
|
|
295
|
+
}
|
|
296
|
+
}, color: "primary" },
|
|
297
|
+
react_1.default.createElement(icons_material_1.MoreVert, null)) : null),
|
|
298
|
+
react_1.default.createElement("div", { style: statusStyle }, status.map((s, i) => react_1.default.createElement(DeviceStatus_1.default, { key: i, status: s }))),
|
|
299
|
+
react_1.default.createElement("div", { style: bodyStyle },
|
|
300
|
+
react_1.default.createElement(material_1.Typography, { variant: "body1", style: deviceInfoStyle },
|
|
301
|
+
react_1.default.createElement("div", { onClick: this.copyToClipboard },
|
|
302
|
+
react_1.default.createElement("b", { style: { marginRight: 4 } }, "ID:"),
|
|
303
|
+
this.props.device.id.replace(/.*\.\d\./, '')),
|
|
304
|
+
this.props.device.manufacturer ? react_1.default.createElement("div", null,
|
|
192
305
|
react_1.default.createElement("b", { style: { marginRight: 4 } },
|
|
193
306
|
(0, Utils_1.getTranslation)('manufacturer'),
|
|
194
307
|
":"),
|
|
195
|
-
getText(device.manufacturer)) : null,
|
|
196
|
-
device.model ? react_1.default.createElement("div", null,
|
|
308
|
+
getText(this.props.device.manufacturer)) : null,
|
|
309
|
+
this.props.device.model ? react_1.default.createElement("div", null,
|
|
197
310
|
react_1.default.createElement("b", { style: { marginRight: 4 } },
|
|
198
311
|
(0, Utils_1.getTranslation)('model'),
|
|
199
312
|
":"),
|
|
200
|
-
getText(device.model)) : null)
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
313
|
+
getText(this.props.device.model)) : null),
|
|
314
|
+
!!((_a = this.props.device.actions) === null || _a === void 0 ? void 0 : _a.length) && react_1.default.createElement("div", { style: {
|
|
315
|
+
flex: 1,
|
|
316
|
+
position: 'relative',
|
|
317
|
+
display: 'flex',
|
|
318
|
+
gap: 8,
|
|
319
|
+
paddingBottom: 5,
|
|
320
|
+
height: 34,
|
|
321
|
+
paddingLeft: 10,
|
|
322
|
+
paddingRight: 10,
|
|
323
|
+
} },
|
|
324
|
+
this.renderActions(),
|
|
325
|
+
react_1.default.createElement("div", { style: { flexGrow: 1 } }),
|
|
326
|
+
this.renderControls())),
|
|
327
|
+
this.renderDialog(),
|
|
328
|
+
this.renderControlDialog());
|
|
329
|
+
}
|
|
330
|
+
render() {
|
|
331
|
+
if (this.props.smallCards) {
|
|
332
|
+
return this.renderSmall();
|
|
333
|
+
}
|
|
334
|
+
return this.renderBig();
|
|
335
|
+
}
|
|
207
336
|
}
|
|
208
337
|
exports.default = DeviceCard;
|
package/DeviceControl.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ interface DeviceControlProps {
|
|
|
7
7
|
controlHandler: (deviceId: string, control: ControlBase, state: ControlState) => () => Promise<ioBroker.State | null>;
|
|
8
8
|
controlStateHandler: (deviceId: string, control: ControlBase) => () => Promise<ioBroker.State | null>;
|
|
9
9
|
colors: any;
|
|
10
|
+
disabled?: boolean;
|
|
10
11
|
}
|
|
11
12
|
interface DeviceControlState {
|
|
12
13
|
value: any;
|
package/DeviceControl.js
CHANGED
|
@@ -44,7 +44,7 @@ class DeviceControl extends react_1.Component {
|
|
|
44
44
|
if (id === this.props.control.stateId && state) {
|
|
45
45
|
// request new state
|
|
46
46
|
const newState = await (this.props.controlStateHandler(this.props.deviceId, this.props.control)());
|
|
47
|
-
if ((newState === null || newState === void 0 ? void 0 : newState.ts) && newState.ts > this.state.ts) {
|
|
47
|
+
if ((newState === null || newState === void 0 ? void 0 : newState.ts) && (!this.state.ts || newState.ts > this.state.ts)) {
|
|
48
48
|
this.setState({
|
|
49
49
|
value: newState.val,
|
|
50
50
|
ts: newState.ts,
|
|
@@ -68,8 +68,8 @@ class DeviceControl extends react_1.Component {
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
static getDerivedStateFromProps(props, state) {
|
|
71
|
-
var _a;
|
|
72
|
-
if (((_a = props.control.state) === null || _a === void 0 ? void 0 : _a.ts) > state.ts) {
|
|
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
73
|
return {
|
|
74
74
|
value: props.control.state.val,
|
|
75
75
|
ts: props.control.state.ts,
|
|
@@ -79,7 +79,7 @@ class DeviceControl extends react_1.Component {
|
|
|
79
79
|
}
|
|
80
80
|
async sendControl(deviceId, control, value) {
|
|
81
81
|
const result = await (this.props.controlHandler(deviceId, control, value)());
|
|
82
|
-
if ((result === null || result === void 0 ? void 0 : result.ts) && (result === null || result === void 0 ? void 0 : result.ts) > this.state.ts) {
|
|
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
83
|
this.setState({
|
|
84
84
|
value: result.val,
|
|
85
85
|
ts: result.ts,
|
|
@@ -90,14 +90,14 @@ class DeviceControl extends react_1.Component {
|
|
|
90
90
|
const tooltip = (0, Utils_1.getTranslation)(this.props.control.description);
|
|
91
91
|
const icon = (0, Utils_1.renderIcon)(this.props.control, this.props.colors, this.state.value);
|
|
92
92
|
if (!this.props.control.label) {
|
|
93
|
-
return react_1.default.createElement(material_1.Fab, { title: tooltip, onClick: () => this.sendControl(this.props.deviceId, this.props.control, true) }, icon);
|
|
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
94
|
}
|
|
95
|
-
return react_1.default.createElement(material_1.Button, { title: tooltip, onClick: () => this.sendControl(this.props.deviceId, this.props.control, true), startIcon: icon }, this.props.control.label);
|
|
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
96
|
}
|
|
97
97
|
renderSwitch() {
|
|
98
98
|
const tooltip = (0, Utils_1.getTranslation)(this.props.control.description);
|
|
99
99
|
// const icon = renderIcon(this.props.control, this.props.colors, this.state.value);
|
|
100
|
-
return react_1.default.createElement(material_1.Switch, { title: tooltip, checked: this.state.value, onChange: e => this.sendControl(this.props.deviceId, this.props.control, e.target.checked) });
|
|
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
101
|
}
|
|
102
102
|
getColor() {
|
|
103
103
|
let color;
|
|
@@ -126,9 +126,9 @@ class DeviceControl extends react_1.Component {
|
|
|
126
126
|
const icon = (0, Utils_1.renderIcon)(this.props.control, this.props.colors, this.state.value);
|
|
127
127
|
const color = this.getColor();
|
|
128
128
|
if (!this.props.control.label) {
|
|
129
|
-
return react_1.default.createElement(material_1.Fab, { 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);
|
|
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
130
|
}
|
|
131
|
-
return react_1.default.createElement(material_1.Button, { 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);
|
|
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
132
|
}
|
|
133
133
|
render() {
|
|
134
134
|
if (this.props.control.type === 'button') {
|
package/DeviceList.d.ts
CHANGED
|
@@ -6,7 +6,8 @@ interface DeviceListProps extends CommunicationProps {
|
|
|
6
6
|
filter?: string;
|
|
7
7
|
embedded?: boolean;
|
|
8
8
|
title?: string;
|
|
9
|
-
style
|
|
9
|
+
style?: React.CSSProperties;
|
|
10
|
+
smallCards?: boolean;
|
|
10
11
|
}
|
|
11
12
|
interface DeviceListState extends CommunicationState {
|
|
12
13
|
devices: DeviceInfo[];
|
package/DeviceList.js
CHANGED
|
@@ -66,7 +66,6 @@ class DeviceList extends Communication_1.default {
|
|
|
66
66
|
'zh-cn': zh_cn_json_1.default,
|
|
67
67
|
});
|
|
68
68
|
}
|
|
69
|
-
// @ts-ignore
|
|
70
69
|
Object.assign(this.state, {
|
|
71
70
|
devices: [],
|
|
72
71
|
filteredDevices: [],
|
|
@@ -76,39 +75,51 @@ class DeviceList extends Communication_1.default {
|
|
|
76
75
|
alive: null,
|
|
77
76
|
});
|
|
78
77
|
this.lastPropsFilter = this.props.filter;
|
|
79
|
-
this.lastInstance =
|
|
78
|
+
this.lastInstance = this.props.selectedInstance;
|
|
80
79
|
this.filterTimeout = null;
|
|
81
80
|
this.language = adapter_react_v5_1.I18n.getLanguage();
|
|
82
81
|
}
|
|
83
82
|
async componentDidMount() {
|
|
84
|
-
|
|
83
|
+
let alive = false;
|
|
84
|
+
if (this.state.alive === null) {
|
|
85
85
|
try {
|
|
86
86
|
// check if instance is alive
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
this.setState({ alive: false });
|
|
91
|
-
return;
|
|
87
|
+
const stateAlive = await this.props.socket.getState(`system.adapter.${this.props.selectedInstance}.alive`);
|
|
88
|
+
if (stateAlive === null || stateAlive === void 0 ? void 0 : stateAlive.val) {
|
|
89
|
+
alive = true;
|
|
92
90
|
}
|
|
93
|
-
const instanceInfo = await this.loadInstanceInfos();
|
|
94
|
-
this.setState({ alive: true, instanceInfo });
|
|
95
91
|
}
|
|
96
92
|
catch (error) {
|
|
97
93
|
console.error(error);
|
|
98
|
-
this.setState({ alive: false });
|
|
99
94
|
}
|
|
95
|
+
this.setState({ alive }, () => this.props.socket.subscribeState(`system.adapter.${this.props.selectedInstance}.alive`, this.aliveHandler));
|
|
96
|
+
if (!alive) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
alive = this.state.alive;
|
|
100
102
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
+
if (!this.props.embedded && alive) {
|
|
104
|
+
try {
|
|
105
|
+
const instanceInfo = await this.loadInstanceInfos();
|
|
106
|
+
this.setState({ instanceInfo });
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
console.error(error);
|
|
110
|
+
}
|
|
103
111
|
}
|
|
104
|
-
|
|
105
|
-
|
|
112
|
+
if (alive) {
|
|
113
|
+
try {
|
|
114
|
+
await this.loadData();
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
console.error(error);
|
|
118
|
+
}
|
|
106
119
|
}
|
|
107
120
|
}
|
|
108
121
|
componentWillUnmount() {
|
|
109
|
-
|
|
110
|
-
this.props.socket.unsubscribeState(`system.adapter.${this.props.selectedInstance}.alive`, this.aliveHandler);
|
|
111
|
-
}
|
|
122
|
+
this.props.socket.unsubscribeState(`system.adapter.${this.props.selectedInstance}.alive`, this.aliveHandler);
|
|
112
123
|
}
|
|
113
124
|
/**
|
|
114
125
|
* Load devices
|
|
@@ -176,7 +187,7 @@ class DeviceList extends Communication_1.default {
|
|
|
176
187
|
react_1.default.createElement("span", null, (0, Utils_1.getTranslation)('allDevicesFilteredOut')));
|
|
177
188
|
}
|
|
178
189
|
else {
|
|
179
|
-
list = this.state.filteredDevices.map(device => react_1.default.createElement(DeviceCard_1.default, { key: device.id, id: device.id, title: this.getText(device.name), device: device, instanceId: this.props.selectedInstance, uploadImagesToInstance: this.props.uploadImagesToInstance, deviceHandler: this.deviceHandler, controlHandler: this.controlHandler, controlStateHandler: this.controlStateHandler, socket: this.props.socket }));
|
|
190
|
+
list = this.state.filteredDevices.map(device => react_1.default.createElement(DeviceCard_1.default, { alive: !!this.state.alive, key: device.id, id: device.id, title: this.getText(device.name), device: device, instanceId: this.props.selectedInstance, uploadImagesToInstance: this.props.uploadImagesToInstance, deviceHandler: this.deviceHandler, controlHandler: this.controlHandler, controlStateHandler: this.controlStateHandler, socket: this.props.socket }));
|
|
180
191
|
}
|
|
181
192
|
if (this.props.embedded) {
|
|
182
193
|
return list;
|
package/README.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iobroker/dm-gui-components",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "ReactJS components to develop admin interface for ioBroker device manager.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Jey Cee",
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"react": "^18.2.0",
|
|
38
38
|
"react-dom": "^18.2.0",
|
|
39
|
-
"@iobroker/adapter-react-v5": "^4.7.
|
|
40
|
-
"@types/react": "^18.2.
|
|
39
|
+
"@iobroker/adapter-react-v5": "^4.7.15",
|
|
40
|
+
"@types/react": "^18.2.45",
|
|
41
41
|
"@types/react-dom": "^18.2.17",
|
|
42
42
|
"eslint": "^8.55.0",
|
|
43
43
|
"eslint-config-airbnb": "^19.0.4",
|