@iobroker/adapter-react-v5 7.2.2 → 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/ComplexCron.js +3 -3
- 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 +33 -15
- package/Components/SimpleCron/index.js +34 -8
- package/Dialogs/SimpleCron.js +1 -1
- package/README.md +7 -2
- package/i18n/de.json +14 -4
- package/i18n/en.json +11 -1
- package/i18n/es.json +11 -1
- package/i18n/fr.json +11 -1
- package/i18n/it.json +11 -1
- package/i18n/nl.json +11 -1
- package/i18n/pl.json +11 -1
- package/i18n/pt.json +11 -1
- package/i18n/ru.json +11 -1
- package/i18n/uk.json +11 -1
- package/i18n/zh-cn.json +11 -1
- package/icons/IconClosed.js +1 -1
- package/icons/IconOpen.js +1 -1
- package/package.json +8 -7
- package/src/Components/ComplexCron.tsx +3 -3
- 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 +49 -13
- package/src/Dialogs/SimpleCron.tsx +1 -0
- package/src/icons/IconClosed.tsx +1 -1
- package/src/icons/IconOpen.tsx +1 -1
|
@@ -38,7 +38,7 @@ const styles = {
|
|
|
38
38
|
periodSelect: {
|
|
39
39
|
// margin: '0 10px 60px 10px',
|
|
40
40
|
display: 'block',
|
|
41
|
-
width:
|
|
41
|
+
width: 250,
|
|
42
42
|
},
|
|
43
43
|
slider: {
|
|
44
44
|
marginTop: 20,
|
|
@@ -400,9 +400,9 @@ class ComplexCron extends react_1.Component {
|
|
|
400
400
|
const everyMinute = this.state.minutes === '*' || this.state.minutes === '*/1';
|
|
401
401
|
const everySecond = this.state.seconds === '*' || this.state.seconds === '*/1';
|
|
402
402
|
return (react_1.default.createElement("div", { style: styles.mainDiv },
|
|
403
|
-
react_1.default.createElement("div", { style: { paddingLeft: 8, width: '100%' } },
|
|
403
|
+
react_1.default.createElement("div", { style: { paddingLeft: 8, width: 'calc(100% - px)' } },
|
|
404
404
|
react_1.default.createElement(material_1.TextField, { variant: "standard", style: { width: '100%' }, value: this.state.cron, disabled: true })),
|
|
405
|
-
react_1.default.createElement("div", { style: { paddingLeft: 8, width: '100%', height: 60 } },
|
|
405
|
+
react_1.default.createElement("div", { style: { paddingLeft: 8, width: 'calc(100% - px)', height: 60 } },
|
|
406
406
|
ComplexCron.convertCronToText(this.state.cron, this.props.language || 'en'),
|
|
407
407
|
react_1.default.createElement("span", { style: styles.warning }, everySecond
|
|
408
408
|
? i18n_1.default.t('ra_warning_every_second')
|
|
@@ -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
|
|
@@ -600,7 +600,11 @@ class Schedule extends react_1.Component {
|
|
|
600
600
|
this.onChange(_schedule);
|
|
601
601
|
} }), label: !fromTo ? i18n_1.default.t('sch_fromTo') : '' }),
|
|
602
602
|
fromTo && [
|
|
603
|
-
react_1.default.createElement(material_1.TextField, { variant: "standard", style: Object.assign(Object.assign({}, styles.inputTime), { marginRight: 10 }), key: "exactTimeFrom", type: "time",
|
|
603
|
+
react_1.default.createElement(material_1.TextField, { variant: "standard", style: Object.assign(Object.assign({}, styles.inputTime), { marginRight: 10 }), key: "exactTimeFrom", type: "time", sx: (theme) => ({
|
|
604
|
+
'& input[type="time"]::-webkit-calendar-picker-indicator': {
|
|
605
|
+
filter: theme.palette.mode === 'dark' ? 'invert(80%)' : undefined,
|
|
606
|
+
},
|
|
607
|
+
}), value: this.state.schedule.time.start,
|
|
604
608
|
// InputProps={{inputComponent: TextTime}}
|
|
605
609
|
onChange: e => {
|
|
606
610
|
const _schedule = JSON.parse(JSON.stringify(this.state.schedule));
|
|
@@ -609,7 +613,11 @@ class Schedule extends react_1.Component {
|
|
|
609
613
|
}, slotProps: {
|
|
610
614
|
inputLabel: { shrink: true },
|
|
611
615
|
}, label: i18n_1.default.t('sch_from'), margin: "normal" }),
|
|
612
|
-
react_1.default.createElement(material_1.TextField, { variant: "standard", style: styles.inputTime, key: "exactTimeTo", type: "time",
|
|
616
|
+
react_1.default.createElement(material_1.TextField, { variant: "standard", style: styles.inputTime, key: "exactTimeTo", type: "time", sx: (theme) => ({
|
|
617
|
+
'& input[type="time"]::-webkit-calendar-picker-indicator': {
|
|
618
|
+
filter: theme.palette.mode === 'dark' ? 'invert(80%)' : undefined,
|
|
619
|
+
},
|
|
620
|
+
}), value: this.state.schedule.time.end,
|
|
613
621
|
// InputProps={{inputComponent: TextTime}}
|
|
614
622
|
onChange: e => {
|
|
615
623
|
const _schedule = JSON.parse(JSON.stringify(this.state.schedule));
|
|
@@ -640,7 +648,7 @@ class Schedule extends react_1.Component {
|
|
|
640
648
|
_schedule.time.end = 'sunrise';
|
|
641
649
|
this.onChange(_schedule);
|
|
642
650
|
} }), label: i18n_1.default.t('sch_astroNight') })))),
|
|
643
|
-
!schedule.time.exactTime && this.getPeriodSettingsMinutes())));
|
|
651
|
+
!schedule.time.exactTime && this.getPeriodSettingsMinutes(fromTo))));
|
|
644
652
|
}
|
|
645
653
|
getTimeExactElements() {
|
|
646
654
|
const isAstro = ASTRO.includes(this.state.schedule.time.start);
|
|
@@ -659,13 +667,17 @@ class Schedule extends react_1.Component {
|
|
|
659
667
|
react_1.default.createElement(material_1.MenuItem, { key: "specific", value: "00:00" }, i18n_1.default.t('sch_specificTime')),
|
|
660
668
|
ASTRO.map(event => (react_1.default.createElement(material_1.MenuItem, { key: event, value: event }, i18n_1.default.t(`sch_astro_${event}`)))))),
|
|
661
669
|
this.state.schedule.time.exactTime && !isAstro && (react_1.default.createElement("div", { style: styles.settingsDiv },
|
|
662
|
-
react_1.default.createElement(material_1.TextField, { variant: "standard", style: styles.inputTime, key: "exactTimeValue", value: this.state.schedule.time.start, type: "time",
|
|
663
|
-
|
|
664
|
-
|
|
670
|
+
react_1.default.createElement(material_1.TextField, { variant: "standard", style: styles.inputTime, key: "exactTimeValue", value: this.state.schedule.time.start, type: "time", sx: (theme) => ({
|
|
671
|
+
'& input[type="time"]::-webkit-calendar-picker-indicator': {
|
|
672
|
+
filter: theme.palette.mode === 'dark' ? 'invert(80%)' : undefined,
|
|
673
|
+
},
|
|
674
|
+
}), onChange: e => {
|
|
665
675
|
const _schedule = JSON.parse(JSON.stringify(this.state.schedule));
|
|
666
676
|
_schedule.time.start = e.target.value;
|
|
667
677
|
this.onChange(_schedule);
|
|
668
|
-
},
|
|
678
|
+
}, slotProps: {
|
|
679
|
+
inputLabel: { shrink: true },
|
|
680
|
+
}, margin: "normal" })))));
|
|
669
681
|
}
|
|
670
682
|
static getDivider() {
|
|
671
683
|
return react_1.default.createElement("hr", { style: styles.hr });
|
|
@@ -719,7 +731,9 @@ class Schedule extends react_1.Component {
|
|
|
719
731
|
this.onChange(_schedule);
|
|
720
732
|
}
|
|
721
733
|
}, 1500, e.target.value);
|
|
722
|
-
},
|
|
734
|
+
}, slotProps: {
|
|
735
|
+
inputLabel: { shrink: true },
|
|
736
|
+
}, label: i18n_1.default.t('sch_at'), margin: "normal" })))),
|
|
723
737
|
// ----- days ---
|
|
724
738
|
react_1.default.createElement(material_1.Box, { component: "div", key: "days", sx: Utils_1.default.getStyle(this.props.theme, styles.rowDiv, styles.rowDays) },
|
|
725
739
|
react_1.default.createElement("div", { style: styles.modeDiv },
|
|
@@ -854,9 +868,9 @@ class Schedule extends react_1.Component {
|
|
|
854
868
|
MONTHS.map((month, i) => (react_1.default.createElement(material_1.MenuItem, { key: month, value: i + 1 }, i18n_1.default.t(month))))))))),
|
|
855
869
|
];
|
|
856
870
|
}
|
|
857
|
-
getPeriodSettingsMinutes() {
|
|
858
|
-
return (react_1.default.createElement("div", { style: { display: 'inline-block' } },
|
|
859
|
-
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')),
|
|
860
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 => {
|
|
861
875
|
const _schedule = JSON.parse(JSON.stringify(this.state.schedule));
|
|
862
876
|
_schedule.time.interval = parseInt(e.target.value, 10);
|
|
@@ -1218,7 +1232,9 @@ class Schedule extends react_1.Component {
|
|
|
1218
1232
|
this.onChange(_schedule);
|
|
1219
1233
|
}
|
|
1220
1234
|
}, 1500, e.target.value);
|
|
1221
|
-
},
|
|
1235
|
+
}, slotProps: {
|
|
1236
|
+
inputLabel: { shrink: true },
|
|
1237
|
+
}, margin: "normal" }),
|
|
1222
1238
|
react_1.default.createElement(material_1.FormControlLabel, { control: react_1.default.createElement(material_1.Checkbox, { style: styles.inputRadio, checked: !!schedule.valid.to, onClick: () => {
|
|
1223
1239
|
const _schedule = JSON.parse(JSON.stringify(this.state.schedule));
|
|
1224
1240
|
_schedule.valid.to = _schedule.valid.to ? '' : Schedule.now2string(true);
|
|
@@ -1243,7 +1259,9 @@ class Schedule extends react_1.Component {
|
|
|
1243
1259
|
this.onChange(_schedule);
|
|
1244
1260
|
}
|
|
1245
1261
|
}, 1500, e.target.value);
|
|
1246
|
-
},
|
|
1262
|
+
}, slotProps: {
|
|
1263
|
+
inputLabel: { shrink: true },
|
|
1264
|
+
}, margin: "normal" })))));
|
|
1247
1265
|
}
|
|
1248
1266
|
render() {
|
|
1249
1267
|
return (react_1.default.createElement("div", { style: { height: 'calc(100% - 48px)', width: '100%', overflow: 'hidden' } },
|
|
@@ -36,7 +36,16 @@ const PERIODIC_TYPES = {
|
|
|
36
36
|
minutes: 'minutes',
|
|
37
37
|
// hours: 'hours',
|
|
38
38
|
};
|
|
39
|
-
const WEEKDAYS = [
|
|
39
|
+
const WEEKDAYS = [
|
|
40
|
+
'ra_Sunday',
|
|
41
|
+
'ra_Monday',
|
|
42
|
+
'ra_Tuesday',
|
|
43
|
+
'ra_Wednesday',
|
|
44
|
+
'ra_Thursday',
|
|
45
|
+
'ra_Friday',
|
|
46
|
+
'ra_Saturday',
|
|
47
|
+
'ra_Sunday',
|
|
48
|
+
];
|
|
40
49
|
function padding(num) {
|
|
41
50
|
if (num < 10) {
|
|
42
51
|
return `0${num}`;
|
|
@@ -281,6 +290,9 @@ class SimpleCron extends react_1.default.Component {
|
|
|
281
290
|
const text = [];
|
|
282
291
|
let start = null;
|
|
283
292
|
let end = null;
|
|
293
|
+
if (!list.length) {
|
|
294
|
+
return '_';
|
|
295
|
+
}
|
|
284
296
|
for (let i = 0; i < list.length; i++) {
|
|
285
297
|
if (start === null) {
|
|
286
298
|
start = list[i];
|
|
@@ -459,13 +471,21 @@ class SimpleCron extends react_1.default.Component {
|
|
|
459
471
|
}
|
|
460
472
|
getControlsWeekdaysElements(type) {
|
|
461
473
|
const settings = type === 'intervalBetween' ? this.state.intervalBetween : this.state.specific;
|
|
462
|
-
return (react_1.default.createElement("div", { key: "weekdays", style: { paddingLeft: 8, width: '100%', maxWidth: 600 } },
|
|
474
|
+
return (react_1.default.createElement("div", { key: "weekdays", style: { paddingLeft: 8, width: 'calc(100% - 8px)', maxWidth: 600 } },
|
|
463
475
|
react_1.default.createElement("h5", null, i18n_1.default.t('ra_On weekdays')),
|
|
464
476
|
[1, 2, 3, 4, 5, 6, 0].map(day => (react_1.default.createElement(material_1.FormControlLabel, { key: WEEKDAYS[day], control: react_1.default.createElement(material_1.Checkbox, { checked: settings.weekdays.includes(day), onChange: e => {
|
|
465
477
|
const _settings = JSON.parse(JSON.stringify(this.state[type]));
|
|
466
478
|
const pos = _settings.weekdays.indexOf(day);
|
|
467
|
-
e.target.checked
|
|
468
|
-
|
|
479
|
+
if (e.target.checked) {
|
|
480
|
+
if (pos === -1) {
|
|
481
|
+
_settings.weekdays.push(day);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
else {
|
|
485
|
+
if (pos !== -1) {
|
|
486
|
+
_settings.weekdays.splice(pos, 1);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
469
489
|
_settings.weekdays.sort();
|
|
470
490
|
if (type === 'intervalBetween') {
|
|
471
491
|
this.setState({ intervalBetween: _settings }, () => this.recalcCron());
|
|
@@ -564,7 +584,11 @@ class SimpleCron extends react_1.default.Component {
|
|
|
564
584
|
getControlsTime(type) {
|
|
565
585
|
const settings = type === 'once' ? this.state.once : this.state.specific;
|
|
566
586
|
return (react_1.default.createElement(material_1.FormControl, { variant: "standard", sx: Object.assign(Object.assign({}, styles.formControl), { '&.MuiFormControl-root': styles.formControlMarginRight }) },
|
|
567
|
-
react_1.default.createElement(material_1.TextField, { variant: "standard", key: "at", label: i18n_1.default.t('sc_time'), value: settings.time, type: "time",
|
|
587
|
+
react_1.default.createElement(material_1.TextField, { variant: "standard", key: "at", label: i18n_1.default.t('sc_time'), value: settings.time, type: "time", sx: (theme) => ({
|
|
588
|
+
'& input[type="time"]::-webkit-calendar-picker-indicator': {
|
|
589
|
+
filter: theme.palette.mode === 'dark' ? 'invert(80%)' : undefined,
|
|
590
|
+
},
|
|
591
|
+
}), onChange: e => {
|
|
568
592
|
const _settings = JSON.parse(JSON.stringify(this.state[type]));
|
|
569
593
|
_settings.time = e.target.value;
|
|
570
594
|
if (type === 'once') {
|
|
@@ -655,9 +679,11 @@ class SimpleCron extends react_1.default.Component {
|
|
|
655
679
|
}
|
|
656
680
|
render() {
|
|
657
681
|
return (react_1.default.createElement("div", { style: styles.mainDiv },
|
|
658
|
-
react_1.default.createElement("div", { style: { paddingLeft: 8, width: '100%' } },
|
|
659
|
-
react_1.default.createElement(material_1.TextField, { variant: "standard", style: { width: '100%' }, value: this.state.cron, disabled: true })),
|
|
660
|
-
react_1.default.createElement("div", { style: { paddingLeft: 8, width: '100%', height: 60 } },
|
|
682
|
+
react_1.default.createElement("div", { style: { paddingLeft: 8, width: 'calc(100% - 8px)' } },
|
|
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('_')
|
|
685
|
+
? i18n_1.default.t('sc_invalid_cron')
|
|
686
|
+
: (0, cronText_1.default)(this.state.cron, this.props.language || 'en')),
|
|
661
687
|
react_1.default.createElement("div", null,
|
|
662
688
|
react_1.default.createElement(material_1.FormControl, { variant: "standard", style: Object.assign(Object.assign({}, styles.formControl), { marginLeft: 8, marginTop: 8 }) },
|
|
663
689
|
react_1.default.createElement(material_1.InputLabel, null, i18n_1.default.t('ra_Repeat')),
|
package/Dialogs/SimpleCron.js
CHANGED
|
@@ -44,7 +44,7 @@ class DialogSimpleCron extends react_1.default.Component {
|
|
|
44
44
|
react_1.default.createElement(material_1.DialogContent, { style: { height: '100%', overflow: 'hidden' } },
|
|
45
45
|
react_1.default.createElement(SimpleCron_1.default, { cronExpression: this.state.cron, onChange: cron => this.setState({ cron }), language: i18n_1.default.getLanguage() })),
|
|
46
46
|
react_1.default.createElement(material_1.DialogActions, null,
|
|
47
|
-
react_1.default.createElement(material_1.Button, { variant: "contained", onClick: () => this.handleOk(), color: "primary", startIcon: react_1.default.createElement(icons_material_1.Check, null) }, this.props.ok || i18n_1.default.t('ra_Ok')),
|
|
47
|
+
react_1.default.createElement(material_1.Button, { variant: "contained", disabled: !this.state.cron || this.state.cron.includes('_'), onClick: () => this.handleOk(), color: "primary", startIcon: react_1.default.createElement(icons_material_1.Check, null) }, this.props.ok || i18n_1.default.t('ra_Ok')),
|
|
48
48
|
react_1.default.createElement(material_1.Button, { variant: "contained", onClick: () => this.handleCancel(), color: "grey", startIcon: react_1.default.createElement(icons_material_1.Cancel, null) }, this.props.cancel || i18n_1.default.t('ra_Cancel')))));
|
|
49
49
|
}
|
|
50
50
|
}
|
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,6 +697,11 @@ You can find the migration instructions:
|
|
|
697
697
|
-->
|
|
698
698
|
|
|
699
699
|
## Changelog
|
|
700
|
+
### 7.2.4 (2024-10-07)
|
|
701
|
+
|
|
702
|
+
- (@GermanBluefox) Corrected file browser
|
|
703
|
+
- (@GermanBluefox) Changed Open/Close Folder icons
|
|
704
|
+
|
|
700
705
|
### 7.2.2 (2024-10-04)
|
|
701
706
|
- (@GermanBluefox) Small layout change for Icon Picker
|
|
702
707
|
|
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",
|
|
@@ -435,5 +435,15 @@
|
|
|
435
435
|
"ra_warning_every_second": "Achtung: Der CRON-Job wird im angegebenen Zeitraum jede Sekunde ausgeführt!",
|
|
436
436
|
"ra_warning_every_minute": "Achtung: Der CRON-Job wird im angegebenen Zeitraum jede Minute ausgeführt!",
|
|
437
437
|
"ra_The schedule will be executed every second. Are you sure?": "Der Zeitplan wird jede Sekunde ausgeführt. Sind Sie sicher?",
|
|
438
|
-
"ra_The schedule will be executed every minute. Are you sure?": "Der Zeitplan wird jede Minute ausgeführt. Sind Sie sicher?"
|
|
439
|
-
|
|
438
|
+
"ra_The schedule will be executed every minute. Are you sure?": "Der Zeitplan wird jede Minute ausgeführt. Sind Sie sicher?",
|
|
439
|
+
"sc_dow": "Tag",
|
|
440
|
+
"ra_Define CRON...": "Definieren Sie CRON ...",
|
|
441
|
+
"ra_Sunday": "Sonntag",
|
|
442
|
+
"ra_Monday": "Montag",
|
|
443
|
+
"ra_Tuesday": "Dienstag",
|
|
444
|
+
"ra_Wednesday": "Mittwoch",
|
|
445
|
+
"ra_Thursday": "Donnerstag",
|
|
446
|
+
"ra_Friday": "Freitag",
|
|
447
|
+
"ra_Saturday": "Samstag",
|
|
448
|
+
"sc_invalid_cron": "Ungültiger CRON"
|
|
449
|
+
}
|