@iobroker/adapter-react-v5 7.2.3 → 7.2.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/Components/FileBrowser.d.ts +20 -20
- package/Components/FileBrowser.js +28 -16
- package/Components/FileViewer.d.ts +2 -2
- package/Components/ObjectBrowser.d.ts +3 -0
- package/Components/ObjectBrowser.js +32 -18
- package/Components/Schedule.d.ts +1 -1
- package/Components/Schedule.js +6 -6
- package/Components/SimpleCron/index.js +3 -1
- package/README.md +5 -5
- package/i18n/de.json +3 -3
- package/icons/IconClosed.js +1 -1
- package/icons/IconOpen.js +1 -1
- package/package.json +8 -7
- package/src/Components/FileBrowser.tsx +52 -42
- package/src/Components/FileViewer.tsx +2 -2
- package/src/Components/ObjectBrowser.tsx +32 -20
- package/src/Components/Schedule.tsx +11 -8
- package/src/icons/IconClosed.tsx +1 -1
- package/src/icons/IconOpen.tsx +1 -1
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* MIT License
|
|
5
5
|
*
|
|
6
6
|
*/
|
|
7
|
-
import React, { Component } from 'react';
|
|
7
|
+
import React, { Component, type JSX } from 'react';
|
|
8
8
|
import type { Connection } from '@iobroker/socket-client';
|
|
9
9
|
import type { ThemeName, ThemeType, Translate, IobTheme } from '../types';
|
|
10
10
|
export interface MetaACL extends ioBroker.ObjectACL {
|
|
@@ -69,7 +69,7 @@ export interface FileBrowserProps {
|
|
|
69
69
|
/** Padding in pixels for folder levels */
|
|
70
70
|
levelPadding?: number;
|
|
71
71
|
restrictToFolder?: string;
|
|
72
|
-
modalEditOfAccessControl?: (obj: FileBrowserClass) =>
|
|
72
|
+
modalEditOfAccessControl?: (obj: FileBrowserClass) => JSX.Element | null;
|
|
73
73
|
allowNonRestricted?: boolean;
|
|
74
74
|
showTypeSelector?: boolean;
|
|
75
75
|
}
|
|
@@ -145,38 +145,38 @@ export declare class FileBrowserClass extends Component<FileBrowserProps, FileBr
|
|
|
145
145
|
readDirSerial(adapter: string, relPath: string): Promise<ioBroker.ReadDirResult[]>;
|
|
146
146
|
processBrowseList(level?: number): void;
|
|
147
147
|
browseFolder(folderId: string, _newFolders?: Folders | null, _checkEmpty?: boolean, force?: boolean): Promise<Folders>;
|
|
148
|
-
toggleFolder(item: FolderOrFileItem, e: React.MouseEvent
|
|
148
|
+
toggleFolder(item: FolderOrFileItem, e: React.MouseEvent): void;
|
|
149
149
|
onFileChange: (id: string, fileName: string, size: number | null) => void;
|
|
150
150
|
changeFolder(e: React.MouseEvent<HTMLDivElement>, folder?: string): void;
|
|
151
151
|
select(id: string, e?: React.MouseEvent<HTMLDivElement> | null, cb?: () => void): void;
|
|
152
152
|
getText(text?: ioBroker.StringOrTranslated | null): string | undefined;
|
|
153
|
-
renderFolder(item: FolderOrFileItem, expanded?: boolean):
|
|
154
|
-
renderBackFolder():
|
|
155
|
-
formatSize(size: number | null | undefined):
|
|
156
|
-
formatAcl(acl: ioBroker.EvaluatedFileACL | MetaACL | undefined):
|
|
157
|
-
getFileIcon(ext: string | null):
|
|
153
|
+
renderFolder(item: FolderOrFileItem, expanded?: boolean): JSX.Element | null;
|
|
154
|
+
renderBackFolder(): JSX.Element;
|
|
155
|
+
formatSize(size: number | null | undefined): JSX.Element;
|
|
156
|
+
formatAcl(acl: ioBroker.EvaluatedFileACL | MetaACL | undefined): JSX.Element;
|
|
157
|
+
getFileIcon(ext: string | null): JSX.Element;
|
|
158
158
|
static getEditFile(ext: string | null): boolean;
|
|
159
159
|
setStateBackgroundImage: () => void;
|
|
160
160
|
getStyleBackgroundImage: () => React.CSSProperties | null;
|
|
161
|
-
renderFile(item: FolderOrFileItem):
|
|
162
|
-
renderItems(folderId: string):
|
|
163
|
-
renderToolbar():
|
|
161
|
+
renderFile(item: FolderOrFileItem): JSX.Element;
|
|
162
|
+
renderItems(folderId: string): JSX.Element | (JSX.Element | null)[];
|
|
163
|
+
renderToolbar(): JSX.Element;
|
|
164
164
|
findItem(id: string, folders?: Folders | null): null | FolderOrFileItem;
|
|
165
|
-
renderInputDialog():
|
|
165
|
+
renderInputDialog(): JSX.Element | null;
|
|
166
166
|
componentDidUpdate(): void;
|
|
167
167
|
findFirstFolder(id: string): string | null;
|
|
168
168
|
uploadFile(fileName: string, data: string): Promise<void>;
|
|
169
|
-
renderUpload():
|
|
169
|
+
renderUpload(): JSX.Element[] | null;
|
|
170
170
|
deleteRecursive(id: string): Promise<void>;
|
|
171
171
|
deleteItem(deleteItem: string): void;
|
|
172
|
-
renderDeleteDialog():
|
|
173
|
-
renderViewDialog():
|
|
174
|
-
renderError():
|
|
172
|
+
renderDeleteDialog(): JSX.Element | null;
|
|
173
|
+
renderViewDialog(): JSX.Element | null;
|
|
174
|
+
renderError(): JSX.Element | null;
|
|
175
175
|
updateItemsAcl(info: FolderOrFileItem[]): void;
|
|
176
176
|
changeToPath(): void;
|
|
177
|
-
renderBreadcrumb():
|
|
178
|
-
renderPath():
|
|
179
|
-
render():
|
|
177
|
+
renderBreadcrumb(): JSX.Element;
|
|
178
|
+
renderPath(): JSX.Element;
|
|
179
|
+
render(): JSX.Element;
|
|
180
180
|
}
|
|
181
|
-
declare const _default: (props: Record<string, any>) =>
|
|
181
|
+
declare const _default: (props: Record<string, any>) => JSX.Element;
|
|
182
182
|
export default _default;
|
|
@@ -63,9 +63,6 @@ const FILE_TYPE_ICONS = {
|
|
|
63
63
|
video: icons_material_1.Videocam,
|
|
64
64
|
};
|
|
65
65
|
const styles = {
|
|
66
|
-
dialog: (theme) => ({
|
|
67
|
-
height: `calc(100% - ${theme.mixins.toolbar.minHeight}px)`,
|
|
68
|
-
}),
|
|
69
66
|
root: {
|
|
70
67
|
width: '100%',
|
|
71
68
|
overflow: 'hidden',
|
|
@@ -107,7 +104,8 @@ const styles = {
|
|
|
107
104
|
textAlign: 'center',
|
|
108
105
|
opacity: 0.1,
|
|
109
106
|
transition: 'opacity 1s',
|
|
110
|
-
margin:
|
|
107
|
+
margin: '4px',
|
|
108
|
+
borderRadius: '4px',
|
|
111
109
|
'&:hover': {
|
|
112
110
|
background: theme.palette.secondary.light,
|
|
113
111
|
color: Utils_1.default.invertColor(theme.palette.secondary.main, true),
|
|
@@ -228,8 +226,8 @@ const styles = {
|
|
|
228
226
|
opacity: 0.4,
|
|
229
227
|
},
|
|
230
228
|
itemFolderIconTable: (theme) => ({
|
|
231
|
-
marginTop:
|
|
232
|
-
marginLeft:
|
|
229
|
+
marginTop: '1px',
|
|
230
|
+
marginLeft: '8px',
|
|
233
231
|
display: 'inline-block',
|
|
234
232
|
width: 30,
|
|
235
233
|
height: 30,
|
|
@@ -362,6 +360,9 @@ const styles = {
|
|
|
362
360
|
background: theme.palette.primary.main,
|
|
363
361
|
},
|
|
364
362
|
}),
|
|
363
|
+
pathDivBreadcrumbSelected: {
|
|
364
|
+
// todo: add style
|
|
365
|
+
},
|
|
365
366
|
backgroundImageLight: {
|
|
366
367
|
background: 'white',
|
|
367
368
|
},
|
|
@@ -838,7 +839,19 @@ class FileBrowserClass extends react_1.Component {
|
|
|
838
839
|
const adapter = parts.shift();
|
|
839
840
|
const relPath = parts.join('/');
|
|
840
841
|
// make all requests here serial
|
|
841
|
-
|
|
842
|
+
let files;
|
|
843
|
+
try {
|
|
844
|
+
files = await this.readDirSerial(adapter || '', relPath);
|
|
845
|
+
}
|
|
846
|
+
catch (error) {
|
|
847
|
+
// work around: 0_userdata.0 is a special folder, that should exist event when other folders and itself do not exit, as the browser shows it anyway.
|
|
848
|
+
if (error === 'Not exists' && adapter === '0_userdata.0') {
|
|
849
|
+
files = [];
|
|
850
|
+
}
|
|
851
|
+
else {
|
|
852
|
+
throw error;
|
|
853
|
+
}
|
|
854
|
+
}
|
|
842
855
|
try {
|
|
843
856
|
const _folders = [];
|
|
844
857
|
files.forEach(file => {
|
|
@@ -922,9 +935,7 @@ class FileBrowserClass extends react_1.Component {
|
|
|
922
935
|
}
|
|
923
936
|
}
|
|
924
937
|
changeFolder(e, folder) {
|
|
925
|
-
|
|
926
|
-
e.stopPropagation();
|
|
927
|
-
}
|
|
938
|
+
e === null || e === void 0 ? void 0 : e.stopPropagation();
|
|
928
939
|
this.lastSelect = Date.now();
|
|
929
940
|
let _folder = folder || getParentDir(this.state.currentDir);
|
|
930
941
|
if (_folder === '/') {
|
|
@@ -932,8 +943,10 @@ class FileBrowserClass extends react_1.Component {
|
|
|
932
943
|
}
|
|
933
944
|
this.localStorage.setItem('files.currentDir', _folder);
|
|
934
945
|
if (folder && e && (e.altKey || e.shiftKey || e.ctrlKey || e.metaKey)) {
|
|
935
|
-
|
|
946
|
+
this.setState({ selected: _folder });
|
|
947
|
+
return;
|
|
936
948
|
}
|
|
949
|
+
// If desired folder is not yet loaded
|
|
937
950
|
if (_folder && !this.state.folders[_folder]) {
|
|
938
951
|
this.browseFolder(_folder)
|
|
939
952
|
.then(folders => this.setState({
|
|
@@ -946,7 +959,7 @@ class FileBrowserClass extends react_1.Component {
|
|
|
946
959
|
.catch(_e => console.error(`Cannot read folder: ${_e.message}`));
|
|
947
960
|
return;
|
|
948
961
|
}
|
|
949
|
-
|
|
962
|
+
this.setState({
|
|
950
963
|
currentDir: _folder,
|
|
951
964
|
selected: _folder,
|
|
952
965
|
path: _folder,
|
|
@@ -997,10 +1010,9 @@ class FileBrowserClass extends react_1.Component {
|
|
|
997
1010
|
const padding = this.state.viewType === TABLE ? item.level * this.levelPadding : 0;
|
|
998
1011
|
const isUserData = item.name === USER_DATA;
|
|
999
1012
|
const isSpecialData = isUserData || item.name === 'vis.0' || item.name === 'vis-2.0';
|
|
1013
|
+
const iconStyle = Utils_1.default.getStyle(this.props.theme, styles[`itemFolderIcon${this.state.viewType}`], isSpecialData && styles.specialFolder);
|
|
1000
1014
|
return (react_1.default.createElement(material_1.Box, { component: "div", key: item.id, id: item.id, style: this.state.viewType === TABLE ? { marginLeft: padding, width: `calc(100% - ${padding}px` } : {}, onClick: e => (this.state.viewType === TABLE ? this.select(item.id, e) : this.changeFolder(e, item.id)), onDoubleClick: e => this.state.viewType === TABLE && this.toggleFolder(item, e), title: this.getText(item.title), className: "browserItem", sx: Utils_1.default.getStyle(this.props.theme, styles[`item${this.state.viewType}`], styles[`itemFolder${this.state.viewType}`], this.state.selected === item.id ? styles.itemSelected : {}, item.temp ? styles.itemFolderTemp : {}) },
|
|
1001
|
-
react_1.default.createElement(IconEl, { style:
|
|
1002
|
-
? (e) => this.toggleFolder(item, e)
|
|
1003
|
-
: undefined }),
|
|
1015
|
+
react_1.default.createElement(IconEl, { style: iconStyle, onClick: this.state.viewType === TABLE ? (e) => this.toggleFolder(item, e) : undefined }),
|
|
1004
1016
|
react_1.default.createElement(material_1.Box, { component: "div", sx: Utils_1.default.getStyle(this.props.theme, styles[`itemName${this.state.viewType}`], styles[`itemNameFolder${this.state.viewType}`]) }, isUserData ? this.props.t('ra_User files') : item.name),
|
|
1005
1017
|
react_1.default.createElement(material_1.Box, { component: "div", style: styles[`itemSize${this.state.viewType}`], sx: { display: { md: 'inline-block', sm: 'none' } } }, this.state.viewType === TABLE && this.state.folders[item.id]
|
|
1006
1018
|
? this.state.folders[item.id].length
|
|
@@ -1024,7 +1036,7 @@ class FileBrowserClass extends react_1.Component {
|
|
|
1024
1036
|
}
|
|
1025
1037
|
renderBackFolder() {
|
|
1026
1038
|
return (react_1.default.createElement(material_1.Box, { component: "div", key: this.state.currentDir, id: this.state.currentDir, onClick: e => this.changeFolder(e), title: this.props.t('ra_Back to %s', getParentDir(this.state.currentDir)), className: "browserItem", sx: Utils_1.default.getStyle(this.props.theme, styles[`item${this.state.viewType}`], styles[`itemFolder${this.state.viewType}`]) },
|
|
1027
|
-
react_1.default.createElement(IconClosed_1.default, { style: styles[`itemFolderIcon${this.state.viewType}`] }),
|
|
1039
|
+
react_1.default.createElement(IconClosed_1.default, { style: Utils_1.default.getStyle(this.props.theme, styles[`itemFolderIcon${this.state.viewType}`]) }),
|
|
1028
1040
|
react_1.default.createElement(icons_material_1.ArrowBack, { sx: styles.itemFolderIconBack }),
|
|
1029
1041
|
react_1.default.createElement(material_1.Box, { component: "div", sx: Utils_1.default.getStyle(this.props.theme, styles[`itemName${this.state.viewType}`], styles[`itemNameFolder${this.state.viewType}`]) }, "..")));
|
|
1030
1042
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { type JSX } from 'react';
|
|
2
2
|
export declare const EXTENSIONS: {
|
|
3
3
|
images: string[];
|
|
4
4
|
code: string[];
|
|
@@ -6,5 +6,5 @@ export declare const EXTENSIONS: {
|
|
|
6
6
|
audio: string[];
|
|
7
7
|
video: string[];
|
|
8
8
|
};
|
|
9
|
-
declare const _default: (props: Record<string, any>) =>
|
|
9
|
+
declare const _default: (props: Record<string, any>) => JSX.Element;
|
|
10
10
|
export default _default;
|
|
@@ -571,6 +571,9 @@ export declare class ObjectBrowserClass extends Component<ObjectBrowserProps, Ob
|
|
|
571
571
|
navigateKeyPress(event: React.KeyboardEvent): void;
|
|
572
572
|
/**
|
|
573
573
|
* Find the id from the root
|
|
574
|
+
*
|
|
575
|
+
* @param root The current root
|
|
576
|
+
* @param id The object id to find
|
|
574
577
|
*/
|
|
575
578
|
private static getItemFromRoot;
|
|
576
579
|
resizerReset: () => void;
|
|
@@ -871,10 +871,13 @@ function binarySearch(list, find, _start, _end) {
|
|
|
871
871
|
return false;
|
|
872
872
|
}
|
|
873
873
|
function getName(name, lang) {
|
|
874
|
-
if (
|
|
874
|
+
if (typeof name === 'object') {
|
|
875
|
+
if (!name) {
|
|
876
|
+
return '';
|
|
877
|
+
}
|
|
875
878
|
return (name[lang] || name.en || '').toString();
|
|
876
879
|
}
|
|
877
|
-
return
|
|
880
|
+
return name ? name.toString() : '';
|
|
878
881
|
}
|
|
879
882
|
function getSelectIdIconFromObjects(objects, id, lang, imagePrefix) {
|
|
880
883
|
// `admin` has prefix '.' and `web` has '../..'
|
|
@@ -3021,13 +3024,17 @@ class ObjectBrowserClass extends react_1.Component {
|
|
|
3021
3024
|
}
|
|
3022
3025
|
parseObjectForAdmins(columnsForAdmin, obj) {
|
|
3023
3026
|
if (obj.common && obj.common.adminColumns && obj.common.name) {
|
|
3024
|
-
|
|
3027
|
+
const columns = obj.common.adminColumns;
|
|
3028
|
+
let aColumns;
|
|
3025
3029
|
if (columns && typeof columns !== 'object') {
|
|
3026
|
-
|
|
3030
|
+
aColumns = [columns];
|
|
3031
|
+
}
|
|
3032
|
+
else if (columns) {
|
|
3033
|
+
aColumns = columns;
|
|
3027
3034
|
}
|
|
3028
3035
|
let cColumns;
|
|
3029
3036
|
if (columns) {
|
|
3030
|
-
cColumns =
|
|
3037
|
+
cColumns = aColumns
|
|
3031
3038
|
.map((_item) => {
|
|
3032
3039
|
if (typeof _item !== 'object') {
|
|
3033
3040
|
return { path: _item, name: _item.split('.').pop() };
|
|
@@ -3063,7 +3070,7 @@ class ObjectBrowserClass extends react_1.Component {
|
|
|
3063
3070
|
objTypes: item.objTypes,
|
|
3064
3071
|
};
|
|
3065
3072
|
})
|
|
3066
|
-
.filter(item => item);
|
|
3073
|
+
.filter((item) => item);
|
|
3067
3074
|
}
|
|
3068
3075
|
else {
|
|
3069
3076
|
cColumns = null;
|
|
@@ -5282,21 +5289,29 @@ class ObjectBrowserClass extends react_1.Component {
|
|
|
5282
5289
|
}
|
|
5283
5290
|
/**
|
|
5284
5291
|
* Find the id from the root
|
|
5292
|
+
*
|
|
5293
|
+
* @param root The current root
|
|
5294
|
+
* @param id The object id to find
|
|
5285
5295
|
*/
|
|
5286
|
-
static getItemFromRoot(
|
|
5287
|
-
/** The current root */
|
|
5288
|
-
root,
|
|
5289
|
-
/** the object id to find */
|
|
5290
|
-
id) {
|
|
5291
|
-
var _b;
|
|
5296
|
+
static getItemFromRoot(root, id) {
|
|
5292
5297
|
const idArr = id.split('.');
|
|
5293
5298
|
let currId = '';
|
|
5294
5299
|
let _root = root;
|
|
5295
|
-
for (
|
|
5300
|
+
for (let i = 0; i < idArr.length; i++) {
|
|
5301
|
+
const idEntry = idArr[i];
|
|
5296
5302
|
currId = currId ? `${currId}.${idEntry}` : idEntry;
|
|
5297
|
-
|
|
5298
|
-
if (
|
|
5299
|
-
|
|
5303
|
+
let found = false;
|
|
5304
|
+
if (_root.children) {
|
|
5305
|
+
for (let j = 0; j < _root.children.length; j++) {
|
|
5306
|
+
if (_root.children[j].data.id === currId) {
|
|
5307
|
+
_root = _root.children[j];
|
|
5308
|
+
found = true;
|
|
5309
|
+
break;
|
|
5310
|
+
}
|
|
5311
|
+
}
|
|
5312
|
+
}
|
|
5313
|
+
if (!found) {
|
|
5314
|
+
return null;
|
|
5300
5315
|
}
|
|
5301
5316
|
}
|
|
5302
5317
|
return _root || null;
|
|
@@ -5662,7 +5677,6 @@ class ObjectBrowserClass extends react_1.Component {
|
|
|
5662
5677
|
visibility: !!(!this.props.notEditable &&
|
|
5663
5678
|
this.props.objectBrowserAliasEditor &&
|
|
5664
5679
|
this.props.objectBrowserEditObject &&
|
|
5665
|
-
this.state.filter.expertMode &&
|
|
5666
5680
|
(obj === null || obj === void 0 ? void 0 : obj.type) === 'state' &&
|
|
5667
5681
|
// @ts-expect-error deprecated from js-controller 6
|
|
5668
5682
|
((_e = obj.common) === null || _e === void 0 ? void 0 : _e.type) !== 'file'),
|
|
@@ -5765,7 +5779,7 @@ class ObjectBrowserClass extends react_1.Component {
|
|
|
5765
5779
|
react_1.default.createElement(material_1.ListItemText, null,
|
|
5766
5780
|
ITEMS[key].label,
|
|
5767
5781
|
"..."),
|
|
5768
|
-
react_1.default.createElement(
|
|
5782
|
+
react_1.default.createElement("div", { style: Object.assign(Object.assign({}, styles.contextMenuKeys), { opacity: 1 }) },
|
|
5769
5783
|
react_1.default.createElement(icons_material_1.ArrowRight, null))));
|
|
5770
5784
|
if (((_b = this.state.showContextMenu) === null || _b === void 0 ? void 0 : _b.subItem) === key) {
|
|
5771
5785
|
items.push(react_1.default.createElement(material_1.Menu, { key: "subContextMenu", open: !0, anchorEl: this.state.showContextMenu.subAnchor, onClose: () => {
|
package/Components/Schedule.d.ts
CHANGED
|
@@ -47,7 +47,7 @@ declare class Schedule extends Component<ScheduleProps, ScheduleState> {
|
|
|
47
47
|
getTimeExactElements(): JSX.Element;
|
|
48
48
|
static getDivider(): JSX.Element;
|
|
49
49
|
getPeriodModes(): JSX.Element[];
|
|
50
|
-
getPeriodSettingsMinutes(): JSX.Element;
|
|
50
|
+
getPeriodSettingsMinutes(fromTo: boolean): JSX.Element;
|
|
51
51
|
getPeriodSettingsWeekdays(): JSX.Element[];
|
|
52
52
|
getPeriodSettingsDaily(): JSX.Element[] | null;
|
|
53
53
|
getPeriodSettingsWeekly(): JSX.Element[] | null;
|
package/Components/Schedule.js
CHANGED
|
@@ -526,7 +526,7 @@ class Schedule extends react_1.Component {
|
|
|
526
526
|
desc.push(i18n_1.default.t('sch_desc_everyMinute'));
|
|
527
527
|
}
|
|
528
528
|
else {
|
|
529
|
-
// every N
|
|
529
|
+
// every N minute
|
|
530
530
|
desc.push(i18n_1.default.t('sch_desc_everyNMinutes', schedule.time.interval.toString()));
|
|
531
531
|
}
|
|
532
532
|
}
|
|
@@ -535,7 +535,7 @@ class Schedule extends react_1.Component {
|
|
|
535
535
|
desc.push(i18n_1.default.t('sch_desc_everyHour'));
|
|
536
536
|
}
|
|
537
537
|
else {
|
|
538
|
-
// every N
|
|
538
|
+
// every N minute
|
|
539
539
|
desc.push(i18n_1.default.t('sch_desc_everyNHours', schedule.time.interval.toString()));
|
|
540
540
|
}
|
|
541
541
|
const start = ASTRO.indexOf(schedule.time.start) !== -1
|
|
@@ -648,7 +648,7 @@ class Schedule extends react_1.Component {
|
|
|
648
648
|
_schedule.time.end = 'sunrise';
|
|
649
649
|
this.onChange(_schedule);
|
|
650
650
|
} }), label: i18n_1.default.t('sch_astroNight') })))),
|
|
651
|
-
!schedule.time.exactTime && this.getPeriodSettingsMinutes())));
|
|
651
|
+
!schedule.time.exactTime && this.getPeriodSettingsMinutes(fromTo))));
|
|
652
652
|
}
|
|
653
653
|
getTimeExactElements() {
|
|
654
654
|
const isAstro = ASTRO.includes(this.state.schedule.time.start);
|
|
@@ -868,9 +868,9 @@ class Schedule extends react_1.Component {
|
|
|
868
868
|
MONTHS.map((month, i) => (react_1.default.createElement(material_1.MenuItem, { key: month, value: i + 1 }, i18n_1.default.t(month))))))))),
|
|
869
869
|
];
|
|
870
870
|
}
|
|
871
|
-
getPeriodSettingsMinutes() {
|
|
872
|
-
return (react_1.default.createElement("div", { style: { display: 'inline-block' } },
|
|
873
|
-
react_1.default.createElement("label",
|
|
871
|
+
getPeriodSettingsMinutes(fromTo) {
|
|
872
|
+
return (react_1.default.createElement("div", { style: { display: 'inline-block', marginTop: fromTo ? 15 : 'inherit' } },
|
|
873
|
+
react_1.default.createElement("label", { style: { marginLeft: 4, marginRight: 4 } }, i18n_1.default.t('sch_every')),
|
|
874
874
|
react_1.default.createElement(material_1.Input, { value: this.state.schedule.time.interval, style: Object.assign(Object.assign({}, styles.inputEvery), { verticalAlign: 'bottom' }), type: "number", inputProps: { min: 1 }, onChange: e => {
|
|
875
875
|
const _schedule = JSON.parse(JSON.stringify(this.state.schedule));
|
|
876
876
|
_schedule.time.interval = parseInt(e.target.value, 10);
|
|
@@ -681,7 +681,9 @@ class SimpleCron extends react_1.default.Component {
|
|
|
681
681
|
return (react_1.default.createElement("div", { style: styles.mainDiv },
|
|
682
682
|
react_1.default.createElement("div", { style: { paddingLeft: 8, width: 'calc(100% - 8px)' } },
|
|
683
683
|
react_1.default.createElement(material_1.TextField, { variant: "standard", style: { width: '100%' }, value: this.state.cron, disabled: true, error: this.state.cron.includes('_') })),
|
|
684
|
-
react_1.default.createElement("div", { style: { paddingLeft: 8, width: 'calc(100% - 8px)', height: 60 } }, this.state.cron.includes('_')
|
|
684
|
+
react_1.default.createElement("div", { style: { paddingLeft: 8, width: 'calc(100% - 8px)', height: 60 } }, this.state.cron.includes('_')
|
|
685
|
+
? i18n_1.default.t('sc_invalid_cron')
|
|
686
|
+
: (0, cronText_1.default)(this.state.cron, this.props.language || 'en')),
|
|
685
687
|
react_1.default.createElement("div", null,
|
|
686
688
|
react_1.default.createElement(material_1.FormControl, { variant: "standard", style: Object.assign(Object.assign({}, styles.formControl), { marginLeft: 8, marginTop: 8 }) },
|
|
687
689
|
react_1.default.createElement(material_1.InputLabel, null, i18n_1.default.t('ra_Repeat')),
|
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ If you want to create the configuration page with ReactJS:
|
|
|
13
13
|
- Change `name` from `src` to `ADAPTERNAME-admin` (Of course replace `ADAPTERNAME` with yours)
|
|
14
14
|
- Add to devDependencies:
|
|
15
15
|
```
|
|
16
|
-
"@iobroker/adapter-react-v5": "^7.2.
|
|
16
|
+
"@iobroker/adapter-react-v5": "^7.2.4",
|
|
17
17
|
```
|
|
18
18
|
Versions can be higher.
|
|
19
19
|
So your `src/package.json` should look like:
|
|
@@ -24,7 +24,7 @@ If you want to create the configuration page with ReactJS:
|
|
|
24
24
|
"version": "0.1.0",
|
|
25
25
|
"private": true,
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@iobroker/adapter-react-v5": "^7.2.
|
|
27
|
+
"@iobroker/adapter-react-v5": "^7.2.4",
|
|
28
28
|
"@iobroker/build-tools": "^1.0.0",
|
|
29
29
|
"@iobroker/eslint-config": "^0.1.2",
|
|
30
30
|
"@mui/material": "^6.0.2",
|
|
@@ -697,12 +697,12 @@ You can find the migration instructions:
|
|
|
697
697
|
-->
|
|
698
698
|
|
|
699
699
|
## Changelog
|
|
700
|
-
### 7.2.
|
|
700
|
+
### 7.2.4 (2024-10-07)
|
|
701
701
|
|
|
702
|
-
- (@GermanBluefox) Corrected
|
|
702
|
+
- (@GermanBluefox) Corrected file browser
|
|
703
|
+
- (@GermanBluefox) Changed Open/Close Folder icons
|
|
703
704
|
|
|
704
705
|
### 7.2.2 (2024-10-04)
|
|
705
|
-
|
|
706
706
|
- (@GermanBluefox) Small layout change for Icon Picker
|
|
707
707
|
|
|
708
708
|
### 7.2.1 (2024-09-30)
|
package/i18n/de.json
CHANGED
|
@@ -115,8 +115,8 @@
|
|
|
115
115
|
"sc_to": "Bis",
|
|
116
116
|
"sc_wizard": "Wizard",
|
|
117
117
|
"sch_all": "alle",
|
|
118
|
-
"sch_astroDay": "
|
|
119
|
-
"sch_astroNight": "
|
|
118
|
+
"sch_astroDay": "Astronomischer Tag",
|
|
119
|
+
"sch_astroNight": "Astronomische Nacht",
|
|
120
120
|
"sch_astro_dawn": "Morgendämmerung",
|
|
121
121
|
"sch_astro_dusk": "Abenddämmerung",
|
|
122
122
|
"sch_astro_goldenHour": "Goldene Stunde",
|
|
@@ -446,4 +446,4 @@
|
|
|
446
446
|
"ra_Friday": "Freitag",
|
|
447
447
|
"ra_Saturday": "Samstag",
|
|
448
448
|
"sc_invalid_cron": "Ungültiger CRON"
|
|
449
|
-
}
|
|
449
|
+
}
|
package/icons/IconClosed.js
CHANGED
|
@@ -6,5 +6,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const react_1 = __importDefault(require("react"));
|
|
7
7
|
// Icon copied from https://github.com/FortAwesome/Font-Awesome/blob/0d1f27efb836eb2ab994ba37221849ed64a73e5c/svgs/regular/
|
|
8
8
|
const IconClosed = (props) => (react_1.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", onClick: e => props.onClick && props.onClick(e), viewBox: "0 0 650 512", width: props.width || (props.fontSize === 'small' ? 16 : 20), height: props.height || props.width || (props.fontSize === 'small' ? 16 : 20), className: props.className, style: props.style },
|
|
9
|
-
react_1.default.createElement("path", { fill: "currentColor", d: "
|
|
9
|
+
react_1.default.createElement("path", { fill: "currentColor", d: "m524,128l-192,0l-64,-64l-160,0c-26.51,0 -48,21.49 -48,48l0,288c0,26.51 21.49,48 48,48l416,0c26.51,0 48,-21.49 48,-48l0,-224c0,-26.51 -21.49,-48 -48,-48z" })));
|
|
10
10
|
exports.default = IconClosed;
|
package/icons/IconOpen.js
CHANGED
|
@@ -6,5 +6,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const react_1 = __importDefault(require("react"));
|
|
7
7
|
// Icon copied from https://github.com/FortAwesome/Font-Awesome/blob/0d1f27efb836eb2ab994ba37221849ed64a73e5c/svgs/regular/
|
|
8
8
|
const IconOpen = (props) => (react_1.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", onClick: e => props.onClick && props.onClick(e), viewBox: "0 0 650 512", width: props.width || (props.fontSize === 'small' ? 16 : 20), height: props.height || props.width || (props.fontSize === 'small' ? 16 : 20), className: props.className, style: props.style },
|
|
9
|
-
react_1.default.createElement("path", { fill: "currentColor", d: "
|
|
9
|
+
react_1.default.createElement("path", { fill: "currentColor", d: "m631.75617,292.093l-72.424,124.155a63.997,63.997 0 0 1 -55.281,31.752l-399.964,0c-18.523,0 -30.064,-20.093 -20.731,-36.093l72.424,-124.155a64,64 0 0 1 55.282,-31.752l399.964,0c18.523,0 30.064,20.093 20.73,36.093zm-420.694,-68.093l328,0l0,-48c0,-26.51 -21.49,-48 -48,-48l-160,0l-64,-64l-160,0c-26.51,0 -48,21.49 -48,48l0,278.046l69.077,-118.418c17.137,-29.378 48.912,-47.628 82.923,-47.628z" })));
|
|
10
10
|
exports.default = IconOpen;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iobroker/adapter-react-v5",
|
|
3
|
-
"version": "7.2.
|
|
3
|
+
"version": "7.2.4",
|
|
4
4
|
"description": "React classes to develop admin interfaces for ioBroker with react.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Denis Haev (bluefox)",
|
|
@@ -27,21 +27,22 @@
|
|
|
27
27
|
"homepage": "https://github.com/ioBroker/adapter-react-v5#readme",
|
|
28
28
|
"devDependencies": {},
|
|
29
29
|
"dependencies": {
|
|
30
|
+
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
|
30
31
|
"@emotion/react": "^11.13.3",
|
|
31
32
|
"@emotion/styled": "^11.13.0",
|
|
32
|
-
"@iobroker/socket-client": "^3.1.
|
|
33
|
+
"@iobroker/socket-client": "^3.1.1",
|
|
33
34
|
"@iobroker/types": "^6.0.11",
|
|
34
35
|
"@iobroker/js-controller-common": "^6.0.11",
|
|
35
36
|
"@iobroker/js-controller-common-db": "^6.0.11",
|
|
36
|
-
"@mui/icons-material": "^6.1.
|
|
37
|
-
"@mui/material": "^6.1.
|
|
38
|
-
"@mui/x-date-pickers": "^7.
|
|
39
|
-
"@sentry/browser": "^8.
|
|
37
|
+
"@mui/icons-material": "^6.1.2",
|
|
38
|
+
"@mui/material": "^6.1.2",
|
|
39
|
+
"@mui/x-date-pickers": "^7.19.0",
|
|
40
|
+
"@sentry/browser": "^8.33.1",
|
|
40
41
|
"cronstrue": "^2.50.0",
|
|
41
42
|
"react-color": "^2.19.3",
|
|
42
43
|
"react-colorful": "^5.6.1",
|
|
43
44
|
"react-cropper": "^2.3.3",
|
|
44
|
-
"react-dropzone": "^14.2.
|
|
45
|
+
"react-dropzone": "^14.2.9",
|
|
45
46
|
"react-icons": "^5.3.0",
|
|
46
47
|
"react-inlinesvg": "^4.1.3"
|
|
47
48
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* MIT License
|
|
5
5
|
*
|
|
6
6
|
*/
|
|
7
|
-
import React, { Component } from 'react';
|
|
7
|
+
import React, { Component, type JSX } from 'react';
|
|
8
8
|
import Dropzone from 'react-dropzone';
|
|
9
9
|
|
|
10
10
|
import {
|
|
@@ -102,9 +102,6 @@ const FILE_TYPE_ICONS: Record<string, React.FC<{ fontSize?: 'small' }>> = {
|
|
|
102
102
|
};
|
|
103
103
|
|
|
104
104
|
const styles: Record<string, any> = {
|
|
105
|
-
dialog: (theme: IobTheme) => ({
|
|
106
|
-
height: `calc(100% - ${theme.mixins.toolbar.minHeight}px)`,
|
|
107
|
-
}),
|
|
108
105
|
root: {
|
|
109
106
|
width: '100%',
|
|
110
107
|
overflow: 'hidden',
|
|
@@ -147,7 +144,8 @@ const styles: Record<string, any> = {
|
|
|
147
144
|
textAlign: 'center',
|
|
148
145
|
opacity: 0.1,
|
|
149
146
|
transition: 'opacity 1s',
|
|
150
|
-
margin:
|
|
147
|
+
margin: '4px',
|
|
148
|
+
borderRadius: '4px',
|
|
151
149
|
'&:hover': {
|
|
152
150
|
background: theme.palette.secondary.light,
|
|
153
151
|
color: Utils.invertColor(theme.palette.secondary.main, true),
|
|
@@ -270,8 +268,8 @@ const styles: Record<string, any> = {
|
|
|
270
268
|
opacity: 0.4,
|
|
271
269
|
},
|
|
272
270
|
itemFolderIconTable: (theme: IobTheme) => ({
|
|
273
|
-
marginTop:
|
|
274
|
-
marginLeft:
|
|
271
|
+
marginTop: '1px',
|
|
272
|
+
marginLeft: '8px',
|
|
275
273
|
display: 'inline-block',
|
|
276
274
|
width: 30,
|
|
277
275
|
height: 30,
|
|
@@ -406,6 +404,9 @@ const styles: Record<string, any> = {
|
|
|
406
404
|
background: theme.palette.primary.main,
|
|
407
405
|
},
|
|
408
406
|
}),
|
|
407
|
+
pathDivBreadcrumbSelected: {
|
|
408
|
+
// todo: add style
|
|
409
|
+
},
|
|
409
410
|
backgroundImageLight: {
|
|
410
411
|
background: 'white',
|
|
411
412
|
},
|
|
@@ -500,7 +501,7 @@ export interface FileBrowserProps {
|
|
|
500
501
|
|
|
501
502
|
restrictToFolder?: string;
|
|
502
503
|
|
|
503
|
-
modalEditOfAccessControl?: (obj: FileBrowserClass) =>
|
|
504
|
+
modalEditOfAccessControl?: (obj: FileBrowserClass) => JSX.Element | null;
|
|
504
505
|
|
|
505
506
|
allowNonRestricted?: boolean;
|
|
506
507
|
|
|
@@ -1026,7 +1027,17 @@ export class FileBrowserClass extends Component<FileBrowserProps, FileBrowserSta
|
|
|
1026
1027
|
const relPath = parts.join('/');
|
|
1027
1028
|
|
|
1028
1029
|
// make all requests here serial
|
|
1029
|
-
|
|
1030
|
+
let files: ioBroker.ReadDirResult[];
|
|
1031
|
+
try {
|
|
1032
|
+
files = await this.readDirSerial(adapter || '', relPath);
|
|
1033
|
+
} catch (error: unknown) {
|
|
1034
|
+
// work around: 0_userdata.0 is a special folder, that should exist event when other folders and itself do not exit, as the browser shows it anyway.
|
|
1035
|
+
if (error === 'Not exists' && adapter === '0_userdata.0') {
|
|
1036
|
+
files = [];
|
|
1037
|
+
} else {
|
|
1038
|
+
throw error;
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1030
1041
|
try {
|
|
1031
1042
|
const _folders: FolderOrFileItem[] = [];
|
|
1032
1043
|
|
|
@@ -1090,7 +1101,7 @@ export class FileBrowserClass extends Component<FileBrowserProps, FileBrowserSta
|
|
|
1090
1101
|
return newFoldersNotNull;
|
|
1091
1102
|
}
|
|
1092
1103
|
|
|
1093
|
-
toggleFolder(item: FolderOrFileItem, e: React.MouseEvent
|
|
1104
|
+
toggleFolder(item: FolderOrFileItem, e: React.MouseEvent): void {
|
|
1094
1105
|
e?.stopPropagation();
|
|
1095
1106
|
const expanded = [...this.state.expanded];
|
|
1096
1107
|
const pos = expanded.indexOf(item.id);
|
|
@@ -1142,9 +1153,7 @@ export class FileBrowserClass extends Component<FileBrowserProps, FileBrowserSta
|
|
|
1142
1153
|
};
|
|
1143
1154
|
|
|
1144
1155
|
changeFolder(e: React.MouseEvent<HTMLDivElement>, folder?: string): void {
|
|
1145
|
-
|
|
1146
|
-
e.stopPropagation();
|
|
1147
|
-
}
|
|
1156
|
+
e?.stopPropagation();
|
|
1148
1157
|
|
|
1149
1158
|
this.lastSelect = Date.now();
|
|
1150
1159
|
|
|
@@ -1157,9 +1166,11 @@ export class FileBrowserClass extends Component<FileBrowserProps, FileBrowserSta
|
|
|
1157
1166
|
this.localStorage.setItem('files.currentDir', _folder);
|
|
1158
1167
|
|
|
1159
1168
|
if (folder && e && (e.altKey || e.shiftKey || e.ctrlKey || e.metaKey)) {
|
|
1160
|
-
|
|
1169
|
+
this.setState({ selected: _folder });
|
|
1170
|
+
return;
|
|
1161
1171
|
}
|
|
1162
1172
|
|
|
1173
|
+
// If desired folder is not yet loaded
|
|
1163
1174
|
if (_folder && !this.state.folders[_folder]) {
|
|
1164
1175
|
this.browseFolder(_folder)
|
|
1165
1176
|
.then(folders =>
|
|
@@ -1178,7 +1189,7 @@ export class FileBrowserClass extends Component<FileBrowserProps, FileBrowserSta
|
|
|
1178
1189
|
return;
|
|
1179
1190
|
}
|
|
1180
1191
|
|
|
1181
|
-
|
|
1192
|
+
this.setState(
|
|
1182
1193
|
{
|
|
1183
1194
|
currentDir: _folder,
|
|
1184
1195
|
selected: _folder,
|
|
@@ -1226,7 +1237,7 @@ export class FileBrowserClass extends Component<FileBrowserProps, FileBrowserSta
|
|
|
1226
1237
|
return undefined;
|
|
1227
1238
|
}
|
|
1228
1239
|
|
|
1229
|
-
renderFolder(item: FolderOrFileItem, expanded?: boolean):
|
|
1240
|
+
renderFolder(item: FolderOrFileItem, expanded?: boolean): JSX.Element | null {
|
|
1230
1241
|
if (
|
|
1231
1242
|
this.state.viewType === TABLE &&
|
|
1232
1243
|
this.state.filterEmpty &&
|
|
@@ -1241,6 +1252,11 @@ export class FileBrowserClass extends Component<FileBrowserProps, FileBrowserSta
|
|
|
1241
1252
|
const isUserData = item.name === USER_DATA;
|
|
1242
1253
|
const isSpecialData = isUserData || item.name === 'vis.0' || item.name === 'vis-2.0';
|
|
1243
1254
|
|
|
1255
|
+
const iconStyle = Utils.getStyle(
|
|
1256
|
+
this.props.theme,
|
|
1257
|
+
styles[`itemFolderIcon${this.state.viewType}`],
|
|
1258
|
+
isSpecialData && styles.specialFolder,
|
|
1259
|
+
);
|
|
1244
1260
|
return (
|
|
1245
1261
|
<Box
|
|
1246
1262
|
component="div"
|
|
@@ -1260,15 +1276,9 @@ export class FileBrowserClass extends Component<FileBrowserProps, FileBrowserSta
|
|
|
1260
1276
|
)}
|
|
1261
1277
|
>
|
|
1262
1278
|
<IconEl
|
|
1263
|
-
style={
|
|
1264
|
-
this.props.theme,
|
|
1265
|
-
styles[`itemFolderIcon${this.state.viewType}`],
|
|
1266
|
-
isSpecialData && styles.specialFolder,
|
|
1267
|
-
)}
|
|
1279
|
+
style={iconStyle}
|
|
1268
1280
|
onClick={
|
|
1269
|
-
this.state.viewType === TABLE
|
|
1270
|
-
? (e: React.MouseEvent<Element>) => this.toggleFolder(item, e)
|
|
1271
|
-
: undefined
|
|
1281
|
+
this.state.viewType === TABLE ? (e: React.MouseEvent) => this.toggleFolder(item, e) : undefined
|
|
1272
1282
|
}
|
|
1273
1283
|
/>
|
|
1274
1284
|
|
|
@@ -1340,7 +1350,7 @@ export class FileBrowserClass extends Component<FileBrowserProps, FileBrowserSta
|
|
|
1340
1350
|
);
|
|
1341
1351
|
}
|
|
1342
1352
|
|
|
1343
|
-
renderBackFolder():
|
|
1353
|
+
renderBackFolder(): JSX.Element {
|
|
1344
1354
|
return (
|
|
1345
1355
|
<Box
|
|
1346
1356
|
component="div"
|
|
@@ -1355,7 +1365,7 @@ export class FileBrowserClass extends Component<FileBrowserProps, FileBrowserSta
|
|
|
1355
1365
|
styles[`itemFolder${this.state.viewType}`],
|
|
1356
1366
|
)}
|
|
1357
1367
|
>
|
|
1358
|
-
<IconClosed style={styles[`itemFolderIcon${this.state.viewType}`]} />
|
|
1368
|
+
<IconClosed style={Utils.getStyle(this.props.theme, styles[`itemFolderIcon${this.state.viewType}`])} />
|
|
1359
1369
|
<IconBack sx={styles.itemFolderIconBack} />
|
|
1360
1370
|
|
|
1361
1371
|
<Box
|
|
@@ -1372,7 +1382,7 @@ export class FileBrowserClass extends Component<FileBrowserProps, FileBrowserSta
|
|
|
1372
1382
|
);
|
|
1373
1383
|
}
|
|
1374
1384
|
|
|
1375
|
-
formatSize(size: number | null | undefined):
|
|
1385
|
+
formatSize(size: number | null | undefined): JSX.Element {
|
|
1376
1386
|
return (
|
|
1377
1387
|
<div style={styles[`itemSize${this.state.viewType}`]}>
|
|
1378
1388
|
{size || size === 0 ? Utils.formatBytes(size) : ''}
|
|
@@ -1380,7 +1390,7 @@ export class FileBrowserClass extends Component<FileBrowserProps, FileBrowserSta
|
|
|
1380
1390
|
);
|
|
1381
1391
|
}
|
|
1382
1392
|
|
|
1383
|
-
formatAcl(acl: ioBroker.EvaluatedFileACL | MetaACL | undefined):
|
|
1393
|
+
formatAcl(acl: ioBroker.EvaluatedFileACL | MetaACL | undefined): JSX.Element {
|
|
1384
1394
|
const access: number = acl ? (acl as ioBroker.EvaluatedFileACL).permissions || (acl as MetaACL).file : 0;
|
|
1385
1395
|
let accessStr: string;
|
|
1386
1396
|
if (access) {
|
|
@@ -1406,7 +1416,7 @@ export class FileBrowserClass extends Component<FileBrowserProps, FileBrowserSta
|
|
|
1406
1416
|
);
|
|
1407
1417
|
}
|
|
1408
1418
|
|
|
1409
|
-
getFileIcon(ext: string | null):
|
|
1419
|
+
getFileIcon(ext: string | null): JSX.Element {
|
|
1410
1420
|
switch (ext) {
|
|
1411
1421
|
case 'json':
|
|
1412
1422
|
case 'json5':
|
|
@@ -1483,7 +1493,7 @@ export class FileBrowserClass extends Component<FileBrowserProps, FileBrowserSta
|
|
|
1483
1493
|
}
|
|
1484
1494
|
};
|
|
1485
1495
|
|
|
1486
|
-
renderFile(item: FolderOrFileItem):
|
|
1496
|
+
renderFile(item: FolderOrFileItem): JSX.Element {
|
|
1487
1497
|
const padding = this.state.viewType === TABLE ? item.level * this.levelPadding : 0;
|
|
1488
1498
|
const ext = Utils.getFileExtension(item.name);
|
|
1489
1499
|
|
|
@@ -1639,11 +1649,11 @@ export class FileBrowserClass extends Component<FileBrowserProps, FileBrowserSta
|
|
|
1639
1649
|
);
|
|
1640
1650
|
}
|
|
1641
1651
|
|
|
1642
|
-
renderItems(folderId: string):
|
|
1652
|
+
renderItems(folderId: string): JSX.Element | (JSX.Element | null)[] {
|
|
1643
1653
|
if (this.state.folders && this.state.folders[folderId]) {
|
|
1644
1654
|
// tile
|
|
1645
1655
|
if (this.state.viewType === TILE) {
|
|
1646
|
-
const res: (
|
|
1656
|
+
const res: (JSX.Element | null)[] = [];
|
|
1647
1657
|
if (folderId && folderId !== '/') {
|
|
1648
1658
|
res.push(this.renderBackFolder());
|
|
1649
1659
|
}
|
|
@@ -1662,7 +1672,7 @@ export class FileBrowserClass extends Component<FileBrowserProps, FileBrowserSta
|
|
|
1662
1672
|
return res;
|
|
1663
1673
|
}
|
|
1664
1674
|
|
|
1665
|
-
const totalResult: (
|
|
1675
|
+
const totalResult: (JSX.Element | null)[] = [];
|
|
1666
1676
|
this.state.folders[folderId].forEach(item => {
|
|
1667
1677
|
if (item.folder) {
|
|
1668
1678
|
const expanded = this.state.expanded.includes(item.id);
|
|
@@ -1716,7 +1726,7 @@ export class FileBrowserClass extends Component<FileBrowserProps, FileBrowserSta
|
|
|
1716
1726
|
);
|
|
1717
1727
|
}
|
|
1718
1728
|
|
|
1719
|
-
renderToolbar():
|
|
1729
|
+
renderToolbar(): JSX.Element {
|
|
1720
1730
|
const IconType: React.FC<{ fontSize?: 'small' }> | null = this.props.showTypeSelector
|
|
1721
1731
|
? FILE_TYPE_ICONS[this.state.filterByType || 'all'] || FILE_TYPE_ICONS.all
|
|
1722
1732
|
: null;
|
|
@@ -1965,7 +1975,7 @@ export class FileBrowserClass extends Component<FileBrowserProps, FileBrowserSta
|
|
|
1965
1975
|
return folders[parentFolder].find(item => item.id === id) || null;
|
|
1966
1976
|
}
|
|
1967
1977
|
|
|
1968
|
-
renderInputDialog():
|
|
1978
|
+
renderInputDialog(): JSX.Element | null {
|
|
1969
1979
|
if (this.state.addFolder) {
|
|
1970
1980
|
const parentFolder = this.findFirstFolder(this.state.selected);
|
|
1971
1981
|
|
|
@@ -2074,7 +2084,7 @@ export class FileBrowserClass extends Component<FileBrowserProps, FileBrowserSta
|
|
|
2074
2084
|
}
|
|
2075
2085
|
}
|
|
2076
2086
|
|
|
2077
|
-
renderUpload():
|
|
2087
|
+
renderUpload(): JSX.Element[] | null {
|
|
2078
2088
|
if (this.state.uploadFile) {
|
|
2079
2089
|
return [
|
|
2080
2090
|
<Fab
|
|
@@ -2274,7 +2284,7 @@ export class FileBrowserClass extends Component<FileBrowserProps, FileBrowserSta
|
|
|
2274
2284
|
);
|
|
2275
2285
|
}
|
|
2276
2286
|
|
|
2277
|
-
renderDeleteDialog():
|
|
2287
|
+
renderDeleteDialog(): JSX.Element | null {
|
|
2278
2288
|
if (this.state.deleteItem) {
|
|
2279
2289
|
return (
|
|
2280
2290
|
<Dialog
|
|
@@ -2322,7 +2332,7 @@ export class FileBrowserClass extends Component<FileBrowserProps, FileBrowserSta
|
|
|
2322
2332
|
return null;
|
|
2323
2333
|
}
|
|
2324
2334
|
|
|
2325
|
-
renderViewDialog():
|
|
2335
|
+
renderViewDialog(): JSX.Element | null {
|
|
2326
2336
|
return this.state.viewer ? (
|
|
2327
2337
|
<FileViewer
|
|
2328
2338
|
supportSubscribes={this.supportSubscribes}
|
|
@@ -2341,7 +2351,7 @@ export class FileBrowserClass extends Component<FileBrowserProps, FileBrowserSta
|
|
|
2341
2351
|
) : null;
|
|
2342
2352
|
}
|
|
2343
2353
|
|
|
2344
|
-
renderError():
|
|
2354
|
+
renderError(): JSX.Element | null {
|
|
2345
2355
|
if (this.state.errorText) {
|
|
2346
2356
|
return (
|
|
2347
2357
|
<ErrorDialog
|
|
@@ -2415,7 +2425,7 @@ export class FileBrowserClass extends Component<FileBrowserProps, FileBrowserSta
|
|
|
2415
2425
|
}, 100);
|
|
2416
2426
|
}
|
|
2417
2427
|
|
|
2418
|
-
renderBreadcrumb():
|
|
2428
|
+
renderBreadcrumb(): JSX.Element {
|
|
2419
2429
|
const parts = this.state.currentDir.startsWith('/')
|
|
2420
2430
|
? this.state.currentDir.split('/')
|
|
2421
2431
|
: `/${this.state.currentDir}`.split('/');
|
|
@@ -2454,7 +2464,7 @@ export class FileBrowserClass extends Component<FileBrowserProps, FileBrowserSta
|
|
|
2454
2464
|
);
|
|
2455
2465
|
}
|
|
2456
2466
|
|
|
2457
|
-
renderPath():
|
|
2467
|
+
renderPath(): JSX.Element {
|
|
2458
2468
|
return (
|
|
2459
2469
|
<Box
|
|
2460
2470
|
component="div"
|
|
@@ -2490,7 +2500,7 @@ export class FileBrowserClass extends Component<FileBrowserProps, FileBrowserSta
|
|
|
2490
2500
|
);
|
|
2491
2501
|
}
|
|
2492
2502
|
|
|
2493
|
-
render():
|
|
2503
|
+
render(): JSX.Element {
|
|
2494
2504
|
if (!this.props.ready) {
|
|
2495
2505
|
return <LinearProgress />;
|
|
2496
2506
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// File viewer in adapter-react does not support write
|
|
2
2
|
// import { Buffer } from 'buffer';
|
|
3
|
-
import React, { Component } from 'react';
|
|
3
|
+
import React, { Component, type JSX } from 'react';
|
|
4
4
|
|
|
5
5
|
import { TextField, Button, Dialog, DialogActions, DialogContent, DialogTitle, IconButton } from '@mui/material';
|
|
6
6
|
|
|
@@ -338,7 +338,7 @@ class FileViewer extends Component<FileViewerProps, FileViewerState> {
|
|
|
338
338
|
return null;
|
|
339
339
|
}
|
|
340
340
|
|
|
341
|
-
render():
|
|
341
|
+
render(): JSX.Element {
|
|
342
342
|
return (
|
|
343
343
|
<Dialog
|
|
344
344
|
sx={{
|
|
@@ -28,7 +28,6 @@ import {
|
|
|
28
28
|
ListItem,
|
|
29
29
|
ListItemButton,
|
|
30
30
|
ListItemIcon,
|
|
31
|
-
ListItemSecondaryAction,
|
|
32
31
|
ListItemText,
|
|
33
32
|
Menu,
|
|
34
33
|
MenuItem,
|
|
@@ -1111,11 +1110,14 @@ function binarySearch(list: string[], find: string, _start?: number, _end?: numb
|
|
|
1111
1110
|
}
|
|
1112
1111
|
|
|
1113
1112
|
function getName(name: ioBroker.StringOrTranslated, lang: ioBroker.Languages): string {
|
|
1114
|
-
if (
|
|
1113
|
+
if (typeof name === 'object') {
|
|
1114
|
+
if (!name) {
|
|
1115
|
+
return '';
|
|
1116
|
+
}
|
|
1115
1117
|
return (name[lang] || name.en || '').toString();
|
|
1116
1118
|
}
|
|
1117
1119
|
|
|
1118
|
-
return
|
|
1120
|
+
return name ? name.toString() : '';
|
|
1119
1121
|
}
|
|
1120
1122
|
|
|
1121
1123
|
export function getSelectIdIconFromObjects(
|
|
@@ -3824,13 +3826,16 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
3824
3826
|
obj: ioBroker.AdapterObject,
|
|
3825
3827
|
): Record<string, CustomAdminColumnStored[]> | null {
|
|
3826
3828
|
if (obj.common && obj.common.adminColumns && obj.common.name) {
|
|
3827
|
-
|
|
3829
|
+
const columns: string | (string | ioBroker.CustomAdminColumn)[] = obj.common.adminColumns;
|
|
3830
|
+
let aColumns: (string | ioBroker.CustomAdminColumn)[] | undefined;
|
|
3828
3831
|
if (columns && typeof columns !== 'object') {
|
|
3829
|
-
|
|
3832
|
+
aColumns = [columns];
|
|
3833
|
+
} else if (columns) {
|
|
3834
|
+
aColumns = columns as (string | ioBroker.CustomAdminColumn)[];
|
|
3830
3835
|
}
|
|
3831
3836
|
let cColumns: CustomAdminColumnStored[] | null;
|
|
3832
3837
|
if (columns) {
|
|
3833
|
-
cColumns =
|
|
3838
|
+
cColumns = aColumns
|
|
3834
3839
|
.map((_item: string | ioBroker.CustomAdminColumn) => {
|
|
3835
3840
|
if (typeof _item !== 'object') {
|
|
3836
3841
|
return { path: _item, name: _item.split('.').pop() };
|
|
@@ -3866,7 +3871,7 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
3866
3871
|
objTypes: item.objTypes,
|
|
3867
3872
|
} as CustomAdminColumnStored;
|
|
3868
3873
|
})
|
|
3869
|
-
.filter(item => item)
|
|
3874
|
+
.filter((item: CustomAdminColumnStored) => item);
|
|
3870
3875
|
} else {
|
|
3871
3876
|
cColumns = null;
|
|
3872
3877
|
}
|
|
@@ -7753,22 +7758,30 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
7753
7758
|
|
|
7754
7759
|
/**
|
|
7755
7760
|
* Find the id from the root
|
|
7761
|
+
*
|
|
7762
|
+
* @param root The current root
|
|
7763
|
+
* @param id The object id to find
|
|
7756
7764
|
*/
|
|
7757
|
-
private static getItemFromRoot(
|
|
7758
|
-
/** The current root */
|
|
7759
|
-
root: TreeItem,
|
|
7760
|
-
/** the object id to find */
|
|
7761
|
-
id: string,
|
|
7762
|
-
): TreeItem | null {
|
|
7765
|
+
private static getItemFromRoot(root: TreeItem, id: string): TreeItem | null {
|
|
7763
7766
|
const idArr = id.split('.');
|
|
7764
7767
|
let currId = '';
|
|
7765
7768
|
let _root: TreeItem | null | undefined = root;
|
|
7766
7769
|
|
|
7767
|
-
for (
|
|
7770
|
+
for (let i = 0; i < idArr.length; i++) {
|
|
7771
|
+
const idEntry = idArr[i];
|
|
7768
7772
|
currId = currId ? `${currId}.${idEntry}` : idEntry;
|
|
7769
|
-
|
|
7770
|
-
if (
|
|
7771
|
-
|
|
7773
|
+
let found = false;
|
|
7774
|
+
if (_root.children) {
|
|
7775
|
+
for (let j = 0; j < _root.children.length; j++) {
|
|
7776
|
+
if (_root.children[j].data.id === currId) {
|
|
7777
|
+
_root = _root.children[j];
|
|
7778
|
+
found = true;
|
|
7779
|
+
break;
|
|
7780
|
+
}
|
|
7781
|
+
}
|
|
7782
|
+
}
|
|
7783
|
+
if (!found) {
|
|
7784
|
+
return null;
|
|
7772
7785
|
}
|
|
7773
7786
|
}
|
|
7774
7787
|
|
|
@@ -8495,7 +8508,6 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
8495
8508
|
!this.props.notEditable &&
|
|
8496
8509
|
this.props.objectBrowserAliasEditor &&
|
|
8497
8510
|
this.props.objectBrowserEditObject &&
|
|
8498
|
-
this.state.filter.expertMode &&
|
|
8499
8511
|
obj?.type === 'state' &&
|
|
8500
8512
|
// @ts-expect-error deprecated from js-controller 6
|
|
8501
8513
|
obj.common?.type !== 'file'
|
|
@@ -8630,9 +8642,9 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
8630
8642
|
{ITEMS[key].label}
|
|
8631
8643
|
...
|
|
8632
8644
|
</ListItemText>
|
|
8633
|
-
<
|
|
8645
|
+
<div style={{ ...styles.contextMenuKeys, opacity: 1 }}>
|
|
8634
8646
|
<ArrowRightIcon />
|
|
8635
|
-
</
|
|
8647
|
+
</div>
|
|
8636
8648
|
</MenuItem>,
|
|
8637
8649
|
);
|
|
8638
8650
|
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
Select,
|
|
11
11
|
TextField,
|
|
12
12
|
Box,
|
|
13
|
-
type Theme
|
|
13
|
+
type Theme,
|
|
14
14
|
} from '@mui/material';
|
|
15
15
|
|
|
16
16
|
import I18n from '../i18n';
|
|
@@ -558,14 +558,14 @@ class Schedule extends Component<ScheduleProps, ScheduleState> {
|
|
|
558
558
|
// every minute
|
|
559
559
|
desc.push(I18n.t('sch_desc_everyMinute'));
|
|
560
560
|
} else {
|
|
561
|
-
// every N
|
|
561
|
+
// every N minute
|
|
562
562
|
desc.push(I18n.t('sch_desc_everyNMinutes', schedule.time.interval.toString()));
|
|
563
563
|
}
|
|
564
564
|
} else if (schedule.time.interval === 1) {
|
|
565
565
|
// every minute
|
|
566
566
|
desc.push(I18n.t('sch_desc_everyHour'));
|
|
567
567
|
} else {
|
|
568
|
-
// every N
|
|
568
|
+
// every N minute
|
|
569
569
|
desc.push(I18n.t('sch_desc_everyNHours', schedule.time.interval.toString()));
|
|
570
570
|
}
|
|
571
571
|
|
|
@@ -767,7 +767,7 @@ class Schedule extends Component<ScheduleProps, ScheduleState> {
|
|
|
767
767
|
</div>
|
|
768
768
|
)}
|
|
769
769
|
</div>
|
|
770
|
-
{!schedule.time.exactTime && this.getPeriodSettingsMinutes()}
|
|
770
|
+
{!schedule.time.exactTime && this.getPeriodSettingsMinutes(fromTo)}
|
|
771
771
|
</div>
|
|
772
772
|
</div>
|
|
773
773
|
);
|
|
@@ -1202,13 +1202,16 @@ class Schedule extends Component<ScheduleProps, ScheduleState> {
|
|
|
1202
1202
|
];
|
|
1203
1203
|
}
|
|
1204
1204
|
|
|
1205
|
-
getPeriodSettingsMinutes(): JSX.Element {
|
|
1205
|
+
getPeriodSettingsMinutes(fromTo: boolean): JSX.Element {
|
|
1206
1206
|
return (
|
|
1207
|
-
<div style={{ display: 'inline-block' }}>
|
|
1208
|
-
<label>{I18n.t('sch_every')}</label>
|
|
1207
|
+
<div style={{ display: 'inline-block', marginTop: fromTo ? 15 : 'inherit' }}>
|
|
1208
|
+
<label style={{ marginLeft: 4, marginRight: 4 }}>{I18n.t('sch_every')}</label>
|
|
1209
1209
|
<Input
|
|
1210
1210
|
value={this.state.schedule.time.interval}
|
|
1211
|
-
style={{
|
|
1211
|
+
style={{
|
|
1212
|
+
...styles.inputEvery,
|
|
1213
|
+
verticalAlign: 'bottom',
|
|
1214
|
+
}}
|
|
1212
1215
|
type="number"
|
|
1213
1216
|
inputProps={{ min: 1 }}
|
|
1214
1217
|
onChange={e => {
|
package/src/icons/IconClosed.tsx
CHANGED
|
@@ -14,7 +14,7 @@ const IconClosed = (props: IconProps): React.JSX.Element => (
|
|
|
14
14
|
>
|
|
15
15
|
<path
|
|
16
16
|
fill="currentColor"
|
|
17
|
-
d="
|
|
17
|
+
d="m524,128l-192,0l-64,-64l-160,0c-26.51,0 -48,21.49 -48,48l0,288c0,26.51 21.49,48 48,48l416,0c26.51,0 48,-21.49 48,-48l0,-224c0,-26.51 -21.49,-48 -48,-48z"
|
|
18
18
|
/>
|
|
19
19
|
</svg>
|
|
20
20
|
);
|
package/src/icons/IconOpen.tsx
CHANGED
|
@@ -14,7 +14,7 @@ const IconOpen = (props: IconProps): JSX.Element => (
|
|
|
14
14
|
>
|
|
15
15
|
<path
|
|
16
16
|
fill="currentColor"
|
|
17
|
-
d="
|
|
17
|
+
d="m631.75617,292.093l-72.424,124.155a63.997,63.997 0 0 1 -55.281,31.752l-399.964,0c-18.523,0 -30.064,-20.093 -20.731,-36.093l72.424,-124.155a64,64 0 0 1 55.282,-31.752l399.964,0c18.523,0 30.064,20.093 20.73,36.093zm-420.694,-68.093l328,0l0,-48c0,-26.51 -21.49,-48 -48,-48l-160,0l-64,-64l-160,0c-26.51,0 -48,21.49 -48,48l0,278.046l69.077,-118.418c17.137,-29.378 48.912,-47.628 82.923,-47.628z"
|
|
18
18
|
/>
|
|
19
19
|
</svg>
|
|
20
20
|
);
|