@iobroker/adapter-react-v5 6.1.3 → 6.1.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.
Files changed (66) hide show
  1. package/README.md +3 -0
  2. package/craco-module-federation.js +1 -1
  3. package/package.json +1 -1
  4. package/src/AdminConnection.tsx +3 -0
  5. package/src/Components/404.tsx +121 -0
  6. package/src/Components/ColorPicker.tsx +315 -0
  7. package/src/Components/ComplexCron.tsx +507 -0
  8. package/src/Components/CopyToClipboard.tsx +165 -0
  9. package/src/Components/CustomModal.tsx +163 -0
  10. package/src/Components/FileBrowser.tsx +2394 -0
  11. package/src/Components/FileViewer.tsx +384 -0
  12. package/src/Components/Icon.tsx +210 -0
  13. package/src/Components/IconPicker.tsx +149 -0
  14. package/src/Components/IconSelector.tsx +2202 -0
  15. package/src/Components/Image.tsx +176 -0
  16. package/src/Components/Loader.tsx +304 -0
  17. package/src/Components/Logo.tsx +166 -0
  18. package/src/Components/MDUtils.tsx +100 -0
  19. package/src/Components/ObjectBrowser.tsx +7915 -0
  20. package/src/Components/Router.tsx +90 -0
  21. package/src/Components/SaveCloseButtons.tsx +113 -0
  22. package/src/Components/Schedule.tsx +1724 -0
  23. package/src/Components/SelectWithIcon.tsx +197 -0
  24. package/src/Components/TabContainer.tsx +55 -0
  25. package/src/Components/TabContent.tsx +37 -0
  26. package/src/Components/TabHeader.tsx +19 -0
  27. package/src/Components/TableResize.tsx +259 -0
  28. package/src/Components/TextWithIcon.tsx +148 -0
  29. package/src/Components/ToggleThemeMenu.tsx +34 -0
  30. package/src/Components/TreeTable.tsx +919 -0
  31. package/src/Components/UploadImage.tsx +599 -0
  32. package/src/Components/Utils.tsx +1794 -0
  33. package/src/Components/loader.css +222 -0
  34. package/src/Components/withWidth.tsx +21 -0
  35. package/src/Connection.tsx +7 -0
  36. package/src/Dialogs/ComplexCron.tsx +129 -0
  37. package/src/Dialogs/Confirm.tsx +162 -0
  38. package/src/Dialogs/Cron.tsx +182 -0
  39. package/src/Dialogs/Error.tsx +72 -0
  40. package/src/Dialogs/Message.tsx +71 -0
  41. package/src/Dialogs/SelectFile.tsx +270 -0
  42. package/src/Dialogs/SelectID.tsx +298 -0
  43. package/src/Dialogs/SimpleCron.tsx +100 -0
  44. package/src/Dialogs/TextInput.tsx +107 -0
  45. package/src/GenericApp.tsx +976 -0
  46. package/src/LegacyConnection.tsx +3589 -0
  47. package/src/Prompt.tsx +20 -0
  48. package/src/Theme.tsx +479 -0
  49. package/src/icons/IconAdapter.tsx +20 -0
  50. package/src/icons/IconAlias.tsx +20 -0
  51. package/src/icons/IconChannel.tsx +21 -0
  52. package/src/icons/IconClearFilter.tsx +22 -0
  53. package/src/icons/IconClosed.tsx +17 -0
  54. package/src/icons/IconCopy.tsx +16 -0
  55. package/src/icons/IconDevice.tsx +27 -0
  56. package/src/icons/IconDocument.tsx +17 -0
  57. package/src/icons/IconDocumentReadOnly.tsx +18 -0
  58. package/src/icons/IconExpert.tsx +18 -0
  59. package/src/icons/IconFx.tsx +36 -0
  60. package/src/icons/IconInstance.tsx +20 -0
  61. package/src/icons/IconLogout.tsx +30 -0
  62. package/src/icons/IconNoIcon.tsx +19 -0
  63. package/src/icons/IconOpen.tsx +17 -0
  64. package/src/icons/IconProps.tsx +15 -0
  65. package/src/icons/IconState.tsx +17 -0
  66. package/src/index.css +55 -0
