@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
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
Fab,
|
|
22
22
|
FormControl,
|
|
23
23
|
FormControlLabel,
|
|
24
|
-
|
|
24
|
+
Grid2,
|
|
25
25
|
IconButton,
|
|
26
26
|
Input,
|
|
27
27
|
List,
|
|
@@ -275,6 +275,8 @@ interface TreeInfo {
|
|
|
275
275
|
customs: string[];
|
|
276
276
|
enums: string[];
|
|
277
277
|
hasSomeCustoms: boolean;
|
|
278
|
+
// List of all aliases that shows to this state
|
|
279
|
+
aliasesMap: { [stateId: string]: string[] };
|
|
278
280
|
}
|
|
279
281
|
|
|
280
282
|
interface GetValueStyleOptions {
|
|
@@ -986,7 +988,7 @@ function walkThroughArray(object: any[], iteratee: (result: any[], value: any, k
|
|
|
986
988
|
*/
|
|
987
989
|
function walkThroughObject(
|
|
988
990
|
object: Record<string, any>,
|
|
989
|
-
iteratee: (result: Record<string, any>, value: any, key: string) => void
|
|
991
|
+
iteratee: (result: Record<string, any>, value: any, key: string) => void,
|
|
990
992
|
): Record<string, any> {
|
|
991
993
|
const copiedObject: Record<string, any> = {};
|
|
992
994
|
for (const key in object) {
|
|
@@ -1533,13 +1535,14 @@ function buildTree(
|
|
|
1533
1535
|
const info: TreeInfo = {
|
|
1534
1536
|
funcEnums: [],
|
|
1535
1537
|
roomEnums: [],
|
|
1536
|
-
roles:
|
|
1537
|
-
ids:
|
|
1538
|
-
types:
|
|
1538
|
+
roles: [],
|
|
1539
|
+
ids: [],
|
|
1540
|
+
types: [],
|
|
1539
1541
|
objects,
|
|
1540
|
-
customs:
|
|
1541
|
-
enums:
|
|
1542
|
+
customs: ['_'],
|
|
1543
|
+
enums: [],
|
|
1542
1544
|
hasSomeCustoms: false,
|
|
1545
|
+
aliasesMap: {},
|
|
1543
1546
|
};
|
|
1544
1547
|
|
|
1545
1548
|
let cRoot: TreeItem = root;
|
|
@@ -1573,6 +1576,35 @@ function buildTree(
|
|
|
1573
1576
|
info.hasSomeCustoms = true;
|
|
1574
1577
|
info.customs.push(id.substring('system.adapter.'.length));
|
|
1575
1578
|
}
|
|
1579
|
+
|
|
1580
|
+
// Build a map of aliases
|
|
1581
|
+
if (id.startsWith('alias.') && obj.common.alias?.id) {
|
|
1582
|
+
if (typeof obj.common.alias.id === 'string') {
|
|
1583
|
+
const usedId = obj.common.alias.id;
|
|
1584
|
+
if (!info.aliasesMap[usedId]) {
|
|
1585
|
+
info.aliasesMap[usedId] = [id];
|
|
1586
|
+
} else if (!info.aliasesMap[usedId].includes(id)) {
|
|
1587
|
+
info.aliasesMap[usedId].push(id);
|
|
1588
|
+
}
|
|
1589
|
+
} else {
|
|
1590
|
+
const readId = obj.common.alias.id.read;
|
|
1591
|
+
if (readId) {
|
|
1592
|
+
if (!info.aliasesMap[readId]) {
|
|
1593
|
+
info.aliasesMap[readId] = [id];
|
|
1594
|
+
} else if (!info.aliasesMap[readId].includes(id)) {
|
|
1595
|
+
info.aliasesMap[readId].push(id);
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
const writeId = obj.common.alias.id.write;
|
|
1599
|
+
if (writeId) {
|
|
1600
|
+
if (!info.aliasesMap[writeId]) {
|
|
1601
|
+
info.aliasesMap[writeId] = [id];
|
|
1602
|
+
} else if (!info.aliasesMap[writeId].includes(id)) {
|
|
1603
|
+
info.aliasesMap[writeId].push(id);
|
|
1604
|
+
}
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1576
1608
|
}
|
|
1577
1609
|
|
|
1578
1610
|
info.ids.push(id);
|
|
@@ -2016,12 +2048,13 @@ function formatValue(
|
|
|
2016
2048
|
* Get CSS style for given state value
|
|
2017
2049
|
*/
|
|
2018
2050
|
function getValueStyle(options: GetValueStyleOptions): { color: string } {
|
|
2019
|
-
const { state, isExpertMode, isButton } = options;
|
|
2020
|
-
|
|
2051
|
+
const { state /* , isExpertMode, isButton */ } = options;
|
|
2052
|
+
const color = state?.ack ? (state.q ? '#ffa500' : '') : '#ff2222c9';
|
|
2021
2053
|
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2054
|
+
// do not show the color of the button in non-expert mode
|
|
2055
|
+
// if (!isExpertMode && isButton) {
|
|
2056
|
+
// color = '';
|
|
2057
|
+
// }
|
|
2025
2058
|
|
|
2026
2059
|
return { color };
|
|
2027
2060
|
}
|
|
@@ -2448,7 +2481,12 @@ interface ObjectBrowserState {
|
|
|
2448
2481
|
showAllExportOptions: boolean;
|
|
2449
2482
|
linesEnabled: boolean;
|
|
2450
2483
|
showDescription: boolean;
|
|
2451
|
-
showContextMenu: {
|
|
2484
|
+
showContextMenu: {
|
|
2485
|
+
item: TreeItem;
|
|
2486
|
+
position: { left: number; top: number };
|
|
2487
|
+
subItem?: string;
|
|
2488
|
+
subAnchor?: HTMLLIElement;
|
|
2489
|
+
} | null;
|
|
2452
2490
|
noStatesByExportImport: boolean;
|
|
2453
2491
|
beautifyJsonExport: boolean;
|
|
2454
2492
|
excludeSystemRepositoriesFromExport: boolean;
|
|
@@ -2460,6 +2498,8 @@ interface ObjectBrowserState {
|
|
|
2460
2498
|
modalEditOfAccessObjData?: TreeItemData;
|
|
2461
2499
|
updateOpened?: boolean;
|
|
2462
2500
|
tooltipInfo: null | { el: React.JSX.Element[]; id: string };
|
|
2501
|
+
/** Show the menu with aliases for state */
|
|
2502
|
+
aliasMenu: string;
|
|
2463
2503
|
}
|
|
2464
2504
|
|
|
2465
2505
|
export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrowserState> {
|
|
@@ -2761,6 +2801,7 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
2761
2801
|
excludeSystemRepositoriesFromExport: true,
|
|
2762
2802
|
excludeTranslations: false,
|
|
2763
2803
|
tooltipInfo: null,
|
|
2804
|
+
aliasMenu: '',
|
|
2764
2805
|
};
|
|
2765
2806
|
|
|
2766
2807
|
this.texts = {
|
|
@@ -2908,6 +2949,7 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
2908
2949
|
if (typeof props.filterFunc === 'function') {
|
|
2909
2950
|
this.objects = {};
|
|
2910
2951
|
const filterFunc: (obj: ioBroker.Object) => boolean = props.filterFunc;
|
|
2952
|
+
|
|
2911
2953
|
Object.keys(objects).forEach(id => {
|
|
2912
2954
|
try {
|
|
2913
2955
|
if (filterFunc(objects[id])) {
|
|
@@ -2933,6 +2975,7 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
2933
2975
|
} else if (props.types) {
|
|
2934
2976
|
this.objects = {};
|
|
2935
2977
|
const propsTypes = props.types;
|
|
2978
|
+
|
|
2936
2979
|
Object.keys(objects).forEach(id => {
|
|
2937
2980
|
const type = objects[id] && objects[id].type;
|
|
2938
2981
|
// include "folder" types too
|
|
@@ -3166,7 +3209,12 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
3166
3209
|
// console.log(`CONTEXT MENU: ${this.contextMenu ? Date.now() - this.contextMenu.ts : 'false'}`);
|
|
3167
3210
|
if (this.contextMenu && Date.now() - this.contextMenu.ts < 2000) {
|
|
3168
3211
|
e.preventDefault();
|
|
3169
|
-
this.setState({
|
|
3212
|
+
this.setState({
|
|
3213
|
+
showContextMenu: {
|
|
3214
|
+
item: this.contextMenu.item,
|
|
3215
|
+
position: { left: e.clientX + 2, top: e.clientY - 6 },
|
|
3216
|
+
},
|
|
3217
|
+
});
|
|
3170
3218
|
} else if (this.state.showContextMenu) {
|
|
3171
3219
|
e.preventDefault();
|
|
3172
3220
|
this.setState({ showContextMenu: null });
|
|
@@ -3667,7 +3715,7 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
3667
3715
|
cColumns = null;
|
|
3668
3716
|
}
|
|
3669
3717
|
|
|
3670
|
-
if (cColumns
|
|
3718
|
+
if (cColumns && cColumns.length) {
|
|
3671
3719
|
columnsForAdmin = columnsForAdmin || {};
|
|
3672
3720
|
columnsForAdmin[obj.common.name] = cColumns.sort((a, b) =>
|
|
3673
3721
|
(a.path > b.path ? -1 : a.path < b.path ? 1 : 0));
|
|
@@ -3734,6 +3782,50 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
3734
3782
|
}
|
|
3735
3783
|
}
|
|
3736
3784
|
|
|
3785
|
+
// This function is called when the user changes the alias of an object.
|
|
3786
|
+
// It updates the aliasMap and returns true if the aliasMap has changed.
|
|
3787
|
+
updateAliases(aliasId: string): void {
|
|
3788
|
+
if (!this.objects || !this.info?.aliasesMap || !aliasId?.startsWith('alias.')) {
|
|
3789
|
+
return;
|
|
3790
|
+
}
|
|
3791
|
+
// Rebuild aliases map
|
|
3792
|
+
const aliasesIds = Object.keys(this.objects)
|
|
3793
|
+
.filter(id => id.startsWith('alias.0'));
|
|
3794
|
+
|
|
3795
|
+
this.info.aliasesMap = {};
|
|
3796
|
+
|
|
3797
|
+
for (const id of aliasesIds) {
|
|
3798
|
+
const obj = this.objects[id];
|
|
3799
|
+
if (obj?.common?.alias?.id) {
|
|
3800
|
+
if (typeof obj.common.alias.id === 'string') {
|
|
3801
|
+
const usedId = obj.common.alias.id;
|
|
3802
|
+
if (!this.info.aliasesMap[usedId]) {
|
|
3803
|
+
this.info.aliasesMap[usedId] = [id];
|
|
3804
|
+
} else if (!this.info.aliasesMap[usedId].includes(id)) {
|
|
3805
|
+
this.info.aliasesMap[usedId].push(id);
|
|
3806
|
+
}
|
|
3807
|
+
} else {
|
|
3808
|
+
const readId = obj.common.alias.id.read;
|
|
3809
|
+
if (readId) {
|
|
3810
|
+
if (!this.info.aliasesMap[readId]) {
|
|
3811
|
+
this.info.aliasesMap[readId] = [id];
|
|
3812
|
+
} else if (!this.info.aliasesMap[readId].includes(id)) {
|
|
3813
|
+
this.info.aliasesMap[readId].push(id);
|
|
3814
|
+
}
|
|
3815
|
+
}
|
|
3816
|
+
const writeId = obj.common.alias.id.write;
|
|
3817
|
+
if (writeId) {
|
|
3818
|
+
if (!this.info.aliasesMap[writeId]) {
|
|
3819
|
+
this.info.aliasesMap[writeId] = [id];
|
|
3820
|
+
} else if (!this.info.aliasesMap[writeId].includes(id)) {
|
|
3821
|
+
this.info.aliasesMap[writeId].push(id);
|
|
3822
|
+
}
|
|
3823
|
+
}
|
|
3824
|
+
}
|
|
3825
|
+
}
|
|
3826
|
+
}
|
|
3827
|
+
}
|
|
3828
|
+
|
|
3737
3829
|
/**
|
|
3738
3830
|
* Processes a single element in regard to certain filters, columns for admin and updates object dict
|
|
3739
3831
|
* @returns Returns an object containing the new state (if any) and whether the object was filtered.
|
|
@@ -3750,6 +3842,7 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
3750
3842
|
console.log(`> objectChange ${id}`);
|
|
3751
3843
|
const type = obj?.type;
|
|
3752
3844
|
|
|
3845
|
+
// If the object is filtered out, we don't need to update the React state
|
|
3753
3846
|
if (
|
|
3754
3847
|
obj &&
|
|
3755
3848
|
typeof this.props.filterFunc === 'function' &&
|
|
@@ -3764,7 +3857,7 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
3764
3857
|
}
|
|
3765
3858
|
|
|
3766
3859
|
let newInnerState = null;
|
|
3767
|
-
if (id.startsWith('system.adapter.') && obj
|
|
3860
|
+
if (id.startsWith('system.adapter.') && obj?.type === 'adapter') {
|
|
3768
3861
|
const columnsForAdmin: Record<string, CustomAdminColumnStored[]> | null = JSON.parse(JSON.stringify(this.state.columnsForAdmin));
|
|
3769
3862
|
|
|
3770
3863
|
this.parseObjectForAdmins(columnsForAdmin, obj as ioBroker.AdapterObject);
|
|
@@ -3773,12 +3866,17 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
3773
3866
|
newInnerState = { columnsForAdmin };
|
|
3774
3867
|
}
|
|
3775
3868
|
}
|
|
3869
|
+
|
|
3776
3870
|
this.objects = this.objects || {};
|
|
3871
|
+
|
|
3777
3872
|
if (obj) {
|
|
3778
3873
|
this.objects[id] = obj;
|
|
3779
3874
|
} else if (this.objects[id]) {
|
|
3780
3875
|
delete this.objects[id];
|
|
3781
3876
|
}
|
|
3877
|
+
|
|
3878
|
+
this.updateAliases(id);
|
|
3879
|
+
|
|
3782
3880
|
return { newInnerState, filtered: false };
|
|
3783
3881
|
}
|
|
3784
3882
|
|
|
@@ -4650,7 +4748,7 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
4650
4748
|
>
|
|
4651
4749
|
<Tooltip
|
|
4652
4750
|
title={this.props.t('ra_Refresh tree')}
|
|
4653
|
-
|
|
4751
|
+
slotProps={{ popper: { sx: styles.tooltip } }}
|
|
4654
4752
|
>
|
|
4655
4753
|
<div>
|
|
4656
4754
|
<IconButton
|
|
@@ -4664,7 +4762,7 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
4664
4762
|
</Tooltip>
|
|
4665
4763
|
{this.props.showExpertButton && !this.props.expertMode && <Tooltip
|
|
4666
4764
|
title={this.props.t('ra_expertMode')}
|
|
4667
|
-
|
|
4765
|
+
slotProps={{ popper: { sx: styles.tooltip } }}
|
|
4668
4766
|
>
|
|
4669
4767
|
<IconButton
|
|
4670
4768
|
key="expertMode"
|
|
@@ -4677,7 +4775,7 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
4677
4775
|
</Tooltip>}
|
|
4678
4776
|
{!this.props.disableColumnSelector && this.props.width !== 'xs' && <Tooltip
|
|
4679
4777
|
title={this.props.t('ra_Configure')}
|
|
4680
|
-
|
|
4778
|
+
slotProps={{ popper: { sx: styles.tooltip } }}
|
|
4681
4779
|
>
|
|
4682
4780
|
<IconButton
|
|
4683
4781
|
key="columnSelector"
|
|
@@ -4690,7 +4788,7 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
4690
4788
|
</Tooltip>}
|
|
4691
4789
|
{this.props.width !== 'xs' && this.state.expandAllVisible && <Tooltip
|
|
4692
4790
|
title={this.props.t('ra_Expand all nodes')}
|
|
4693
|
-
|
|
4791
|
+
slotProps={{ popper: { sx: styles.tooltip } }}
|
|
4694
4792
|
>
|
|
4695
4793
|
<IconButton key="expandAll" onClick={() => this.onExpandAll()} size="large">
|
|
4696
4794
|
<IconOpen />
|
|
@@ -4698,7 +4796,7 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
4698
4796
|
</Tooltip>}
|
|
4699
4797
|
<Tooltip
|
|
4700
4798
|
title={this.props.t('ra_Collapse all nodes')}
|
|
4701
|
-
|
|
4799
|
+
slotProps={{ popper: { sx: styles.tooltip } }}
|
|
4702
4800
|
>
|
|
4703
4801
|
<IconButton key="collapseAll" onClick={() => this.onCollapseAll()} size="large">
|
|
4704
4802
|
<IconClosed />
|
|
@@ -4706,7 +4804,7 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
4706
4804
|
</Tooltip>
|
|
4707
4805
|
{this.props.width !== 'xs' && <Tooltip
|
|
4708
4806
|
title={this.props.t('ra_Expand one step node')}
|
|
4709
|
-
|
|
4807
|
+
slotProps={{ popper: { sx: styles.tooltip } }}
|
|
4710
4808
|
>
|
|
4711
4809
|
<IconButton
|
|
4712
4810
|
key="expandVisible"
|
|
@@ -4732,7 +4830,7 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
4732
4830
|
</Tooltip>}
|
|
4733
4831
|
{this.props.width !== 'xs' && <Tooltip
|
|
4734
4832
|
title={this.props.t('ra_Collapse one step node')}
|
|
4735
|
-
|
|
4833
|
+
slotProps={{ popper: { sx: styles.tooltip } }}
|
|
4736
4834
|
>
|
|
4737
4835
|
<IconButton
|
|
4738
4836
|
key="collapseVisible"
|
|
@@ -4758,7 +4856,7 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
4758
4856
|
</Tooltip>}
|
|
4759
4857
|
{this.props.objectStatesView && <Tooltip
|
|
4760
4858
|
title={this.props.t('ra_Toggle the states view')}
|
|
4761
|
-
|
|
4859
|
+
slotProps={{ popper: { sx: styles.tooltip } }}
|
|
4762
4860
|
>
|
|
4763
4861
|
<IconButton onClick={() => this.onStatesViewVisible()} size="large">
|
|
4764
4862
|
<LooksOneIcon color={this.state.statesView ? 'primary' : 'inherit'} />
|
|
@@ -4767,7 +4865,7 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
4767
4865
|
|
|
4768
4866
|
<Tooltip
|
|
4769
4867
|
title={this.props.t('ra_Show/Hide object descriptions')}
|
|
4770
|
-
|
|
4868
|
+
slotProps={{ popper: { sx: styles.tooltip } }}
|
|
4771
4869
|
>
|
|
4772
4870
|
<IconButton
|
|
4773
4871
|
onClick={() => {
|
|
@@ -4785,7 +4883,7 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
4785
4883
|
|
|
4786
4884
|
{this.props.objectAddBoolean ? <Tooltip
|
|
4787
4885
|
title={this.toolTipObjectCreating()}
|
|
4788
|
-
|
|
4886
|
+
slotProps={{ popper: { sx: styles.tooltip } }}
|
|
4789
4887
|
>
|
|
4790
4888
|
<div>
|
|
4791
4889
|
<IconButton
|
|
@@ -4804,7 +4902,7 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
4804
4902
|
|
|
4805
4903
|
{this.props.objectImportExport && <Tooltip
|
|
4806
4904
|
title={this.props.t('ra_Add objects tree from JSON file')}
|
|
4807
|
-
|
|
4905
|
+
slotProps={{ popper: { sx: styles.tooltip } }}
|
|
4808
4906
|
>
|
|
4809
4907
|
<IconButton
|
|
4810
4908
|
onClick={() => {
|
|
@@ -4824,7 +4922,7 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
4824
4922
|
(!!this.state.selected.length || this.state.selectedNonObject) &&
|
|
4825
4923
|
<Tooltip
|
|
4826
4924
|
title={this.props.t('ra_Save objects tree as JSON file')}
|
|
4827
|
-
|
|
4925
|
+
slotProps={{ popper: { sx: styles.tooltip } }}
|
|
4828
4926
|
>
|
|
4829
4927
|
<IconButton
|
|
4830
4928
|
onClick={() =>
|
|
@@ -4844,7 +4942,7 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
4844
4942
|
</div>}
|
|
4845
4943
|
{this.props.objectEditBoolean && <Tooltip
|
|
4846
4944
|
title={this.props.t('ra_Edit custom config')}
|
|
4847
|
-
|
|
4945
|
+
slotProps={{ popper: { sx: styles.tooltip } }}
|
|
4848
4946
|
>
|
|
4849
4947
|
<IconButton
|
|
4850
4948
|
onClick={() => {
|
|
@@ -5049,7 +5147,7 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
5049
5147
|
this.state.filter.expertMode && this.props.objectEditOfAccessControl ? <Tooltip
|
|
5050
5148
|
key="acl"
|
|
5051
5149
|
title={item.data.aclTooltip}
|
|
5052
|
-
|
|
5150
|
+
slotProps={{ popper: { sx: styles.tooltip } }}
|
|
5053
5151
|
>
|
|
5054
5152
|
<IconButton
|
|
5055
5153
|
sx={{
|
|
@@ -5378,7 +5476,7 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
5378
5476
|
return <Tooltip
|
|
5379
5477
|
key="value"
|
|
5380
5478
|
title={this.state.tooltipInfo?.el}
|
|
5381
|
-
|
|
5479
|
+
slotProps={{
|
|
5382
5480
|
popper: { sx: styles.cellValueTooltipBox },
|
|
5383
5481
|
tooltip: { sx: styles.cellValueTooltip },
|
|
5384
5482
|
}}
|
|
@@ -5544,6 +5642,7 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
5544
5642
|
}
|
|
5545
5643
|
this.setState({ enumDialogEnums });
|
|
5546
5644
|
}}
|
|
5645
|
+
secondaryAction={icon}
|
|
5547
5646
|
>
|
|
5548
5647
|
<ListItemIcon sx={{ '&.MuiListItemIcon-root': styles.enumCheckbox }}>
|
|
5549
5648
|
<Checkbox
|
|
@@ -5555,7 +5654,6 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
5555
5654
|
/>
|
|
5556
5655
|
</ListItemIcon>
|
|
5557
5656
|
<ListItemText id={labelId}>{name}</ListItemText>
|
|
5558
|
-
{icon ? <ListItemSecondaryAction>{icon}</ListItemSecondaryAction> : null}
|
|
5559
5657
|
</ListItem>;
|
|
5560
5658
|
})}
|
|
5561
5659
|
</List>
|
|
@@ -5874,6 +5972,37 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
5874
5972
|
return null;
|
|
5875
5973
|
}
|
|
5876
5974
|
|
|
5975
|
+
renderAliasLink(id: string, index?: number, customStyle?: Record<string, any>): React.JSX.Element | null {
|
|
5976
|
+
// read the type of operation
|
|
5977
|
+
const aliasObj = this.objects[this.info.aliasesMap[id][index]].common.alias.id;
|
|
5978
|
+
if (aliasObj) {
|
|
5979
|
+
index = index || 0;
|
|
5980
|
+
return <Box
|
|
5981
|
+
component="div"
|
|
5982
|
+
onClick={e => {
|
|
5983
|
+
e.stopPropagation();
|
|
5984
|
+
e.preventDefault();
|
|
5985
|
+
const aliasId = this.info.aliasesMap[id][index];
|
|
5986
|
+
// if more than one alias, close the menu
|
|
5987
|
+
if (this.info.aliasesMap[id].length > 1) {
|
|
5988
|
+
this.setState({ aliasMenu: '' });
|
|
5989
|
+
}
|
|
5990
|
+
this.onSelect(aliasId);
|
|
5991
|
+
setTimeout(() => this.expandAllSelected(() => this.scrollToItem(aliasId)), 100);
|
|
5992
|
+
}}
|
|
5993
|
+
sx={customStyle || this.styles.aliasAlone}
|
|
5994
|
+
>
|
|
5995
|
+
<span className="admin-browser-arrow">
|
|
5996
|
+
{(typeof aliasObj === 'string' ||
|
|
5997
|
+
(aliasObj.read === id && aliasObj.write === id)) ? '↔' : (aliasObj.read === id ? '→' : '←')}
|
|
5998
|
+
</span>
|
|
5999
|
+
{this.info.aliasesMap[id][index]}
|
|
6000
|
+
</Box>;
|
|
6001
|
+
}
|
|
6002
|
+
|
|
6003
|
+
return null;
|
|
6004
|
+
}
|
|
6005
|
+
|
|
5877
6006
|
/**
|
|
5878
6007
|
* Renders a leaf.
|
|
5879
6008
|
*/
|
|
@@ -5996,60 +6125,81 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
5996
6125
|
}
|
|
5997
6126
|
}
|
|
5998
6127
|
|
|
5999
|
-
|
|
6000
|
-
|
|
6001
|
-
|
|
6002
|
-
|
|
6003
|
-
|
|
6004
|
-
|
|
6005
|
-
|
|
6006
|
-
component="div"
|
|
6007
|
-
onClick={e => {
|
|
6008
|
-
e.stopPropagation();
|
|
6009
|
-
e.preventDefault();
|
|
6010
|
-
this.onSelect(common.alias.id.read);
|
|
6011
|
-
setTimeout(
|
|
6012
|
-
() => this.expandAllSelected(() => this.scrollToItem(common.alias.id.read)),
|
|
6013
|
-
100,
|
|
6014
|
-
);
|
|
6015
|
-
}}
|
|
6016
|
-
sx={this.styles.aliasReadWrite}
|
|
6017
|
-
>
|
|
6018
|
-
←
|
|
6019
|
-
{common.alias.id.read}
|
|
6020
|
-
</Box> : null}
|
|
6021
|
-
{common.alias.id.write ? <Box
|
|
6022
|
-
component="div"
|
|
6023
|
-
onClick={e => {
|
|
6024
|
-
e.stopPropagation();
|
|
6025
|
-
e.preventDefault();
|
|
6026
|
-
this.onSelect(common.alias.id.write);
|
|
6027
|
-
setTimeout(
|
|
6028
|
-
() => this.expandAllSelected(() => this.scrollToItem(common.alias.id.write)),
|
|
6029
|
-
100,
|
|
6030
|
-
);
|
|
6031
|
-
}}
|
|
6032
|
-
sx={this.styles.aliasReadWrite}
|
|
6033
|
-
>
|
|
6034
|
-
→
|
|
6035
|
-
{common.alias.id.write}
|
|
6036
|
-
</Box> : null}
|
|
6037
|
-
</div>
|
|
6038
|
-
:
|
|
6039
|
-
<Box
|
|
6128
|
+
let readWriteAlias: boolean = false;
|
|
6129
|
+
let alias: React.JSX.Element | null = null;
|
|
6130
|
+
if (id.startsWith('alias.') && common?.alias?.id) {
|
|
6131
|
+
readWriteAlias = typeof common.alias.id === 'object';
|
|
6132
|
+
if (readWriteAlias) {
|
|
6133
|
+
alias = <div style={styles.cellIdAliasReadWriteDiv}>
|
|
6134
|
+
{common.alias.id.read ? <Box
|
|
6040
6135
|
component="div"
|
|
6041
6136
|
onClick={e => {
|
|
6042
6137
|
e.stopPropagation();
|
|
6043
6138
|
e.preventDefault();
|
|
6044
|
-
this.onSelect(common.alias.id);
|
|
6045
|
-
setTimeout(
|
|
6139
|
+
this.onSelect(common.alias.id.read);
|
|
6140
|
+
setTimeout(
|
|
6141
|
+
() => this.expandAllSelected(() => this.scrollToItem(common.alias.id.read)),
|
|
6142
|
+
100,
|
|
6143
|
+
);
|
|
6046
6144
|
}}
|
|
6047
|
-
sx={this.styles.
|
|
6145
|
+
sx={this.styles.aliasReadWrite}
|
|
6146
|
+
>
|
|
6147
|
+
←
|
|
6148
|
+
{common.alias.id.read}
|
|
6149
|
+
</Box> : null}
|
|
6150
|
+
{common.alias.id.write ? <Box
|
|
6151
|
+
component="div"
|
|
6152
|
+
onClick={e => {
|
|
6153
|
+
e.stopPropagation();
|
|
6154
|
+
e.preventDefault();
|
|
6155
|
+
this.onSelect(common.alias.id.write);
|
|
6156
|
+
setTimeout(
|
|
6157
|
+
() => this.expandAllSelected(() => this.scrollToItem(common.alias.id.write)),
|
|
6158
|
+
100,
|
|
6159
|
+
);
|
|
6160
|
+
}}
|
|
6161
|
+
sx={this.styles.aliasReadWrite}
|
|
6048
6162
|
>
|
|
6049
6163
|
→
|
|
6050
|
-
{common.alias.id}
|
|
6051
|
-
</Box>
|
|
6052
|
-
|
|
6164
|
+
{common.alias.id.write}
|
|
6165
|
+
</Box> : null}
|
|
6166
|
+
</div>;
|
|
6167
|
+
} else {
|
|
6168
|
+
alias = <Box
|
|
6169
|
+
component="div"
|
|
6170
|
+
onClick={e => {
|
|
6171
|
+
e.stopPropagation();
|
|
6172
|
+
e.preventDefault();
|
|
6173
|
+
this.onSelect(common.alias.id);
|
|
6174
|
+
setTimeout(() => this.expandAllSelected(() => this.scrollToItem(common.alias.id)), 100);
|
|
6175
|
+
}}
|
|
6176
|
+
sx={this.styles.aliasAlone}
|
|
6177
|
+
>
|
|
6178
|
+
→
|
|
6179
|
+
{common.alias.id}
|
|
6180
|
+
</Box>;
|
|
6181
|
+
}
|
|
6182
|
+
} else if (this.info.aliasesMap[id]) {
|
|
6183
|
+
// Some alias points to this object. It can be more than one
|
|
6184
|
+
if (this.info.aliasesMap[id].length > 1) {
|
|
6185
|
+
// Show number of aliases and open a menu by click
|
|
6186
|
+
alias = <Box
|
|
6187
|
+
component="div"
|
|
6188
|
+
id={`alias_${id}`}
|
|
6189
|
+
onClick={e => {
|
|
6190
|
+
e.stopPropagation();
|
|
6191
|
+
e.preventDefault();
|
|
6192
|
+
this.setState({ aliasMenu: id });
|
|
6193
|
+
}}
|
|
6194
|
+
sx={this.styles.aliasAlone}
|
|
6195
|
+
>
|
|
6196
|
+
{this.props.t('ra_%s links from aliases', this.info.aliasesMap[id].length)}
|
|
6197
|
+
</Box>;
|
|
6198
|
+
} else {
|
|
6199
|
+
// Show name of alias and open it by click
|
|
6200
|
+
alias = this.renderAliasLink(id, 0);
|
|
6201
|
+
}
|
|
6202
|
+
}
|
|
6053
6203
|
|
|
6054
6204
|
let checkColor = common?.color;
|
|
6055
6205
|
let invertBackground;
|
|
@@ -6209,19 +6359,18 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
6209
6359
|
|
|
6210
6360
|
const narrowStyleWithDetails = this.props.width === 'xs' && this.state.focused === id;
|
|
6211
6361
|
|
|
6212
|
-
const colID = <
|
|
6362
|
+
const colID = <Grid2
|
|
6213
6363
|
container
|
|
6214
6364
|
wrap="nowrap"
|
|
6215
6365
|
direction="row"
|
|
6216
6366
|
sx={styles.cellId}
|
|
6217
6367
|
style={{ width: this.columnsVisibility.id, paddingLeft }}
|
|
6218
6368
|
>
|
|
6219
|
-
<
|
|
6369
|
+
<Grid2 container alignItems="center">
|
|
6220
6370
|
{checkbox}
|
|
6221
6371
|
{iconFolder}
|
|
6222
|
-
</
|
|
6223
|
-
<
|
|
6224
|
-
item
|
|
6372
|
+
</Grid2>
|
|
6373
|
+
<Grid2
|
|
6225
6374
|
style={{
|
|
6226
6375
|
...styles.cellIdSpan,
|
|
6227
6376
|
...(invertBackground ? this.styles.invertedBackground : undefined),
|
|
@@ -6231,17 +6380,17 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
6231
6380
|
>
|
|
6232
6381
|
<Tooltip
|
|
6233
6382
|
title={getIdFieldTooltip(item.data, this.props.lang)}
|
|
6234
|
-
|
|
6383
|
+
slotProps={{ popper: { sx: styles.tooltip } }}
|
|
6235
6384
|
>
|
|
6236
6385
|
<div>{item.data.name}</div>
|
|
6237
6386
|
</Tooltip>
|
|
6238
6387
|
{alias}
|
|
6239
6388
|
{icons}
|
|
6240
|
-
</
|
|
6389
|
+
</Grid2>
|
|
6241
6390
|
<div style={{ ...styles.grow, ...(invertBackground ? this.styles.invertedBackgroundFlex : {}) }} />
|
|
6242
|
-
<
|
|
6391
|
+
<Grid2 container alignItems="center">
|
|
6243
6392
|
{iconItem}
|
|
6244
|
-
</
|
|
6393
|
+
</Grid2>
|
|
6245
6394
|
{this.props.width !== 'xs' ? <div>
|
|
6246
6395
|
<IconCopy
|
|
6247
6396
|
className={narrowStyleWithDetails ? '' : 'copyButton'}
|
|
@@ -6249,7 +6398,7 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
6249
6398
|
onClick={e => this.onCopy(e, id)}
|
|
6250
6399
|
/>
|
|
6251
6400
|
</div> : null}
|
|
6252
|
-
</
|
|
6401
|
+
</Grid2>;
|
|
6253
6402
|
|
|
6254
6403
|
let colName = (narrowStyleWithDetails && name) || this.columnsVisibility.name ? <Box
|
|
6255
6404
|
component="div"
|
|
@@ -6595,7 +6744,7 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
6595
6744
|
colButtons = null;
|
|
6596
6745
|
}
|
|
6597
6746
|
|
|
6598
|
-
const row = <
|
|
6747
|
+
const row = <Grid2
|
|
6599
6748
|
container
|
|
6600
6749
|
direction="row"
|
|
6601
6750
|
wrap="nowrap"
|
|
@@ -6650,7 +6799,7 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
6650
6799
|
{colCustom}
|
|
6651
6800
|
{colValue}
|
|
6652
6801
|
{colButtons}
|
|
6653
|
-
</
|
|
6802
|
+
</Grid2>;
|
|
6654
6803
|
return { row, details: colDetails };
|
|
6655
6804
|
}
|
|
6656
6805
|
|
|
@@ -7470,6 +7619,33 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
7470
7619
|
});
|
|
7471
7620
|
}
|
|
7472
7621
|
|
|
7622
|
+
/** Renders the aliases list for one state (if more than 2) */
|
|
7623
|
+
private renderAliasMenu(): React.JSX.Element | null {
|
|
7624
|
+
if (!this.state.aliasMenu) {
|
|
7625
|
+
return null;
|
|
7626
|
+
}
|
|
7627
|
+
|
|
7628
|
+
return <Menu
|
|
7629
|
+
key="aliasmenu"
|
|
7630
|
+
open={!0}
|
|
7631
|
+
anchorEl={window.document.getElementById(`alias_${this.state.aliasMenu}`)}
|
|
7632
|
+
onClose={() => this.setState({ aliasMenu: '' })}
|
|
7633
|
+
>
|
|
7634
|
+
{this.info.aliasesMap[this.state.aliasMenu].map((aliasId, i) => <MenuItem
|
|
7635
|
+
key={aliasId}
|
|
7636
|
+
onClick={() => this.onSelect(aliasId)}
|
|
7637
|
+
>
|
|
7638
|
+
<ListItemText>
|
|
7639
|
+
{this.renderAliasLink(this.state.aliasMenu, i, {
|
|
7640
|
+
'& .admin-browser-arrow': {
|
|
7641
|
+
mr: '8px',
|
|
7642
|
+
},
|
|
7643
|
+
})}
|
|
7644
|
+
</ListItemText>
|
|
7645
|
+
</MenuItem>)}
|
|
7646
|
+
</Menu>;
|
|
7647
|
+
}
|
|
7648
|
+
|
|
7473
7649
|
/**
|
|
7474
7650
|
* Renders the right mouse button context menu
|
|
7475
7651
|
*/
|
|
@@ -7667,10 +7843,10 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
7667
7843
|
? this.styles.cellButtonsButtonWithCustoms
|
|
7668
7844
|
: styles.cellButtonsButtonWithoutCustoms}
|
|
7669
7845
|
/>,
|
|
7670
|
-
label: this.props.t('ra_Edit alias'),
|
|
7846
|
+
label: this.info.aliasesMap[item.data.id] ? this.props.t('ra_Edit alias') : this.props.t('ra_Create alias'),
|
|
7671
7847
|
onClick: () => {
|
|
7672
7848
|
if (obj?.common?.alias) {
|
|
7673
|
-
this.setState({ editObjectDialog: item.data.id,
|
|
7849
|
+
this.setState({ showContextMenu: null, editObjectDialog: item.data.id, editObjectAlias: true });
|
|
7674
7850
|
} else {
|
|
7675
7851
|
this.setState({ showContextMenu: null, showAliasEditor: item.data.id });
|
|
7676
7852
|
}
|
|
@@ -7749,9 +7925,11 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
7749
7925
|
if (ITEMS[key].subMenu) {
|
|
7750
7926
|
items.push(<MenuItem
|
|
7751
7927
|
key={key}
|
|
7752
|
-
|
|
7928
|
+
href=""
|
|
7929
|
+
onClick={(e: React.MouseEvent<HTMLAnchorElement>) => this.state.showContextMenu && this.setState({
|
|
7753
7930
|
showContextMenu: {
|
|
7754
7931
|
item: this.state.showContextMenu.item,
|
|
7932
|
+
position: this.state.showContextMenu.position,
|
|
7755
7933
|
subItem: key,
|
|
7756
7934
|
subAnchor: e.target as HTMLLIElement,
|
|
7757
7935
|
},
|
|
@@ -7777,7 +7955,12 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
7777
7955
|
anchorEl={this.state.showContextMenu.subAnchor}
|
|
7778
7956
|
onClose={() => {
|
|
7779
7957
|
if (this.state.showContextMenu) {
|
|
7780
|
-
this.setState({
|
|
7958
|
+
this.setState({
|
|
7959
|
+
showContextMenu: {
|
|
7960
|
+
item: this.state.showContextMenu.item,
|
|
7961
|
+
position: this.state.showContextMenu.position,
|
|
7962
|
+
},
|
|
7963
|
+
});
|
|
7781
7964
|
}
|
|
7782
7965
|
this.contextMenu = null;
|
|
7783
7966
|
}}
|
|
@@ -7819,8 +8002,6 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
7819
8002
|
return null;
|
|
7820
8003
|
}
|
|
7821
8004
|
|
|
7822
|
-
const el = document.getElementById(id);
|
|
7823
|
-
|
|
7824
8005
|
return <Menu
|
|
7825
8006
|
key="contextMenu"
|
|
7826
8007
|
open={!0}
|
|
@@ -7834,7 +8015,8 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
7834
8015
|
});
|
|
7835
8016
|
}
|
|
7836
8017
|
}}
|
|
7837
|
-
|
|
8018
|
+
anchorReference="anchorPosition"
|
|
8019
|
+
anchorPosition={this.state.showContextMenu.position}
|
|
7838
8020
|
onClose={() => {
|
|
7839
8021
|
this.setState({ showContextMenu: null });
|
|
7840
8022
|
this.contextMenu = null;
|
|
@@ -8009,6 +8191,7 @@ export class ObjectBrowserClass extends Component<ObjectBrowserProps, ObjectBrow
|
|
|
8009
8191
|
</div>
|
|
8010
8192
|
</TabContent>
|
|
8011
8193
|
{this.renderContextMenu()}
|
|
8194
|
+
{this.renderAliasMenu()}
|
|
8012
8195
|
{this.renderToast()}
|
|
8013
8196
|
{this.renderColumnsEditCustomDialog()}
|
|
8014
8197
|
{this.renderColumnsSelectorDialog()}
|