@iobroker/adapter-react-v5 6.1.10 → 7.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Components/FileBrowser.js +42 -16
- package/Components/ObjectBrowser.d.ts +10 -0
- package/Components/ObjectBrowser.js +228 -80
- package/README.md +1009 -1001
- package/Theme.js +8 -7
- package/i18n/de.json +4 -1
- package/i18n/en.json +4 -1
- package/i18n/es.json +4 -1
- package/i18n/fr.json +4 -1
- package/i18n/it.json +4 -1
- package/i18n/nl.json +4 -1
- package/i18n/pl.json +4 -1
- package/i18n/pt.json +4 -1
- package/i18n/ru.json +4 -1
- package/i18n/uk.json +4 -1
- package/i18n/zh-cn.json +4 -1
- package/package.json +5 -5
- package/src/Components/FileBrowser.tsx +45 -16
- package/src/Components/ObjectBrowser.tsx +281 -98
- package/src/Theme.tsx +2 -2
- package/types.d.ts +0 -134
package/README.md
CHANGED
|
@@ -1,1331 +1,1339 @@
|
|
|
1
|
-
# Help ReactJS classes for adapter config
|
|
2
|
-
You can find demo on https://github.com/ioBroker/adapter-react-demo
|
|
3
|
-
|
|
4
|
-
## Getting started
|
|
5
|
-
If you want to create the configuration page with ReactJS:
|
|
6
|
-
1. Create github repo for adapter.
|
|
7
|
-
2. execute `npx create-react-app src` . It will take a while.
|
|
8
|
-
3. `cd src`
|
|
9
|
-
4. Modify package.json file in src directory:
|
|
10
|
-
- Change `name` from `src` to `ADAPTERNAME-admin` (Of course replace `ADAPTERNAME` with yours)
|
|
11
|
-
- Add to devDependencies:
|
|
12
|
-
```
|
|
13
|
-
"@iobroker/adapter-react": "^4.0.10",
|
|
14
|
-
```
|
|
15
|
-
Versions can be higher.
|
|
16
|
-
So your src/package.json should look like:
|
|
17
|
-
```
|
|
18
|
-
{
|
|
19
|
-
"name": "ADAPTERNAME-admin",
|
|
20
|
-
"version": "0.1.0",
|
|
21
|
-
"private": true,
|
|
22
|
-
"dependencies": {
|
|
23
|
-
"react": "^18.2.0",
|
|
24
|
-
"react-dom": "^18.2.0",
|
|
25
|
-
"react-icons": "^4.6.0",
|
|
26
|
-
"react-scripts": "^5.0.1",
|
|
27
|
-
"@iobroker/adapter-react-v5": "^3.2.7",
|
|
28
|
-
"del": "^6.1.1",
|
|
29
|
-
"gulp": "^4.0.2"
|
|
30
|
-
},
|
|
31
|
-
"scripts": {
|
|
32
|
-
"start": "react-scripts start",
|
|
33
|
-
"build": "react-scripts build",
|
|
34
|
-
"test": "react-scripts test",
|
|
35
|
-
"eject": "react-scripts eject"
|
|
36
|
-
},
|
|
37
|
-
"eslintConfig": {
|
|
38
|
-
"extends": "react-app"
|
|
39
|
-
},
|
|
40
|
-
"homepage": ".",
|
|
41
|
-
"browserslist": [
|
|
42
|
-
">0.2%",
|
|
43
|
-
"not dead",
|
|
44
|
-
"not ie <= 11",
|
|
45
|
-
"not op_mini all"
|
|
46
|
-
]
|
|
47
|
-
}
|
|
48
|
-
```
|
|
49
|
-
5. Call in `src`: `npm install`
|
|
50
|
-
6. Copy
|
|
51
|
-
7. Start your dummy application `npm run start` for developing or build with `npm run build` and
|
|
52
|
-
copy files in `build` directory to `www` or to `admin`. In the admin you must rename `index.html` to `index_m.html`.
|
|
53
|
-
8. You can do that with `gulp` tasks: `gulp build`, `gulp copy`, `gulp renameIndex` or `gulp renameTab`
|
|
54
|
-
|
|
55
|
-
## Development
|
|
56
|
-
1. Add `socket.io` to `public/index.html`.
|
|
57
|
-
After
|
|
58
|
-
|
|
59
|
-
```
|
|
60
|
-
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
insert
|
|
64
|
-
|
|
65
|
-
```
|
|
66
|
-
<script>
|
|
67
|
-
var script = document.createElement('script');
|
|
68
|
-
window.registerSocketOnLoad = function (cb) {
|
|
69
|
-
window.socketLoadedHandler = cb;
|
|
70
|
-
};
|
|
71
|
-
const parts = (window.location.search || '').replace(/^\?/, '').split('&');
|
|
72
|
-
const query = {};
|
|
73
|
-
parts.forEach(item => {
|
|
74
|
-
const [name, val] = item.split('=');
|
|
75
|
-
query[decodeURIComponent(name)] = val !== undefined ? decodeURIComponent(val) : true;
|
|
76
|
-
});
|
|
77
|
-
script.onload = function () { typeof window.socketLoadedHandler === 'function' && window.socketLoadedHandler(); };
|
|
78
|
-
script.src = window.location.port === '3000' ? window.location.protocol + '//' + (query.host || window.location.hostname) + ':' + (query.port || 8081) + '/lib/js/socket.io.js' : '%PUBLIC_URL%/../../lib/js/socket.io.js';
|
|
79
|
-
|
|
80
|
-
document.head.appendChild(script);
|
|
81
|
-
</script>
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
3. Add to App.js constructor initialization for I18n:
|
|
85
|
-
```
|
|
86
|
-
class App extends GenericApp {
|
|
87
|
-
constructor(props) {
|
|
88
|
-
const extendedProps = {...props};
|
|
89
|
-
extendedProps.encryptedFields = ['pass']; // this parameter will be encrypted and decrypted automatically
|
|
90
|
-
extendedProps.translations = {
|
|
91
|
-
'en': require('./i18n/en'),
|
|
92
|
-
'de': require('./i18n/de'),
|
|
93
|
-
'ru': require('./i18n/ru'),
|
|
94
|
-
'pt': require('./i18n/pt'),
|
|
95
|
-
'nl': require('./i18n/nl'),
|
|
96
|
-
'fr': require('./i18n/fr'),
|
|
97
|
-
'it': require('./i18n/it'),
|
|
98
|
-
'es': require('./i18n/es'),
|
|
99
|
-
'pl': require('./i18n/pl'),
|
|
100
|
-
'uk': require('./i18n/uk'),
|
|
101
|
-
'zh-cn': require('./i18n/zh-cn'),
|
|
102
|
-
};
|
|
103
|
-
// get actual admin port
|
|
104
|
-
extendedProps.socket = {port: parseInt(window.location.port, 10)};
|
|
105
|
-
|
|
106
|
-
// Only if close, save buttons are not required at the bottom (e.g. if admin tab)
|
|
107
|
-
// extendedProps.bottomButtons = false;
|
|
108
|
-
|
|
109
|
-
// only for debug purposes
|
|
110
|
-
if (extendedProps.socket.port === 3000) {
|
|
111
|
-
extendedProps.socket.port = 8081;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// allow to manage GenericApp the sentry initialisation or do not set the sentryDSN if no sentry available
|
|
115
|
-
extendedProps.sentryDSN = 'https://yyy@sentry.iobroker.net/xx';
|
|
116
|
-
|
|
117
|
-
super(extendedProps);
|
|
118
|
-
}
|
|
119
|
-
...
|
|
120
|
-
}
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
4. Replace `index.js` with the following code to support themes:
|
|
124
|
-
```
|
|
125
|
-
import React from 'react';
|
|
126
|
-
import ReactDOM from 'react-dom';
|
|
127
|
-
import { MuiThemeProvider} from '@material-ui/core/styles';
|
|
128
|
-
import * as serviceWorker from './serviceWorker';
|
|
129
|
-
|
|
130
|
-
import './index.css';
|
|
131
|
-
import App from './App';
|
|
132
|
-
import { version } from '../package.json';
|
|
133
|
-
|
|
134
|
-
import theme from '@iobroker/adapter-react/Theme';
|
|
135
|
-
|
|
136
|
-
console.log('iobroker.scenes@' + version);
|
|
137
|
-
let themeName = window.localStorage ? window.localStorage.getItem('App.theme') || 'light' : 'light';
|
|
138
|
-
|
|
139
|
-
function build() {
|
|
140
|
-
return ReactDOM.render(<MuiThemeProvider theme={ theme(themeName) }>
|
|
141
|
-
<App onThemeChange={_theme => {
|
|
142
|
-
themeName = _theme;
|
|
143
|
-
build();
|
|
144
|
-
}}/>
|
|
145
|
-
</MuiThemeProvider>, document.getElementById('root'));
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
build();
|
|
149
|
-
|
|
150
|
-
// If you want your app to work offline and load faster, you can change
|
|
151
|
-
// unregister() to register() below. Note this comes with some pitfalls.
|
|
152
|
-
// Learn more about service workers: http://bit.ly/CRA-PWA
|
|
153
|
-
serviceWorker.unregister();
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
5. Add to App.js encoding and decoding of values:
|
|
157
|
-
```
|
|
158
|
-
class App extend GenericApp {
|
|
159
|
-
...
|
|
160
|
-
onPrepareLoad(settings) {
|
|
161
|
-
settings.pass = this.decode(settings.pass);
|
|
162
|
-
}
|
|
163
|
-
onPrepareSave(settings) {
|
|
164
|
-
settings.pass = this.encode(settings.pass);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
6. The optional step is to validate the data to be saved:
|
|
170
|
-
```
|
|
171
|
-
onPrepareSave(settings) {
|
|
172
|
-
super.onPrepareSave(settings);
|
|
173
|
-
if (DATA_INVALID) {
|
|
174
|
-
return false; // configuration will not be saved
|
|
175
|
-
} else {
|
|
176
|
-
return true;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
## Components
|
|
182
|
-
|
|
183
|
-
### Connection.tsx
|
|
184
|
-
This is a non-react class to provide the communication for socket connection with the server.
|
|
185
|
-
|
|
186
|
-
### GenericApp.tsx
|
|
187
|
-
|
|
188
|
-
### i18n.ts
|
|
189
|
-
|
|
190
|
-
### Theme.tsx
|
|
191
|
-
|
|
192
|
-
### Dialogs
|
|
193
|
-
Some dialogs are predefined and could be used out of the box.
|
|
194
|
-
|
|
195
|
-
#### Confirm.tsx
|
|
196
|
-
<!-- TODO: Provide screenshot here -->
|
|
197
|
-
|
|
198
|
-
Usage:
|
|
199
|
-
```
|
|
200
|
-
import React from 'react';
|
|
201
|
-
import ConfirmDialog from '@iobroker/adapter-react/Dialogs/Confirm'
|
|
202
|
-
import I18n from '@iobroker/adapter-react/i18n';
|
|
203
|
-
|
|
204
|
-
class ExportImportDialog extends React.Component {
|
|
205
|
-
constructor(props) {
|
|
206
|
-
super(props);
|
|
207
|
-
|
|
208
|
-
this.state = {
|
|
209
|
-
confirmDialog: false,
|
|
210
|
-
};
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
renderConfirmDialog() {
|
|
214
|
-
if (!this.state.confirmDialog) {
|
|
215
|
-
return null;
|
|
216
|
-
}
|
|
217
|
-
return <ConfirmDialog
|
|
218
|
-
title={ I18n.t('Scene will be overwritten.') }
|
|
219
|
-
text={ I18n.t('All data will be lost. Confirm?') }
|
|
220
|
-
ok={ I18n.t('Yes') }
|
|
221
|
-
cancel={ I18n.t('Cancel') }
|
|
222
|
-
suppressQuestionMinutes={5}
|
|
223
|
-
dialogName="myConfirmDialogThatCouldBeSuppressed"
|
|
224
|
-
suppressText={I18n.t('Suppress question for next %s minutes', 5)}
|
|
225
|
-
onClose={isYes => {
|
|
226
|
-
this.setState({ confirmDialog: false} );
|
|
227
|
-
}}
|
|
228
|
-
/>;
|
|
229
|
-
}
|
|
230
|
-
render() {
|
|
231
|
-
return <div>
|
|
232
|
-
<Button onClick={ () => this.setState({confirmDialog: true}) }>Click</Button>
|
|
233
|
-
{ this.renderConfirmDialog() }
|
|
234
|
-
</div>
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
export default ExportImportDialog;
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
#### Error.tsx
|
|
242
|
-
<!-- TODO: Provide screenshot here -->
|
|
243
|
-
|
|
244
|
-
#### Message.tsx
|
|
245
|
-
<!-- TODO: Provide screenshot here -->
|
|
246
|
-
```
|
|
247
|
-
renderMessage() {
|
|
248
|
-
if (this.state.showMessage) {
|
|
249
|
-
return <Message
|
|
250
|
-
text={this.state.showMessage}
|
|
251
|
-
onClose={() => this.setState({showMessage: false})}
|
|
252
|
-
/>;
|
|
253
|
-
} else {
|
|
254
|
-
return null;
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
#### SelectID.tsx
|
|
260
|
-

|
|
261
|
-
```
|
|
262
|
-
import DialogSelectID from '@iobroker/adapter-react/Dialogs/SelectID';
|
|
263
|
-
|
|
264
|
-
class MyComponent extends Component {
|
|
265
|
-
constructor(props) {
|
|
266
|
-
super(props);
|
|
267
|
-
this.state = {
|
|
268
|
-
showSelectId: false,
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
renderSelectIdDialog() {
|
|
273
|
-
if (this.state.showSelectId) {
|
|
274
|
-
return <DialogSelectID
|
|
275
|
-
key="tableSelect"
|
|
276
|
-
imagePrefix="../.."
|
|
277
|
-
dialogName={this.props.adapterName}
|
|
278
|
-
themeType={this.props.themeType}
|
|
279
|
-
socket={this.props.socket}
|
|
280
|
-
statesOnly={true}
|
|
281
|
-
selected={this.state.selectIdValue}
|
|
282
|
-
onClose={() => this.setState({showSelectId: false})}
|
|
283
|
-
onOk={(selected, name) => {
|
|
284
|
-
this.setState({showSelectId: false, selectIdValue: selected});
|
|
285
|
-
}}
|
|
286
|
-
/>;
|
|
287
|
-
} else {
|
|
288
|
-
return null;
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
render() {
|
|
292
|
-
return renderSelectIdDialog();
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
```
|
|
296
|
-
|
|
297
|
-
#### Cron
|
|
298
|
-
Include `"react-text-mask": "^5.4.3",` in package.json.
|
|
299
|
-
|
|
300
|
-
<!-- TODO: Provide screenshot here -->
|
|
301
|
-
|
|
302
|
-
```
|
|
303
|
-
function renderCron() {
|
|
304
|
-
if (!showCron) {
|
|
305
|
-
return null;
|
|
306
|
-
} else {
|
|
307
|
-
return <DialogCron
|
|
308
|
-
key="dialogCron1"
|
|
309
|
-
cron={this.state.cronValue || '* * * * *'}
|
|
310
|
-
onClose={() => this.setState({ showCron: false })}
|
|
311
|
-
onOk={cronValue => {
|
|
312
|
-
this.setState({ cronValue })
|
|
313
|
-
}}
|
|
314
|
-
/>;
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
```
|
|
318
|
-
|
|
319
|
-
### Components
|
|
320
|
-
|
|
321
|
-
#### Utils.tsx
|
|
322
|
-
##### getObjectNameFromObj
|
|
323
|
-
`getObjectNameFromObj(obj, settings, options, isDesc)`
|
|
324
|
-
|
|
325
|
-
Get object name from a single object.
|
|
326
|
-
|
|
327
|
-
Usage: `Utils.getObjectNameFromObj(this.objects[id], null, {language: I18n.getLanguage()})`
|
|
328
|
-
|
|
329
|
-
##### getObjectIcon
|
|
330
|
-
`getObjectIcon(id, obj)`
|
|
331
|
-
|
|
332
|
-
Get icon from the object.
|
|
333
|
-
|
|
334
|
-
Usage:
|
|
335
|
-
```
|
|
336
|
-
const icon = Utils.getObjectIcon(id, this.objects[id]);
|
|
337
|
-
return (<img src={icon}/>);
|
|
338
|
-
```
|
|
339
|
-
|
|
340
|
-
##### isUseBright
|
|
341
|
-
`isUseBright(color, defaultValue)`
|
|
342
|
-
|
|
343
|
-
Usage: `
|
|
344
|
-
|
|
345
|
-
#### Loader.tsx
|
|
346
|
-

|
|
347
|
-
|
|
348
|
-
```
|
|
349
|
-
render() {
|
|
350
|
-
if (!this.state.loaded) {
|
|
351
|
-
return <MuiThemeProvider theme={this.state.theme}>
|
|
352
|
-
<Loader theme={this.state.themeType}/>
|
|
353
|
-
</MuiThemeProvider>;
|
|
354
|
-
}
|
|
355
|
-
// render loaded data
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
```
|
|
359
|
-
|
|
360
|
-
#### Logo.tsx
|
|
361
|
-

|
|
362
|
-
|
|
363
|
-
```
|
|
364
|
-
render() {
|
|
365
|
-
return <form className={this.props.classes.tab}>
|
|
366
|
-
<Logo
|
|
367
|
-
instance={this.props.instance}
|
|
368
|
-
common={this.props.common}
|
|
369
|
-
native={this.props.native}
|
|
370
|
-
onError={text => this.setState({errorText: text})}
|
|
371
|
-
onLoad={this.props.onLoad}
|
|
372
|
-
/>
|
|
373
|
-
...
|
|
374
|
-
</form>;
|
|
375
|
-
}
|
|
376
|
-
```
|
|
377
|
-
|
|
378
|
-
#### Router.tsx
|
|
379
|
-
|
|
380
|
-
#### ObjectBrowser.js
|
|
381
|
-
It is better to use `Dialog/SelectID`, but if you want:
|
|
382
|
-
|
|
383
|
-

|
|
384
|
-
|
|
385
|
-
```
|
|
386
|
-
<ObjectBrowser
|
|
387
|
-
foldersFirst={this.props.foldersFirst}
|
|
388
|
-
imagePrefix={this.props.imagePrefix || this.props.prefix} // prefix is for back compatibility
|
|
389
|
-
defaultFilters={this.filters}
|
|
390
|
-
dialogName={this.dialogName}
|
|
391
|
-
showExpertButton={this.props.showExpertButton !== undefined ? this.props.showExpertButton : true}
|
|
392
|
-
style={{ width: '100%', height: '100%' }}
|
|
393
|
-
columns={this.props.columns || ['name', 'type', 'role', 'room', 'func', 'val']}
|
|
394
|
-
types={this.props.types || ['state']}
|
|
395
|
-
t={I18n.t}
|
|
396
|
-
lang={this.props.lang || I18n.getLanguage()}
|
|
397
|
-
socket={this.props.socket}
|
|
398
|
-
selected={this.state.selected}
|
|
399
|
-
multiSelect={this.props.multiSelect}
|
|
400
|
-
notEditable={this.props.notEditable === undefined ? true : this.props.notEditable}
|
|
401
|
-
name={this.state.name}
|
|
402
|
-
themeName={this.props.themeName}
|
|
403
|
-
themeType={this.props.themeType}
|
|
404
|
-
customFilter={this.props.customFilter}
|
|
405
|
-
onFilterChanged={filterConfig => {
|
|
406
|
-
this.filters = filterConfig;
|
|
407
|
-
window.localStorage.setItem(this.dialogName, JSON.stringify(filterConfig));
|
|
408
|
-
}}
|
|
409
|
-
onSelect={(selected, name, isDouble) => {
|
|
410
|
-
if (JSON.stringify(selected) !== JSON.stringify(this.state.selected)) {
|
|
411
|
-
this.setState({selected, name}, () =>
|
|
412
|
-
isDouble && this.handleOk());
|
|
413
|
-
} else if (isDouble) {
|
|
414
|
-
this.handleOk();
|
|
415
|
-
}
|
|
416
|
-
}}
|
|
417
|
-
/>
|
|
418
|
-
```
|
|
419
|
-
|
|
420
|
-
#### TreeTable.ts
|
|
421
|
-

|
|
422
|
-
|
|
423
|
-
```
|
|
424
|
-
// STYLES
|
|
425
|
-
const styles = theme => ({
|
|
426
|
-
tableDiv: {
|
|
427
|
-
width: '100%',
|
|
428
|
-
overflow: 'hidden',
|
|
429
|
-
height: 'calc(100% - 48px)',
|
|
430
|
-
},
|
|
431
|
-
});
|
|
432
|
-
class MyComponent extends Component {
|
|
433
|
-
constructor(props) {
|
|
434
|
-
super(props);
|
|
435
|
-
|
|
436
|
-
this.state = {
|
|
437
|
-
data: [
|
|
438
|
-
{
|
|
439
|
-
id: 'UniqueID1' // required
|
|
440
|
-
fieldIdInData: 'Name1',
|
|
441
|
-
myType: 'number',
|
|
442
|
-
},
|
|
443
|
-
{
|
|
444
|
-
id: 'UniqueID2' // required
|
|
445
|
-
fieldIdInData: 'Name12',
|
|
446
|
-
myType: 'string',
|
|
447
|
-
},
|
|
448
|
-
],
|
|
449
|
-
};
|
|
450
|
-
|
|
451
|
-
this.columns = [
|
|
452
|
-
{
|
|
453
|
-
title: 'Name of field', // required, else it will be "field"
|
|
454
|
-
field: 'fieldIdInData', // required
|
|
455
|
-
editable: false, // or true [default - true]
|
|
456
|
-
cellStyle: { // CSS style - // optional
|
|
457
|
-
maxWidth: '12rem',
|
|
458
|
-
overflow: 'hidden',
|
|
459
|
-
wordBreak: 'break-word',
|
|
460
|
-
},
|
|
461
|
-
lookup: { // optional => edit will be automatically "SELECT"
|
|
462
|
-
'value1': 'text1',
|
|
463
|
-
'value2': 'text2',
|
|
464
|
-
}
|
|
465
|
-
},
|
|
466
|
-
{
|
|
467
|
-
title: 'Type', // required, else it will be "field"
|
|
468
|
-
field: 'myType', // required
|
|
469
|
-
editable: true, // or true [default - true]
|
|
470
|
-
lookup: { // optional => edit will be automatically "SELECT"
|
|
471
|
-
'number': 'Number',
|
|
472
|
-
'string': 'String',
|
|
473
|
-
'boolean': 'Boolean',
|
|
474
|
-
},
|
|
475
|
-
type: 'number/string/color/oid/icon/boolean', // oid=ObjectID,icon=base64-icon
|
|
476
|
-
editComponent: props =>
|
|
477
|
-
<div>Prefix{ <br/>
|
|
478
|
-
<textarea
|
|
479
|
-
rows={4}
|
|
480
|
-
style={{width: '100%', resize: 'vertical'}}
|
|
481
|
-
value={props.value}
|
|
482
|
-
onChange={e => props.onChange(e.target.value)}
|
|
483
|
-
/>
|
|
484
|
-
Suffix
|
|
485
|
-
</div>,
|
|
486
|
-
},
|
|
487
|
-
];
|
|
488
|
-
}
|
|
489
|
-
// renderTable
|
|
490
|
-
render() {
|
|
491
|
-
return <div className={this.props.classes.tableDiv}>
|
|
492
|
-
<TreeTable
|
|
493
|
-
columns={this.columns}
|
|
494
|
-
data={this.state.data}
|
|
495
|
-
onUpdate={(newData, oldData) => {
|
|
496
|
-
const data = JSON.parse(JSON.stringify(this.state.data));
|
|
497
|
-
|
|
498
|
-
// Added new line
|
|
499
|
-
if (newData === true) {
|
|
500
|
-
// find unique ID
|
|
501
|
-
let i = 1;
|
|
502
|
-
let id = 'line_' + i;
|
|
503
|
-
|
|
504
|
-
// eslint-disable-next-line
|
|
505
|
-
while(this.state.data.find(item => item.id === id)) {
|
|
506
|
-
i++;
|
|
507
|
-
id = 'line_' + i;
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
data.push({
|
|
511
|
-
id,
|
|
512
|
-
name: I18n.t('New resource') + '_' + i,
|
|
513
|
-
color: '',
|
|
514
|
-
icon: '',
|
|
515
|
-
unit: '',
|
|
516
|
-
price: 0,
|
|
517
|
-
});
|
|
518
|
-
} else {
|
|
519
|
-
// existing line was modifed
|
|
520
|
-
const pos = this.state.data.indexOf(oldData);
|
|
521
|
-
if (pos !== -1) {
|
|
522
|
-
Object.keys(newData).forEach(attr => data[pos][attr] = newData[attr]);
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
this.setState({data});
|
|
527
|
-
}}
|
|
528
|
-
onDelete={oldData => {
|
|
529
|
-
console.log('Delete: ' + JSON.stringify(oldData));
|
|
530
|
-
const pos = this.state.data.indexOf(oldData);
|
|
531
|
-
if (pos !== -1) {
|
|
532
|
-
const data = JSON.parse(JSON.stringify(this.state.data));
|
|
533
|
-
data.splice(pos, 1);
|
|
534
|
-
this.setState({data});
|
|
535
|
-
}
|
|
536
|
-
}}
|
|
537
|
-
/>
|
|
538
|
-
</div>;
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
```
|
|
542
|
-
|
|
543
|
-
#### Toast
|
|
544
|
-
<!-- TODO: Provide screenshot here -->
|
|
545
|
-
|
|
546
|
-
Toast is not a part of `adapter-react` but it is an example how to use toast in application:
|
|
547
|
-
|
|
548
|
-
```
|
|
549
|
-
import Snackbar from '@material-ui/core/Snackbar';
|
|
550
|
-
|
|
551
|
-
class MyComponent {
|
|
552
|
-
constructor(props) {
|
|
553
|
-
super(props);
|
|
554
|
-
this.state = {
|
|
555
|
-
// ....
|
|
556
|
-
toast: '',
|
|
557
|
-
};
|
|
558
|
-
}
|
|
559
|
-
// ...
|
|
560
|
-
renderToast() {
|
|
561
|
-
if (!this.state.toast) {
|
|
562
|
-
return null;
|
|
563
|
-
}
|
|
564
|
-
return <Snackbar
|
|
565
|
-
anchorOrigin={{
|
|
566
|
-
vertical: 'bottom',
|
|
567
|
-
horizontal: 'left',
|
|
568
|
-
}}
|
|
569
|
-
open={true}
|
|
570
|
-
autoHideDuration={6000}
|
|
571
|
-
onClose={() => this.setState({toast: ''})}
|
|
572
|
-
ContentProps={{'aria-describedby': 'message-id'}}
|
|
573
|
-
message={<span id="message-id">{this.state.toast}</span>}
|
|
574
|
-
action={[
|
|
575
|
-
<IconButton
|
|
576
|
-
key="close"
|
|
577
|
-
aria-label="Close"
|
|
578
|
-
color="inherit"
|
|
579
|
-
className={this.props.classes.close}
|
|
580
|
-
onClick={() => this.setState({toast: ''})}
|
|
581
|
-
>
|
|
582
|
-
<IconClose />
|
|
583
|
-
</IconButton>,
|
|
584
|
-
]}
|
|
585
|
-
/>;
|
|
586
|
-
}
|
|
587
|
-
render() {
|
|
588
|
-
return <div>
|
|
589
|
-
{this.renderToast()}
|
|
590
|
-
</div>;
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
```
|
|
594
|
-
|
|
595
|
-
## List of adapters that use adapter-react
|
|
596
|
-
- Admin
|
|
597
|
-
- Backitup
|
|
598
|
-
- iot
|
|
599
|
-
- echarts
|
|
600
|
-
- text2command
|
|
601
|
-
- scenes
|
|
602
|
-
- javascript
|
|
603
|
-
- devices
|
|
604
|
-
- eventlist
|
|
605
|
-
- cameras
|
|
606
|
-
- web
|
|
607
|
-
- vis-2
|
|
608
|
-
- vis-2-widgets-xxx
|
|
609
|
-
- fullcalendar
|
|
610
|
-
- openweathermap
|
|
611
|
-
|
|
612
|
-
## Usability
|
|
613
|
-
In dialogs, the OK button is first (on the left) and the cancel button is last (on the right)
|
|
614
|
-
|
|
615
|
-
## Used icons
|
|
616
|
-
This project uses icons from [Flaticon](https://www.flaticon.com/).
|
|
617
|
-
|
|
618
|
-
ioBroker GmbH has a valid license for all the used icons.
|
|
619
|
-
The icons may not be reused in other projects without the proper flaticon license or flaticon subscription.
|
|
620
|
-
|
|
621
|
-
## Migration from adapter-react to adapter-react-v5
|
|
622
|
-
### In src/package.json => dependencies
|
|
623
|
-
- `"@iobroker/adapter-react": "^2.0.22",` => `"@iobroker/adapter-react-v5": "^3.1.34",`
|
|
624
|
-
- `"@material-ui/core": "^4.12.3",` => `"@mui/material": "^5.10.9",`
|
|
625
|
-
- `"@material-ui/icons": "^4.11.2",` => `"@mui/icons-material": "^5.10.9",`
|
|
626
|
-
- Add `"@mui/styles": "^5.10.9",`
|
|
627
|
-
- Add `"babel-eslint": "^10.1.0",`
|
|
628
|
-
|
|
629
|
-
### In Source files
|
|
630
|
-
- All `@iobroker/adapter-react/...` => `@iobroker/adapter-react-v5/...`
|
|
631
|
-
- All `@material-ui/icons/...` => `@mui/icons-material/...`
|
|
632
|
-
- Change `import { withStyles } from '@material-ui/core/styles';` => `import { withStyles } from '@mui/styles';`
|
|
633
|
-
- Change `import { makeStyles } from '@mui/material/styles';` => `import { makeStyles } from '@mui/styles';`
|
|
634
|
-
- Change `import withWidth from '@material-ui/core/withWidth';` => `import { withWidth } from '@iobroker/adapter-react-v5';`
|
|
635
|
-
- All `@material-ui/core...` => `@mui/material...`
|
|
636
|
-
- Change `import { MuiThemeProvider } from '@material-ui/core/styles';` => `import { ThemeProvider, StyledEngineProvider } from '@mui/material/styles';`
|
|
637
|
-
- Change all `<MuiThemeProvider theme={this.state.theme}>` to `<StyledEngineProvider injectFirst><ThemeProvider theme={this.state.theme}>`
|
|
638
|
-
- Rename in styles `theme.palette.type` => `theme.palette.mode`
|
|
639
|
-
- Add to all `TextField`, `Select`, `FormControl` the property `variant="standard"`
|
|
640
|
-
- Add to all `Button` that do not have `color` property: `color="grey"`
|
|
641
|
-
- Replace by `TextField` the `readOnly` attribute (if exists) with `InputProps={{readOnly: true}}`
|
|
642
|
-
- Remove px by all `theme.spacing`: `calc(100% - ${theme.spacing(4)}px)` => `calc(100% - ${theme.spacing(4)})`
|
|
643
|
-
- Replace `this.selectTab(e.target.parentNode.dataset.name, index)` => `this.selectTab(e.target.dataset.name, index)`
|
|
644
|
-
|
|
645
|
-
If you still have questions, try to find an answer [here](https://mui.com/guides/migration-v4/).
|
|
646
|
-
|
|
647
|
-
## Migration from adapter-react-v5@3.x to adapter-react-v5@4.x
|
|
648
|
-
- Look for getObjectView socket requests and replace `socket.getObjectView('startKey', 'endKey', 'instance')` to `socket.getObjectViewSystem('instance', 'startKey', 'endKey')`
|
|
649
|
-
- Look for calls of custom like
|
|
650
|
-
```
|
|
651
|
-
this.props.socket._socket.emit('getObjectView', 'system', 'custom', {startKey: '', endKey:'\u9999'}, (err, objs) => {
|
|
652
|
-
(objs?.rows || [])
|
|
653
|
-
.forEach(item => console.log(item.id, item.value));
|
|
654
|
-
});
|
|
655
|
-
```
|
|
656
|
-
to
|
|
657
|
-
```
|
|
658
|
-
socket.getObjectViewCustom('custom', 'state', 'startKey', 'endKey')
|
|
659
|
-
.then(objects => {
|
|
660
|
-
Object.keys(objects).forEach(obj => console.log(obj._id));
|
|
661
|
-
});
|
|
662
|
-
```
|
|
663
|
-
- Replace all `socket.log.error('text')` to `socket.log('text', 'error')`
|
|
664
|
-
- Add to App.js `import { AdminConnection } from '@iobroker/adapter-react-v5';` and `super(props, { Connection: AdminConnection });` if run in admin
|
|
665
|
-
|
|
666
|
-
## Migration from adapter-react-v5@4.x to adapter-react-v5@5.x
|
|
667
|
-
- `Theme` is renamed to IobTheme. It is an object with classes inside. `Theme` is still inside and it same as mui `createTheme`.
|
|
668
|
-
- adapter-react-v5 has all types exported. So you can use `import { type IobTheme, Theme } from '@iobroker/adapter-react-v5';` and `const theme: IobTheme = Theme('light');`
|
|
669
|
-
- Json-Config is now an external package and must be included as dependency separately.
|
|
670
|
-
- Use type `Translate` for `t(word: string, ...args: any[]) => string`
|
|
671
|
-
- All components for admin JsonConfig must be changed:
|
|
672
|
-
Before `adapter-react-v5@5.x`:
|
|
673
|
-
|
|
674
|
-
```
|
|
675
|
-
import { ConfigGeneric, I18n } from '@iobroker/adapter-react-v5';
|
|
676
|
-
class JsonComponent extends ConfigGeneric {
|
|
677
|
-
...
|
|
678
|
-
}
|
|
679
|
-
```
|
|
680
|
-
|
|
681
|
-
With `adapter-react-v5@5.x`:
|
|
682
|
-
|
|
683
|
-
```
|
|
684
|
-
import { I18n } from '@iobroker/adapter-react-v5';
|
|
685
|
-
import { ConfigGeneric } from '@iobroker/json-config';
|
|
686
|
-
class JsonComponent extends ConfigGeneric {
|
|
687
|
-
...
|
|
688
|
-
}
|
|
689
|
-
```
|
|
690
|
-
## Migration from v5 to v6
|
|
691
|
-
The main change is that the `withStyles` was removed. So you have to replace all `withStyles` with `sx` or `style` properties.
|
|
692
|
-
|
|
693
|
-
You can read more about sx [here](https://mui.com/system/getting-started/the-sx-prop/).
|
|
694
|
-
- Remove at start of the file `import { withStyles } from '@mui/styles';`
|
|
695
|
-
- Replace at the very end of the file `export default withStyles(styles)(MyComponent);` with `export default MyComponent;`
|
|
696
|
-
- Modify `const styles`:
|
|
697
|
-
Before:
|
|
698
|
-
```
|
|
699
|
-
const styles: Record<string, any> = (theme: IobTheme) => ({
|
|
700
|
-
dialog: {
|
|
701
|
-
height: `calc(100% - ${theme.mixins.toolbar.minHeight}px)`,
|
|
702
|
-
padding: theme.spacing(1),
|
|
703
|
-
margin: theme.spacing(2),
|
|
704
|
-
gap: 5,
|
|
705
|
-
borderRadius: 5,
|
|
706
|
-
marginLeft: 10, // marginTop, marginRight, marginBottom
|
|
707
|
-
paddingLeft: 10, // paddingTop, paddingRight, paddingBottom
|
|
708
|
-
},
|
|
709
|
-
...
|
|
710
|
-
});
|
|
711
|
-
```
|
|
712
|
-
|
|
713
|
-
After:
|
|
714
|
-
```
|
|
715
|
-
const styles: Record<string, any> = {
|
|
716
|
-
dialog: (theme: IobTheme) => ({
|
|
717
|
-
height: `calc(100% - ${theme => theme.mixins.toolbar.minHeight}px)`,
|
|
718
|
-
p: 1, // or 8px, padding is OK too
|
|
719
|
-
m: '16px', // or 2, margin is OK too
|
|
720
|
-
gap: '5px',
|
|
721
|
-
borderRadius: '5px',
|
|
722
|
-
ml: '10px', // mt, mr, mb, but marginLeft, marginRight, marginBottom is OK too
|
|
723
|
-
pl: '10px', // pt, pr, pb, but paddingTop, paddingRight, paddingBottom is OK too
|
|
724
|
-
}),
|
|
725
|
-
};
|
|
726
|
-
```
|
|
727
|
-
|
|
728
|
-
- Modify `className`:
|
|
729
|
-
Before: `<div className={this.props.classes.box}>`
|
|
730
|
-
|
|
731
|
-
After: `<Box sx={styles.box}>`
|
|
732
|
-
|
|
733
|
-
Before: `<span className={Utils.clsx(this.props.classes.box1, condition && this.props.classes.box2)}>`
|
|
734
|
-
|
|
735
|
-
After: `<Box component="span" sx={Utils.getStyle(this.props.theme, this.props.classes.box1, condition && this.props.classes.box2)}>`
|
|
736
|
-
Or if no one style is a function: `<Box component="div" sx={{ ...this.props.classes.box1, ...(condition ? this.props.classes.box2 : undefined) }}>`
|
|
737
|
-
|
|
738
|
-
Do not use `sx` if the style is not dynamic (not a function). Use `style` instead.
|
|
739
|
-
|
|
740
|
-
Be aware, that all paddings and margins are now in `theme.spacing(1)` format.
|
|
741
|
-
So you have to replace all `padding: 8` with `padding: 1` or with `padding: '8px'`.
|
|
742
|
-
|
|
743
|
-
The best practice is to replace `padding` with `p` and `margin` with `m`, so you will see immediately that it is a padding or margin for `sx` property.
|
|
744
|
-
|
|
745
|
-
- Modify `classes`:
|
|
746
|
-
Before: `<Dialog classes={{ scrollPaper: this.props.classes.dialog, paper: this.props.classes.paper }}>`
|
|
747
|
-
After: `<Dialog sx={{ '&.MuiDialog-scrollPaper': styles.dialog, '& .MuiDialog-paper': styles.paper }}>`,
|
|
748
|
-
|
|
749
|
-
Before: `<Dialog classes={{ scrollPaper: this.props.classes.dialog, paper: this.props.classes.paper }}>`
|
|
750
|
-
After: `<Dialog sx={{ '&.MuiDialog-scrollPaper': styles.dialog, '& .MuiDialog-paper': styles.paper }}>`
|
|
751
|
-
|
|
752
|
-
Before: `<ListItem classes={{ root: this.props.classes.listItem }} >`,
|
|
753
|
-
After: `<ListItem sx={{ '&.MuiListItem-root': styles.listItem }} >`
|
|
754
|
-
|
|
755
|
-
Before: `<Typography component="h2" variant="h6" classes={{ root: this.props.classes.typography }}>`,
|
|
756
|
-
After: `<Typography component="h2" variant="h6" sx={{ '&.MuiTypography-root': styles.typography }}>`
|
|
757
|
-
|
|
758
|
-
Before: `<Badge classes={{ 'badge': this.props.classes.expertBadge }}>`,
|
|
759
|
-
After: `<Badge sx={{ '& .MuiBadge-badge': styles.expertBadge }}>`
|
|
760
|
-
|
|
761
|
-
Before: `<Tab classes={{ selected: this.props.classes..selected }} />`,
|
|
762
|
-
After: `<Tab sx={{ '&.Mui-selected': styles.selected }} />`
|
|
763
|
-
|
|
764
|
-
Before: `<Tabs classes={{ indicator: this.props.classes.indicator }} />`,
|
|
765
|
-
After: `<Tabs sx={{ '& .MuiTabs-indicator': styles.indicator }} />`
|
|
766
|
-
|
|
767
|
-
Before: `<Tooltip title={this.props.t('ra_Refresh tree')} classes={{ popper: this.props.classes.tooltip }}>`,
|
|
768
|
-
After: `<Tooltip title={this.props.t('ra_Refresh tree')} componentsProps={{ popper: { sx: { pointerEvents: 'none' } } }}>`,
|
|
769
|
-
Or: `<Tooltip title={this.props.t('ra_Refresh tree')} componentsProps={{ popper: { sx: styles.tooltip } }}>`
|
|
770
|
-
|
|
771
|
-
Before. `<AccordionSummary classes={{ root: this.props.classes.rootStyle, content: this.props.classes.content }}>`,
|
|
772
|
-
After. `<AccordionSummary sx={{ '&.MuiAccordionSummary-root': styles.rootStyle, '& .MuiAccordionSummary-content': styles.content }}>`
|
|
773
|
-
|
|
774
|
-
Before. `<Drawer classes={{ paper: this.props.classes.paperStyle }}>`,
|
|
775
|
-
After. `<Drawer sx={{ '& .MuiDrawer-paper': styles.paperStyle }}>`
|
|
776
|
-
|
|
777
|
-
<!--
|
|
778
|
-
Placeholder for the next version (at the beginning of the line):
|
|
779
|
-
### **WORK IN PROGRESS**
|
|
780
|
-
-->
|
|
781
|
-
|
|
1
|
+
# Help ReactJS classes for adapter config
|
|
2
|
+
You can find demo on https://github.com/ioBroker/adapter-react-demo
|
|
3
|
+
|
|
4
|
+
## Getting started
|
|
5
|
+
If you want to create the configuration page with ReactJS:
|
|
6
|
+
1. Create github repo for adapter.
|
|
7
|
+
2. execute `npx create-react-app src` . It will take a while.
|
|
8
|
+
3. `cd src`
|
|
9
|
+
4. Modify package.json file in src directory:
|
|
10
|
+
- Change `name` from `src` to `ADAPTERNAME-admin` (Of course replace `ADAPTERNAME` with yours)
|
|
11
|
+
- Add to devDependencies:
|
|
12
|
+
```
|
|
13
|
+
"@iobroker/adapter-react": "^4.0.10",
|
|
14
|
+
```
|
|
15
|
+
Versions can be higher.
|
|
16
|
+
So your src/package.json should look like:
|
|
17
|
+
```
|
|
18
|
+
{
|
|
19
|
+
"name": "ADAPTERNAME-admin",
|
|
20
|
+
"version": "0.1.0",
|
|
21
|
+
"private": true,
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"react": "^18.2.0",
|
|
24
|
+
"react-dom": "^18.2.0",
|
|
25
|
+
"react-icons": "^4.6.0",
|
|
26
|
+
"react-scripts": "^5.0.1",
|
|
27
|
+
"@iobroker/adapter-react-v5": "^3.2.7",
|
|
28
|
+
"del": "^6.1.1",
|
|
29
|
+
"gulp": "^4.0.2"
|
|
30
|
+
},
|
|
31
|
+
"scripts": {
|
|
32
|
+
"start": "react-scripts start",
|
|
33
|
+
"build": "react-scripts build",
|
|
34
|
+
"test": "react-scripts test",
|
|
35
|
+
"eject": "react-scripts eject"
|
|
36
|
+
},
|
|
37
|
+
"eslintConfig": {
|
|
38
|
+
"extends": "react-app"
|
|
39
|
+
},
|
|
40
|
+
"homepage": ".",
|
|
41
|
+
"browserslist": [
|
|
42
|
+
">0.2%",
|
|
43
|
+
"not dead",
|
|
44
|
+
"not ie <= 11",
|
|
45
|
+
"not op_mini all"
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
5. Call in `src`: `npm install`
|
|
50
|
+
6. Copy tasks.js into `src`: `cp node_modules/@iobroker/adapter-react/tasks.js tasks.js`
|
|
51
|
+
7. Start your dummy application `npm run start` for developing or build with `npm run build` and
|
|
52
|
+
copy files in `build` directory to `www` or to `admin`. In the admin you must rename `index.html` to `index_m.html`.
|
|
53
|
+
8. You can do that with `gulp` tasks: `gulp build`, `gulp copy`, `gulp renameIndex` or `gulp renameTab`
|
|
54
|
+
|
|
55
|
+
## Development
|
|
56
|
+
1. Add `socket.io` to `public/index.html`.
|
|
57
|
+
After
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
insert
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
<script>
|
|
67
|
+
var script = document.createElement('script');
|
|
68
|
+
window.registerSocketOnLoad = function (cb) {
|
|
69
|
+
window.socketLoadedHandler = cb;
|
|
70
|
+
};
|
|
71
|
+
const parts = (window.location.search || '').replace(/^\?/, '').split('&');
|
|
72
|
+
const query = {};
|
|
73
|
+
parts.forEach(item => {
|
|
74
|
+
const [name, val] = item.split('=');
|
|
75
|
+
query[decodeURIComponent(name)] = val !== undefined ? decodeURIComponent(val) : true;
|
|
76
|
+
});
|
|
77
|
+
script.onload = function () { typeof window.socketLoadedHandler === 'function' && window.socketLoadedHandler(); };
|
|
78
|
+
script.src = window.location.port === '3000' ? window.location.protocol + '//' + (query.host || window.location.hostname) + ':' + (query.port || 8081) + '/lib/js/socket.io.js' : '%PUBLIC_URL%/../../lib/js/socket.io.js';
|
|
79
|
+
|
|
80
|
+
document.head.appendChild(script);
|
|
81
|
+
</script>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
3. Add to App.js constructor initialization for I18n:
|
|
85
|
+
```
|
|
86
|
+
class App extends GenericApp {
|
|
87
|
+
constructor(props) {
|
|
88
|
+
const extendedProps = {...props};
|
|
89
|
+
extendedProps.encryptedFields = ['pass']; // this parameter will be encrypted and decrypted automatically
|
|
90
|
+
extendedProps.translations = {
|
|
91
|
+
'en': require('./i18n/en'),
|
|
92
|
+
'de': require('./i18n/de'),
|
|
93
|
+
'ru': require('./i18n/ru'),
|
|
94
|
+
'pt': require('./i18n/pt'),
|
|
95
|
+
'nl': require('./i18n/nl'),
|
|
96
|
+
'fr': require('./i18n/fr'),
|
|
97
|
+
'it': require('./i18n/it'),
|
|
98
|
+
'es': require('./i18n/es'),
|
|
99
|
+
'pl': require('./i18n/pl'),
|
|
100
|
+
'uk': require('./i18n/uk'),
|
|
101
|
+
'zh-cn': require('./i18n/zh-cn'),
|
|
102
|
+
};
|
|
103
|
+
// get actual admin port
|
|
104
|
+
extendedProps.socket = {port: parseInt(window.location.port, 10)};
|
|
105
|
+
|
|
106
|
+
// Only if close, save buttons are not required at the bottom (e.g. if admin tab)
|
|
107
|
+
// extendedProps.bottomButtons = false;
|
|
108
|
+
|
|
109
|
+
// only for debug purposes
|
|
110
|
+
if (extendedProps.socket.port === 3000) {
|
|
111
|
+
extendedProps.socket.port = 8081;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// allow to manage GenericApp the sentry initialisation or do not set the sentryDSN if no sentry available
|
|
115
|
+
extendedProps.sentryDSN = 'https://yyy@sentry.iobroker.net/xx';
|
|
116
|
+
|
|
117
|
+
super(extendedProps);
|
|
118
|
+
}
|
|
119
|
+
...
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
4. Replace `index.js` with the following code to support themes:
|
|
124
|
+
```
|
|
125
|
+
import React from 'react';
|
|
126
|
+
import ReactDOM from 'react-dom';
|
|
127
|
+
import { MuiThemeProvider} from '@material-ui/core/styles';
|
|
128
|
+
import * as serviceWorker from './serviceWorker';
|
|
129
|
+
|
|
130
|
+
import './index.css';
|
|
131
|
+
import App from './App';
|
|
132
|
+
import { version } from '../package.json';
|
|
133
|
+
|
|
134
|
+
import theme from '@iobroker/adapter-react/Theme';
|
|
135
|
+
|
|
136
|
+
console.log('iobroker.scenes@' + version);
|
|
137
|
+
let themeName = window.localStorage ? window.localStorage.getItem('App.theme') || 'light' : 'light';
|
|
138
|
+
|
|
139
|
+
function build() {
|
|
140
|
+
return ReactDOM.render(<MuiThemeProvider theme={ theme(themeName) }>
|
|
141
|
+
<App onThemeChange={_theme => {
|
|
142
|
+
themeName = _theme;
|
|
143
|
+
build();
|
|
144
|
+
}}/>
|
|
145
|
+
</MuiThemeProvider>, document.getElementById('root'));
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
build();
|
|
149
|
+
|
|
150
|
+
// If you want your app to work offline and load faster, you can change
|
|
151
|
+
// unregister() to register() below. Note this comes with some pitfalls.
|
|
152
|
+
// Learn more about service workers: http://bit.ly/CRA-PWA
|
|
153
|
+
serviceWorker.unregister();
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
5. Add to App.js encoding and decoding of values:
|
|
157
|
+
```
|
|
158
|
+
class App extend GenericApp {
|
|
159
|
+
...
|
|
160
|
+
onPrepareLoad(settings) {
|
|
161
|
+
settings.pass = this.decode(settings.pass);
|
|
162
|
+
}
|
|
163
|
+
onPrepareSave(settings) {
|
|
164
|
+
settings.pass = this.encode(settings.pass);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
6. The optional step is to validate the data to be saved:
|
|
170
|
+
```
|
|
171
|
+
onPrepareSave(settings) {
|
|
172
|
+
super.onPrepareSave(settings);
|
|
173
|
+
if (DATA_INVALID) {
|
|
174
|
+
return false; // configuration will not be saved
|
|
175
|
+
} else {
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## Components
|
|
182
|
+
|
|
183
|
+
### Connection.tsx
|
|
184
|
+
This is a non-react class to provide the communication for socket connection with the server.
|
|
185
|
+
|
|
186
|
+
### GenericApp.tsx
|
|
187
|
+
|
|
188
|
+
### i18n.ts
|
|
189
|
+
|
|
190
|
+
### Theme.tsx
|
|
191
|
+
|
|
192
|
+
### Dialogs
|
|
193
|
+
Some dialogs are predefined and could be used out of the box.
|
|
194
|
+
|
|
195
|
+
#### Confirm.tsx
|
|
196
|
+
<!-- TODO: Provide screenshot here -->
|
|
197
|
+
|
|
198
|
+
Usage:
|
|
199
|
+
```
|
|
200
|
+
import React from 'react';
|
|
201
|
+
import ConfirmDialog from '@iobroker/adapter-react/Dialogs/Confirm'
|
|
202
|
+
import I18n from '@iobroker/adapter-react/i18n';
|
|
203
|
+
|
|
204
|
+
class ExportImportDialog extends React.Component {
|
|
205
|
+
constructor(props) {
|
|
206
|
+
super(props);
|
|
207
|
+
|
|
208
|
+
this.state = {
|
|
209
|
+
confirmDialog: false,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
renderConfirmDialog() {
|
|
214
|
+
if (!this.state.confirmDialog) {
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
return <ConfirmDialog
|
|
218
|
+
title={ I18n.t('Scene will be overwritten.') }
|
|
219
|
+
text={ I18n.t('All data will be lost. Confirm?') }
|
|
220
|
+
ok={ I18n.t('Yes') }
|
|
221
|
+
cancel={ I18n.t('Cancel') }
|
|
222
|
+
suppressQuestionMinutes={5}
|
|
223
|
+
dialogName="myConfirmDialogThatCouldBeSuppressed"
|
|
224
|
+
suppressText={I18n.t('Suppress question for next %s minutes', 5)}
|
|
225
|
+
onClose={isYes => {
|
|
226
|
+
this.setState({ confirmDialog: false} );
|
|
227
|
+
}}
|
|
228
|
+
/>;
|
|
229
|
+
}
|
|
230
|
+
render() {
|
|
231
|
+
return <div>
|
|
232
|
+
<Button onClick={ () => this.setState({confirmDialog: true}) }>Click</Button>
|
|
233
|
+
{ this.renderConfirmDialog() }
|
|
234
|
+
</div>
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export default ExportImportDialog;
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
#### Error.tsx
|
|
242
|
+
<!-- TODO: Provide screenshot here -->
|
|
243
|
+
|
|
244
|
+
#### Message.tsx
|
|
245
|
+
<!-- TODO: Provide screenshot here -->
|
|
246
|
+
```
|
|
247
|
+
renderMessage() {
|
|
248
|
+
if (this.state.showMessage) {
|
|
249
|
+
return <Message
|
|
250
|
+
text={this.state.showMessage}
|
|
251
|
+
onClose={() => this.setState({showMessage: false})}
|
|
252
|
+
/>;
|
|
253
|
+
} else {
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
#### SelectID.tsx
|
|
260
|
+

|
|
261
|
+
```
|
|
262
|
+
import DialogSelectID from '@iobroker/adapter-react/Dialogs/SelectID';
|
|
263
|
+
|
|
264
|
+
class MyComponent extends Component {
|
|
265
|
+
constructor(props) {
|
|
266
|
+
super(props);
|
|
267
|
+
this.state = {
|
|
268
|
+
showSelectId: false,
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
renderSelectIdDialog() {
|
|
273
|
+
if (this.state.showSelectId) {
|
|
274
|
+
return <DialogSelectID
|
|
275
|
+
key="tableSelect"
|
|
276
|
+
imagePrefix="../.."
|
|
277
|
+
dialogName={this.props.adapterName}
|
|
278
|
+
themeType={this.props.themeType}
|
|
279
|
+
socket={this.props.socket}
|
|
280
|
+
statesOnly={true}
|
|
281
|
+
selected={this.state.selectIdValue}
|
|
282
|
+
onClose={() => this.setState({showSelectId: false})}
|
|
283
|
+
onOk={(selected, name) => {
|
|
284
|
+
this.setState({showSelectId: false, selectIdValue: selected});
|
|
285
|
+
}}
|
|
286
|
+
/>;
|
|
287
|
+
} else {
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
render() {
|
|
292
|
+
return renderSelectIdDialog();
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
#### Cron
|
|
298
|
+
Include `"react-text-mask": "^5.4.3",` in package.json.
|
|
299
|
+
|
|
300
|
+
<!-- TODO: Provide screenshot here -->
|
|
301
|
+
|
|
302
|
+
```
|
|
303
|
+
function renderCron() {
|
|
304
|
+
if (!showCron) {
|
|
305
|
+
return null;
|
|
306
|
+
} else {
|
|
307
|
+
return <DialogCron
|
|
308
|
+
key="dialogCron1"
|
|
309
|
+
cron={this.state.cronValue || '* * * * *'}
|
|
310
|
+
onClose={() => this.setState({ showCron: false })}
|
|
311
|
+
onOk={cronValue => {
|
|
312
|
+
this.setState({ cronValue })
|
|
313
|
+
}}
|
|
314
|
+
/>;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### Components
|
|
320
|
+
|
|
321
|
+
#### Utils.tsx
|
|
322
|
+
##### getObjectNameFromObj
|
|
323
|
+
`getObjectNameFromObj(obj, settings, options, isDesc)`
|
|
324
|
+
|
|
325
|
+
Get object name from a single object.
|
|
326
|
+
|
|
327
|
+
Usage: `Utils.getObjectNameFromObj(this.objects[id], null, {language: I18n.getLanguage()})`
|
|
328
|
+
|
|
329
|
+
##### getObjectIcon
|
|
330
|
+
`getObjectIcon(id, obj)`
|
|
331
|
+
|
|
332
|
+
Get icon from the object.
|
|
333
|
+
|
|
334
|
+
Usage:
|
|
335
|
+
```
|
|
336
|
+
const icon = Utils.getObjectIcon(id, this.objects[id]);
|
|
337
|
+
return (<img src={icon}/>);
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
##### isUseBright
|
|
341
|
+
`isUseBright(color, defaultValue)`
|
|
342
|
+
|
|
343
|
+
Usage: `
|
|
344
|
+
|
|
345
|
+
#### Loader.tsx
|
|
346
|
+

|
|
347
|
+
|
|
348
|
+
```
|
|
349
|
+
render() {
|
|
350
|
+
if (!this.state.loaded) {
|
|
351
|
+
return <MuiThemeProvider theme={this.state.theme}>
|
|
352
|
+
<Loader theme={this.state.themeType}/>
|
|
353
|
+
</MuiThemeProvider>;
|
|
354
|
+
}
|
|
355
|
+
// render loaded data
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
#### Logo.tsx
|
|
361
|
+

|
|
362
|
+
|
|
363
|
+
```
|
|
364
|
+
render() {
|
|
365
|
+
return <form className={this.props.classes.tab}>
|
|
366
|
+
<Logo
|
|
367
|
+
instance={this.props.instance}
|
|
368
|
+
common={this.props.common}
|
|
369
|
+
native={this.props.native}
|
|
370
|
+
onError={text => this.setState({errorText: text})}
|
|
371
|
+
onLoad={this.props.onLoad}
|
|
372
|
+
/>
|
|
373
|
+
...
|
|
374
|
+
</form>;
|
|
375
|
+
}
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
#### Router.tsx
|
|
379
|
+
|
|
380
|
+
#### ObjectBrowser.js
|
|
381
|
+
It is better to use `Dialog/SelectID`, but if you want:
|
|
382
|
+
|
|
383
|
+

|
|
384
|
+
|
|
385
|
+
```
|
|
386
|
+
<ObjectBrowser
|
|
387
|
+
foldersFirst={this.props.foldersFirst}
|
|
388
|
+
imagePrefix={this.props.imagePrefix || this.props.prefix} // prefix is for back compatibility
|
|
389
|
+
defaultFilters={this.filters}
|
|
390
|
+
dialogName={this.dialogName}
|
|
391
|
+
showExpertButton={this.props.showExpertButton !== undefined ? this.props.showExpertButton : true}
|
|
392
|
+
style={{ width: '100%', height: '100%' }}
|
|
393
|
+
columns={this.props.columns || ['name', 'type', 'role', 'room', 'func', 'val']}
|
|
394
|
+
types={this.props.types || ['state']}
|
|
395
|
+
t={I18n.t}
|
|
396
|
+
lang={this.props.lang || I18n.getLanguage()}
|
|
397
|
+
socket={this.props.socket}
|
|
398
|
+
selected={this.state.selected}
|
|
399
|
+
multiSelect={this.props.multiSelect}
|
|
400
|
+
notEditable={this.props.notEditable === undefined ? true : this.props.notEditable}
|
|
401
|
+
name={this.state.name}
|
|
402
|
+
themeName={this.props.themeName}
|
|
403
|
+
themeType={this.props.themeType}
|
|
404
|
+
customFilter={this.props.customFilter}
|
|
405
|
+
onFilterChanged={filterConfig => {
|
|
406
|
+
this.filters = filterConfig;
|
|
407
|
+
window.localStorage.setItem(this.dialogName, JSON.stringify(filterConfig));
|
|
408
|
+
}}
|
|
409
|
+
onSelect={(selected, name, isDouble) => {
|
|
410
|
+
if (JSON.stringify(selected) !== JSON.stringify(this.state.selected)) {
|
|
411
|
+
this.setState({selected, name}, () =>
|
|
412
|
+
isDouble && this.handleOk());
|
|
413
|
+
} else if (isDouble) {
|
|
414
|
+
this.handleOk();
|
|
415
|
+
}
|
|
416
|
+
}}
|
|
417
|
+
/>
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
#### TreeTable.ts
|
|
421
|
+

|
|
422
|
+
|
|
423
|
+
```
|
|
424
|
+
// STYLES
|
|
425
|
+
const styles = theme => ({
|
|
426
|
+
tableDiv: {
|
|
427
|
+
width: '100%',
|
|
428
|
+
overflow: 'hidden',
|
|
429
|
+
height: 'calc(100% - 48px)',
|
|
430
|
+
},
|
|
431
|
+
});
|
|
432
|
+
class MyComponent extends Component {
|
|
433
|
+
constructor(props) {
|
|
434
|
+
super(props);
|
|
435
|
+
|
|
436
|
+
this.state = {
|
|
437
|
+
data: [
|
|
438
|
+
{
|
|
439
|
+
id: 'UniqueID1' // required
|
|
440
|
+
fieldIdInData: 'Name1',
|
|
441
|
+
myType: 'number',
|
|
442
|
+
},
|
|
443
|
+
{
|
|
444
|
+
id: 'UniqueID2' // required
|
|
445
|
+
fieldIdInData: 'Name12',
|
|
446
|
+
myType: 'string',
|
|
447
|
+
},
|
|
448
|
+
],
|
|
449
|
+
};
|
|
450
|
+
|
|
451
|
+
this.columns = [
|
|
452
|
+
{
|
|
453
|
+
title: 'Name of field', // required, else it will be "field"
|
|
454
|
+
field: 'fieldIdInData', // required
|
|
455
|
+
editable: false, // or true [default - true]
|
|
456
|
+
cellStyle: { // CSS style - // optional
|
|
457
|
+
maxWidth: '12rem',
|
|
458
|
+
overflow: 'hidden',
|
|
459
|
+
wordBreak: 'break-word',
|
|
460
|
+
},
|
|
461
|
+
lookup: { // optional => edit will be automatically "SELECT"
|
|
462
|
+
'value1': 'text1',
|
|
463
|
+
'value2': 'text2',
|
|
464
|
+
}
|
|
465
|
+
},
|
|
466
|
+
{
|
|
467
|
+
title: 'Type', // required, else it will be "field"
|
|
468
|
+
field: 'myType', // required
|
|
469
|
+
editable: true, // or true [default - true]
|
|
470
|
+
lookup: { // optional => edit will be automatically "SELECT"
|
|
471
|
+
'number': 'Number',
|
|
472
|
+
'string': 'String',
|
|
473
|
+
'boolean': 'Boolean',
|
|
474
|
+
},
|
|
475
|
+
type: 'number/string/color/oid/icon/boolean', // oid=ObjectID,icon=base64-icon
|
|
476
|
+
editComponent: props =>
|
|
477
|
+
<div>Prefix{ <br/>
|
|
478
|
+
<textarea
|
|
479
|
+
rows={4}
|
|
480
|
+
style={{width: '100%', resize: 'vertical'}}
|
|
481
|
+
value={props.value}
|
|
482
|
+
onChange={e => props.onChange(e.target.value)}
|
|
483
|
+
/>
|
|
484
|
+
Suffix
|
|
485
|
+
</div>,
|
|
486
|
+
},
|
|
487
|
+
];
|
|
488
|
+
}
|
|
489
|
+
// renderTable
|
|
490
|
+
render() {
|
|
491
|
+
return <div className={this.props.classes.tableDiv}>
|
|
492
|
+
<TreeTable
|
|
493
|
+
columns={this.columns}
|
|
494
|
+
data={this.state.data}
|
|
495
|
+
onUpdate={(newData, oldData) => {
|
|
496
|
+
const data = JSON.parse(JSON.stringify(this.state.data));
|
|
497
|
+
|
|
498
|
+
// Added new line
|
|
499
|
+
if (newData === true) {
|
|
500
|
+
// find unique ID
|
|
501
|
+
let i = 1;
|
|
502
|
+
let id = 'line_' + i;
|
|
503
|
+
|
|
504
|
+
// eslint-disable-next-line
|
|
505
|
+
while(this.state.data.find(item => item.id === id)) {
|
|
506
|
+
i++;
|
|
507
|
+
id = 'line_' + i;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
data.push({
|
|
511
|
+
id,
|
|
512
|
+
name: I18n.t('New resource') + '_' + i,
|
|
513
|
+
color: '',
|
|
514
|
+
icon: '',
|
|
515
|
+
unit: '',
|
|
516
|
+
price: 0,
|
|
517
|
+
});
|
|
518
|
+
} else {
|
|
519
|
+
// existing line was modifed
|
|
520
|
+
const pos = this.state.data.indexOf(oldData);
|
|
521
|
+
if (pos !== -1) {
|
|
522
|
+
Object.keys(newData).forEach(attr => data[pos][attr] = newData[attr]);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
this.setState({data});
|
|
527
|
+
}}
|
|
528
|
+
onDelete={oldData => {
|
|
529
|
+
console.log('Delete: ' + JSON.stringify(oldData));
|
|
530
|
+
const pos = this.state.data.indexOf(oldData);
|
|
531
|
+
if (pos !== -1) {
|
|
532
|
+
const data = JSON.parse(JSON.stringify(this.state.data));
|
|
533
|
+
data.splice(pos, 1);
|
|
534
|
+
this.setState({data});
|
|
535
|
+
}
|
|
536
|
+
}}
|
|
537
|
+
/>
|
|
538
|
+
</div>;
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
#### Toast
|
|
544
|
+
<!-- TODO: Provide screenshot here -->
|
|
545
|
+
|
|
546
|
+
Toast is not a part of `adapter-react` but it is an example how to use toast in application:
|
|
547
|
+
|
|
548
|
+
```
|
|
549
|
+
import Snackbar from '@material-ui/core/Snackbar';
|
|
550
|
+
|
|
551
|
+
class MyComponent {
|
|
552
|
+
constructor(props) {
|
|
553
|
+
super(props);
|
|
554
|
+
this.state = {
|
|
555
|
+
// ....
|
|
556
|
+
toast: '',
|
|
557
|
+
};
|
|
558
|
+
}
|
|
559
|
+
// ...
|
|
560
|
+
renderToast() {
|
|
561
|
+
if (!this.state.toast) {
|
|
562
|
+
return null;
|
|
563
|
+
}
|
|
564
|
+
return <Snackbar
|
|
565
|
+
anchorOrigin={{
|
|
566
|
+
vertical: 'bottom',
|
|
567
|
+
horizontal: 'left',
|
|
568
|
+
}}
|
|
569
|
+
open={true}
|
|
570
|
+
autoHideDuration={6000}
|
|
571
|
+
onClose={() => this.setState({toast: ''})}
|
|
572
|
+
ContentProps={{'aria-describedby': 'message-id'}}
|
|
573
|
+
message={<span id="message-id">{this.state.toast}</span>}
|
|
574
|
+
action={[
|
|
575
|
+
<IconButton
|
|
576
|
+
key="close"
|
|
577
|
+
aria-label="Close"
|
|
578
|
+
color="inherit"
|
|
579
|
+
className={this.props.classes.close}
|
|
580
|
+
onClick={() => this.setState({toast: ''})}
|
|
581
|
+
>
|
|
582
|
+
<IconClose />
|
|
583
|
+
</IconButton>,
|
|
584
|
+
]}
|
|
585
|
+
/>;
|
|
586
|
+
}
|
|
587
|
+
render() {
|
|
588
|
+
return <div>
|
|
589
|
+
{this.renderToast()}
|
|
590
|
+
</div>;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
## List of adapters that use adapter-react
|
|
596
|
+
- Admin
|
|
597
|
+
- Backitup
|
|
598
|
+
- iot
|
|
599
|
+
- echarts
|
|
600
|
+
- text2command
|
|
601
|
+
- scenes
|
|
602
|
+
- javascript
|
|
603
|
+
- devices
|
|
604
|
+
- eventlist
|
|
605
|
+
- cameras
|
|
606
|
+
- web
|
|
607
|
+
- vis-2
|
|
608
|
+
- vis-2-widgets-xxx
|
|
609
|
+
- fullcalendar
|
|
610
|
+
- openweathermap
|
|
611
|
+
|
|
612
|
+
## Usability
|
|
613
|
+
In dialogs, the OK button is first (on the left) and the cancel button is last (on the right)
|
|
614
|
+
|
|
615
|
+
## Used icons
|
|
616
|
+
This project uses icons from [Flaticon](https://www.flaticon.com/).
|
|
617
|
+
|
|
618
|
+
ioBroker GmbH has a valid license for all the used icons.
|
|
619
|
+
The icons may not be reused in other projects without the proper flaticon license or flaticon subscription.
|
|
620
|
+
|
|
621
|
+
## Migration from adapter-react to adapter-react-v5
|
|
622
|
+
### In src/package.json => dependencies
|
|
623
|
+
- `"@iobroker/adapter-react": "^2.0.22",` => `"@iobroker/adapter-react-v5": "^3.1.34",`
|
|
624
|
+
- `"@material-ui/core": "^4.12.3",` => `"@mui/material": "^5.10.9",`
|
|
625
|
+
- `"@material-ui/icons": "^4.11.2",` => `"@mui/icons-material": "^5.10.9",`
|
|
626
|
+
- Add `"@mui/styles": "^5.10.9",`
|
|
627
|
+
- Add `"babel-eslint": "^10.1.0",`
|
|
628
|
+
|
|
629
|
+
### In Source files
|
|
630
|
+
- All `@iobroker/adapter-react/...` => `@iobroker/adapter-react-v5/...`
|
|
631
|
+
- All `@material-ui/icons/...` => `@mui/icons-material/...`
|
|
632
|
+
- Change `import { withStyles } from '@material-ui/core/styles';` => `import { withStyles } from '@mui/styles';`
|
|
633
|
+
- Change `import { makeStyles } from '@mui/material/styles';` => `import { makeStyles } from '@mui/styles';`
|
|
634
|
+
- Change `import withWidth from '@material-ui/core/withWidth';` => `import { withWidth } from '@iobroker/adapter-react-v5';`
|
|
635
|
+
- All `@material-ui/core...` => `@mui/material...`
|
|
636
|
+
- Change `import { MuiThemeProvider } from '@material-ui/core/styles';` => `import { ThemeProvider, StyledEngineProvider } from '@mui/material/styles';`
|
|
637
|
+
- Change all `<MuiThemeProvider theme={this.state.theme}>` to `<StyledEngineProvider injectFirst><ThemeProvider theme={this.state.theme}>`
|
|
638
|
+
- Rename in styles `theme.palette.type` => `theme.palette.mode`
|
|
639
|
+
- Add to all `TextField`, `Select`, `FormControl` the property `variant="standard"`
|
|
640
|
+
- Add to all `Button` that do not have `color` property: `color="grey"`
|
|
641
|
+
- Replace by `TextField` the `readOnly` attribute (if exists) with `InputProps={{readOnly: true}}`
|
|
642
|
+
- Remove px by all `theme.spacing`: `calc(100% - ${theme.spacing(4)}px)` => `calc(100% - ${theme.spacing(4)})`
|
|
643
|
+
- Replace `this.selectTab(e.target.parentNode.dataset.name, index)` => `this.selectTab(e.target.dataset.name, index)`
|
|
644
|
+
|
|
645
|
+
If you still have questions, try to find an answer [here](https://mui.com/guides/migration-v4/).
|
|
646
|
+
|
|
647
|
+
## Migration from adapter-react-v5@3.x to adapter-react-v5@4.x
|
|
648
|
+
- Look for getObjectView socket requests and replace `socket.getObjectView('startKey', 'endKey', 'instance')` to `socket.getObjectViewSystem('instance', 'startKey', 'endKey')`
|
|
649
|
+
- Look for calls of custom like
|
|
650
|
+
```
|
|
651
|
+
this.props.socket._socket.emit('getObjectView', 'system', 'custom', {startKey: '', endKey:'\u9999'}, (err, objs) => {
|
|
652
|
+
(objs?.rows || [])
|
|
653
|
+
.forEach(item => console.log(item.id, item.value));
|
|
654
|
+
});
|
|
655
|
+
```
|
|
656
|
+
to
|
|
657
|
+
```
|
|
658
|
+
socket.getObjectViewCustom('custom', 'state', 'startKey', 'endKey')
|
|
659
|
+
.then(objects => {
|
|
660
|
+
Object.keys(objects).forEach(obj => console.log(obj._id));
|
|
661
|
+
});
|
|
662
|
+
```
|
|
663
|
+
- Replace all `socket.log.error('text')` to `socket.log('text', 'error')`
|
|
664
|
+
- Add to App.js `import { AdminConnection } from '@iobroker/adapter-react-v5';` and `super(props, { Connection: AdminConnection });` if run in admin
|
|
665
|
+
|
|
666
|
+
## Migration from adapter-react-v5@4.x to adapter-react-v5@5.x
|
|
667
|
+
- `Theme` is renamed to IobTheme. It is an object with classes inside. `Theme` is still inside and it same as mui `createTheme`.
|
|
668
|
+
- adapter-react-v5 has all types exported. So you can use `import { type IobTheme, Theme } from '@iobroker/adapter-react-v5';` and `const theme: IobTheme = Theme('light');`
|
|
669
|
+
- Json-Config is now an external package and must be included as dependency separately.
|
|
670
|
+
- Use type `Translate` for `t(word: string, ...args: any[]) => string`
|
|
671
|
+
- All components for admin JsonConfig must be changed:
|
|
672
|
+
Before `adapter-react-v5@5.x`:
|
|
673
|
+
|
|
674
|
+
```
|
|
675
|
+
import { ConfigGeneric, I18n } from '@iobroker/adapter-react-v5';
|
|
676
|
+
class JsonComponent extends ConfigGeneric {
|
|
677
|
+
...
|
|
678
|
+
}
|
|
679
|
+
```
|
|
680
|
+
|
|
681
|
+
With `adapter-react-v5@5.x`:
|
|
682
|
+
|
|
683
|
+
```
|
|
684
|
+
import { I18n } from '@iobroker/adapter-react-v5';
|
|
685
|
+
import { ConfigGeneric } from '@iobroker/json-config';
|
|
686
|
+
class JsonComponent extends ConfigGeneric {
|
|
687
|
+
...
|
|
688
|
+
}
|
|
689
|
+
```
|
|
690
|
+
## Migration from v5 to v6
|
|
691
|
+
The main change is that the `withStyles` was removed. So you have to replace all `withStyles` with `sx` or `style` properties.
|
|
692
|
+
|
|
693
|
+
You can read more about sx [here](https://mui.com/system/getting-started/the-sx-prop/).
|
|
694
|
+
- Remove at start of the file `import { withStyles } from '@mui/styles';`
|
|
695
|
+
- Replace it at the very end of the file `export default withStyles(styles)(MyComponent);` with `export default MyComponent;`
|
|
696
|
+
- Modify `const styles`:
|
|
697
|
+
Before:
|
|
698
|
+
```
|
|
699
|
+
const styles: Record<string, any> = (theme: IobTheme) => ({
|
|
700
|
+
dialog: {
|
|
701
|
+
height: `calc(100% - ${theme.mixins.toolbar.minHeight}px)`,
|
|
702
|
+
padding: theme.spacing(1),
|
|
703
|
+
margin: theme.spacing(2),
|
|
704
|
+
gap: 5,
|
|
705
|
+
borderRadius: 5,
|
|
706
|
+
marginLeft: 10, // marginTop, marginRight, marginBottom
|
|
707
|
+
paddingLeft: 10, // paddingTop, paddingRight, paddingBottom
|
|
708
|
+
},
|
|
709
|
+
...
|
|
710
|
+
});
|
|
711
|
+
```
|
|
712
|
+
|
|
713
|
+
After:
|
|
714
|
+
```
|
|
715
|
+
const styles: Record<string, any> = {
|
|
716
|
+
dialog: (theme: IobTheme) => ({
|
|
717
|
+
height: `calc(100% - ${theme => theme.mixins.toolbar.minHeight}px)`,
|
|
718
|
+
p: 1, // or 8px, padding is OK too
|
|
719
|
+
m: '16px', // or 2, margin is OK too
|
|
720
|
+
gap: '5px',
|
|
721
|
+
borderRadius: '5px',
|
|
722
|
+
ml: '10px', // mt, mr, mb, but marginLeft, marginRight, marginBottom is OK too
|
|
723
|
+
pl: '10px', // pt, pr, pb, but paddingTop, paddingRight, paddingBottom is OK too
|
|
724
|
+
}),
|
|
725
|
+
};
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
- Modify `className`:
|
|
729
|
+
Before: `<div className={this.props.classes.box}>`
|
|
730
|
+
|
|
731
|
+
After: `<Box sx={styles.box}>`
|
|
732
|
+
|
|
733
|
+
Before: `<span className={Utils.clsx(this.props.classes.box1, condition && this.props.classes.box2)}>`
|
|
734
|
+
|
|
735
|
+
After: `<Box component="span" sx={Utils.getStyle(this.props.theme, this.props.classes.box1, condition && this.props.classes.box2)}>`
|
|
736
|
+
Or if no one style is a function: `<Box component="div" sx={{ ...this.props.classes.box1, ...(condition ? this.props.classes.box2 : undefined) }}>`
|
|
737
|
+
|
|
738
|
+
Do not use `sx` if the style is not dynamic (not a function). Use `style` instead.
|
|
739
|
+
|
|
740
|
+
Be aware, that all paddings and margins are now in `theme.spacing(1)` format.
|
|
741
|
+
So you have to replace all `padding: 8` with `padding: 1` or with `padding: '8px'`.
|
|
742
|
+
|
|
743
|
+
The best practice is to replace `padding` with `p` and `margin` with `m`, so you will see immediately that it is a padding or margin for `sx` property.
|
|
744
|
+
|
|
745
|
+
- Modify `classes`:
|
|
746
|
+
Before: `<Dialog classes={{ scrollPaper: this.props.classes.dialog, paper: this.props.classes.paper }}>`
|
|
747
|
+
After: `<Dialog sx={{ '&.MuiDialog-scrollPaper': styles.dialog, '& .MuiDialog-paper': styles.paper }}>`,
|
|
748
|
+
|
|
749
|
+
Before: `<Dialog classes={{ scrollPaper: this.props.classes.dialog, paper: this.props.classes.paper }}>`
|
|
750
|
+
After: `<Dialog sx={{ '&.MuiDialog-scrollPaper': styles.dialog, '& .MuiDialog-paper': styles.paper }}>`
|
|
751
|
+
|
|
752
|
+
Before: `<ListItem classes={{ root: this.props.classes.listItem }} >`,
|
|
753
|
+
After: `<ListItem sx={{ '&.MuiListItem-root': styles.listItem }} >`
|
|
754
|
+
|
|
755
|
+
Before: `<Typography component="h2" variant="h6" classes={{ root: this.props.classes.typography }}>`,
|
|
756
|
+
After: `<Typography component="h2" variant="h6" sx={{ '&.MuiTypography-root': styles.typography }}>`
|
|
757
|
+
|
|
758
|
+
Before: `<Badge classes={{ 'badge': this.props.classes.expertBadge }}>`,
|
|
759
|
+
After: `<Badge sx={{ '& .MuiBadge-badge': styles.expertBadge }}>`
|
|
760
|
+
|
|
761
|
+
Before: `<Tab classes={{ selected: this.props.classes..selected }} />`,
|
|
762
|
+
After: `<Tab sx={{ '&.Mui-selected': styles.selected }} />`
|
|
763
|
+
|
|
764
|
+
Before: `<Tabs classes={{ indicator: this.props.classes.indicator }} />`,
|
|
765
|
+
After: `<Tabs sx={{ '& .MuiTabs-indicator': styles.indicator }} />`
|
|
766
|
+
|
|
767
|
+
Before: `<Tooltip title={this.props.t('ra_Refresh tree')} classes={{ popper: this.props.classes.tooltip }}>`,
|
|
768
|
+
After: `<Tooltip title={this.props.t('ra_Refresh tree')} componentsProps={{ popper: { sx: { pointerEvents: 'none' } } }}>`,
|
|
769
|
+
Or: `<Tooltip title={this.props.t('ra_Refresh tree')} componentsProps={{ popper: { sx: styles.tooltip } }}>`
|
|
770
|
+
|
|
771
|
+
Before. `<AccordionSummary classes={{ root: this.props.classes.rootStyle, content: this.props.classes.content }}>`,
|
|
772
|
+
After. `<AccordionSummary sx={{ '&.MuiAccordionSummary-root': styles.rootStyle, '& .MuiAccordionSummary-content': styles.content }}>`
|
|
773
|
+
|
|
774
|
+
Before. `<Drawer classes={{ paper: this.props.classes.paperStyle }}>`,
|
|
775
|
+
After. `<Drawer sx={{ '& .MuiDrawer-paper': styles.paperStyle }}>`
|
|
776
|
+
|
|
777
|
+
<!--
|
|
778
|
+
Placeholder for the next version (at the beginning of the line):
|
|
779
|
+
### **WORK IN PROGRESS**
|
|
780
|
+
-->
|
|
781
|
+
|
|
782
782
|
## Changelog
|
|
783
|
-
###
|
|
783
|
+
### 7.0.2 (2024-09-10)
|
|
784
|
+
* (bluefox) Showed the context menu under cursor position in the object browser
|
|
785
|
+
* (bluefox) Added links to aliases in the object browser
|
|
786
|
+
|
|
787
|
+
### 7.0.1 (2024-08-29)
|
|
788
|
+
* (bluefox) Updated the object browser
|
|
789
|
+
* (bluefox) Used MUI Library 6.0
|
|
790
|
+
|
|
791
|
+
### 6.1.10 (2024-08-30)
|
|
784
792
|
* (bluefox) Updated the object browser
|
|
785
793
|
|
|
786
|
-
### 6.1.9 (2024-08-14)
|
|
794
|
+
### 6.1.9 (2024-08-14)
|
|
787
795
|
* (bluefox) Updated JSON schema
|
|
788
796
|
|
|
789
|
-
### 6.1.8 (2024-08-03)
|
|
797
|
+
### 6.1.8 (2024-08-03)
|
|
790
798
|
* (bluefox) Added translations
|
|
791
799
|
|
|
792
|
-
### 6.1.6 (2024-07-23)
|
|
800
|
+
### 6.1.6 (2024-07-23)
|
|
793
801
|
* (bluefox) Optimize package
|
|
794
802
|
|
|
795
|
-
### 6.1.5 (2024-07-20)
|
|
803
|
+
### 6.1.5 (2024-07-20)
|
|
796
804
|
* (bluefox) Added sources to package
|
|
797
805
|
|
|
798
|
-
### 6.1.3 (2024-07-20)
|
|
806
|
+
### 6.1.3 (2024-07-20)
|
|
799
807
|
* (bluefox) Better typing of legacy connection
|
|
800
808
|
|
|
801
|
-
### 6.1.1 (2024-07-16)
|
|
809
|
+
### 6.1.1 (2024-07-16)
|
|
802
810
|
* (bluefox) Added translations
|
|
803
811
|
|
|
804
|
-
### 6.1.0 (2024-07-15)
|
|
812
|
+
### 6.1.0 (2024-07-15)
|
|
805
813
|
* (bluefox) Replace by CRON to text the package to `cronstrue`
|
|
806
814
|
|
|
807
|
-
### 6.0.19 (2024-07-14)
|
|
815
|
+
### 6.0.19 (2024-07-14)
|
|
808
816
|
* (bluefox) added some packages for federation
|
|
809
817
|
|
|
810
|
-
### 6.0.17 (2024-07-14)
|
|
811
|
-
* (bluefox) Allowed playing mp3 files in the file browser
|
|
818
|
+
### 6.0.17 (2024-07-14)
|
|
819
|
+
* (bluefox) Allowed playing mp3 files in the file browser
|
|
812
820
|
* (bluefox) Corrected jump by object selection
|
|
813
821
|
|
|
814
|
-
### 6.0.14 (2024-07-07)
|
|
822
|
+
### 6.0.14 (2024-07-07)
|
|
815
823
|
* (bluefox) Corrected theme type selection
|
|
816
824
|
|
|
817
|
-
### 6.0.13 (2024-06-30)
|
|
825
|
+
### 6.0.13 (2024-06-30)
|
|
818
826
|
* (bluefox) Corrected color picker
|
|
819
827
|
|
|
820
|
-
### 6.0.12 (2024-06-29)
|
|
828
|
+
### 6.0.12 (2024-06-29)
|
|
821
829
|
* (bluefox) Added support for the overrides in the theme
|
|
822
830
|
|
|
823
|
-
### 6.0.10 (2024-06-27)
|
|
824
|
-
* (bluefox) Added translation
|
|
831
|
+
### 6.0.10 (2024-06-27)
|
|
832
|
+
* (bluefox) Added translation
|
|
825
833
|
* (bluefox) Mobile object browser improved
|
|
826
834
|
|
|
827
|
-
### 6.0.9 (2024-06-26)
|
|
835
|
+
### 6.0.9 (2024-06-26)
|
|
828
836
|
* (bluefox) Corrected Icons
|
|
829
837
|
|
|
830
|
-
### 6.0.8 (2024-06-26)
|
|
831
|
-
* (bluefox) Corrected types of the select ID dialog
|
|
838
|
+
### 6.0.8 (2024-06-26)
|
|
839
|
+
* (bluefox) Corrected types of the select ID dialog
|
|
832
840
|
* (bluefox) Made the tooltips neutral to the pointer events
|
|
833
841
|
|
|
834
|
-
### 6.0.6 (2024-06-24)
|
|
835
|
-
* (bluefox) Synchronised with admin
|
|
842
|
+
### 6.0.6 (2024-06-24)
|
|
843
|
+
* (bluefox) Synchronised with admin
|
|
836
844
|
* (bluefox) Added translations for time scheduler
|
|
837
845
|
|
|
838
|
-
### 6.0.4 (2024-06-21)
|
|
839
|
-
* (bluefox) Removed the usage of `withStyles` in favor of `sx` and `style` properties (see [Migration from v5 to v6](#migration-from-v5-to-v6)
|
|
846
|
+
### 6.0.4 (2024-06-21)
|
|
847
|
+
* (bluefox) Removed the usage of `withStyles` in favor of `sx` and `style` properties (see [Migration from v5 to v6](#migration-from-v5-to-v6)
|
|
840
848
|
* (bluefox) (BREAKING) Higher version of `@mui/material` (5.15.20) is used
|
|
841
849
|
|
|
842
|
-
### 5.0.8 (2024-06-15)
|
|
850
|
+
### 5.0.8 (2024-06-15)
|
|
843
851
|
* (bluefox) Added `modulefederation.admin.config.js` for module federation
|
|
844
852
|
|
|
845
|
-
### 5.0.5 (2024-06-10)
|
|
853
|
+
### 5.0.5 (2024-06-10)
|
|
846
854
|
* (bluefox) Sources were synchronized with admin
|
|
847
855
|
|
|
848
|
-
### 5.0.4 (2024-06-07)
|
|
856
|
+
### 5.0.4 (2024-06-07)
|
|
849
857
|
* (bluefox) Added better typing
|
|
850
858
|
|
|
851
|
-
### 5.0.2 (2024-05-30)
|
|
852
|
-
* (bluefox) Added better typing
|
|
859
|
+
### 5.0.2 (2024-05-30)
|
|
860
|
+
* (bluefox) Added better typing
|
|
853
861
|
* (bluefox) Json-Config is now a separate package and must be installed additionally
|
|
854
862
|
|
|
855
|
-
### 5.0.0 (2024-05-29)
|
|
856
|
-
* (bluefox) Types are now exported
|
|
857
|
-
* (bluefox) Translator renamed to Translate
|
|
863
|
+
### 5.0.0 (2024-05-29)
|
|
864
|
+
* (bluefox) Types are now exported
|
|
865
|
+
* (bluefox) Translator renamed to Translate
|
|
858
866
|
* (bluefox) Breaking: Theme renamed to IobTheme because of the naming conflict
|
|
859
867
|
|
|
860
|
-
### 4.13.24 (2024-05-25)
|
|
861
|
-
* (bluefox) Updated packages
|
|
862
|
-
|
|
863
|
-
* ### 4.13.22 (2024-05-23)
|
|
868
|
+
### 4.13.24 (2024-05-25)
|
|
869
|
+
* (bluefox) Updated packages
|
|
870
|
+
|
|
871
|
+
* ### 4.13.22 (2024-05-23)
|
|
864
872
|
* (bluefox) Updated packages
|
|
865
873
|
|
|
866
|
-
### 4.13.20 (2024-05-22)
|
|
867
|
-
* (bluefox) Better types added
|
|
868
|
-
* (bluefox) updated theme definitions
|
|
874
|
+
### 4.13.20 (2024-05-22)
|
|
875
|
+
* (bluefox) Better types added
|
|
876
|
+
* (bluefox) updated theme definitions
|
|
869
877
|
* (bluefox) corrected dates in cron dialog
|
|
870
878
|
|
|
871
|
-
### 4.13.14 (2024-05-19)
|
|
879
|
+
### 4.13.14 (2024-05-19)
|
|
872
880
|
* (bluefox) Updated packages
|
|
873
881
|
|
|
874
|
-
### 4.13.13 (2024-05-09)
|
|
882
|
+
### 4.13.13 (2024-05-09)
|
|
875
883
|
* (bluefox) Updated ioBroker types
|
|
876
884
|
|
|
877
|
-
### 4.13.12 (2024-05-06)
|
|
885
|
+
### 4.13.12 (2024-05-06)
|
|
878
886
|
* (bluefox) All files are migrated to Typescript
|
|
879
887
|
|
|
880
|
-
### 4.13.11 (2024-04-23)
|
|
888
|
+
### 4.13.11 (2024-04-23)
|
|
881
889
|
* (bluefox) Corrected the size of icons
|
|
882
890
|
|
|
883
|
-
### 4.13.10 (2024-04-22)
|
|
891
|
+
### 4.13.10 (2024-04-22)
|
|
884
892
|
* (bluefox) Migrated all icons to Typescript
|
|
885
893
|
|
|
886
|
-
### 4.13.9 (2024-04-20)
|
|
894
|
+
### 4.13.9 (2024-04-20)
|
|
887
895
|
* (bluefox) Updated socket-client package
|
|
888
896
|
|
|
889
|
-
### 4.13.8 (2024-04-19)
|
|
897
|
+
### 4.13.8 (2024-04-19)
|
|
890
898
|
* (bluefox) Corrected CRON selector
|
|
891
899
|
|
|
892
|
-
### 4.13.7 (2024-04-19)
|
|
900
|
+
### 4.13.7 (2024-04-19)
|
|
893
901
|
* (bluefox) Migrated ColorPicker to typescript
|
|
894
902
|
|
|
895
|
-
### 4.13.6 (2024-04-11)
|
|
896
|
-
* (bluefox) Migrated TreeTable to typescript
|
|
903
|
+
### 4.13.6 (2024-04-11)
|
|
904
|
+
* (bluefox) Migrated TreeTable to typescript
|
|
897
905
|
* (bluefox) corrected the object subscription
|
|
898
906
|
|
|
899
|
-
### 4.13.5 (2024-04-02)
|
|
900
|
-
* (bluefox) used new connection classes
|
|
907
|
+
### 4.13.5 (2024-04-02)
|
|
908
|
+
* (bluefox) used new connection classes
|
|
901
909
|
* (bluefox) Improved the `SelectID` dialog
|
|
902
910
|
|
|
903
|
-
### 4.13.3 (2024-04-01)
|
|
911
|
+
### 4.13.3 (2024-04-01)
|
|
904
912
|
* (bluefox) used new connection classes
|
|
905
913
|
|
|
906
|
-
### 4.12.3 (2024-03-30)
|
|
914
|
+
### 4.12.3 (2024-03-30)
|
|
907
915
|
* (bluefox) Migrated legacy connection to typescript
|
|
908
916
|
|
|
909
|
-
### 4.12.2 (2024-03-25)
|
|
917
|
+
### 4.12.2 (2024-03-25)
|
|
910
918
|
* (bluefox) Added support for remote cloud
|
|
911
919
|
|
|
912
|
-
### 4.11.6 (2024-03-19)
|
|
920
|
+
### 4.11.6 (2024-03-19)
|
|
913
921
|
* (bluefox) Corrected rendering of LoaderMV
|
|
914
922
|
|
|
915
|
-
### 4.11.4 (2024-03-18)
|
|
923
|
+
### 4.11.4 (2024-03-18)
|
|
916
924
|
* (bluefox) Corrected types of IconPicker
|
|
917
925
|
|
|
918
|
-
### 4.11.3 (2024-03-17)
|
|
926
|
+
### 4.11.3 (2024-03-17)
|
|
919
927
|
* (bluefox) Made filters for the file selector dialog optional
|
|
920
928
|
|
|
921
|
-
### 4.11.2 (2024-03-16)
|
|
929
|
+
### 4.11.2 (2024-03-16)
|
|
922
930
|
* (bluefox) Migrated GenericApp to typescript
|
|
923
931
|
|
|
924
|
-
### 4.10.4 (2024-03-16)
|
|
932
|
+
### 4.10.4 (2024-03-16)
|
|
925
933
|
* (bluefox) Migrated some components to typescript
|
|
926
934
|
|
|
927
|
-
### 4.10.1 (2024-03-11)
|
|
935
|
+
### 4.10.1 (2024-03-11)
|
|
928
936
|
* (bluefox) Migrated some components to typescript
|
|
929
937
|
|
|
930
|
-
### 4.9.11 (2024-03-08)
|
|
938
|
+
### 4.9.11 (2024-03-08)
|
|
931
939
|
* (foxriver76) type GenericApp socket correctly
|
|
932
940
|
|
|
933
|
-
### 4.9.10 (2024-02-21)
|
|
934
|
-
* (bluefox) translations
|
|
941
|
+
### 4.9.10 (2024-02-21)
|
|
942
|
+
* (bluefox) translations
|
|
935
943
|
* (bluefox) updated json config
|
|
936
944
|
|
|
937
|
-
### 4.9.9 (2024-02-16)
|
|
945
|
+
### 4.9.9 (2024-02-16)
|
|
938
946
|
* (foxriver76) also check plugin state of instance to see if Sentry is explicitly disabled
|
|
939
947
|
|
|
940
|
-
### 4.9.8 (2024-02-13)
|
|
948
|
+
### 4.9.8 (2024-02-13)
|
|
941
949
|
* (bluefox) allowed hiding wizard in cron dialog
|
|
942
950
|
|
|
943
|
-
### 4.9.7 (2024-02-03)
|
|
951
|
+
### 4.9.7 (2024-02-03)
|
|
944
952
|
* (foxriver76) allow passing down the instance number do avoid determining from url
|
|
945
953
|
|
|
946
|
-
### 4.9.5 (2024-01-01)
|
|
954
|
+
### 4.9.5 (2024-01-01)
|
|
947
955
|
* (foxriver76) make `copyToClipboard` event parameter optional
|
|
948
956
|
|
|
949
|
-
### 4.9.4 (2024-01-01)
|
|
957
|
+
### 4.9.4 (2024-01-01)
|
|
950
958
|
* (foxriver76) try to fix `SelectID` scrolling
|
|
951
959
|
|
|
952
|
-
### 4.9.2 (2023-12-30)
|
|
960
|
+
### 4.9.2 (2023-12-30)
|
|
953
961
|
* (foxriver76) bump version of `@iobroker/json-config`
|
|
954
962
|
|
|
955
|
-
### 4.9.1 (2023-12-22)
|
|
963
|
+
### 4.9.1 (2023-12-22)
|
|
956
964
|
* (foxriver76) `@iobroker/json-config` moved to real dependencies
|
|
957
965
|
|
|
958
|
-
### 4.9.0 (2023-12-22)
|
|
959
|
-
* (foxriver76) migrate to `@iobroker/json-config` module to have a single point of truth
|
|
966
|
+
### 4.9.0 (2023-12-22)
|
|
967
|
+
* (foxriver76) migrate to `@iobroker/json-config` module to have a single point of truth
|
|
960
968
|
* (bluefox) Allowed using of `filterFunc` as string
|
|
961
969
|
|
|
962
|
-
### 4.8.1 (2023-12-14)
|
|
970
|
+
### 4.8.1 (2023-12-14)
|
|
963
971
|
* (bluefox) Added Device manager to JSON Config
|
|
964
972
|
|
|
965
|
-
### 4.7.15 (2023-12-12)
|
|
973
|
+
### 4.7.15 (2023-12-12)
|
|
966
974
|
* (bluefox) Corrected parsing of a text
|
|
967
975
|
|
|
968
|
-
### 4.7.13 (2023-12-10)
|
|
976
|
+
### 4.7.13 (2023-12-10)
|
|
969
977
|
* (bluefox) Added possibility to define the root style and embedded property
|
|
970
978
|
|
|
971
|
-
### 4.7.11 (2023-12-06)
|
|
979
|
+
### 4.7.11 (2023-12-06)
|
|
972
980
|
* (bluefox) Extended color picker with "noInputField" option
|
|
973
981
|
|
|
974
|
-
### 4.7.9 (2023-12-04)
|
|
982
|
+
### 4.7.9 (2023-12-04)
|
|
975
983
|
* (bluefox) Corrected the icon picker
|
|
976
984
|
|
|
977
|
-
### 4.7.8 (2023-12-04)
|
|
985
|
+
### 4.7.8 (2023-12-04)
|
|
978
986
|
* (foxriver76) port to `@iobroker/types`
|
|
979
987
|
|
|
980
|
-
### 4.7.6 (2023-11-29)
|
|
988
|
+
### 4.7.6 (2023-11-29)
|
|
981
989
|
* (bluefox) Added translations
|
|
982
990
|
|
|
983
|
-
### 4.7.5 (2023-11-28)
|
|
991
|
+
### 4.7.5 (2023-11-28)
|
|
984
992
|
* (bluefox) Corrected subscribe on objects in the legacy connection
|
|
985
993
|
|
|
986
|
-
### 4.7.4 (2023-11-23)
|
|
987
|
-
* (bluefox) Updated packages
|
|
994
|
+
### 4.7.4 (2023-11-23)
|
|
995
|
+
* (bluefox) Updated packages
|
|
988
996
|
* (bluefox) Made getStates method in legacy connection compatible with new one
|
|
989
997
|
|
|
990
|
-
### 4.7.3 (2023-11-08)
|
|
998
|
+
### 4.7.3 (2023-11-08)
|
|
991
999
|
* (bluefox) Updated packages
|
|
992
1000
|
|
|
993
|
-
### 4.7.2 (2023-11-03)
|
|
994
|
-
* (foxriver76) fixed problem with color picker, where editing TextField was buggy
|
|
1001
|
+
### 4.7.2 (2023-11-03)
|
|
1002
|
+
* (foxriver76) fixed problem with color picker, where editing TextField was buggy
|
|
995
1003
|
* (foxriver76) fixed light mode color of a path in FileBrowser
|
|
996
1004
|
|
|
997
|
-
### 4.7.0 (2023-10-31)
|
|
998
|
-
* (bluefox) Synced with admin
|
|
1005
|
+
### 4.7.0 (2023-10-31)
|
|
1006
|
+
* (bluefox) Synced with admin
|
|
999
1007
|
* (bluefox) Added GIF to image files
|
|
1000
1008
|
|
|
1001
|
-
### 4.6.7 (2023-10-19)
|
|
1009
|
+
### 4.6.7 (2023-10-19)
|
|
1002
1010
|
* (bluefox) Added return value for `subscribeOnInstance` for Connection class
|
|
1003
1011
|
|
|
1004
|
-
### 4.6.6 (2023-10-13)
|
|
1012
|
+
### 4.6.6 (2023-10-13)
|
|
1005
1013
|
* (bluefox) Fixed the legacy connection
|
|
1006
1014
|
|
|
1007
|
-
### 4.6.5 (2023-10-12)
|
|
1015
|
+
### 4.6.5 (2023-10-12)
|
|
1008
1016
|
* (foxriver76) fixed object browser with date
|
|
1009
1017
|
|
|
1010
|
-
### 4.6.4 (2023-10-11)
|
|
1018
|
+
### 4.6.4 (2023-10-11)
|
|
1011
1019
|
* (bluefox) Updated the packages
|
|
1012
1020
|
|
|
1013
|
-
### 4.6.3 (2023-10-09)
|
|
1014
|
-
* (bluefox) Just updated the packages
|
|
1021
|
+
### 4.6.3 (2023-10-09)
|
|
1022
|
+
* (bluefox) Just updated the packages
|
|
1015
1023
|
* (bluefox) Synced with admin
|
|
1016
1024
|
|
|
1017
|
-
### 4.6.2 (2023-09-29)
|
|
1025
|
+
### 4.6.2 (2023-09-29)
|
|
1018
1026
|
* (bluefox) Experimental feature added: update states on re-subscribe
|
|
1019
1027
|
|
|
1020
|
-
### 4.5.5 (2023-09-27)
|
|
1028
|
+
### 4.5.5 (2023-09-27)
|
|
1021
1029
|
* (bluefox) Added export for IconNoIcon
|
|
1022
1030
|
|
|
1023
|
-
### 4.5.4 (2023-09-17)
|
|
1031
|
+
### 4.5.4 (2023-09-17)
|
|
1024
1032
|
* (bluefox) Added the restricting to folder property for select file dialog
|
|
1025
1033
|
|
|
1026
|
-
### 4.5.3 (2023-08-20)
|
|
1034
|
+
### 4.5.3 (2023-08-20)
|
|
1027
1035
|
* (foxriver76) fixed css classes of TableResize, see https://github.com/ioBroker/ioBroker.admin/issues/1860
|
|
1028
1036
|
|
|
1029
|
-
### 4.5.2 (2023-08-20)
|
|
1037
|
+
### 4.5.2 (2023-08-20)
|
|
1030
1038
|
* (foxriver76) added missing export of TableResize
|
|
1031
1039
|
|
|
1032
|
-
### 4.5.1 (2023-08-19)
|
|
1040
|
+
### 4.5.1 (2023-08-19)
|
|
1033
1041
|
* (foxriver76) fix dialog TextInput
|
|
1034
1042
|
|
|
1035
|
-
### 4.5.0 (2023-08-18)
|
|
1043
|
+
### 4.5.0 (2023-08-18)
|
|
1036
1044
|
* (bluefox) Synchronize components with admin
|
|
1037
1045
|
|
|
1038
|
-
### 4.4.8 (2023-08-17)
|
|
1046
|
+
### 4.4.8 (2023-08-17)
|
|
1039
1047
|
* (bluefox) Added translations
|
|
1040
1048
|
|
|
1041
|
-
### 4.4.7 (2023-08-10)
|
|
1042
|
-
* (bluefox) Added `subscribeStateAsync` method to wait for answer
|
|
1049
|
+
### 4.4.7 (2023-08-10)
|
|
1050
|
+
* (bluefox) Added `subscribeStateAsync` method to wait for answer
|
|
1043
1051
|
* (bluefox) Added support for arrays for un/subscriptions
|
|
1044
1052
|
|
|
1045
|
-
### 4.4.5 (2023-08-01)
|
|
1053
|
+
### 4.4.5 (2023-08-01)
|
|
1046
1054
|
* (bluefox) Updated packages
|
|
1047
1055
|
|
|
1048
|
-
### 4.3.3 (2023-07-28)
|
|
1056
|
+
### 4.3.3 (2023-07-28)
|
|
1049
1057
|
* (bluefox) Added translations
|
|
1050
1058
|
|
|
1051
|
-
### 4.3.0 (2023-07-19)
|
|
1052
|
-
* (bluefox) Updated packages
|
|
1053
|
-
* (bluefox) Added translations
|
|
1054
|
-
* (bluefox) Synced object browser
|
|
1059
|
+
### 4.3.0 (2023-07-19)
|
|
1060
|
+
* (bluefox) Updated packages
|
|
1061
|
+
* (bluefox) Added translations
|
|
1062
|
+
* (bluefox) Synced object browser
|
|
1055
1063
|
* (bluefox) formatting
|
|
1056
1064
|
|
|
1057
|
-
### 4.2.1 (2023-07-17)
|
|
1058
|
-
* (bluefox) Updated packages
|
|
1065
|
+
### 4.2.1 (2023-07-17)
|
|
1066
|
+
* (bluefox) Updated packages
|
|
1059
1067
|
* (bluefox) Added translations
|
|
1060
1068
|
|
|
1061
|
-
### 4.2.0 (2023-07-07)
|
|
1062
|
-
* (bluefox) Updated packages
|
|
1069
|
+
### 4.2.0 (2023-07-07)
|
|
1070
|
+
* (bluefox) Updated packages
|
|
1063
1071
|
* (bluefox) Added new method `getObjectsById` to the socket communication
|
|
1064
1072
|
|
|
1065
|
-
### 4.1.2 (2023-06-20)
|
|
1073
|
+
### 4.1.2 (2023-06-20)
|
|
1066
1074
|
* (bluefox) Allowed setting theme name directly by theme toggle
|
|
1067
1075
|
|
|
1068
|
-
### 4.1.0 (2023-05-10)
|
|
1076
|
+
### 4.1.0 (2023-05-10)
|
|
1069
1077
|
* (bluefox) `craco-module-federation.js` was added. For node 16
|
|
1070
1078
|
|
|
1071
|
-
### 4.0.27 (2023-05-09)
|
|
1079
|
+
### 4.0.27 (2023-05-09)
|
|
1072
1080
|
* (bluefox) Allowed showing only specific root in SelectIDDialog
|
|
1073
1081
|
|
|
1074
|
-
### 4.0.26 (2023-05-08)
|
|
1082
|
+
### 4.0.26 (2023-05-08)
|
|
1075
1083
|
* (bluefox) Added IDs to the buttons in the dialog for GUI tests
|
|
1076
1084
|
|
|
1077
|
-
### 4.0.25 (2023-04-23)
|
|
1085
|
+
### 4.0.25 (2023-04-23)
|
|
1078
1086
|
* (bluefox) Extended `TextWithIcon` with defined color and icon
|
|
1079
1087
|
|
|
1080
|
-
### 4.0.24 (2023-04-03)
|
|
1088
|
+
### 4.0.24 (2023-04-03)
|
|
1081
1089
|
* (bluefox) Updated the file selector in tile mode
|
|
1082
1090
|
|
|
1083
|
-
### 4.0.23 (2023-03-27)
|
|
1091
|
+
### 4.0.23 (2023-03-27)
|
|
1084
1092
|
* (bluefox) Added translations
|
|
1085
1093
|
|
|
1086
|
-
### 4.0.22 (2023-03-22)
|
|
1094
|
+
### 4.0.22 (2023-03-22)
|
|
1087
1095
|
* (bluefox) Re-Activate legacy connection
|
|
1088
1096
|
|
|
1089
|
-
### 4.0.21 (2023-03-22)
|
|
1097
|
+
### 4.0.21 (2023-03-22)
|
|
1090
1098
|
* (bluefox) Added translations
|
|
1091
1099
|
|
|
1092
|
-
### 4.0.20 (2023-03-21)
|
|
1100
|
+
### 4.0.20 (2023-03-21)
|
|
1093
1101
|
* (bluefox) Color picker was improved
|
|
1094
1102
|
|
|
1095
|
-
### 4.0.19 (2023-03-20)
|
|
1096
|
-
* (bluefox) Packages were updated
|
|
1103
|
+
### 4.0.19 (2023-03-20)
|
|
1104
|
+
* (bluefox) Packages were updated
|
|
1097
1105
|
* (bluefox) Added new translations
|
|
1098
1106
|
|
|
1099
|
-
### 4.0.18 (2023-03-16)
|
|
1107
|
+
### 4.0.18 (2023-03-16)
|
|
1100
1108
|
* (bluefox) Packages were updated
|
|
1101
1109
|
|
|
1102
|
-
### 4.0.17 (2023-03-15)
|
|
1103
|
-
* (bluefox) Added translations
|
|
1110
|
+
### 4.0.17 (2023-03-15)
|
|
1111
|
+
* (bluefox) Added translations
|
|
1104
1112
|
* (bluefox) Added port controller to JSON config
|
|
1105
1113
|
|
|
1106
|
-
### 4.0.15 (2023-03-12)
|
|
1114
|
+
### 4.0.15 (2023-03-12)
|
|
1107
1115
|
* (bluefox) Updated the object browser and file browser
|
|
1108
1116
|
|
|
1109
|
-
### 4.0.14 (2023-03-03)
|
|
1117
|
+
### 4.0.14 (2023-03-03)
|
|
1110
1118
|
* (bluefox) added handler of alert messages
|
|
1111
1119
|
|
|
1112
|
-
### 4.0.13 (2023-02-15)
|
|
1120
|
+
### 4.0.13 (2023-02-15)
|
|
1113
1121
|
* (bluefox) Corrected the theme button
|
|
1114
1122
|
|
|
1115
|
-
### 4.0.12 (2023-02-15)
|
|
1123
|
+
### 4.0.12 (2023-02-15)
|
|
1116
1124
|
* (bluefox) made the fix for `echarts`
|
|
1117
1125
|
|
|
1118
|
-
### 4.0.11 (2023-02-14)
|
|
1119
|
-
* (bluefox) Updated packages
|
|
1126
|
+
### 4.0.11 (2023-02-14)
|
|
1127
|
+
* (bluefox) Updated packages
|
|
1120
1128
|
* (bluefox) The `chartReady` event was omitted
|
|
1121
1129
|
|
|
1122
|
-
### 4.0.10 (2023-02-10)
|
|
1123
|
-
* (bluefox) Updated packages
|
|
1130
|
+
### 4.0.10 (2023-02-10)
|
|
1131
|
+
* (bluefox) Updated packages
|
|
1124
1132
|
* (bluefox) made the fix for `material`
|
|
1125
1133
|
|
|
1126
|
-
### 4.0.9 (2023-02-02)
|
|
1134
|
+
### 4.0.9 (2023-02-02)
|
|
1127
1135
|
* (bluefox) Updated packages
|
|
1128
1136
|
|
|
1129
|
-
### 4.0.8 (2022-12-19)
|
|
1137
|
+
### 4.0.8 (2022-12-19)
|
|
1130
1138
|
* (bluefox) Extended socket with `log` command
|
|
1131
1139
|
|
|
1132
|
-
### 4.0.6 (2022-12-19)
|
|
1140
|
+
### 4.0.6 (2022-12-19)
|
|
1133
1141
|
* (bluefox) Corrected URL for the connection
|
|
1134
1142
|
|
|
1135
|
-
### 4.0.5 (2022-12-14)
|
|
1143
|
+
### 4.0.5 (2022-12-14)
|
|
1136
1144
|
* (bluefox) Added support of custom palette for color picker
|
|
1137
1145
|
|
|
1138
|
-
### 4.0.2 (2022-12-01)
|
|
1146
|
+
### 4.0.2 (2022-12-01)
|
|
1139
1147
|
* (bluefox) use `@iobroker/socket-client` instead of `Connection.tsx`
|
|
1140
1148
|
|
|
1141
|
-
### 3.5.3 (2022-11-30)
|
|
1149
|
+
### 3.5.3 (2022-11-30)
|
|
1142
1150
|
* (bluefox) Improved `renderTextWithA` function to support `<b>` and `<i>` tags
|
|
1143
1151
|
|
|
1144
|
-
### 3.5.2 (2022-11-30)
|
|
1152
|
+
### 3.5.2 (2022-11-30)
|
|
1145
1153
|
* (bluefox) updated json config component
|
|
1146
1154
|
|
|
1147
|
-
### 3.4.1 (2022-11-29)
|
|
1155
|
+
### 3.4.1 (2022-11-29)
|
|
1148
1156
|
* (bluefox) Added button text for message dialog
|
|
1149
1157
|
|
|
1150
|
-
### 3.4.0 (2022-11-29)
|
|
1158
|
+
### 3.4.0 (2022-11-29)
|
|
1151
1159
|
* (bluefox) Added file selector
|
|
1152
1160
|
|
|
1153
|
-
### 3.3.0 (2022-11-26)
|
|
1161
|
+
### 3.3.0 (2022-11-26)
|
|
1154
1162
|
* (bluefox) Added subscribe on files
|
|
1155
1163
|
|
|
1156
|
-
### 3.2.7 (2022-11-13)
|
|
1164
|
+
### 3.2.7 (2022-11-13)
|
|
1157
1165
|
* (bluefox) Added `fullWidth` property to `Dialog`
|
|
1158
1166
|
|
|
1159
|
-
### 3.2.6 (2022-11-08)
|
|
1167
|
+
### 3.2.6 (2022-11-08)
|
|
1160
1168
|
* (xXBJXx) Improved TreeTable component
|
|
1161
1169
|
|
|
1162
|
-
### 3.2.5 (2022-11-08)
|
|
1170
|
+
### 3.2.5 (2022-11-08)
|
|
1163
1171
|
* (bluefox) Added the role filter for the object browser
|
|
1164
1172
|
|
|
1165
|
-
### 3.2.4 (2022-11-03)
|
|
1173
|
+
### 3.2.4 (2022-11-03)
|
|
1166
1174
|
* (bluefox) Added support for alfa channel for `invertColor`
|
|
1167
1175
|
|
|
1168
|
-
### 3.2.3 (2022-10-26)
|
|
1176
|
+
### 3.2.3 (2022-10-26)
|
|
1169
1177
|
* (bluefox) Corrected expert mode for object browser
|
|
1170
1178
|
|
|
1171
|
-
### 3.2.2 (2022-10-25)
|
|
1179
|
+
### 3.2.2 (2022-10-25)
|
|
1172
1180
|
* (bluefox) Added support for prefixes for translations
|
|
1173
1181
|
|
|
1174
|
-
### 3.2.1 (2022-10-24)
|
|
1182
|
+
### 3.2.1 (2022-10-24)
|
|
1175
1183
|
* (bluefox) Corrected color inversion
|
|
1176
1184
|
|
|
1177
|
-
### 3.2.0 (2022-10-19)
|
|
1185
|
+
### 3.2.0 (2022-10-19)
|
|
1178
1186
|
* (bluefox) Added ukrainian translation
|
|
1179
1187
|
|
|
1180
|
-
### 3.1.35 (2022-10-17)
|
|
1188
|
+
### 3.1.35 (2022-10-17)
|
|
1181
1189
|
* (bluefox) small changes for material
|
|
1182
1190
|
|
|
1183
|
-
### 3.1.34 (2022-08-24)
|
|
1191
|
+
### 3.1.34 (2022-08-24)
|
|
1184
1192
|
* (bluefox) Implemented fallback to english by translations
|
|
1185
1193
|
|
|
1186
|
-
### 3.1.33 (2022-08-24)
|
|
1194
|
+
### 3.1.33 (2022-08-24)
|
|
1187
1195
|
* (bluefox) Added support for onchange flag
|
|
1188
1196
|
|
|
1189
|
-
### 3.1.30 (2022-08-23)
|
|
1190
|
-
* (bluefox) Added method `getCompactSystemRepositories`
|
|
1197
|
+
### 3.1.30 (2022-08-23)
|
|
1198
|
+
* (bluefox) Added method `getCompactSystemRepositories`
|
|
1191
1199
|
* (bluefox) corrected error in `ObjectBrowser`
|
|
1192
1200
|
|
|
1193
|
-
### 3.1.27 (2022-08-01)
|
|
1201
|
+
### 3.1.27 (2022-08-01)
|
|
1194
1202
|
* (bluefox) Disable file editing in FileViewer
|
|
1195
1203
|
|
|
1196
|
-
### 3.1.26 (2022-08-01)
|
|
1197
|
-
* (bluefox) Added translations
|
|
1204
|
+
### 3.1.26 (2022-08-01)
|
|
1205
|
+
* (bluefox) Added translations
|
|
1198
1206
|
* (bluefox) JSON schema was extended with missing definitions
|
|
1199
1207
|
|
|
1200
|
-
### 3.1.24 (2022-07-28)
|
|
1208
|
+
### 3.1.24 (2022-07-28)
|
|
1201
1209
|
* (bluefox) Updated file browser and object browser
|
|
1202
1210
|
|
|
1203
|
-
### 3.1.23 (2022-07-25)
|
|
1211
|
+
### 3.1.23 (2022-07-25)
|
|
1204
1212
|
* (bluefox) Extend custom filter for object selector
|
|
1205
1213
|
|
|
1206
|
-
### 3.1.22 (2022-07-22)
|
|
1214
|
+
### 3.1.22 (2022-07-22)
|
|
1207
1215
|
* (bluefox) Added i18n tools for development
|
|
1208
1216
|
|
|
1209
|
-
### 3.1.20 (2022-07-14)
|
|
1217
|
+
### 3.1.20 (2022-07-14)
|
|
1210
1218
|
* (bluefox) Allowed to show select dialog with the expert mode enabled
|
|
1211
1219
|
|
|
1212
|
-
### 3.1.19 (2022-07-08)
|
|
1220
|
+
### 3.1.19 (2022-07-08)
|
|
1213
1221
|
* (bluefox) Allowed extending translations for all languages together
|
|
1214
1222
|
|
|
1215
|
-
### 3.1.18 (2022-07-06)
|
|
1223
|
+
### 3.1.18 (2022-07-06)
|
|
1216
1224
|
* (bluefox) Added translation
|
|
1217
1225
|
|
|
1218
|
-
### 3.1.17 (2022-07-05)
|
|
1226
|
+
### 3.1.17 (2022-07-05)
|
|
1219
1227
|
* (bluefox) Deactivate JSON editor for JSONConfig because of space
|
|
1220
1228
|
|
|
1221
|
-
### 3.1.16 (2022-06-27)
|
|
1229
|
+
### 3.1.16 (2022-06-27)
|
|
1222
1230
|
* (bluefox) Update object browser
|
|
1223
1231
|
|
|
1224
|
-
### 3.1.15 (2022-06-27)
|
|
1232
|
+
### 3.1.15 (2022-06-27)
|
|
1225
1233
|
* (bluefox) Allowed using of spaces in name
|
|
1226
1234
|
|
|
1227
|
-
### 3.1.14 (2022-06-23)
|
|
1235
|
+
### 3.1.14 (2022-06-23)
|
|
1228
1236
|
* (bluefox) Added translations
|
|
1229
1237
|
|
|
1230
|
-
### 3.1.11 (2022-06-22)
|
|
1238
|
+
### 3.1.11 (2022-06-22)
|
|
1231
1239
|
* (bluefox) Added preparations for iobroker cloud
|
|
1232
1240
|
|
|
1233
|
-
### 3.1.10 (2022-06-22)
|
|
1241
|
+
### 3.1.10 (2022-06-22)
|
|
1234
1242
|
* (bluefox) Added translations
|
|
1235
1243
|
|
|
1236
|
-
### 3.1.9 (2022-06-20)
|
|
1244
|
+
### 3.1.9 (2022-06-20)
|
|
1237
1245
|
* (bluefox) Allowed working behind reverse proxy
|
|
1238
1246
|
|
|
1239
|
-
### 3.1.7 (2022-06-19)
|
|
1247
|
+
### 3.1.7 (2022-06-19)
|
|
1240
1248
|
* (bluefox) Added file select dialog
|
|
1241
1249
|
|
|
1242
|
-
### 3.1.3 (2022-06-13)
|
|
1250
|
+
### 3.1.3 (2022-06-13)
|
|
1243
1251
|
* (bluefox) Added table with resized headers
|
|
1244
1252
|
|
|
1245
|
-
### 3.1.2 (2022-06-09)
|
|
1253
|
+
### 3.1.2 (2022-06-09)
|
|
1246
1254
|
* (bluefox) Added new document icon (read only)
|
|
1247
1255
|
|
|
1248
|
-
### 3.1.1 (2022-06-09)
|
|
1256
|
+
### 3.1.1 (2022-06-09)
|
|
1249
1257
|
* (bluefox) Allowed working behind reverse proxy
|
|
1250
1258
|
|
|
1251
|
-
### 3.1.0 (2022-06-07)
|
|
1259
|
+
### 3.1.0 (2022-06-07)
|
|
1252
1260
|
* (bluefox) Some german texts were corrected
|
|
1253
1261
|
|
|
1254
|
-
### 3.0.17 (2022-06-03)
|
|
1262
|
+
### 3.0.17 (2022-06-03)
|
|
1255
1263
|
* (bluefox) Allowed calling getAdapterInstances not for admin too
|
|
1256
1264
|
|
|
1257
|
-
### 3.0.15 (2022-06-01)
|
|
1265
|
+
### 3.0.15 (2022-06-01)
|
|
1258
1266
|
* (bluefox) Updated JsonConfigComponent: password, table
|
|
1259
1267
|
|
|
1260
|
-
### 3.0.14 (2022-05-25)
|
|
1268
|
+
### 3.0.14 (2022-05-25)
|
|
1261
1269
|
* (bluefox) Added ConfigGeneric to import
|
|
1262
1270
|
|
|
1263
|
-
### 3.0.7 (2022-05-25)
|
|
1271
|
+
### 3.0.7 (2022-05-25)
|
|
1264
1272
|
* (bluefox) Made the module definitions
|
|
1265
1273
|
|
|
1266
|
-
### 3.0.6 (2022-05-25)
|
|
1274
|
+
### 3.0.6 (2022-05-25)
|
|
1267
1275
|
* (bluefox) Added JsonConfigComponent
|
|
1268
1276
|
|
|
1269
|
-
### 2.1.11 (2022-05-24)
|
|
1277
|
+
### 2.1.11 (2022-05-24)
|
|
1270
1278
|
* (bluefox) Update file browser. It supports now the file changed events.
|
|
1271
1279
|
|
|
1272
|
-
### 2.1.10 (2022-05-24)
|
|
1280
|
+
### 2.1.10 (2022-05-24)
|
|
1273
1281
|
* (bluefox) Corrected object browser
|
|
1274
1282
|
|
|
1275
|
-
### 2.1.9 (2022-05-16)
|
|
1283
|
+
### 2.1.9 (2022-05-16)
|
|
1276
1284
|
* (bluefox) Corrected expert mode in object browser
|
|
1277
1285
|
|
|
1278
|
-
### 2.1.7 (2022-05-09)
|
|
1279
|
-
* (bluefox) Changes were synchronized with adapter-react-v5
|
|
1286
|
+
### 2.1.7 (2022-05-09)
|
|
1287
|
+
* (bluefox) Changes were synchronized with adapter-react-v5
|
|
1280
1288
|
* (bluefox) Added `I18n.disableWarning` method
|
|
1281
1289
|
|
|
1282
|
-
### 2.1.6 (2022-03-28)
|
|
1283
|
-
* (bluefox) Added `log` method to connection
|
|
1290
|
+
### 2.1.6 (2022-03-28)
|
|
1291
|
+
* (bluefox) Added `log` method to connection
|
|
1284
1292
|
* (bluefox) Corrected translations
|
|
1285
1293
|
|
|
1286
|
-
### 2.1.1 (2022-03-27)
|
|
1294
|
+
### 2.1.1 (2022-03-27)
|
|
1287
1295
|
* (bluefox) Corrected error in TreeTable
|
|
1288
1296
|
|
|
1289
|
-
### 2.1.0 (2022-03-26)
|
|
1297
|
+
### 2.1.0 (2022-03-26)
|
|
1290
1298
|
* (bluefox) BREAKING_CHANGE: Corrected error with readFile(base64=false)
|
|
1291
1299
|
|
|
1292
|
-
### 2.0.0 (2022-03-26)
|
|
1300
|
+
### 2.0.0 (2022-03-26)
|
|
1293
1301
|
* (bluefox) Initial version
|
|
1294
1302
|
|
|
1295
|
-
### 0.1.0 (2022-03-23)
|
|
1303
|
+
### 0.1.0 (2022-03-23)
|
|
1296
1304
|
* (bluefox) Fixed theme errors
|
|
1297
1305
|
|
|
1298
|
-
### 0.0.4 (2022-03-22)
|
|
1306
|
+
### 0.0.4 (2022-03-22)
|
|
1299
1307
|
* (bluefox) Fixed eslint warnings
|
|
1300
1308
|
|
|
1301
|
-
### 0.0.3 (2022-03-19)
|
|
1309
|
+
### 0.0.3 (2022-03-19)
|
|
1302
1310
|
* (bluefox) beta version
|
|
1303
1311
|
|
|
1304
|
-
### 0.0.2 (2022-02-24)
|
|
1312
|
+
### 0.0.2 (2022-02-24)
|
|
1305
1313
|
* (bluefox) try to publish a first version
|
|
1306
1314
|
|
|
1307
|
-
### 0.0.1 (2022-02-24)
|
|
1315
|
+
### 0.0.1 (2022-02-24)
|
|
1308
1316
|
* initial commit
|
|
1309
1317
|
|
|
1310
|
-
## License
|
|
1311
|
-
The MIT License (MIT)
|
|
1312
|
-
|
|
1313
|
-
Copyright (c) 2019-2024 bluefox <dogafox@gmail.com>
|
|
1314
|
-
|
|
1315
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
1316
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
1317
|
-
in the Software without restriction, including without limitation the rights
|
|
1318
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
1319
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
1320
|
-
furnished to do so, subject to the following conditions:
|
|
1321
|
-
|
|
1322
|
-
The above copyright notice and this permission notice shall be included in all
|
|
1323
|
-
copies or substantial portions of the Software.
|
|
1324
|
-
|
|
1325
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
1326
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
1327
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
1328
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
1329
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
1330
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
1318
|
+
## License
|
|
1319
|
+
The MIT License (MIT)
|
|
1320
|
+
|
|
1321
|
+
Copyright (c) 2019-2024 bluefox <dogafox@gmail.com>
|
|
1322
|
+
|
|
1323
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
1324
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
1325
|
+
in the Software without restriction, including without limitation the rights
|
|
1326
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
1327
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
1328
|
+
furnished to do so, subject to the following conditions:
|
|
1329
|
+
|
|
1330
|
+
The above copyright notice and this permission notice shall be included in all
|
|
1331
|
+
copies or substantial portions of the Software.
|
|
1332
|
+
|
|
1333
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
1334
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
1335
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
1336
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
1337
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
1338
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
1331
1339
|
SOFTWARE.
|