@iobroker/dm-gui-components 0.0.3 → 0.0.4

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/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,41 @@ 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
+ }
17
+ interface DeviceCardState {
18
+ open: boolean;
19
+ details: DeviceDetails | null;
20
+ data: Record<string, any>;
21
+ icon: string | undefined;
22
+ showControlDialog: boolean;
15
23
  }
16
24
  /**
17
25
  * Device Card Component
18
26
  */
19
- export default function DeviceCard(params: DeviceCardProps): React.JSX.Element;
20
- export {};
27
+ declare class DeviceCard extends Component<DeviceCardProps, DeviceCardState> {
28
+ constructor(props: DeviceCardProps);
29
+ fetchIcon(): Promise<void>;
30
+ componentDidMount(): void;
31
+ /**
32
+ * Load the device details
33
+ */
34
+ loadDetails(): Promise<void>;
35
+ /**
36
+ * Refresh the device details
37
+ */
38
+ refresh: () => void;
39
+ /**
40
+ * Copy the device ID to the clipboard
41
+ * @returns {void}
42
+ */
43
+ copyToClipboard: () => Promise<void>;
44
+ renderDialog(): React.JSX.Element;
45
+ renderControlDialog(): React.JSX.Element;
46
+ renderControls(): React.JSX.Element;
47
+ renderActions(): React.JSX.Element[];
48
+ renderSmall(): React.JSX.Element;
49
+ renderBig(): React.JSX.Element;
50
+ render(): React.JSX.Element;
51
+ }
52
+ export default DeviceCard;
package/DeviceCard.js CHANGED
@@ -47,162 +47,291 @@ function getText(text) {
47
47
  /**
48
48
  * Device Card Component
49
49
  */
50
- function DeviceCard(params) {
51
- var _a, _b, _c, _d;
52
- const { title, device, instanceId, socket, deviceHandler, uploadImagesToInstance, controlHandler, controlStateHandler, } = params;
53
- const [open, setOpen] = (0, react_1.useState)(false);
54
- const [details, setDetails] = (0, react_1.useState)(null);
55
- const [data, setData] = (0, react_1.useState)({});
56
- const [icon, setIcon] = (0, react_1.useState)(device.icon);
57
- const [showControlDialog, setShowControlDialog] = (0, react_1.useState)(false);
58
- // const [uploadedImage, setUploadedImage] = useState(null);
59
- const hasDetails = device.hasDetails;
60
- const status = !device.status ? [] : Array.isArray(device.status) ? device.status : [device.status];
61
- const colors = { primary: '#111', secondary: '#888' };
62
- (0, react_1.useEffect)(() => {
63
- async function fetchIcon() {
64
- if (!device.icon) {
65
- // try to load the icon from file storage
66
- const fileName = `${device.manufacturer ? `${device.manufacturer}_` : ''}${device.model ? device.model : device.id}`;
67
- try {
68
- const file = await socket.readFile(instanceId.replace('system.adapter.', ''), `${fileName}.webp`, true);
69
- setIcon(`data:image/${file.mimeType},${file}`);
70
- // const response = await fetch(url);
71
- // if (response.ok) {
72
- // const blob = await response.blob();
73
- // const reader = new FileReader();
74
- // reader.onloadend = () => {
75
- // setIcon(reader.result);
76
- // };
77
- // reader.readAsDataURL(blob);
78
- // } else {
79
- // throw new Error('Response not ok');
80
- // }
81
- }
82
- catch (error) {
83
- setIcon('');
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
- fetchIcon()
100
+ }
101
+ componentDidMount() {
102
+ this.fetchIcon()
88
103
  .catch(e => console.error(e));
89
- }, [device, instanceId]);
104
+ }
90
105
  /**
91
106
  * Load the device details
92
107
  */
93
- const loadDetails = async () => {
94
- console.log(`Loading device details for ${device.id}... from ${instanceId}`);
95
- const result = await socket.sendTo(instanceId, 'dm:deviceDetails', device.id);
96
- console.log(`Got device details for ${device.id}:`, result);
97
- setDetails(result);
98
- };
99
- /**
100
- * Refresh the device details
101
- */
102
- const refresh = () => {
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
- * Close the modal
117
- */
118
- const handleClose = () => setOpen(false);
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, { variant: "contained", color: "primary", onClick: () => this.setState({ open: false }), autoFocus: true }, (0, Utils_1.getTranslation)('closeButtonText'))));
141
124
  }
142
- else if ((_c = device.controls) === null || _c === void 0 ? void 0 : _c.length) {
143
- // place button and show controls dialog
144
- renderedControls = react_1.default.createElement(material_1.Fab, { size: "small", onClick: () => setShowControlDialog(true) },
145
- react_1.default.createElement(icons_material_1.VideogameAsset, null));
146
- if (showControlDialog) {
147
- controlDialog = react_1.default.createElement(material_1.Dialog, { open: !0, onClose: () => setShowControlDialog(false) },
148
- react_1.default.createElement(material_1.DialogTitle, null,
149
- title,
150
- react_1.default.createElement(material_1.IconButton, { style: {
151
- position: 'absolute',
152
- top: 5,
153
- right: 5,
154
- zIndex: 10,
155
- }, onClick: () => setShowControlDialog(false) },
156
- react_1.default.createElement(icons_material_1.Close, null))),
157
- react_1.default.createElement(material_1.DialogContent, null, device.controls.map(control => react_1.default.createElement(DeviceControl_1.default, { key: control.id, control: control, socket: socket, colors: colors, deviceId: device.id, controlHandler: controlHandler, controlStateHandler: controlStateHandler }))));
125
+ renderControlDialog() {
126
+ var _a;
127
+ if (!this.state.showControlDialog) {
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, null, (_a = this.props.device.controls) === null || _a === void 0 ? void 0 : _a.map(control => react_1.default.createElement(DeviceControl_1.default, { 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, { 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", onClick: () => this.setState({ showControlDialog: true }) },
154
+ react_1.default.createElement(icons_material_1.VideogameAsset, null));
158
155
  }
156
+ return null;
159
157
  }
160
- const renderedActions = ((_d = device.actions) === null || _d === void 0 ? void 0 : _d.length) ? device.actions.map(a => react_1.default.createElement(DeviceActionButton_1.default, { key: a.id, deviceId: device.id, action: a, deviceHandler: deviceHandler, refresh: refresh })) : null;
161
- return react_1.default.createElement(material_1.Card, { sx: {
162
- maxWidth: 345,
163
- minWidth: 200,
164
- } },
165
- react_1.default.createElement(material_1.CardHeader, { sx: theme => ({
166
- backgroundColor: device.color || theme.palette.secondary.main,
167
- color: device.color ? adapter_react_v5_1.Utils.invertColor(device.color, true) : theme.palette.secondary.contrastText,
168
- }), avatar: react_1.default.createElement("div", null,
169
- uploadImagesToInstance ? react_1.default.createElement(DeviceImageUpload_1.default, { uploadImagesToInstance: uploadImagesToInstance, deviceId: device.id, manufacturer: getText(device.manufacturer), model: getText(device.model), onImageSelect: handleImageClick, socket: socket }) : null,
170
- icon ? react_1.default.createElement(adapter_react_v5_1.Icon, { src: icon }) : react_1.default.createElement(NoImageIcon, null)), action: hasDetails ? react_1.default.createElement(material_1.IconButton, { "aria-label": "settings", onClick: openModal },
171
- react_1.default.createElement(icons_material_1.MoreVert, null)) : null, title: title, subheader: device.manufacturer ? react_1.default.createElement("span", null,
172
- react_1.default.createElement("b", { style: { marginRight: 4 } },
173
- (0, Utils_1.getTranslation)('manufacturer'),
174
- ":"),
175
- getText(device.manufacturer)) : null }),
176
- react_1.default.createElement(material_1.CardContent, { style: { position: 'relative' } },
177
- (status === null || status === void 0 ? void 0 : status.length) ? react_1.default.createElement("div", { style: {
178
- display: 'flex',
179
- position: 'absolute',
180
- top: -11,
181
- background: '#88888880',
182
- padding: '0 8px',
183
- borderRadius: 5,
184
- width: 'calc(100% - 46px)',
185
- } }, status.map((s, i) => react_1.default.createElement(DeviceStatus_1.default, { key: i, status: s }))) : null,
186
- react_1.default.createElement("div", null,
187
- react_1.default.createElement(material_1.Typography, { variant: "body1" },
188
- react_1.default.createElement("div", { onClick: copyToClipboard },
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, { 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, { 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 },
189
302
  react_1.default.createElement("b", null, "ID:"),
190
- react_1.default.createElement("span", { style: { marginLeft: 4 } }, device.id.replace(/.*\.\d\./, ''))),
191
- device.manufacturer ? react_1.default.createElement("div", null,
192
- react_1.default.createElement("b", { style: { marginRight: 4 } },
303
+ " ",
304
+ this.props.device.id.replace(/.*\.\d\./, '')),
305
+ this.props.device.manufacturer ? react_1.default.createElement("div", null,
306
+ react_1.default.createElement("b", null,
193
307
  (0, Utils_1.getTranslation)('manufacturer'),
194
308
  ":"),
195
- getText(device.manufacturer)) : null,
196
- device.model ? react_1.default.createElement("div", null,
197
- react_1.default.createElement("b", { style: { marginRight: 4 } },
309
+ " ",
310
+ getText(this.props.device.manufacturer)) : null,
311
+ this.props.device.model ? react_1.default.createElement("div", null,
312
+ react_1.default.createElement("b", null,
198
313
  (0, Utils_1.getTranslation)('model'),
199
314
  ":"),
200
- getText(device.model)) : null))),
201
- react_1.default.createElement(material_1.CardActions, { disableSpacing: true },
202
- renderedActions,
203
- react_1.default.createElement("div", { style: { flexGrow: 1 } }),
204
- renderedControls),
205
- renderedDialog,
206
- controlDialog);
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
+ } }, this.renderActions())),
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/DeviceList.d.ts CHANGED
@@ -7,6 +7,7 @@ interface DeviceListProps extends CommunicationProps {
7
7
  embedded?: boolean;
8
8
  title?: string;
9
9
  style: React.CSSProperties;
10
+ smallCards: boolean;
10
11
  }
11
12
  interface DeviceListState extends CommunicationState {
12
13
  devices: DeviceInfo[];
package/README.md CHANGED
@@ -20,6 +20,9 @@ render() {
20
20
  -->
21
21
 
22
22
  ## Changelog
23
+ ### 0.0.4 (2023-12-12)
24
+ * (bluefox) return the style of big cards
25
+
23
26
  ### 0.0.3 (2023-12-12)
24
27
  * (bluefox) initial commit
25
28
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iobroker/dm-gui-components",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
4
4
  "description": "ReactJS components to develop admin interface for ioBroker device manager.",
5
5
  "author": {
6
6
  "name": "Jey Cee",