@iobroker/dm-gui-components 10.0.2 → 10.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/README.md +270 -154
- package/build/DeviceCard.d.ts +14 -0
- package/build/DeviceCard.js +66 -9
- package/build/DeviceCard.js.map +1 -1
- package/build/DeviceList.d.ts +26 -0
- package/build/DeviceList.js +124 -5
- package/build/DeviceList.js.map +1 -1
- package/build/StatusIndicator.d.ts +50 -0
- package/build/StatusIndicator.js +136 -0
- package/build/StatusIndicator.js.map +1 -0
- package/build/Utils.d.ts +20 -1
- package/build/Utils.js +56 -0
- package/build/Utils.js.map +1 -1
- package/build/i18n/de.json +2 -0
- package/build/i18n/en.json +2 -0
- package/build/i18n/es.json +2 -0
- package/build/i18n/fr.json +2 -0
- package/build/i18n/it.json +2 -0
- package/build/i18n/nl.json +2 -0
- package/build/i18n/pl.json +2 -0
- package/build/i18n/pt.json +2 -0
- package/build/i18n/ru.json +2 -0
- package/build/i18n/uk.json +2 -0
- package/build/i18n/zh-cn.json +2 -0
- package/build/protocol/api.d.ts +1 -1
- package/build/protocol/api.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -1,210 +1,326 @@
|
|
|
1
|
-
# ReactJS component for ioBroker device manager
|
|
2
|
-
|
|
3
|
-
This component requires the [dm-utils](https://github.com/ioBroker/dm-utils) in an adapter.
|
|
4
|
-
|
|
5
|
-
## Usage
|
|
6
|
-
|
|
7
|
-
```jsx
|
|
8
|
-
import React from 'react';
|
|
9
|
-
import DeviceList from '@iobroker/dm-gui-components';
|
|
10
|
-
|
|
11
|
-
//...
|
|
12
|
-
render() {
|
|
13
|
-
return <DeviceList
|
|
14
|
-
socket={this.props.socket}
|
|
15
|
-
selectedInstance="matter.0"
|
|
16
|
-
/>;
|
|
17
|
-
}
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
## Icon names
|
|
21
|
-
|
|
22
|
-
You can use the following icon names for actions and controls.
|
|
23
|
-
Icons are resolved by the action/control `id` or by the `icon` property. You can also provide a `data:image/...` base64 string for custom icons.
|
|
24
|
-
|
|
25
|
-
### Action and control icons (by name)
|
|
26
|
-
|
|
27
|
-
| Name(s) | MUI Icon | Description |
|
|
28
|
-
|----------------------------|--------------------|--------------------------------------|
|
|
29
|
-
| `edit`, `rename` | Edit | Edit or rename an item |
|
|
30
|
-
| `delete` | Delete | Delete an item |
|
|
31
|
-
| `refresh` | Refresh | Refresh / reload |
|
|
32
|
-
| `newDevice`, `new`, `add` | Add | Add or create a new item |
|
|
33
|
-
| `discover`, `search` | Search | Discover or search for devices |
|
|
34
|
-
| `unpairDevice`, `unpair` | LinkOff | Unpair / unlink a device |
|
|
35
|
-
| `pairDevice`, `pair` | Link | Pair / link a device |
|
|
36
|
-
| `identify` | NotListedLocation | Identify / locate a device |
|
|
37
|
-
| `play` | PlayArrow | Start playback |
|
|
38
|
-
| `stop` | Stop | Stop playback |
|
|
39
|
-
| `pause` | Pause | Pause playback |
|
|
40
|
-
| `forward`, `next` | FastForward | Skip forward / next track |
|
|
41
|
-
| `rewind`, `previous` | FastRewind | Skip backward / previous track |
|
|
42
|
-
| `lamp`, `light` | Lightbulb | Light / lamp control |
|
|
43
|
-
| `backlight` | Fluorescent | Backlight control |
|
|
44
|
-
| `dimmer` | WbIncandescent | Dimmer control |
|
|
45
|
-
| `socket` | Power | Power socket control |
|
|
46
|
-
| `settings` | Settings | Settings / configuration |
|
|
47
|
-
| `users`, `group` | Group | User group |
|
|
48
|
-
| `user` | Person | Single user |
|
|
49
|
-
| `update` | Upgrade | Update / upgrade |
|
|
50
|
-
| `qrcode` | QrCode | QR code |
|
|
51
|
-
| `info` | Info | Information |
|
|
52
|
-
| `lines` | Article | Text lines / log |
|
|
53
|
-
| `web` | Launch | Open web link |
|
|
54
|
-
|
|
55
|
-
Any unrecognized name renders a **QuestionMark** icon as fallback.
|
|
56
|
-
|
|
57
|
-
### Legacy Font Awesome icons
|
|
58
|
-
|
|
59
|
-
These names are supported for backward compatibility. Prefer the names from the table above.
|
|
60
|
-
|
|
61
|
-
| Name(s) | MUI Icon | Description |
|
|
62
|
-
|--------------------------------|--------------------|--------------------------------|
|
|
63
|
-
| `fa-trash-can`, `fa-trash` | Delete | Delete |
|
|
64
|
-
| `fa-pen` | Edit | Edit |
|
|
65
|
-
| `fa-redo-alt` | Refresh | Refresh / redo |
|
|
66
|
-
| `fa-plus` | Add | Add |
|
|
67
|
-
| `fa-qrcode`, `qrcode` | QrCode | QR code |
|
|
68
|
-
| `fa-wifi` | Wifi | Wi-Fi enabled |
|
|
69
|
-
| `fa-wifi-slash` | WifiOff | Wi-Fi disabled |
|
|
70
|
-
| `fa-bluetooth` | Bluetooth | Bluetooth enabled |
|
|
71
|
-
| `fa-bluetooth-slash` | BluetoothDisabled | Bluetooth disabled |
|
|
72
|
-
| `fa-eye` | Visibility | View / visible |
|
|
73
|
-
| `fa-search` | Search | Search |
|
|
74
|
-
| `fa-unlink` | LinkOff | Unlink |
|
|
75
|
-
| `fa-link` | Link | Link |
|
|
76
|
-
| `fa-search-location` | NotListedLocation | Search location / identify |
|
|
77
|
-
| `fa-play` | PlayArrow | Play |
|
|
78
|
-
| `fa-stop` | Stop | Stop |
|
|
79
|
-
| `fa-pause` | Pause | Pause |
|
|
80
|
-
|
|
81
|
-
Unrecognized FA names render a **QuestionMark** icon.
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
1
|
+
# ReactJS component for ioBroker device manager
|
|
2
|
+
|
|
3
|
+
This component requires the [dm-utils](https://github.com/ioBroker/dm-utils) in an adapter.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```jsx
|
|
8
|
+
import React from 'react';
|
|
9
|
+
import DeviceList from '@iobroker/dm-gui-components';
|
|
10
|
+
|
|
11
|
+
//...
|
|
12
|
+
render() {
|
|
13
|
+
return <DeviceList
|
|
14
|
+
socket={this.props.socket}
|
|
15
|
+
selectedInstance="matter.0"
|
|
16
|
+
/>;
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Icon names
|
|
21
|
+
|
|
22
|
+
You can use the following icon names for actions and controls.
|
|
23
|
+
Icons are resolved by the action/control `id` or by the `icon` property. You can also provide a `data:image/...` base64 string for custom icons.
|
|
24
|
+
|
|
25
|
+
### Action and control icons (by name)
|
|
26
|
+
|
|
27
|
+
| Name(s) | MUI Icon | Description |
|
|
28
|
+
|----------------------------|--------------------|--------------------------------------|
|
|
29
|
+
| `edit`, `rename` | Edit | Edit or rename an item |
|
|
30
|
+
| `delete` | Delete | Delete an item |
|
|
31
|
+
| `refresh` | Refresh | Refresh / reload |
|
|
32
|
+
| `newDevice`, `new`, `add` | Add | Add or create a new item |
|
|
33
|
+
| `discover`, `search` | Search | Discover or search for devices |
|
|
34
|
+
| `unpairDevice`, `unpair` | LinkOff | Unpair / unlink a device |
|
|
35
|
+
| `pairDevice`, `pair` | Link | Pair / link a device |
|
|
36
|
+
| `identify` | NotListedLocation | Identify / locate a device |
|
|
37
|
+
| `play` | PlayArrow | Start playback |
|
|
38
|
+
| `stop` | Stop | Stop playback |
|
|
39
|
+
| `pause` | Pause | Pause playback |
|
|
40
|
+
| `forward`, `next` | FastForward | Skip forward / next track |
|
|
41
|
+
| `rewind`, `previous` | FastRewind | Skip backward / previous track |
|
|
42
|
+
| `lamp`, `light` | Lightbulb | Light / lamp control |
|
|
43
|
+
| `backlight` | Fluorescent | Backlight control |
|
|
44
|
+
| `dimmer` | WbIncandescent | Dimmer control |
|
|
45
|
+
| `socket` | Power | Power socket control |
|
|
46
|
+
| `settings` | Settings | Settings / configuration |
|
|
47
|
+
| `users`, `group` | Group | User group |
|
|
48
|
+
| `user` | Person | Single user |
|
|
49
|
+
| `update` | Upgrade | Update / upgrade |
|
|
50
|
+
| `qrcode` | QrCode | QR code |
|
|
51
|
+
| `info` | Info | Information |
|
|
52
|
+
| `lines` | Article | Text lines / log |
|
|
53
|
+
| `web` | Launch | Open web link |
|
|
54
|
+
|
|
55
|
+
Any unrecognized name renders a **QuestionMark** icon as fallback.
|
|
56
|
+
|
|
57
|
+
### Legacy Font Awesome icons
|
|
58
|
+
|
|
59
|
+
These names are supported for backward compatibility. Prefer the names from the table above.
|
|
60
|
+
|
|
61
|
+
| Name(s) | MUI Icon | Description |
|
|
62
|
+
|--------------------------------|--------------------|--------------------------------|
|
|
63
|
+
| `fa-trash-can`, `fa-trash` | Delete | Delete |
|
|
64
|
+
| `fa-pen` | Edit | Edit |
|
|
65
|
+
| `fa-redo-alt` | Refresh | Refresh / redo |
|
|
66
|
+
| `fa-plus` | Add | Add |
|
|
67
|
+
| `fa-qrcode`, `qrcode` | QrCode | QR code |
|
|
68
|
+
| `fa-wifi` | Wifi | Wi-Fi enabled |
|
|
69
|
+
| `fa-wifi-slash` | WifiOff | Wi-Fi disabled |
|
|
70
|
+
| `fa-bluetooth` | Bluetooth | Bluetooth enabled |
|
|
71
|
+
| `fa-bluetooth-slash` | BluetoothDisabled | Bluetooth disabled |
|
|
72
|
+
| `fa-eye` | Visibility | View / visible |
|
|
73
|
+
| `fa-search` | Search | Search |
|
|
74
|
+
| `fa-unlink` | LinkOff | Unlink |
|
|
75
|
+
| `fa-link` | Link | Link |
|
|
76
|
+
| `fa-search-location` | NotListedLocation | Search location / identify |
|
|
77
|
+
| `fa-play` | PlayArrow | Play |
|
|
78
|
+
| `fa-stop` | Stop | Stop |
|
|
79
|
+
| `fa-pause` | Pause | Pause |
|
|
80
|
+
|
|
81
|
+
Unrecognized FA names render a **QuestionMark** icon.
|
|
82
|
+
|
|
83
|
+
## Status line
|
|
84
|
+
|
|
85
|
+
The status line at the top of a device card shows the built-in indicators (connection, RSSI, battery,
|
|
86
|
+
warning, update, enabled). Two mechanisms let an adapter add its own entries there.
|
|
87
|
+
|
|
88
|
+
> **Note:** the types are defined in `@iobroker/dm-utils` from version 3.2.0 on
|
|
89
|
+
> (`StatusIndicator`, `StatusIndicatorLevel`, `IndicatorColor`, `ActionPlacement`) and are only
|
|
90
|
+
> re-exported here. See the README of `dm-utils` for the adapter side.
|
|
91
|
+
|
|
92
|
+
### Actions in the status line
|
|
93
|
+
|
|
94
|
+
Any action can be moved from the button row at the bottom of the card into the status line with
|
|
95
|
+
`placement: 'status'`:
|
|
96
|
+
|
|
97
|
+
```js
|
|
98
|
+
const actions = [{ id: 'openLog', icon: 'lines', placement: 'status', handler: openLogHandler }];
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The action keeps all its features (`icon`, `color`, `title`, `confirmation`, `inputBefore`, `url`, …)
|
|
102
|
+
and is not rendered a second time in the footer.
|
|
103
|
+
|
|
104
|
+
### Custom indicators
|
|
105
|
+
|
|
106
|
+
`DeviceInfo.indicators` (device card) and `InstanceDetails.indicators` (toolbar) describe indicators
|
|
107
|
+
whose appearance follows a state or object value live. Every visual property accepts either a literal
|
|
108
|
+
value or a `{ stateId }` / `{ objectId, property }` reference.
|
|
109
|
+
|
|
110
|
+
| Property | Description |
|
|
111
|
+
| ---------------- | ---------------------------------------------------------------------------------------------------------- |
|
|
112
|
+
| `id` | Unique ID within the device / instance |
|
|
113
|
+
| `value` | Live value. Controls visibility, `iconOn`/`colorOn` and the matching `levels` entry |
|
|
114
|
+
| `icon` | Icon name (see above), `fa-*`, `data:image/...`, URL or path |
|
|
115
|
+
| `iconOn` | Icon used while the value is truthy |
|
|
116
|
+
| `color` | `ok`, `warning`, `error`, `info`, `inactive`, `primary`, `secondary` or a CSS color |
|
|
117
|
+
| `colorOn` | Color used while the value is truthy |
|
|
118
|
+
| `text` | Text below the icon |
|
|
119
|
+
| `showValue` | Show the value as text below the icon |
|
|
120
|
+
| `unit` | Appended to the text |
|
|
121
|
+
| `tooltip` | Tooltip |
|
|
122
|
+
| `levels` | Value ranges mapped to `icon` / `color` / `text` / `tooltip`. First match wins |
|
|
123
|
+
| `actionId` | ID of an action of the same device/instance. Makes the indicator clickable |
|
|
124
|
+
| `hideIfEmpty` | Hide while the value is `undefined`, `null`, `''` or `false` (default `true`; the number `0` stays visible) |
|
|
125
|
+
| `order` | Sort order in the line (default 100) |
|
|
126
|
+
| `configurable` | Let the user show or hide this indicator in the toolbar |
|
|
127
|
+
| `defaultVisible` | Visibility of a configurable indicator until the user decides otherwise (default `true`) |
|
|
128
|
+
| `label` | Name in the visibility settings. Falls back to `tooltip` and then to `id` |
|
|
129
|
+
|
|
130
|
+
A `levels` entry matches by exact `value`, by `min`/`max` (both inclusive, numeric values only) or,
|
|
131
|
+
if it defines no condition at all, as a catch-all — put such an entry last.
|
|
132
|
+
|
|
133
|
+
If `actionId` is given, a click triggers that action through the normal device/instance action flow,
|
|
134
|
+
including `confirmation`, `inputBefore`, `url`, the progress dialog and the `refresh` handling. The
|
|
135
|
+
referenced action is then not rendered as a normal button anymore.
|
|
136
|
+
|
|
137
|
+
```js
|
|
138
|
+
const deviceInfo = {
|
|
139
|
+
id: 'sensor-1',
|
|
140
|
+
name: 'Window sensor kitchen',
|
|
141
|
+
actions: [{ id: 'openLog', icon: 'lines', description: { en: 'Open device log' }, handler: openLogHandler }],
|
|
142
|
+
status: { connection: { stateId: 'zigbee.0.abc.available', mapping: { true: 'connected', false: 'disconnected' } } },
|
|
143
|
+
indicators: [
|
|
144
|
+
{
|
|
145
|
+
id: 'linkQuality',
|
|
146
|
+
value: { stateId: 'zigbee.0.abc.link_quality' },
|
|
147
|
+
icon: 'fa-wifi',
|
|
148
|
+
showValue: true,
|
|
149
|
+
unit: 'lqi',
|
|
150
|
+
tooltip: { en: 'Link quality', de: 'Verbindungsqualität' },
|
|
151
|
+
levels: [
|
|
152
|
+
{ max: 50, color: 'error' },
|
|
153
|
+
{ max: 100, color: 'warning' },
|
|
154
|
+
{ color: 'ok' },
|
|
155
|
+
],
|
|
156
|
+
actionId: 'openLog',
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
id: 'tamper',
|
|
160
|
+
value: { stateId: 'zigbee.0.abc.tamper' },
|
|
161
|
+
icon: 'fa-eye',
|
|
162
|
+
colorOn: 'error',
|
|
163
|
+
tooltip: { en: 'Tamper contact triggered' },
|
|
164
|
+
},
|
|
165
|
+
],
|
|
166
|
+
};
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
The indicator line wraps if it does not fit on one line, so the number of indicators is not limited.
|
|
170
|
+
|
|
171
|
+
### Indicators the user can switch off
|
|
172
|
+
|
|
173
|
+
An indicator marked with `configurable: true` can be shown or hidden by the user through the
|
|
174
|
+
sliders button in the toolbar. The choice is stored in the browser (`localStorage`, one entry per
|
|
175
|
+
instance) and never reaches the backend. `defaultVisible: false` starts with a hidden indicator, so
|
|
176
|
+
rarely needed information does not clutter the cards of everybody.
|
|
177
|
+
|
|
178
|
+
Indicators with the same `id` — typically the same indicator on many devices — are configured
|
|
179
|
+
together. If a hidden indicator references an action, that action is hidden as well and does not
|
|
180
|
+
reappear as a button in the footer.
|
|
181
|
+
|
|
182
|
+
```js
|
|
183
|
+
const indicator = {
|
|
184
|
+
id: 'tamper',
|
|
185
|
+
value: { stateId: 'zigbee.0.abc.tamper' },
|
|
186
|
+
icon: 'fa-eye',
|
|
187
|
+
colorOn: 'error',
|
|
188
|
+
label: { en: 'Tamper contact', de: 'Sabotagekontakt' },
|
|
189
|
+
configurable: true,
|
|
190
|
+
defaultVisible: false,
|
|
191
|
+
};
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
<!--
|
|
195
|
+
Placeholder for the next version (at the beginning of the line):
|
|
196
|
+
### **WORK IN PROGRESS**
|
|
197
|
+
-->
|
|
198
|
+
|
|
88
199
|
## Changelog
|
|
89
|
-
### 10.0.
|
|
200
|
+
### 10.0.4 (2026-07-26)
|
|
201
|
+
- (@GermanBluefox) Added custom status indicators for devices and instances
|
|
202
|
+
- (@GermanBluefox) Added `placement: 'status'` for device actions
|
|
203
|
+
- (@GermanBluefox) Added user-configurable visibility of indicators
|
|
204
|
+
|
|
205
|
+
### 10.0.3 (2026-07-25)
|
|
90
206
|
# (@GermanBluefox) Breaking: React 19, MUI 9, TS 6
|
|
91
207
|
|
|
92
|
-
### 9.1.12 (2026-07-24)
|
|
208
|
+
### 9.1.12 (2026-07-24)
|
|
93
209
|
- (@GermanBluefox) Updated packages
|
|
94
210
|
|
|
95
|
-
### 9.1.9 (2026-07-20)
|
|
211
|
+
### 9.1.9 (2026-07-20)
|
|
96
212
|
- (@GermanBluefox) Fixing tabs
|
|
97
213
|
|
|
98
|
-
### 9.1.8 (2026-07-12)
|
|
214
|
+
### 9.1.8 (2026-07-12)
|
|
99
215
|
- (@GermanBluefox) Strict types
|
|
100
216
|
|
|
101
|
-
### 9.1.7 (2026-06-21)
|
|
217
|
+
### 9.1.7 (2026-06-21)
|
|
102
218
|
- (@GermanBluefox) Remove double loading of devices
|
|
103
219
|
|
|
104
|
-
### 9.1.6 (2026-06-21)
|
|
220
|
+
### 9.1.6 (2026-06-21)
|
|
105
221
|
- (@GermanBluefox) Updated packages
|
|
106
222
|
|
|
107
|
-
### 9.1.5 (2026-06-20)
|
|
223
|
+
### 9.1.5 (2026-06-20)
|
|
108
224
|
- (@GermanBluefox) Implemented filter on different fields (name, id, type, alive, enabled, connected, etc.)
|
|
109
225
|
|
|
110
|
-
### 9.1.1 (2026-06-13)
|
|
226
|
+
### 9.1.1 (2026-06-13)
|
|
111
227
|
- (@GermanBluefox) Updated packages
|
|
112
228
|
|
|
113
|
-
### 9.1.0 (2026-06-06)
|
|
114
|
-
- (@GermanBluefox) Replaced the instance selector with a root page that shows all instances as cards; the toolbar shows a back arrow to return to the root page
|
|
229
|
+
### 9.1.0 (2026-06-06)
|
|
230
|
+
- (@GermanBluefox) Replaced the instance selector with a root page that shows all instances as cards; the toolbar shows a back arrow to return to the root page
|
|
115
231
|
- (@GermanBluefox) Updated packages
|
|
116
232
|
|
|
117
|
-
### 9.0.27 (2026-04-11)
|
|
233
|
+
### 9.0.27 (2026-04-11)
|
|
118
234
|
- (@GermanBluefox) Fixed filter for devices
|
|
119
235
|
|
|
120
|
-
### 9.0.26 (2026-03-31)
|
|
236
|
+
### 9.0.26 (2026-03-31)
|
|
121
237
|
- (@GermanBluefox) Added support for `applyDisabledRule`
|
|
122
238
|
|
|
123
|
-
### 9.0.24 (2026-03-30)
|
|
239
|
+
### 9.0.24 (2026-03-30)
|
|
124
240
|
- (@GermanBluefox) Layout improved
|
|
125
241
|
|
|
126
|
-
### 9.0.7 (2026-03-27)
|
|
242
|
+
### 9.0.7 (2026-03-27)
|
|
127
243
|
- (@GermanBluefox) Added possibility to show custom information on Card
|
|
128
244
|
|
|
129
|
-
### 9.0.6 (2026-03-26)
|
|
130
|
-
|
|
245
|
+
### 9.0.6 (2026-03-26)
|
|
246
|
+
|
|
131
247
|
- (@GermanBluefox) Small layout optimizations for controls
|
|
132
248
|
|
|
133
|
-
### 9.0.3 (2026-03-04)
|
|
134
|
-
|
|
135
|
-
- (@UncleSamSwiss) Fix handling of "result" response from action handler (update, delete a device)
|
|
136
|
-
- (@UncleSamSwiss) Fix handling of V1 protocol action responses
|
|
249
|
+
### 9.0.3 (2026-03-04)
|
|
250
|
+
|
|
251
|
+
- (@UncleSamSwiss) Fix handling of "result" response from action handler (update, delete a device)
|
|
252
|
+
- (@UncleSamSwiss) Fix handling of V1 protocol action responses
|
|
137
253
|
- (@UncleSamSwiss) Fix handling of "refresh" response from instance actions
|
|
138
254
|
|
|
139
|
-
### 9.0.2 (2026-03-03)
|
|
140
|
-
|
|
255
|
+
### 9.0.2 (2026-03-03)
|
|
256
|
+
|
|
141
257
|
- (@UncleSamSwiss) Implemented v3 protocol: added support to use states and objects as values
|
|
142
258
|
|
|
143
|
-
### 8.0.9 (2026-01-28)
|
|
144
|
-
|
|
259
|
+
### 8.0.9 (2026-01-28)
|
|
260
|
+
|
|
145
261
|
- (@GermanBluefox) Analyze an API version and do not show anything if a version is higher than supported
|
|
146
262
|
|
|
147
|
-
### 8.0.8 (2026-01-27)
|
|
148
|
-
|
|
263
|
+
### 8.0.8 (2026-01-27)
|
|
264
|
+
|
|
149
265
|
- (@GermanBluefox) Added support of instance selection if not provided
|
|
150
266
|
|
|
151
|
-
### 8.0.7 (2026-01-02)
|
|
152
|
-
|
|
267
|
+
### 8.0.7 (2026-01-02)
|
|
268
|
+
|
|
153
269
|
- (@GermanBluefox) Added `ignoreApplyDisabled` flag
|
|
154
270
|
|
|
155
|
-
### 8.0.6 (2025-12-30)
|
|
156
|
-
|
|
157
|
-
- (@GermanBluefox) Added update icon for device actions
|
|
271
|
+
### 8.0.6 (2025-12-30)
|
|
272
|
+
|
|
273
|
+
- (@GermanBluefox) Added update icon for device actions
|
|
158
274
|
- (@GermanBluefox) Added indeterminate progress
|
|
159
275
|
|
|
160
|
-
### 8.0.4 (2025-10-25)
|
|
161
|
-
|
|
276
|
+
### 8.0.4 (2025-10-25)
|
|
277
|
+
|
|
162
278
|
- (@GermanBluefox) Updated packages
|
|
163
279
|
|
|
164
|
-
### 8.0.2 (2025-10-23)
|
|
165
|
-
|
|
280
|
+
### 8.0.2 (2025-10-23)
|
|
281
|
+
|
|
166
282
|
- (@GermanBluefox) Renamed gui-components to adapter-react-v5
|
|
167
283
|
|
|
168
|
-
### 8.0.1 (2025-10-23)
|
|
169
|
-
|
|
284
|
+
### 8.0.1 (2025-10-23)
|
|
285
|
+
|
|
170
286
|
- (@GermanBluefox) Make package independent
|
|
171
287
|
|
|
172
|
-
### 0.0.10 (2023-12-14)
|
|
173
|
-
|
|
288
|
+
### 0.0.10 (2023-12-14)
|
|
289
|
+
|
|
174
290
|
- (bluefox) Changed layout of the device list
|
|
175
291
|
|
|
176
|
-
### 0.0.7 (2023-12-14)
|
|
177
|
-
|
|
292
|
+
### 0.0.7 (2023-12-14)
|
|
293
|
+
|
|
178
294
|
- (bluefox) Added alive flag
|
|
179
295
|
|
|
180
|
-
### 0.0.4 (2023-12-12)
|
|
181
|
-
|
|
296
|
+
### 0.0.4 (2023-12-12)
|
|
297
|
+
|
|
182
298
|
- (bluefox) return the style of big cards
|
|
183
299
|
|
|
184
|
-
### 0.0.3 (2023-12-12)
|
|
185
|
-
|
|
300
|
+
### 0.0.3 (2023-12-12)
|
|
301
|
+
|
|
186
302
|
- (bluefox) initial commit
|
|
187
303
|
|
|
188
|
-
## License
|
|
189
|
-
|
|
190
|
-
MIT License
|
|
191
|
-
|
|
192
|
-
Copyright (c) 2023-2026 Jey Cee <iobroker@all-smart.net>
|
|
193
|
-
|
|
194
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
195
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
196
|
-
in the Software without restriction, including without limitation the rights
|
|
197
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
198
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
199
|
-
furnished to do so, subject to the following conditions:
|
|
200
|
-
|
|
201
|
-
The above copyright notice and this permission notice shall be included in all
|
|
202
|
-
copies or substantial portions of the Software.
|
|
203
|
-
|
|
204
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
205
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
206
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
207
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
208
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
209
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
304
|
+
## License
|
|
305
|
+
|
|
306
|
+
MIT License
|
|
307
|
+
|
|
308
|
+
Copyright (c) 2023-2026 Jey Cee <iobroker@all-smart.net>
|
|
309
|
+
|
|
310
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
311
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
312
|
+
in the Software without restriction, including without limitation the rights
|
|
313
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
314
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
315
|
+
furnished to do so, subject to the following conditions:
|
|
316
|
+
|
|
317
|
+
The above copyright notice and this permission notice shall be included in all
|
|
318
|
+
copies or substantial portions of the Software.
|
|
319
|
+
|
|
320
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
321
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
322
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
323
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
324
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
325
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
210
326
|
SOFTWARE.
|
package/build/DeviceCard.d.ts
CHANGED
|
@@ -27,6 +27,8 @@ interface DeviceCardProps {
|
|
|
27
27
|
onlyBatteryProblem?: boolean;
|
|
28
28
|
/** Device field the text filter applies to. Default `name` */
|
|
29
29
|
filterField?: DeviceFilterField;
|
|
30
|
+
/** IDs of configurable indicators the user has switched off */
|
|
31
|
+
hiddenIndicators?: string[];
|
|
30
32
|
/** Reports the resolved model value of this device up to the list (used to build the model filter dropdown) */
|
|
31
33
|
onModel?: (deviceId: DeviceId, model: string | undefined) => void;
|
|
32
34
|
}
|
|
@@ -85,6 +87,18 @@ export default class DeviceCard extends Component<DeviceCardProps, DeviceCardSta
|
|
|
85
87
|
}, parentGroupId?: string): JSX.Element[];
|
|
86
88
|
renderControlDialog(): JSX.Element | null;
|
|
87
89
|
renderControls(): JSX.Element | null;
|
|
90
|
+
/**
|
|
91
|
+
* IDs of all actions that are not rendered as a normal button in the footer, because they
|
|
92
|
+
* already have their place in the status line: the reserved actions, the actions with
|
|
93
|
+
* `placement: 'status'` and the actions referenced by a custom indicator.
|
|
94
|
+
*/
|
|
95
|
+
private getStatusActionIds;
|
|
96
|
+
/** True if at least one action is left for the button row at the bottom of the card */
|
|
97
|
+
private hasFooterActions;
|
|
98
|
+
/** Resolve how a custom indicator behaves on click by looking up the referenced action */
|
|
99
|
+
private resolveIndicatorAction;
|
|
100
|
+
/** Custom indicators and the actions that requested to be shown in the status line */
|
|
101
|
+
renderIndicators(small?: boolean): JSX.Element | null;
|
|
88
102
|
renderActions(): JSX.Element[] | null;
|
|
89
103
|
renderSmall(): JSX.Element;
|
|
90
104
|
getCardHeaderStyle(theme: IobTheme, maxWidth?: number): React.CSSProperties;
|
package/build/DeviceCard.js
CHANGED
|
@@ -7,6 +7,7 @@ import DeviceControlComponent from './DeviceControl';
|
|
|
7
7
|
import DeviceImageUpload from './DeviceImageUpload';
|
|
8
8
|
import DeviceStatusComponent from './DeviceStatus';
|
|
9
9
|
import JsonConfig from './JsonConfig';
|
|
10
|
+
import { StatusIndicators } from './StatusIndicator';
|
|
10
11
|
import { getTranslation } from './Utils';
|
|
11
12
|
import { StateOrObjectHandler } from './StateOrObjectHandler';
|
|
12
13
|
/** Reserved action names (this is copied from https://github.com/ioBroker/dm-utils/blob/main/src/types/base.ts as we can only have type references to dm-utils) */
|
|
@@ -75,7 +76,8 @@ const styles = {
|
|
|
75
76
|
},
|
|
76
77
|
statusStyle: {
|
|
77
78
|
padding: '15px 25px 0 15px',
|
|
78
|
-
|
|
79
|
+
// The line may grow if the device provides custom indicators, so only the minimum is fixed
|
|
80
|
+
minHeight: 41,
|
|
79
81
|
},
|
|
80
82
|
};
|
|
81
83
|
function NoImageIcon(props) {
|
|
@@ -295,11 +297,62 @@ export default class DeviceCard extends Component {
|
|
|
295
297
|
}
|
|
296
298
|
return null;
|
|
297
299
|
}
|
|
300
|
+
/**
|
|
301
|
+
* IDs of all actions that are not rendered as a normal button in the footer, because they
|
|
302
|
+
* already have their place in the status line: the reserved actions, the actions with
|
|
303
|
+
* `placement: 'status'` and the actions referenced by a custom indicator.
|
|
304
|
+
*/
|
|
305
|
+
getStatusActionIds() {
|
|
306
|
+
const ids = new Set([ACTIONS.STATUS, ACTIONS.ENABLE_DISABLE, ACTIONS.UPDATE, ACTIONS.BATTERY]);
|
|
307
|
+
for (const indicator of this.props.device.indicators || []) {
|
|
308
|
+
if (indicator.actionId) {
|
|
309
|
+
ids.add(indicator.actionId);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
for (const action of this.props.device.actions || []) {
|
|
313
|
+
if (action.placement === 'status') {
|
|
314
|
+
ids.add(action.id);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
return ids;
|
|
318
|
+
}
|
|
319
|
+
/** True if at least one action is left for the button row at the bottom of the card */
|
|
320
|
+
hasFooterActions() {
|
|
321
|
+
const statusActionIds = this.getStatusActionIds();
|
|
322
|
+
return !!this.props.device.actions?.some(action => !statusActionIds.has(action.id));
|
|
323
|
+
}
|
|
324
|
+
/** Resolve how a custom indicator behaves on click by looking up the referenced action */
|
|
325
|
+
resolveIndicatorAction = (actionId) => {
|
|
326
|
+
const action = this.props.device.actions?.find(a => a.id === actionId);
|
|
327
|
+
if (!action) {
|
|
328
|
+
console.warn(`Indicator of device ${JSON.stringify(this.props.device.id)} references the unknown action "${actionId}"`);
|
|
329
|
+
return undefined;
|
|
330
|
+
}
|
|
331
|
+
if ('url' in action && action.url) {
|
|
332
|
+
return { url: getTranslation(action.url), disabled: action.disabled };
|
|
333
|
+
}
|
|
334
|
+
return {
|
|
335
|
+
onClick: this.props.deviceHandler(this.props.device.id, action),
|
|
336
|
+
disabled: action.disabled,
|
|
337
|
+
};
|
|
338
|
+
};
|
|
339
|
+
/** Custom indicators and the actions that requested to be shown in the status line */
|
|
340
|
+
renderIndicators(small) {
|
|
341
|
+
const reserved = [ACTIONS.STATUS, ACTIONS.ENABLE_DISABLE, ACTIONS.UPDATE, ACTIONS.BATTERY];
|
|
342
|
+
const statusActions = this.props.device.actions?.filter(a => a.placement === 'status' && !reserved.includes(a.id)) || [];
|
|
343
|
+
// An indicator switched off by the user is not shown at all. An action referenced by it stays
|
|
344
|
+
// out of the footer too, as hiding the indicator was an explicit decision of the user.
|
|
345
|
+
const indicators = this.props.hiddenIndicators?.length
|
|
346
|
+
? this.props.device.indicators?.filter(indicator => !this.props.hiddenIndicators.includes(indicator.id))
|
|
347
|
+
: this.props.device.indicators;
|
|
348
|
+
if (!indicators?.length && !statusActions.length) {
|
|
349
|
+
return null;
|
|
350
|
+
}
|
|
351
|
+
return (React.createElement(StatusIndicators, { indicators: indicators, theme: this.props.theme, stateOrObjectHandler: this.stateOrObjectHandler, disabled: !this.props.alive, resolveAction: this.resolveIndicatorAction, style: { marginTop: small ? 2 : 4 } }, statusActions.map(action => (React.createElement(DeviceActionButton, { disabled: !this.props.alive, key: action.id, deviceId: this.props.device.id, action: action, deviceHandler: this.props.deviceHandler })))));
|
|
352
|
+
}
|
|
298
353
|
renderActions() {
|
|
299
|
-
const
|
|
300
|
-
|
|
301
|
-
a.id !== ACTIONS.UPDATE &&
|
|
302
|
-
a.id !== ACTIONS.BATTERY);
|
|
354
|
+
const statusActionIds = this.getStatusActionIds();
|
|
355
|
+
const actions = this.props.device.actions?.filter(a => !statusActionIds.has(a.id));
|
|
303
356
|
return actions?.length
|
|
304
357
|
? actions.map(a => (React.createElement(DeviceActionButton, { disabled: !this.props.alive, key: a.id, deviceId: this.props.device.id, action: a, deviceHandler: this.props.deviceHandler })))
|
|
305
358
|
: null;
|
|
@@ -330,7 +383,9 @@ export default class DeviceCard extends Component {
|
|
|
330
383
|
}
|
|
331
384
|
}, color: "primary" },
|
|
332
385
|
React.createElement(MoreVertIcon, null))) : null),
|
|
333
|
-
React.createElement("div", { style: { ...styles.statusStyle, height: 'auto', padding: '8px 15px 0 15px' } },
|
|
386
|
+
React.createElement("div", { style: { ...styles.statusStyle, height: 'auto', padding: '8px 15px 0 15px' } },
|
|
387
|
+
status.map((s, i) => (React.createElement(DeviceStatusComponent, { key: i, socket: this.props.socket, deviceId: this.props.device.id, connectionType: this.state.connectionType, status: s, enabled: this.state.enabled, statusAction: this.props.device.actions?.find(a => a.id === ACTIONS.STATUS), disableEnableAction: this.props.device.actions?.find(a => a.id === ACTIONS.ENABLE_DISABLE), update: i === 0 ? this.props.device.update : undefined, updateAction: i === 0 ? this.props.device.actions?.find(a => a.id === ACTIONS.UPDATE) : undefined, batteryAction: this.props.device.actions?.find(a => a.id === ACTIONS.BATTERY), deviceHandler: this.props.deviceHandler, theme: this.props.theme, stateOrObjectHandler: this.stateOrObjectHandler }))),
|
|
388
|
+
this.renderIndicators(true)),
|
|
334
389
|
React.createElement("div", { style: styles.bodyStyle },
|
|
335
390
|
React.createElement(Typography, { variant: "body2", style: { ...styles.deviceInfoStyle, padding: '10px 10px 0 10px' } },
|
|
336
391
|
this.state.identifier ? (React.createElement("div", { onClick: this.copyToClipboard, style: { textOverflow: 'ellipsis', overflow: 'hidden' } },
|
|
@@ -346,7 +401,7 @@ export default class DeviceCard extends Component {
|
|
|
346
401
|
React.createElement(JsonConfig, { instanceId: this.props.instanceId, socket: this.props.socket, schema: this.props.device.customInfo.schema, data: this.props.device.customInfo.data || {}, onChange: (_data) => {
|
|
347
402
|
/* ignore */
|
|
348
403
|
}, themeName: this.props.themeName, themeType: this.props.themeType, theme: this.props.theme, isFloatComma: this.props.isFloatComma, dateFormat: this.props.dateFormat }))) : null,
|
|
349
|
-
!!(this.
|
|
404
|
+
!!(this.hasFooterActions() || this.props.device.controls?.length) && (React.createElement("div", { style: {
|
|
350
405
|
marginTop: 'auto',
|
|
351
406
|
display: 'flex',
|
|
352
407
|
gap: 4,
|
|
@@ -422,7 +477,9 @@ export default class DeviceCard extends Component {
|
|
|
422
477
|
}
|
|
423
478
|
}, color: "primary" },
|
|
424
479
|
React.createElement(MoreVertIcon, null))) : null),
|
|
425
|
-
React.createElement("div", { style: styles.statusStyle },
|
|
480
|
+
React.createElement("div", { style: styles.statusStyle },
|
|
481
|
+
status.map((s, i) => (React.createElement(DeviceStatusComponent, { key: i, socket: this.props.socket, deviceId: this.props.device.id, connectionType: this.state.connectionType, status: s, enabled: this.state.enabled, statusAction: this.props.device.actions?.find(a => a.id === ACTIONS.STATUS), disableEnableAction: this.props.device.actions?.find(a => a.id === ACTIONS.ENABLE_DISABLE), update: i === 0 ? this.props.device.update : undefined, updateAction: i === 0 ? this.props.device.actions?.find(a => a.id === ACTIONS.UPDATE) : undefined, batteryAction: this.props.device.actions?.find(a => a.id === ACTIONS.BATTERY), deviceHandler: this.props.deviceHandler, theme: this.props.theme, stateOrObjectHandler: this.stateOrObjectHandler }))),
|
|
482
|
+
this.renderIndicators()),
|
|
426
483
|
React.createElement("div", { style: styles.bodyStyle },
|
|
427
484
|
React.createElement(Typography, { variant: "body1", style: styles.deviceInfoStyle },
|
|
428
485
|
this.state.identifier ? (React.createElement("div", { onClick: this.copyToClipboard },
|
|
@@ -444,7 +501,7 @@ export default class DeviceCard extends Component {
|
|
|
444
501
|
React.createElement(JsonConfig, { instanceId: this.props.instanceId, socket: this.props.socket, schema: this.props.device.customInfo.schema, data: this.props.device.customInfo.data || {}, onChange: (_data) => {
|
|
445
502
|
/* ignore */
|
|
446
503
|
}, themeName: this.props.themeName, themeType: this.props.themeType, theme: this.props.theme, isFloatComma: this.props.isFloatComma, dateFormat: this.props.dateFormat }))) : null,
|
|
447
|
-
!!(this.
|
|
504
|
+
!!(this.hasFooterActions() || this.props.device.controls?.length) && (React.createElement("div", { style: {
|
|
448
505
|
marginTop: 'auto',
|
|
449
506
|
display: 'flex',
|
|
450
507
|
gap: 8,
|