@@ -0,0 +1,599 @@
1
+ import React, { Component, createRef } from 'react';
2
+ import Dropzone from 'react-dropzone';
3
+ import { Cropper, ReactCropperElement } from 'react-cropper';
4
+
5
+ import {
6
+ Menu, MenuItem, Tooltip, IconButton,
7
+ } from '@mui/material';
8
+
9
+ import {
10
+ Close as IconClose,
11
+ Crop as CropIcon,
12
+ } from '@mui/icons-material';
13
+ import { FaFileUpload as UploadIcon } from 'react-icons/fa';
14
+
15
+ import I18n from '../i18n';
16
+ import Icon from './Icon';
17
+
18
+ // import 'cropperjs/dist/cropper.css';
19
+ const cropperStyles = `
20
+ /*!
21
+ * Cropper.js v1.5.12
22
+ * https://fengyuanchen.github.io/cropperjs
23
+ *
24
+ * Copyright 2015-present Chen Fengyuan
25
+ * Released under the MIT license
26
+ *
27
+ * Date: 2021-06-12T08:00:11.623Z
28
+ */
29
+
30
+ .cropper-container {
31
+ direction: ltr;
32
+ font-size: 0;
33
+ line-height: 0;
34
+ position: relative;
35
+ -ms-touch-action: none;
36
+ touch-action: none;
37
+ -webkit-user-select: none;
38
+ -moz-user-select: none;
39
+ -ms-user-select: none;
40
+ user-select: none;
41
+ }
42
+
43
+ .cropper-container img {
44
+ display: block;
45
+ height: 100%;
46
+ image-orientation: 0deg;
47
+ max-height: none !important;
48
+ max-width: none !important;
49
+ min-height: 0 !important;
50
+ min-width: 0 !important;
51
+ width: 100%;
52
+ }
53
+
54
+ .cropper-wrap-box,
55
+ .cropper-canvas,
56
+ .cropper-drag-box,
57
+ .cropper-crop-box,
58
+ .cropper-modal {
59
+ bottom: 0;
60
+ left: 0;
61
+ position: absolute;
62
+ right: 0;
63
+ top: 0;
64
+ }
65
+
66
+ .cropper-wrap-box,
67
+ .cropper-canvas {
68
+ overflow: hidden;
69
+ }
70
+
71
+ .cropper-drag-box {
72
+ background-color: #fff;
73
+ opacity: 0;
74
+ }
75
+
76
+ .cropper-modal {
77
+ background-color: #000;
78
+ opacity: 0.5;
79
+ }
80
+
81
+ .cropper-view-box {
82
+ display: block;
83
+ height: 100%;
84
+ outline: 1px solid #39f;
85
+ outline-color: rgba(51, 153, 255, 0.75);
86
+ overflow: hidden;
87
+ width: 100%;
88
+ }
89
+
90
+ .cropper-dashed {
91
+ border: 0 dashed #eee;
92
+ display: block;
93
+ opacity: 0.5;
94
+ position: absolute;
95
+ }
96
+
97
+ .cropper-dashed.dashed-h {
98
+ border-bottom-width: 1px;
99
+ border-top-width: 1px;
100
+ height: calc(100% / 3);
101
+ left: 0;
102
+ top: calc(100% / 3);
103
+ width: 100%;
104
+ }
105
+
106
+ .cropper-dashed.dashed-v {
107
+ border-left-width: 1px;
108
+ border-right-width: 1px;
109
+ height: 100%;
110
+ left: calc(100% / 3);
111
+ top: 0;
112
+ width: calc(100% / 3);
113
+ }
114
+
115
+ .cropper-center {
116
+ display: block;
117
+ height: 0;
118
+ left: 50%;
119
+ opacity: 0.75;
120
+ position: absolute;
121
+ top: 50%;
122
+ width: 0;
123
+ }
124
+
125
+ .cropper-center::before,
126
+ .cropper-center::after {
127
+ background-color: #eee;
128
+ content: ' ';
129
+ display: block;
130
+ position: absolute;
131
+ }
132
+
133
+ .cropper-center::before {
134
+ height: 1px;
135
+ left: -3px;
136
+ top: 0;
137
+ width: 7px;
138
+ }
139
+
140
+ .cropper-center::after {
141
+ height: 7px;
142
+ left: 0;
143
+ top: -3px;
144
+ width: 1px;
145
+ }
146
+
147
+ .cropper-face,
148
+ .cropper-line,
149
+ .cropper-point {
150
+ display: block;
151
+ height: 100%;
152
+ opacity: 0.1;
153
+ position: absolute;
154
+ width: 100%;
155
+ }
156
+
157
+ .cropper-face {
158
+ background-color: #fff;
159
+ left: 0;
160
+ top: 0;
161
+ }
162
+
163
+ .cropper-line {
164
+ background-color: #39f;
165
+ }
166
+
167
+ .cropper-line.line-e {
168
+ cursor: ew-resize;
169
+ right: -3px;
170
+ top: 0;
171
+ width: 5px;
172
+ }
173
+
174
+ .cropper-line.line-n {
175
+ cursor: ns-resize;
176
+ height: 5px;
177
+ left: 0;
178
+ top: -3px;
179
+ }
180
+
181
+ .cropper-line.line-w {
182
+ cursor: ew-resize;
183
+ left: -3px;
184
+ top: 0;
185
+ width: 5px;
186
+ }
187
+
188
+ .cropper-line.line-s {
189
+ bottom: -3px;
190
+ cursor: ns-resize;
191
+ height: 5px;
192
+ left: 0;
193
+ }
194
+
195
+ .cropper-point {
196
+ background-color: #39f;
197
+ height: 5px;
198
+ opacity: 0.75;
199
+ width: 5px;
200
+ }
201
+
202
+ .cropper-point.point-e {
203
+ cursor: ew-resize;
204
+ margin-top: -3px;
205
+ right: -3px;
206
+ top: 50%;
207
+ }
208
+
209
+ .cropper-point.point-n {
210
+ cursor: ns-resize;
211
+ left: 50%;
212
+ margin-left: -3px;
213
+ top: -3px;
214
+ }
215
+
216
+ .cropper-point.point-w {
217
+ cursor: ew-resize;
218
+ left: -3px;
219
+ margin-top: -3px;
220
+ top: 50%;
221
+ }
222
+
223
+ .cropper-point.point-s {
224
+ bottom: -3px;
225
+ cursor: s-resize;
226
+ left: 50%;
227
+ margin-left: -3px;
228
+ }
229
+
230
+ .cropper-point.point-ne {
231
+ cursor: nesw-resize;
232
+ right: -3px;
233
+ top: -3px;
234
+ }
235
+
236
+ .cropper-point.point-nw {
237
+ cursor: nwse-resize;
238
+ left: -3px;
239
+ top: -3px;
240
+ }
241
+
242
+ .cropper-point.point-sw {
243
+ bottom: -3px;
244
+ cursor: nesw-resize;
245
+ left: -3px;
246
+ }
247
+
248
+ .cropper-point.point-se {
249
+ bottom: -3px;
250
+ cursor: nwse-resize;
251
+ height: 20px;
252
+ opacity: 1;
253
+ right: -3px;
254
+ width: 20px;
255
+ }
256
+
257
+ @media (min-width: 768px) {
258
+ .cropper-point.point-se {
259
+ height: 15px;
260
+ width: 15px;
261
+ }
262
+ }
263
+
264
+ @media (min-width: 992px) {
265
+ .cropper-point.point-se {
266
+ height: 10px;
267
+ width: 10px;
268
+ }
269
+ }
270
+
271
+ @media (min-width: 1200px) {
272
+ .cropper-point.point-se {
273
+ height: 5px;
274
+ opacity: 0.75;
275
+ width: 5px;
276
+ }
277
+ }
278
+
279
+ .cropper-point.point-se::before {
280
+ background-color: #39f;
281
+ bottom: -50%;
282
+ content: ' ';
283
+ display: block;
284
+ height: 200%;
285
+ opacity: 0;
286
+ position: absolute;
287
+ right: -50%;
288
+ width: 200%;
289
+ }
290
+
291
+ .cropper-invisible {
292
+ opacity: 0;
293
+ }
294
+
295
+ .cropper-bg {
296
+ background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC');
297
+ }
298
+
299
+ .cropper-hide {
300
+ display: block;
301
+ height: 0;
302
+ position: absolute;
303
+ width: 0;
304
+ }
305
+
306
+ .cropper-hidden {
307
+ display: none !important;
308
+ }
309
+
310
+ .cropper-move {
311
+ cursor: move;
312
+ }
313
+
314
+ .cropper-crop {
315
+ cursor: crosshair;
316
+ }
317
+
318
+ .cropper-disabled .cropper-drag-box,
319
+ .cropper-disabled .cropper-face,
320
+ .cropper-disabled .cropper-line,
321
+ .cropper-disabled .cropper-point {
322
+ cursor: not-allowed;
323
+ }
324
+ `;
325
+
326
+ const styles: Record<string, React.CSSProperties> = {
327
+ dropZone: {
328
+ width: '100%',
329
+ height: 100,
330
+ position: 'relative',
331
+ },
332
+ dropZoneEmpty: {
333
+
334
+ },
335
+ image: {
336
+ objectFit: 'contain',
337
+ margin: 'auto',
338
+ display: 'flex',
339
+ width: '100%',
340
+ height: '100%',
341
+ },
342
+
343
+ uploadDiv: {
344
+ position: 'relative',
345
+ width: '100%',
346
+ height: 300,
347
+ opacity: 0.9,
348
+ marginTop: 30,
349
+ cursor: 'pointer',
350
+ outline: 'none',
351
+ },
352
+ uploadDivDragging: {
353
+ opacity: 1,
354
+ background: 'rgba(128,255,128,0.1)',
355
+ },
356
+
357
+ uploadCenterDiv: {
358
+ margin: 5,
359
+ border: '3px dashed grey',
360
+ borderRadius: 5,
361
+ width: 'calc(100% - 10px)',
362
+ height: 'calc(100% - 10px)',
363
+ position: 'relative',
364
+ display: 'flex',
365
+ },
366
+ uploadCenterIcon: {
367
+ paddingTop: 10,
368
+ width: 48,
369
+ height: 48,
370
+ },
371
+ uploadCenterText: {
372
+ fontSize: 16,
373
+ },
374
+ uploadCenterTextAndIcon: {
375
+ textAlign: 'center',
376
+ position: 'absolute',
377
+ top: 0,
378
+ bottom: 0,
379
+ left: 0,
380
+ right: 0,
381
+ display: 'flex',
382
+ flexDirection: 'column',
383
+ alignItems: 'center',
384
+ justifyContent: 'center',
385
+
386
+ },
387
+ disabledOpacity: {
388
+ opacity: 0.3,
389
+ cursor: 'default',
390
+ },
391
+ buttonRemoveWrapper: {
392
+ position: 'absolute',
393
+ zIndex: 222,
394
+ right: 0,
395
+ },
396
+ buttonCropWrapper: {
397
+ position: 'absolute',
398
+ zIndex: 222,
399
+ right: 0,
400
+ top: 50,
401
+ },
402
+ error: {
403
+ border: '2px solid red',
404
+ boxSizing: 'border-box',
405
+ },
406
+ };
407
+
408
+ interface UploadImageProps {
409
+ maxSize?: number;
410
+ disabled?: boolean;
411
+ crop?: boolean;
412
+ error?: boolean;
413
+ onChange: (base64: string) => void | undefined;
414
+ icon: string | null;
415
+ removeIconFunc: () => void | null;
416
+ accept?: Record<string, string[]>;
417
+ }
418
+
419
+ interface UploadImageState {
420
+ uploadFile: boolean | 'dragging';
421
+ anchorEl: HTMLElement | null;
422
+ cropHandler: boolean;
423
+ }
424
+
425
+ class UploadImage extends Component<UploadImageProps, UploadImageState> {
426
+ private readonly cropperRef: React.RefObject<ReactCropperElement>;
427
+
428
+ constructor(props: UploadImageProps) {
429
+ super(props);
430
+
431
+ this.state = {
432
+ uploadFile: false,
433
+ anchorEl: null,
434
+ cropHandler: false,
435
+ };
436
+ this.cropperRef = createRef();
437
+
438
+ if (!window.document.getElementById('cropper-style-json-component')) {
439
+ const style = window.document.createElement('style');
440
+ style.setAttribute('id', 'cropper-style-json-component');
441
+ style.innerHTML = cropperStyles;
442
+ window.document.head.appendChild(style);
443
+ }
444
+ }
445
+
446
+ onDrop(acceptedFiles: File[]) {
447
+ const onChange = this.props.onChange;
448
+ const maxSize = this.props.maxSize || 10 * 1024;
449
+
450
+ const file = acceptedFiles[0];
451
+ const reader = new FileReader();
452
+
453
+ reader.onabort = () => console.log('file reading was aborted');
454
+ reader.onerror = () => console.log('file reading has failed');
455
+ reader.onload = () => {
456
+ if (!file || !file.name) {
457
+ return;
458
+ }
459
+ const parts = file.name?.split('.');
460
+ let ext = parts?.length ? `image/${parts.pop()?.toLowerCase()}` : 'image/jpeg';
461
+ if (ext === 'image/jpg') {
462
+ ext = 'image/jpeg';
463
+ } else if (ext.includes('svg')) {
464
+ ext = 'image/svg+xml';
465
+ }
466
+ if (file.size > maxSize) {
467
+ window.alert(I18n.t('ra_File is too big. Max %sk allowed. Try use SVG.', Math.round(maxSize / 1024)));
468
+ } else {
469
+ const base64 = `data:${ext};base64,${btoa(
470
+ new Uint8Array(reader.result as ArrayBufferLike)
471
+ .reduce((data, byte) => data + String.fromCharCode(byte), ''),
472
+ )}`;
473
+
474
+ if (onChange) {
475
+ onChange(base64);
476
+ } else {
477
+ console.log(base64);
478
+ }
479
+ }
480
+ };
481
+ reader.readAsArrayBuffer(file);
482
+ }
483
+
484
+ render() {
485
+ const {
486
+ disabled, icon, removeIconFunc, error, crop, onChange,
487
+ } = this.props;
488
+ const maxSize = this.props.maxSize || 10 * 1024;
489
+ const accept = this.props.accept || { 'image/*': [] };
490
+ const { uploadFile, anchorEl, cropHandler } = this.state;
491
+ return <Dropzone
492
+ disabled={!!disabled || cropHandler}
493
+ key="dropzone"
494
+ multiple={false}
495
+ accept={accept}
496
+ maxSize={maxSize}
497
+ onDragEnter={() => this.setState({ uploadFile: 'dragging' })}
498
+ onDragLeave={() => this.setState({ uploadFile: true })}
499
+ onDrop={(acceptedFiles: File[], errors) => {
500
+ this.setState({ uploadFile: false });
501
+ if (!acceptedFiles.length) {
502
+ window.alert((errors && errors[0] && errors[0].errors && errors[0].errors[0] && errors[0].errors[0].message) || I18n.t('ra_Cannot upload'));
503
+ } else {
504
+ this.onDrop(acceptedFiles);
505
+ }
506
+ }}
507
+ >
508
+ {({ getRootProps, getInputProps }) => <div
509
+ style={{
510
+ ...styles.uploadDiv,
511
+ ...(uploadFile === 'dragging' ? styles.uploadDivDragging : undefined),
512
+ ...styles.dropZone,
513
+ ...(disabled ? styles.disabledOpacity : undefined),
514
+ ...(!icon ? styles.dropZoneEmpty : undefined),
515
+ }}
516
+ {...getRootProps()}
517
+ >
518
+ <input {...getInputProps()} />
519
+ <div style={{ ...styles.uploadCenterDiv, ...(error ? styles.error : undefined) }}>
520
+ {!icon ? <div style={styles.uploadCenterTextAndIcon}>
521
+ <UploadIcon style={styles.uploadCenterIcon} />
522
+ <div style={styles.uploadCenterText}>
523
+ {uploadFile === 'dragging' ? I18n.t('ra_Drop file here') :
524
+ I18n.t('ra_Place your files here or click here to open the browse dialog')}
525
+ </div>
526
+ </div>
527
+ :
528
+ removeIconFunc && !cropHandler && <div style={styles.buttonRemoveWrapper}>
529
+ <Tooltip title={I18n.t('ra_Clear')} componentsProps={{ popper: { sx: { pointerEvents: 'none' } } }}>
530
+ <IconButton
531
+ size="large"
532
+ onClick={e => {
533
+ removeIconFunc && removeIconFunc();
534
+ e.stopPropagation();
535
+ }}
536
+ >
537
+ <IconClose />
538
+ </IconButton>
539
+ </Tooltip>
540
+ </div>}
541
+ {icon && crop && <div style={styles.buttonCropWrapper}>
542
+ <Tooltip title={I18n.t('ra_Crop')} componentsProps={{ popper: { sx: { pointerEvents: 'none' } } }}>
543
+ <IconButton
544
+ size="large"
545
+ onClick={e => {
546
+ if (!cropHandler) {
547
+ this.setState({ cropHandler: true });
548
+ } else {
549
+ this.setState({ anchorEl: e.currentTarget });
550
+ }
551
+ e.stopPropagation();
552
+ }}
553
+ >
554
+ <CropIcon color={cropHandler ? 'primary' : 'inherit'} />
555
+ </IconButton>
556
+ </Tooltip>
557
+ <Menu
558
+ anchorEl={anchorEl}
559
+ keepMounted
560
+ open={Boolean(anchorEl)}
561
+ onClose={() => this.setState({ anchorEl: null })}
562
+ >
563
+ <MenuItem onClick={() => this.setState({ anchorEl: null, cropHandler: false }, () => {
564
+ const imageElement = this.cropperRef?.current?.cropper;
565
+ if (imageElement) {
566
+ if (onChange) {
567
+ onChange(imageElement.getCroppedCanvas().toDataURL());
568
+ } else {
569
+ console.log(imageElement.getCroppedCanvas().toDataURL());
570
+ }
571
+ }
572
+ })}
573
+ >
574
+ {I18n.t('ra_Save')}
575
+ </MenuItem>
576
+ <MenuItem onClick={() => this.setState({ anchorEl: null, cropHandler: false })}>{I18n.t('ra_Close')}</MenuItem>
577
+ </Menu>
578
+ </div>}
579
+ {icon && !cropHandler ? <Icon src={icon} style={styles.image} alt="icon" /> : null}
580
+
581
+ {icon && crop && cropHandler ? <Cropper
582
+ ref={this.cropperRef}
583
+ style={styles.image}
584
+ src={icon}
585
+ initialAspectRatio={1}
586
+ viewMode={1}
587
+ guides={false}
588
+ minCropBoxHeight={10}
589
+ minCropBoxWidth={10}
590
+ background={false}
591
+ checkOrientation={false}
592
+ /> : null}
593
+ </div>
594
+ </div>}
595
+ </Dropzone>;
596
+ }
597
+ }
598
+
599
+ export default UploadImage;