@iobroker/dm-gui-components 0.0.2

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.
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ const react_1 = __importStar(require("react"));
27
+ const material_1 = require("@mui/material");
28
+ const Utils_1 = require("./Utils");
29
+ /**
30
+ * Device Control component
31
+ * @param {object} props - Parameters
32
+ * @param {object} props.control - Control object
33
+ * @param {object} props.socket - Socket object
34
+ * @param {object} props.controlHandler - Control handler to set the state
35
+ * @param {object} props.controlStateHandler - Control handler to read the state
36
+ * @returns {React.JSX.Element|null}
37
+ * @constructor
38
+ */
39
+ class DeviceControl extends react_1.Component {
40
+ constructor(props) {
41
+ var _a, _b;
42
+ super(props);
43
+ this.stateHandler = async (id, state) => {
44
+ if (id === this.props.control.stateId && state) {
45
+ // request new state
46
+ const newState = await (this.props.controlStateHandler(this.props.deviceId, this.props.control)());
47
+ if ((newState === null || newState === void 0 ? void 0 : newState.ts) && newState.ts > this.state.ts) {
48
+ this.setState({
49
+ value: newState.val,
50
+ ts: newState.ts,
51
+ });
52
+ }
53
+ }
54
+ };
55
+ this.state = {
56
+ value: (_a = props.control.state) === null || _a === void 0 ? void 0 : _a.val,
57
+ ts: (_b = props.control.state) === null || _b === void 0 ? void 0 : _b.ts,
58
+ };
59
+ }
60
+ componentDidMount() {
61
+ if (this.props.control.stateId) {
62
+ this.props.socket.subscribeState(this.props.control.stateId, this.stateHandler);
63
+ }
64
+ }
65
+ componentWillUnmount() {
66
+ if (this.props.control.stateId) {
67
+ this.props.socket.unsubscribeState(this.props.control.stateId, this.stateHandler);
68
+ }
69
+ }
70
+ static getDerivedStateFromProps(props, state) {
71
+ var _a;
72
+ if (((_a = props.control.state) === null || _a === void 0 ? void 0 : _a.ts) > state.ts) {
73
+ return {
74
+ value: props.control.state.val,
75
+ ts: props.control.state.ts,
76
+ };
77
+ }
78
+ return null;
79
+ }
80
+ async sendControl(deviceId, control, value) {
81
+ const result = await (this.props.controlHandler(deviceId, control, value)());
82
+ if ((result === null || result === void 0 ? void 0 : result.ts) && (result === null || result === void 0 ? void 0 : result.ts) > this.state.ts) {
83
+ this.setState({
84
+ value: result.val,
85
+ ts: result.ts,
86
+ });
87
+ }
88
+ }
89
+ renderButton() {
90
+ const tooltip = (0, Utils_1.getTranslation)(this.props.control.description);
91
+ const icon = (0, Utils_1.renderIcon)(this.props.control, this.props.colors, this.state.value);
92
+ if (!this.props.control.label) {
93
+ return react_1.default.createElement(material_1.Fab, { title: tooltip, onClick: () => this.sendControl(this.props.deviceId, this.props.control, true) }, icon);
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);
96
+ }
97
+ renderSwitch() {
98
+ const tooltip = (0, Utils_1.getTranslation)(this.props.control.description);
99
+ // const icon = renderIcon(this.props.control, this.props.colors, this.state.value);
100
+ return react_1.default.createElement(material_1.Switch, { title: tooltip, checked: this.state.value, onChange: e => this.sendControl(this.props.deviceId, this.props.control, e.target.checked) });
101
+ }
102
+ getColor() {
103
+ let color;
104
+ if (this.state.value) {
105
+ color = this.props.control.colorOn || 'primary';
106
+ }
107
+ else if (this.props.control.type === 'switch') {
108
+ color = this.props.control.color;
109
+ }
110
+ if (color === 'primary') {
111
+ return this.props.colors.primary;
112
+ }
113
+ if (color === 'secondary') {
114
+ return this.props.colors.secondary;
115
+ }
116
+ return color;
117
+ }
118
+ renderSelect() {
119
+ }
120
+ renderSlider() {
121
+ }
122
+ renderColor() {
123
+ }
124
+ renderIcon() {
125
+ const tooltip = (0, Utils_1.getTranslation)(this.props.control.description);
126
+ const icon = (0, Utils_1.renderIcon)(this.props.control, this.props.colors, this.state.value);
127
+ const color = this.getColor();
128
+ if (!this.props.control.label) {
129
+ return react_1.default.createElement(material_1.Fab, { size: "small", title: tooltip, color: color === this.props.colors.primary ? 'primary' : (color === this.props.colors.secondary ? 'secondary' : undefined), style: color === this.props.colors.primary || color === this.props.colors.secondary ? undefined : { color }, onClick: () => this.sendControl(this.props.deviceId, this.props.control, !this.state.value) }, icon);
130
+ }
131
+ return react_1.default.createElement(material_1.Button, { title: tooltip, color: color === this.props.colors.primary ? 'primary' : (color === this.props.colors.secondary ? 'secondary' : undefined), style: color === this.props.colors.primary || color === this.props.colors.secondary ? undefined : { color }, onClick: () => this.sendControl(this.props.deviceId, this.props.control, !this.state.value), startIcon: icon }, this.props.control.label);
132
+ }
133
+ render() {
134
+ if (this.props.control.type === 'button') {
135
+ return this.renderButton();
136
+ }
137
+ if (this.props.control.type === 'icon') {
138
+ return this.renderIcon();
139
+ }
140
+ if (this.props.control.type === 'switch') {
141
+ return this.renderSwitch();
142
+ }
143
+ return react_1.default.createElement("div", { style: { color: 'red' } }, this.props.control.type);
144
+ }
145
+ }
146
+ exports.default = DeviceControl;
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import { Connection } from '@iobroker/adapter-react-v5';
3
+ interface DeviceImageUploadProps {
4
+ socket: Connection;
5
+ manufacturer?: string;
6
+ model?: string;
7
+ deviceId: string;
8
+ onImageSelect: (image: string) => void;
9
+ uploadImagesToInstance: string;
10
+ }
11
+ declare function DeviceImageUpload(params: DeviceImageUploadProps): React.JSX.Element | null;
12
+ export default DeviceImageUpload;
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const react_1 = __importDefault(require("react"));
7
+ function DeviceImageUpload(params) {
8
+ const { socket, manufacturer, model, deviceId, onImageSelect, uploadImagesToInstance, } = params;
9
+ const handleImageUpload = async (event) => {
10
+ const target = event.target;
11
+ const files = target.files;
12
+ if (!files || files.length === 0) {
13
+ return;
14
+ }
15
+ const file = files[0];
16
+ if (file) {
17
+ const reader = new FileReader();
18
+ reader.onload = async (e) => {
19
+ if (!e.target || !e.target.result) {
20
+ return;
21
+ }
22
+ const img = new Image();
23
+ img.src = e.target.result;
24
+ img.onload = async () => {
25
+ const maxWidth = 50;
26
+ const maxHeight = 50;
27
+ let width = img.width;
28
+ let height = img.height;
29
+ if (width > height) {
30
+ if (width > maxWidth) {
31
+ height *= maxWidth / width;
32
+ width = maxWidth;
33
+ }
34
+ }
35
+ else if (height > maxHeight) {
36
+ width *= maxHeight / height;
37
+ height = maxHeight;
38
+ }
39
+ const canvas = document.createElement('canvas');
40
+ const ctx = canvas.getContext('2d');
41
+ if (ctx) {
42
+ canvas.width = width;
43
+ canvas.height = height;
44
+ ctx.drawImage(img, 0, 0, width, height);
45
+ const resizedImage = canvas.toDataURL('image/webp');
46
+ // Build the file name from a manufacturer and model, if not available, use device id
47
+ const fileName = `${manufacturer ? `${manufacturer}_` : ''}${model || deviceId}`;
48
+ const base64Data = resizedImage.replace(/^data:image\/webp;base64,/, '');
49
+ const response = await socket.writeFile64(uploadImagesToInstance, fileName, base64Data);
50
+ console.log(`saveImage response: ${JSON.stringify(response)}`);
51
+ onImageSelect && onImageSelect(resizedImage);
52
+ }
53
+ };
54
+ };
55
+ reader.readAsDataURL(file);
56
+ }
57
+ };
58
+ const imageUploadButtonStyle = {
59
+ // make the button invisible but still clickable
60
+ opacity: 0,
61
+ position: 'absolute',
62
+ width: '45px',
63
+ height: '45px',
64
+ zIndex: 3,
65
+ };
66
+ return react_1.default.createElement("div", null,
67
+ react_1.default.createElement("input", { style: imageUploadButtonStyle, type: "file", accept: "image/*", onChange: handleImageUpload }));
68
+ }
69
+ exports.default = DeviceImageUpload;
@@ -0,0 +1,50 @@
1
+ import React from 'react';
2
+ import { DeviceInfo, InstanceDetails } from '@iobroker/dm-utils';
3
+ import Communication, { CommunicationProps, CommunicationState } from './Communication';
4
+ interface DeviceListProps extends CommunicationProps {
5
+ uploadImagesToInstance?: string;
6
+ filter?: string;
7
+ empbedded?: boolean;
8
+ title?: string;
9
+ style: React.CSSProperties;
10
+ }
11
+ interface DeviceListState extends CommunicationState {
12
+ devices: DeviceInfo[];
13
+ filteredDevices: DeviceInfo[];
14
+ filter: string;
15
+ instanceInfo: InstanceDetails;
16
+ loading: boolean;
17
+ alive: boolean | null;
18
+ }
19
+ /**
20
+ * Device List Component
21
+ * @param {object} params - Component parameters
22
+ * @param {object} params.socket - socket object
23
+ * @param {string} params.selectedInstance - Selected instance
24
+ * @param {string} params.uploadImagesToInstance - Instance to upload images to
25
+ * @param {string} params.filter - Filter
26
+ * @param {string} params.empbedded - true if this list used with multiple instances and false if only with one
27
+ * @param {string} params.title - Title in appbar (only in non-embedded mode)
28
+ * @param {string} params.style - Style of devices list
29
+ * @returns {*[]} - Array of device cards
30
+ */
31
+ export default class DeviceList extends Communication<DeviceListProps, DeviceListState> {
32
+ static i18nInitialized: boolean;
33
+ private lastPropsFilter;
34
+ private lastInstance;
35
+ private filterTimeout;
36
+ private language;
37
+ constructor(props: DeviceListProps);
38
+ componentDidMount(): Promise<void>;
39
+ componentWillUnmount(): void;
40
+ aliveHandler: ioBroker.StateChangeHandler;
41
+ /**
42
+ * Load devices
43
+ */
44
+ loadData(): Promise<void>;
45
+ getText(text: ioBroker.StringOrTranslated): string;
46
+ applyFilter(): void;
47
+ handleFilterChange(filter: string): void;
48
+ renderContent(): React.JSX.Element | React.JSX.Element[] | null;
49
+ }
50
+ export {};
package/DeviceList.js ADDED
@@ -0,0 +1,205 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const react_1 = __importDefault(require("react"));
7
+ const material_1 = require("@mui/material");
8
+ const icons_material_1 = require("@mui/icons-material");
9
+ const adapter_react_v5_1 = require("@iobroker/adapter-react-v5");
10
+ const DeviceCard_1 = __importDefault(require("./DeviceCard"));
11
+ const Utils_1 = require("./Utils");
12
+ const Communication_1 = __importDefault(require("./Communication"));
13
+ const InstanceActionButton_1 = __importDefault(require("./InstanceActionButton"));
14
+ const de_json_1 = __importDefault(require("./i18n/de.json"));
15
+ const en_json_1 = __importDefault(require("./i18n/en.json"));
16
+ const ru_json_1 = __importDefault(require("./i18n/ru.json"));
17
+ const pt_json_1 = __importDefault(require("./i18n/pt.json"));
18
+ const nl_json_1 = __importDefault(require("./i18n/nl.json"));
19
+ const fr_json_1 = __importDefault(require("./i18n/fr.json"));
20
+ const it_json_1 = __importDefault(require("./i18n/it.json"));
21
+ const es_json_1 = __importDefault(require("./i18n/es.json"));
22
+ const pl_json_1 = __importDefault(require("./i18n/pl.json"));
23
+ const uk_json_1 = __importDefault(require("./i18n/uk.json"));
24
+ const zh_cn_json_1 = __importDefault(require("./i18n/zh-cn.json"));
25
+ /**
26
+ * Device List Component
27
+ * @param {object} params - Component parameters
28
+ * @param {object} params.socket - socket object
29
+ * @param {string} params.selectedInstance - Selected instance
30
+ * @param {string} params.uploadImagesToInstance - Instance to upload images to
31
+ * @param {string} params.filter - Filter
32
+ * @param {string} params.empbedded - true if this list used with multiple instances and false if only with one
33
+ * @param {string} params.title - Title in appbar (only in non-embedded mode)
34
+ * @param {string} params.style - Style of devices list
35
+ * @returns {*[]} - Array of device cards
36
+ */
37
+ class DeviceList extends Communication_1.default {
38
+ constructor(props) {
39
+ super(props);
40
+ this.aliveHandler = (id, state) => {
41
+ if (id === `system.adapter.${this.props.selectedInstance}.alive`) {
42
+ const alive = !!(state === null || state === void 0 ? void 0 : state.val);
43
+ if (alive !== this.state.alive) {
44
+ this.setState({ alive }, () => {
45
+ if (alive) {
46
+ this.componentDidMount().catch(console.error);
47
+ }
48
+ });
49
+ }
50
+ }
51
+ };
52
+ if (!DeviceList.i18nInitialized) {
53
+ DeviceList.i18nInitialized = true;
54
+ // @ts-expect-error
55
+ adapter_react_v5_1.I18n.extendTranslations({
56
+ en: en_json_1.default,
57
+ de: de_json_1.default,
58
+ ru: ru_json_1.default,
59
+ pt: pt_json_1.default,
60
+ nl: nl_json_1.default,
61
+ fr: fr_json_1.default,
62
+ it: it_json_1.default,
63
+ es: es_json_1.default,
64
+ pl: pl_json_1.default,
65
+ uk: uk_json_1.default,
66
+ 'zh-cn': zh_cn_json_1.default,
67
+ });
68
+ }
69
+ // @ts-ignore
70
+ Object.assing(this.state, {
71
+ devices: [],
72
+ filteredDevices: [],
73
+ filter: '',
74
+ instanceInfo: null,
75
+ loading: null,
76
+ alive: null,
77
+ });
78
+ this.lastPropsFilter = this.props.filter;
79
+ this.lastInstance = '';
80
+ this.filterTimeout = null;
81
+ this.language = adapter_react_v5_1.I18n.getLanguage();
82
+ }
83
+ async componentDidMount() {
84
+ if (!this.props.empbedded) {
85
+ try {
86
+ // check if instance is alive
87
+ const alive = await this.props.socket.getState(`system.adapter.${this.props.selectedInstance}.alive`);
88
+ this.props.socket.unsubscribeState(`system.adapter.${this.props.selectedInstance}.alive`, this.aliveHandler);
89
+ if (!alive || !alive.val) {
90
+ this.setState({ alive: false });
91
+ return;
92
+ }
93
+ const instanceInfo = await this.loadInstanceInfos();
94
+ this.setState({ alive: true, instanceInfo });
95
+ }
96
+ catch (error) {
97
+ console.error(error);
98
+ this.setState({ alive: false });
99
+ }
100
+ }
101
+ try {
102
+ await this.loadData();
103
+ }
104
+ catch (error) {
105
+ console.error(error);
106
+ }
107
+ }
108
+ componentWillUnmount() {
109
+ if (!this.props.empbedded) {
110
+ this.props.socket.unsubscribeState(`system.adapter.${this.props.selectedInstance}.alive`, this.aliveHandler);
111
+ }
112
+ }
113
+ /**
114
+ * Load devices
115
+ */
116
+ async loadData() {
117
+ this.setState({ loading: true });
118
+ console.log(`Loading devices for ${this.props.selectedInstance}...`);
119
+ const devices = await this.loadDevices();
120
+ if (!devices || !Array.isArray(devices)) {
121
+ throw new Error(`Message returned from sendTo() doesn't look like one from DeviceManagement, did you accidentally handle the message in your adapter? ${JSON.stringify(devices)}`);
122
+ }
123
+ this.setState({ devices, loading: false }, () => this.applyFilter());
124
+ }
125
+ getText(text) {
126
+ if (typeof text === 'object') {
127
+ return text[this.language] || text.en;
128
+ }
129
+ return text;
130
+ }
131
+ applyFilter() {
132
+ const filter = this.props.empbedded ? this.props.filter : this.state.filter;
133
+ // filter devices name
134
+ if (filter) {
135
+ const filteredDevices = this.state.devices.filter(device => this.getText(device.name).toLowerCase().includes(filter.toLowerCase()));
136
+ this.setState({ filteredDevices });
137
+ }
138
+ else {
139
+ this.setState({ filteredDevices: this.state.devices });
140
+ }
141
+ }
142
+ handleFilterChange(filter) {
143
+ this.setState({ filter }, () => {
144
+ this.filterTimeout && clearTimeout(this.filterTimeout);
145
+ this.filterTimeout = setTimeout(() => {
146
+ this.filterTimeout = null;
147
+ this.applyFilter();
148
+ }, 250);
149
+ });
150
+ }
151
+ renderContent() {
152
+ var _a, _b;
153
+ /** @type {object} */
154
+ const emptyStyle = {
155
+ padding: 25,
156
+ };
157
+ if (this.props.empbedded && this.lastPropsFilter !== this.props.filter) {
158
+ this.lastPropsFilter = this.props.filter;
159
+ setTimeout(() => this.applyFilter(), 50);
160
+ }
161
+ if (this.props.empbedded && this.lastInstance !== this.props.selectedInstance) {
162
+ this.lastInstance = this.props.selectedInstance;
163
+ setTimeout(() => this.loadData().catch(console.error), 50);
164
+ }
165
+ let list;
166
+ if (!this.props.empbedded && !this.state.alive) {
167
+ list = react_1.default.createElement("div", { style: emptyStyle },
168
+ react_1.default.createElement("span", null, (0, Utils_1.getTranslation)('instanceNotAlive')));
169
+ }
170
+ else if (!this.state.devices.length && this.props.selectedInstance) {
171
+ list = react_1.default.createElement("div", { style: emptyStyle },
172
+ react_1.default.createElement("span", null, (0, Utils_1.getTranslation)('noDevicesFoundText')));
173
+ }
174
+ else if (this.state.devices.length && !this.state.filteredDevices.length) {
175
+ list = react_1.default.createElement("div", { style: emptyStyle },
176
+ react_1.default.createElement("span", null, (0, Utils_1.getTranslation)('allDevicesFilteredOut')));
177
+ }
178
+ 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 }));
180
+ }
181
+ if (this.props.empbedded) {
182
+ return list;
183
+ }
184
+ return react_1.default.createElement("div", { style: { width: '100%', height: '100%', overflow: 'hidden' } },
185
+ react_1.default.createElement(material_1.Toolbar, { variant: "dense", style: { backgroundColor: '#777', display: 'flex' } },
186
+ this.props.title,
187
+ this.state.alive && ((_b = (_a = this.state.instanceInfo) === null || _a === void 0 ? void 0 : _a.actions) === null || _b === void 0 ? void 0 : _b.length) ? react_1.default.createElement("div", { style: {
188
+ marginLeft: 20,
189
+ } }, this.state.instanceInfo.actions.map(action => react_1.default.createElement(InstanceActionButton_1.default, { key: action.id, action: action, instanceHandler: this.instanceHandler }))) : null,
190
+ react_1.default.createElement("div", { style: { flexGrow: 1 } }),
191
+ this.state.alive ? react_1.default.createElement(material_1.TextField, { variant: "standard", style: { width: 200 }, size: "small", label: (0, Utils_1.getTranslation)('filterLabelText'), onChange: e => this.handleFilterChange(e.target.value), value: this.state.filter, autoComplete: "off", inputProps: {
192
+ autoComplete: 'new-password',
193
+ form: { autoComplete: 'off' },
194
+ },
195
+ // eslint-disable-next-line react/jsx-no-duplicate-props
196
+ InputProps: {
197
+ endAdornment: this.state.filter ? react_1.default.createElement(material_1.InputAdornment, { position: "end" },
198
+ react_1.default.createElement(material_1.IconButton, { onClick: () => this.handleFilterChange(''), edge: "end" },
199
+ react_1.default.createElement(icons_material_1.Clear, null))) : null,
200
+ } }) : null),
201
+ react_1.default.createElement("div", { style: Object.assign({ width: '100%', height: 'calc(100% - 56px)', marginTop: 8, overflow: 'auto', justifyContent: 'center', alignItems: 'stretch', display: 'grid', columnGap: 8, rowGap: 8 }, this.props.style) }, list));
202
+ }
203
+ }
204
+ DeviceList.i18nInitialized = false;
205
+ exports.default = DeviceList;
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ interface DeviceStatusProps {
3
+ status: any;
4
+ }
5
+ /**
6
+ * Device Status component
7
+ * @param {object} params - Parameters
8
+ * @param {object} params.status - Status object, e.g. { connection: 'connected', battery: 100, rssi: -50 }
9
+ * @returns {React.JSX.Element|null}
10
+ * @constructor
11
+ */
12
+ export default function DeviceStatus(params: DeviceStatusProps): React.JSX.Element | null;
13
+ export {};
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const react_1 = __importDefault(require("react"));
7
+ const material_1 = require("@mui/material");
8
+ const icons_material_1 = require("@mui/icons-material");
9
+ const Utils_1 = require("./Utils");
10
+ /**
11
+ * Device Status component
12
+ * @param {object} params - Parameters
13
+ * @param {object} params.status - Status object, e.g. { connection: 'connected', battery: 100, rssi: -50 }
14
+ * @returns {React.JSX.Element|null}
15
+ * @constructor
16
+ */
17
+ function DeviceStatus(params) {
18
+ if (!params.status) {
19
+ return null;
20
+ }
21
+ let status;
22
+ if (typeof params.status === 'string') {
23
+ status = {
24
+ connection: params.status,
25
+ };
26
+ }
27
+ else {
28
+ status = params.status;
29
+ }
30
+ /** @type {object} */
31
+ const iconStyleOK = {
32
+ fill: '#00ac00',
33
+ };
34
+ /** @type {object} */
35
+ const iconStyleNotOK = {
36
+ fill: '#ff0000',
37
+ };
38
+ /** @type {object} */
39
+ const iconStyleWarning = {
40
+ fill: '#ff9900',
41
+ };
42
+ /** @type {object} */
43
+ let batteryIconTooltip;
44
+ if (typeof status.battery === 'number') {
45
+ if (status.battery >= 96 && status.battery <= 100) {
46
+ batteryIconTooltip = react_1.default.createElement(icons_material_1.BatteryFull, { style: iconStyleOK });
47
+ }
48
+ else if (status.battery >= 90 && status.battery <= 95) {
49
+ batteryIconTooltip = react_1.default.createElement(icons_material_1.Battery90, { style: iconStyleOK });
50
+ }
51
+ else if (status.battery >= 80 && status.battery <= 89) {
52
+ batteryIconTooltip = react_1.default.createElement(icons_material_1.Battery80, { style: iconStyleOK });
53
+ }
54
+ else if (status.battery >= 60 && status.battery <= 79) {
55
+ batteryIconTooltip = react_1.default.createElement(icons_material_1.Battery60, { style: iconStyleOK });
56
+ }
57
+ else if (status.battery >= 50 && status.battery <= 59) {
58
+ batteryIconTooltip = react_1.default.createElement(icons_material_1.Battery50, { style: iconStyleOK });
59
+ }
60
+ else if (status.battery >= 30 && status.battery <= 49) {
61
+ batteryIconTooltip = react_1.default.createElement(icons_material_1.Battery30, { style: iconStyleOK });
62
+ }
63
+ else if (status.battery >= 20 && status.battery <= 29) {
64
+ batteryIconTooltip = react_1.default.createElement(icons_material_1.Battery20, { style: iconStyleNotOK });
65
+ }
66
+ else {
67
+ batteryIconTooltip = react_1.default.createElement(icons_material_1.BatteryAlert, { style: iconStyleNotOK });
68
+ }
69
+ }
70
+ return react_1.default.createElement("div", { style: { display: 'flex', alignItems: 'center' } },
71
+ status.connection === 'connected' && react_1.default.createElement("div", { style: { display: 'flex', alignItems: 'center' } },
72
+ react_1.default.createElement(material_1.Tooltip, { title: (0, Utils_1.getTranslation)('connectedIconTooltip') },
73
+ react_1.default.createElement("div", { style: { display: 'flex', flexDirection: 'column', alignItems: 'center' } },
74
+ react_1.default.createElement(icons_material_1.Link, { style: iconStyleOK })))),
75
+ status.connection === 'disconnected' && react_1.default.createElement("div", { style: { display: 'flex', alignItems: 'center' } },
76
+ react_1.default.createElement(material_1.Tooltip, { title: (0, Utils_1.getTranslation)('disconnectedIconTooltip') },
77
+ react_1.default.createElement("div", { style: { display: 'flex', flexDirection: 'column', alignItems: 'center' } },
78
+ react_1.default.createElement(icons_material_1.LinkOff, { style: iconStyleNotOK })))),
79
+ status.rssi && react_1.default.createElement("div", { style: { display: 'flex', alignItems: 'center' } },
80
+ react_1.default.createElement(material_1.Tooltip, { title: "RSSI" },
81
+ react_1.default.createElement("div", { style: { display: 'flex', flexDirection: 'column', alignItems: 'center' } },
82
+ react_1.default.createElement(icons_material_1.NetworkCheck, null),
83
+ react_1.default.createElement("p", { style: { fontSize: 'small', margin: 0 } }, status.rssi)))),
84
+ typeof status.battery === 'number' && react_1.default.createElement("div", { style: { display: 'flex', alignItems: 'center' } },
85
+ react_1.default.createElement(material_1.Tooltip, { title: (0, Utils_1.getTranslation)('batteryTooltip') },
86
+ react_1.default.createElement("div", { style: { display: 'flex', flexDirection: 'column', alignItems: 'center' } },
87
+ batteryIconTooltip,
88
+ react_1.default.createElement("p", { style: { fontSize: 'small', margin: 0 } },
89
+ status.battery,
90
+ "%")))),
91
+ typeof status.battery === 'string' && react_1.default.createElement("div", { style: { display: 'flex', alignItems: 'center' } },
92
+ react_1.default.createElement(material_1.Tooltip, { title: (0, Utils_1.getTranslation)('batteryTooltip') },
93
+ react_1.default.createElement("div", { style: { display: 'flex', flexDirection: 'column', alignItems: 'center' } },
94
+ status.battery === 'charging' ? react_1.default.createElement(icons_material_1.BatteryCharging50, null) : react_1.default.createElement(icons_material_1.BatteryFull, null),
95
+ status.battery !== 'charging' ? (status.battery.includes('V') || status.battery.includes('mV') ?
96
+ react_1.default.createElement("p", { style: { fontSize: 'small', margin: 0 } }, status.battery) :
97
+ react_1.default.createElement("p", { style: { fontSize: 'small', margin: 0 } },
98
+ react_1.default.createElement("span", { style: { marginRight: 4 } }, status.battery),
99
+ "mV")) : null))),
100
+ typeof status.battery === 'boolean' && react_1.default.createElement("div", { style: { display: 'flex', alignItems: 'center' } },
101
+ react_1.default.createElement(material_1.Tooltip, { title: (0, Utils_1.getTranslation)('batteryTooltip') },
102
+ react_1.default.createElement("div", { style: { display: 'flex', flexDirection: 'column', alignItems: 'center' } }, status.battery ? react_1.default.createElement(icons_material_1.BatteryFull, { style: iconStyleOK }) :
103
+ react_1.default.createElement(icons_material_1.BatteryAlert, { style: iconStyleNotOK })))),
104
+ status.warning && react_1.default.createElement("div", { style: { display: 'flex', alignItems: 'center' } }, typeof status.warning === 'string' || typeof status.warning === 'object' ?
105
+ react_1.default.createElement(material_1.Tooltip, { title: (0, Utils_1.getTranslation)(status.warning) },
106
+ react_1.default.createElement("div", { style: { display: 'flex', flexDirection: 'column', alignItems: 'center' } },
107
+ react_1.default.createElement(icons_material_1.Warning, { style: iconStyleWarning }))) :
108
+ react_1.default.createElement("div", { style: { display: 'flex', flexDirection: 'column', alignItems: 'center' } },
109
+ react_1.default.createElement(icons_material_1.Warning, { style: iconStyleWarning }))));
110
+ }
111
+ exports.default = DeviceStatus;
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ interface InstanceActionButtonProps {
3
+ action: any;
4
+ instanceHandler: (action: any) => () => void;
5
+ }
6
+ export default function InstanceActionButton(params: InstanceActionButtonProps): React.JSX.Element | null;
7
+ export {};
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const react_1 = __importDefault(require("react"));
7
+ const TooltipButton_1 = __importDefault(require("./TooltipButton"));
8
+ const Utils_1 = require("./Utils");
9
+ function InstanceActionButton(params) {
10
+ const { action, instanceHandler } = params;
11
+ const tooltip = (0, Utils_1.getTranslation)((action === null || action === void 0 ? void 0 : action.description) ? action.description : '');
12
+ const title = (0, Utils_1.getTranslation)((action === null || action === void 0 ? void 0 : action.title) ? action.title : '');
13
+ const icon = (0, Utils_1.renderIcon)(action);
14
+ return react_1.default.createElement(TooltipButton_1.default, { tooltip: tooltip, label: title, disabled: action.disabled, Icon: icon, onClick: instanceHandler(action) });
15
+ }
16
+ exports.default = InstanceActionButton;
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import { Connection } from '@iobroker/adapter-react-v5';
3
+ interface JsonConfigProps {
4
+ instanceId: string;
5
+ socket: Connection;
6
+ schema: Record<string, any>;
7
+ data: Record<string, any>;
8
+ onChange: (data: Record<string, any>) => void;
9
+ }
10
+ export default function JsonConfig(props: JsonConfigProps): React.JSX.Element | null;
11
+ export {};