@iobroker/gui-components 10.2.1 → 10.2.3
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/README.md +14 -1
- package/build/Components/ObjectBrowser/ObjectBrowserClass.d.ts +17 -1
- package/build/Components/ObjectBrowser/ObjectBrowserClass.js +99 -36
- package/build/Components/ObjectBrowser/ObjectBrowserClass.js.map +1 -1
- package/build/Components/ObjectBrowser/dialogs.js +7 -2
- package/build/Components/ObjectBrowser/dialogs.js.map +1 -1
- package/build/Components/ObjectBrowser/toolbar.js +14 -11
- package/build/Components/ObjectBrowser/toolbar.js.map +1 -1
- package/build/ThemeModern.js +13 -4
- package/build/ThemeModern.js.map +1 -1
- package/package.json +10 -10
package/README.md
CHANGED
|
@@ -36,7 +36,7 @@ npm create vite@latest src -- --template react-ts
|
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@emotion/react": "^11.14.0",
|
|
38
38
|
"@emotion/styled": "^11.14.1",
|
|
39
|
-
"@iobroker/gui-components": "^10.2.
|
|
39
|
+
"@iobroker/gui-components": "^10.2.3",
|
|
40
40
|
"@mui/icons-material": "^9.0.1",
|
|
41
41
|
"@mui/material": "^9.0.1",
|
|
42
42
|
"react": "^19.2.5",
|
|
@@ -877,6 +877,19 @@ You can find the migration instructions:
|
|
|
877
877
|
-->
|
|
878
878
|
|
|
879
879
|
## Changelog
|
|
880
|
+
### 10.2.3 (2026-09-04)
|
|
881
|
+
|
|
882
|
+
- (@GermanBluefox) Fixed: Expert button highlighted in the object browser
|
|
883
|
+
|
|
884
|
+
### 10.2.2 (2026-09-03)
|
|
885
|
+
|
|
886
|
+
- (@GermanBluefox) Fixed: the object browser lost the column widths as soon as the page was left and opened again. Every width class has its own widths, and the stored ones were written into the class that was guessed before the container was measured, so the table fell back to the defaults of the class it really had: https://github.com/ioBroker/ioBroker.admin/issues/3616
|
|
887
|
+
- (@GermanBluefox) Fixed: after reopening the object browser, the next resize stored only the two columns it touched and dropped every other width the user had set
|
|
888
|
+
- (@GermanBluefox) Fixed: with "Auto" switched off, the checkboxes for "Changed from", "Quality code", "Timestamp" and "Last change" had no effect, and the header of the states view showed those columns although the rows had no cells for them
|
|
889
|
+
- (@GermanBluefox) Fixed: the buttons column could not be resized, as neither it nor the value column in front of it had a resize handle
|
|
890
|
+
- (@GermanBluefox) Fixed: switching "Auto" off did not store the column selection, so after a reload the table showed nothing but the ID column
|
|
891
|
+
- (@GermanBluefox) A double click on a resize handle resets the widths of all width classes now, not only of the current one
|
|
892
|
+
|
|
880
893
|
### 10.2.1 (2026-08-31)
|
|
881
894
|
|
|
882
895
|
- (@GermanBluefox) Changed layouts for some components
|
|
@@ -32,6 +32,8 @@ export declare class ObjectBrowserClass extends Component<ObjectBrowserProps, Ob
|
|
|
32
32
|
private observedContainer;
|
|
33
33
|
/** Width class for which the columns were calculated the last time */
|
|
34
34
|
private lastCalculatedWidth;
|
|
35
|
+
/** States view for which the columns were calculated the last time */
|
|
36
|
+
private lastCalculatedStatesView;
|
|
35
37
|
private pausedSubscribes;
|
|
36
38
|
/** The tree was rebuilt while subscribes were paused, so the filter must be re-applied on resume */
|
|
37
39
|
private treeRebuiltWhilePaused;
|
|
@@ -74,7 +76,12 @@ export declare class ObjectBrowserClass extends Component<ObjectBrowserProps, Ob
|
|
|
74
76
|
private resizerPosition;
|
|
75
77
|
private resizerActiveDiv;
|
|
76
78
|
private resizerNextDiv;
|
|
77
|
-
|
|
79
|
+
/**
|
|
80
|
+
* The column widths the user stored for this dialog, as they were written to
|
|
81
|
+
* `<dialogName>.table`. They are kept independently of the width class, because the class is
|
|
82
|
+
* only known after the container was measured and changes when the window is resized.
|
|
83
|
+
*/
|
|
84
|
+
private storedColumnWidths;
|
|
78
85
|
systemConfig: ioBroker.SystemConfigObject | null;
|
|
79
86
|
objects: Record<string, ioBroker.Object>;
|
|
80
87
|
defaultHistory: string;
|
|
@@ -128,6 +135,15 @@ export declare class ObjectBrowserClass extends Component<ObjectBrowserProps, Ob
|
|
|
128
135
|
initValue: boolean | number | string;
|
|
129
136
|
};
|
|
130
137
|
constructor(props: ObjectBrowserProps);
|
|
138
|
+
/**
|
|
139
|
+
* Write the stored column widths into the width class that is active now.
|
|
140
|
+
*
|
|
141
|
+
* Every width class has its own default widths, and the class of the object browser is only
|
|
142
|
+
* known after its container was measured - in the constructor it is still the initial guess.
|
|
143
|
+
* The stored widths must therefore be applied again whenever the class changes, otherwise the
|
|
144
|
+
* table falls back to the defaults of the new class and the user sees their widths reset.
|
|
145
|
+
*/
|
|
146
|
+
applyStoredWidths(): void;
|
|
131
147
|
loadAllObjects(update?: boolean): Promise<void>;
|
|
132
148
|
expandAllSelected(cb?: () => void): void;
|
|
133
149
|
/**
|
|
@@ -53,6 +53,8 @@ export class ObjectBrowserClass extends Component {
|
|
|
53
53
|
observedContainer = null;
|
|
54
54
|
/** Width class for which the columns were calculated the last time */
|
|
55
55
|
lastCalculatedWidth = null;
|
|
56
|
+
/** States view for which the columns were calculated the last time */
|
|
57
|
+
lastCalculatedStatesView = null;
|
|
56
58
|
pausedSubscribes = false;
|
|
57
59
|
/** The tree was rebuilt while subscribes were paused, so the filter must be re-applied on resume */
|
|
58
60
|
treeRebuiltWhilePaused = false;
|
|
@@ -95,7 +97,12 @@ export class ObjectBrowserClass extends Component {
|
|
|
95
97
|
resizerPosition = 0;
|
|
96
98
|
resizerActiveDiv = null;
|
|
97
99
|
resizerNextDiv = null;
|
|
98
|
-
|
|
100
|
+
/**
|
|
101
|
+
* The column widths the user stored for this dialog, as they were written to
|
|
102
|
+
* `<dialogName>.table`. They are kept independently of the width class, because the class is
|
|
103
|
+
* only known after the container was measured and changes when the window is resized.
|
|
104
|
+
*/
|
|
105
|
+
storedColumnWidths = null;
|
|
99
106
|
systemConfig = null;
|
|
100
107
|
objects;
|
|
101
108
|
defaultHistory = '';
|
|
@@ -355,29 +362,51 @@ export class ObjectBrowserClass extends Component {
|
|
|
355
362
|
const resizerCurrentWidthsStr = this.localStorage.getItem(`${this.props.dialogName || 'App'}.table`);
|
|
356
363
|
if (resizerCurrentWidthsStr) {
|
|
357
364
|
try {
|
|
358
|
-
const
|
|
359
|
-
const
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
this.screenWidths[width].idWidth = resizerCurrentWidths.id;
|
|
364
|
-
}
|
|
365
|
-
else if (id === 'nameHeader') {
|
|
366
|
-
// widths stored by an older version, where the header had an own width
|
|
367
|
-
this.screenWidths[width].widths.name = resizerCurrentWidths[id];
|
|
368
|
-
}
|
|
369
|
-
else if (this.screenWidths[width].widths[id] !== undefined) {
|
|
370
|
-
this.screenWidths[width].widths[id] = resizerCurrentWidths[id];
|
|
371
|
-
}
|
|
365
|
+
const parsed = JSON.parse(resizerCurrentWidthsStr);
|
|
366
|
+
const storedColumnWidths = {};
|
|
367
|
+
Object.keys(parsed).forEach(id => {
|
|
368
|
+
// widths stored by an older version, where the header had an own width
|
|
369
|
+
storedColumnWidths[id === 'nameHeader' ? 'name' : id] = parsed[id];
|
|
372
370
|
});
|
|
373
|
-
this.
|
|
371
|
+
this.storedColumnWidths = storedColumnWidths;
|
|
372
|
+
// The resizer has to start from the stored widths too. Without them the next drag
|
|
373
|
+
// would write only the two columns it touched back to the storage, and every other
|
|
374
|
+
// width the user had set would be lost.
|
|
375
|
+
this.resizerCurrentWidths = { ...storedColumnWidths };
|
|
374
376
|
}
|
|
375
377
|
catch {
|
|
376
|
-
|
|
378
|
+
this.storedColumnWidths = null;
|
|
377
379
|
}
|
|
378
380
|
}
|
|
381
|
+
this.applyStoredWidths();
|
|
379
382
|
this.calculateColumnsVisibility();
|
|
380
383
|
}
|
|
384
|
+
/**
|
|
385
|
+
* Write the stored column widths into the width class that is active now.
|
|
386
|
+
*
|
|
387
|
+
* Every width class has its own default widths, and the class of the object browser is only
|
|
388
|
+
* known after its container was measured - in the constructor it is still the initial guess.
|
|
389
|
+
* The stored widths must therefore be applied again whenever the class changes, otherwise the
|
|
390
|
+
* table falls back to the defaults of the new class and the user sees their widths reset.
|
|
391
|
+
*/
|
|
392
|
+
applyStoredWidths() {
|
|
393
|
+
if (!this.storedColumnWidths) {
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
const screen = this.screenWidths[this.width || 'lg'];
|
|
397
|
+
const storedColumnWidths = this.storedColumnWidths;
|
|
398
|
+
Object.keys(storedColumnWidths).forEach(id => {
|
|
399
|
+
if (id === 'id') {
|
|
400
|
+
screen.idWidth = storedColumnWidths.id;
|
|
401
|
+
}
|
|
402
|
+
else if (screen.widths[id] !== undefined) {
|
|
403
|
+
// A column that this width class does not know keeps its place; only the widths of
|
|
404
|
+
// the columns the class actually shows may be overwritten.
|
|
405
|
+
screen.widths[id] = storedColumnWidths[id];
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
this.customWidth = true;
|
|
409
|
+
}
|
|
381
410
|
async loadAllObjects(update) {
|
|
382
411
|
const props = this.props;
|
|
383
412
|
try {
|
|
@@ -1873,30 +1902,45 @@ export class ObjectBrowserClass extends Component {
|
|
|
1873
1902
|
}
|
|
1874
1903
|
else {
|
|
1875
1904
|
const width = this.width || 'lg';
|
|
1905
|
+
/**
|
|
1906
|
+
* A row shows either type/role/room/function or the four columns of the states view,
|
|
1907
|
+
* never both. A column of the set that is not shown must have the width zero, so that
|
|
1908
|
+
* the ID column, which fills the rest of the row, gets the right place.
|
|
1909
|
+
*/
|
|
1910
|
+
const shown = (name, inStatesView) => !!this.state.statesView === inStatesView && columns.includes(name);
|
|
1911
|
+
/** Width of one column: what the user set for it, else the default of the width class */
|
|
1912
|
+
const widthOf = (name) => columnsWidths[name] || WIDTHS[name] || 0;
|
|
1913
|
+
/**
|
|
1914
|
+
* The width classes below `lg` do not define the columns of the states view, but the
|
|
1915
|
+
* user can select them by hand there too, so they fall back to the widest class.
|
|
1916
|
+
*/
|
|
1917
|
+
const statesWidthOf = (name) => widthOf(name) || this.screenWidths.xl.widths[name] || 0;
|
|
1876
1918
|
this.columnsVisibility = {
|
|
1877
1919
|
id: columnsWidths.id || this.screenWidths[width].idWidth,
|
|
1878
|
-
name: columns.includes('name')
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
func: columns.includes('func')
|
|
1891
|
-
? columnsWidths.func || WIDTHS.func || this.screenWidths[width].widths.func || 0
|
|
1892
|
-
: 0,
|
|
1920
|
+
name: columns.includes('name') ? widthOf('name') : 0,
|
|
1921
|
+
type: shown('type', false) ? widthOf('type') : 0,
|
|
1922
|
+
role: shown('role', false) ? widthOf('role') : 0,
|
|
1923
|
+
room: shown('room', false) ? widthOf('room') : 0,
|
|
1924
|
+
func: shown('func', false) ? widthOf('func') : 0,
|
|
1925
|
+
// The states view columns were missing here completely: their checkboxes in the
|
|
1926
|
+
// configuration dialog had no effect, and the header showed them although no row
|
|
1927
|
+
// had a cell for them.
|
|
1928
|
+
changedFrom: shown('changedFrom', true) ? statesWidthOf('changedFrom') : 0,
|
|
1929
|
+
qualityCode: shown('qualityCode', true) ? statesWidthOf('qualityCode') : 0,
|
|
1930
|
+
timestamp: shown('timestamp', true) ? statesWidthOf('timestamp') : 0,
|
|
1931
|
+
lastChange: shown('lastChange', true) ? statesWidthOf('lastChange') : 0,
|
|
1893
1932
|
};
|
|
1894
1933
|
let widthSum = this.columnsVisibility.id; // id is always visible
|
|
1895
1934
|
if (this.columnsVisibility.name) {
|
|
1935
|
+
// Only one of the two sets has a width, so both may be added up
|
|
1896
1936
|
widthSum += this.columnsVisibility.type || 0;
|
|
1897
1937
|
widthSum += this.columnsVisibility.role || 0;
|
|
1898
1938
|
widthSum += this.columnsVisibility.room || 0;
|
|
1899
1939
|
widthSum += this.columnsVisibility.func || 0;
|
|
1940
|
+
widthSum += this.columnsVisibility.changedFrom || 0;
|
|
1941
|
+
widthSum += this.columnsVisibility.qualityCode || 0;
|
|
1942
|
+
widthSum += this.columnsVisibility.timestamp || 0;
|
|
1943
|
+
widthSum += this.columnsVisibility.lastChange || 0;
|
|
1900
1944
|
}
|
|
1901
1945
|
if (columnsForAdmin && columns) {
|
|
1902
1946
|
Object.keys(columnsForAdmin)
|
|
@@ -2049,6 +2093,10 @@ export class ObjectBrowserClass extends Component {
|
|
|
2049
2093
|
}
|
|
2050
2094
|
};
|
|
2051
2095
|
resizerMouseUp = () => {
|
|
2096
|
+
// Remember the new widths for the other width classes as well: the drag only changed two CSS
|
|
2097
|
+
// variables, the width class of the container may change at any time afterwards.
|
|
2098
|
+
this.storedColumnWidths = { ...this.resizerCurrentWidths };
|
|
2099
|
+
this.applyStoredWidths();
|
|
2052
2100
|
this.localStorage.setItem(`${this.props.dialogName || 'App'}.table`, JSON.stringify(this.resizerCurrentWidths));
|
|
2053
2101
|
this.resizerActiveName = null;
|
|
2054
2102
|
this.resizerNextName = null;
|
|
@@ -2058,7 +2106,6 @@ export class ObjectBrowserClass extends Component {
|
|
|
2058
2106
|
window.removeEventListener('mouseup', this.resizerMouseUp);
|
|
2059
2107
|
};
|
|
2060
2108
|
resizerMouseDown = (e) => {
|
|
2061
|
-
this.storedWidths ||= JSON.parse(JSON.stringify(this.screenWidths[this.width || 'lg']));
|
|
2062
2109
|
this.resizerCurrentWidths ||= {};
|
|
2063
2110
|
this.resizerActiveDiv = e.target.parentNode;
|
|
2064
2111
|
this.resizerActiveName = this.resizerActiveDiv.dataset.name || null;
|
|
@@ -2085,6 +2132,12 @@ export class ObjectBrowserClass extends Component {
|
|
|
2085
2132
|
i++;
|
|
2086
2133
|
} */
|
|
2087
2134
|
}
|
|
2135
|
+
if (!this.resizerNextDiv) {
|
|
2136
|
+
// The column is the last one of the row, there is no neighbour to take the place from
|
|
2137
|
+
this.resizerActiveDiv = null;
|
|
2138
|
+
this.resizerActiveName = null;
|
|
2139
|
+
return;
|
|
2140
|
+
}
|
|
2088
2141
|
this.resizerNextName = this.resizerNextDiv.dataset.name || null;
|
|
2089
2142
|
this.resizerMin = parseInt(this.resizerActiveDiv.dataset.min, 10) || 0;
|
|
2090
2143
|
this.resizerNextMin = parseInt(this.resizerNextDiv.dataset.min, 10) || 0;
|
|
@@ -2167,7 +2220,13 @@ export class ObjectBrowserClass extends Component {
|
|
|
2167
2220
|
}
|
|
2168
2221
|
resizerReset = () => {
|
|
2169
2222
|
this.customWidth = false;
|
|
2170
|
-
this.
|
|
2223
|
+
this.storedColumnWidths = null;
|
|
2224
|
+
this.resizerCurrentWidths = {};
|
|
2225
|
+
// Back to the defaults of every width class, not only of the one that is active now - the
|
|
2226
|
+
// stored widths had been applied to every class the user had the browser open in.
|
|
2227
|
+
Object.keys(SCREEN_WIDTHS).forEach(width => {
|
|
2228
|
+
this.screenWidths[width] = JSON.parse(JSON.stringify(SCREEN_WIDTHS[width]));
|
|
2229
|
+
});
|
|
2171
2230
|
this.calculateColumnsVisibility();
|
|
2172
2231
|
this.localStorage.removeItem(`${this.props.dialogName || 'App'}.table`);
|
|
2173
2232
|
this.forceUpdate();
|
|
@@ -2381,9 +2440,13 @@ export class ObjectBrowserClass extends Component {
|
|
|
2381
2440
|
if (!this.state.loaded) {
|
|
2382
2441
|
return React.createElement(LinearProgress, { key: `${this.props.dialogName}_c` });
|
|
2383
2442
|
}
|
|
2384
|
-
// the container was resized into another width class => other columns are visible
|
|
2385
|
-
|
|
2443
|
+
// the container was resized into another width class => other columns are visible, and the
|
|
2444
|
+
// stored widths have to be written into the defaults of the new class.
|
|
2445
|
+
// The states view shows other columns too, so it has to be recalculated as well.
|
|
2446
|
+
if (this.lastCalculatedWidth !== this.width || this.lastCalculatedStatesView !== this.state.statesView) {
|
|
2386
2447
|
this.lastCalculatedWidth = this.width;
|
|
2448
|
+
this.lastCalculatedStatesView = this.state.statesView;
|
|
2449
|
+
this.applyStoredWidths();
|
|
2387
2450
|
this.calculateColumnsVisibility();
|
|
2388
2451
|
}
|
|
2389
2452
|
const items = this.root ? this.renderItem(this.root, undefined) : null;
|