pixel-react 1.9.4 → 1.9.6
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/.yarn/install-state.gz +0 -0
- package/lib/ComponentProps/TreeNodeProps.d.ts +31 -0
- package/lib/components/Charts/MultiRadialChart/types.d.ts +2 -2
- package/lib/components/TableTree/Components/TableBody.d.ts +1 -1
- package/lib/components/TableTree/types.d.ts +3 -7
- package/lib/components/Tabs/Tabs.d.ts +1 -1
- package/lib/components/Tabs/types.d.ts +1 -0
- package/lib/index.d.ts +51 -11
- package/lib/index.esm.js +125 -34
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +126 -33
- package/lib/index.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/utils/getTreeDetails/getTreeDetails.d.ts +10 -0
- package/lib/utils/handleTreeNodeSelect/handleTreeNodeSelect.d.ts +2 -0
- package/package.json +1 -1
- package/src/ComponentProps/TreeNodeProps.ts +31 -0
- package/src/components/Charts/DashboardDonutChart/DashboardDonutChart.scss +6 -3
- package/src/components/Charts/DashboardDonutChart/DashboardDonutChart.tsx +10 -4
- package/src/components/Charts/MultiRadialChart/types.ts +16 -17
- package/src/components/TableTree/Components/TableBody.tsx +22 -23
- package/src/components/TableTree/Components/TableCell.tsx +3 -3
- package/src/components/TableTree/Components/TableRow.tsx +0 -3
- package/src/components/TableTree/TableTree.scss +11 -1
- package/src/components/TableTree/TableTree.tsx +28 -15
- package/src/components/TableTree/data.ts +86 -1
- package/src/components/TableTree/types.ts +3 -8
- package/src/components/Tabs/Tabs.scss +44 -1
- package/src/components/Tabs/Tabs.stories.tsx +26 -0
- package/src/components/Tabs/Tabs.tsx +2 -0
- package/src/components/Tabs/types.ts +1 -0
- package/src/index.ts +17 -2
- package/src/utils/findAndInsert/findAndInsert.stories.tsx +1 -0
- package/src/utils/getTreeDetails/getTreeDetails.stories.tsx +167 -0
- package/src/utils/getTreeDetails/getTreeDetails.ts +65 -0
- package/src/utils/handleTreeNodeSelect/HandleTreeNodeSelect.stories.tsx +195 -0
- package/src/utils/handleTreeNodeSelect/handleTreeNodeSelect.ts +61 -0
@@ -5,6 +5,7 @@
|
|
5
5
|
box-sizing: border-box;
|
6
6
|
|
7
7
|
.ff-tab-row {
|
8
|
+
flex: 0 1 auto;
|
8
9
|
&--default {
|
9
10
|
display: flex;
|
10
11
|
gap: 8px;
|
@@ -38,11 +39,13 @@
|
|
38
39
|
font-size: 8px;
|
39
40
|
font-weight: 600;
|
40
41
|
padding: 0 2px;
|
42
|
+
|
41
43
|
&--active {
|
42
44
|
background-color: var(--tabs-label-active-color);
|
43
45
|
}
|
44
46
|
}
|
45
47
|
}
|
48
|
+
|
46
49
|
.ff-tab-bar {
|
47
50
|
width: 100%;
|
48
51
|
border-radius: 2px 2px 0 0;
|
@@ -69,8 +72,10 @@
|
|
69
72
|
color: var(--tabs-label-active-color) !important;
|
70
73
|
}
|
71
74
|
}
|
75
|
+
|
72
76
|
.tab-count {
|
73
77
|
background-color: var(--input-hover-border-color);
|
78
|
+
|
74
79
|
&--active {
|
75
80
|
background-color: var(--tabs-label-active-color);
|
76
81
|
}
|
@@ -125,11 +130,48 @@
|
|
125
130
|
&--no-border {
|
126
131
|
border: none;
|
127
132
|
}
|
133
|
+
|
134
|
+
&--no-padding {
|
135
|
+
border-radius: 8px;
|
136
|
+
background: white;
|
137
|
+
padding: 0px;
|
138
|
+
justify-content: flex-start;
|
139
|
+
margin-right: 8px;
|
140
|
+
|
141
|
+
.ff-tab-button {
|
142
|
+
&--capsule {
|
143
|
+
background: transparent;
|
144
|
+
border: none;
|
145
|
+
padding: 3px 4px;
|
146
|
+
border-radius: 7px;
|
147
|
+
cursor: pointer;
|
148
|
+
|
149
|
+
&:hover {
|
150
|
+
.ff-tab-label {
|
151
|
+
color: var(--input-hover-border-color) !important;
|
152
|
+
|
153
|
+
&--active {
|
154
|
+
color: var(--tabs-label-active-color) !important;
|
155
|
+
}
|
156
|
+
}
|
157
|
+
}
|
158
|
+
|
159
|
+
&.active {
|
160
|
+
background-color: var(--slider-table-color);
|
161
|
+
}
|
162
|
+
|
163
|
+
.ff-tab-bar {
|
164
|
+
display: none;
|
165
|
+
}
|
166
|
+
}
|
167
|
+
}
|
168
|
+
}
|
128
169
|
}
|
129
170
|
|
130
171
|
.ff-tab-content {
|
131
172
|
width: inherit;
|
132
173
|
}
|
174
|
+
|
133
175
|
.ff-defaultStatus {
|
134
176
|
position: absolute;
|
135
177
|
top: 2px;
|
@@ -143,9 +185,10 @@
|
|
143
185
|
background-color: var(--confirm-tick-icon-color);
|
144
186
|
box-shadow: 0px 1px 1px 0px var(--toggle-strip-shadow);
|
145
187
|
}
|
188
|
+
|
146
189
|
&.ff-dangerStatus {
|
147
190
|
background-color: var(--delete-text-color);
|
148
191
|
box-shadow: 0px 1px 1px 0px var(--toggle-strip-shadow);
|
149
192
|
}
|
150
193
|
}
|
151
|
-
}
|
194
|
+
}
|
@@ -150,4 +150,30 @@ export const WithoutBorder: Story = {
|
|
150
150
|
},
|
151
151
|
};
|
152
152
|
|
153
|
+
export const WithoutPadding: Story = {
|
154
|
+
render: () => {
|
155
|
+
const [activeTabIdDefault, setActiveTabIdDefault] =
|
156
|
+
useState<string>('tab-1');
|
157
|
+
|
158
|
+
return (
|
159
|
+
<div style={{ display: 'flex', gap: '10px' }}>
|
160
|
+
<Tabs
|
161
|
+
tabsData={tabsData}
|
162
|
+
activeTabId={activeTabIdDefault}
|
163
|
+
onTabClick={setActiveTabIdDefault}
|
164
|
+
noPadding={true}
|
165
|
+
/>{' '}
|
166
|
+
<hr />
|
167
|
+
<Tabs
|
168
|
+
variant="capsule"
|
169
|
+
tabsData={tabsData}
|
170
|
+
activeTabId={activeTabIdDefault}
|
171
|
+
onTabClick={setActiveTabIdDefault}
|
172
|
+
noPadding={true}
|
173
|
+
/>
|
174
|
+
</div>
|
175
|
+
);
|
176
|
+
},
|
177
|
+
};
|
178
|
+
|
153
179
|
export default meta;
|
@@ -10,12 +10,14 @@ const Tabs = ({
|
|
10
10
|
activeTabId,
|
11
11
|
onTabClick,
|
12
12
|
noBorder = false,
|
13
|
+
noPadding = false,
|
13
14
|
}: TabsProps) => {
|
14
15
|
return (
|
15
16
|
<div className={`ff-tabs-container`}>
|
16
17
|
<div
|
17
18
|
className={classNames(`ff-tab-row--${variant}`, {
|
18
19
|
'ff-tab-row--no-border': noBorder,
|
20
|
+
'ff-tab-row--no-padding': noPadding,
|
19
21
|
})}
|
20
22
|
>
|
21
23
|
{tabsData.map((tab) => (
|
package/src/index.ts
CHANGED
@@ -105,7 +105,13 @@ import ConditionalDropdown from './components/ConditionalDropdown/ConditionalDro
|
|
105
105
|
import { hasDuplicateFile } from './utils/checkDuplicates/checkDuplicates';
|
106
106
|
import PhoneInputField from './components/PhoneInput';
|
107
107
|
import { useKeyboardActions } from './utils/keyBoardActionUtil/UseKeyboardActions';
|
108
|
-
import { rearrangeDragItem } from './utils/swapArrayItem/dragAndDropUtils'
|
108
|
+
import { rearrangeDragItem } from './utils/swapArrayItem/dragAndDropUtils';
|
109
|
+
|
110
|
+
import { getTreeDetails } from './utils/getTreeDetails/getTreeDetails';
|
111
|
+
import { handleTreeNodeSect } from './utils/handleTreeNodeSelect/handleTreeNodeSelect';
|
112
|
+
|
113
|
+
import { TreeNodeProps } from './ComponentProps/TreeNodeProps';
|
114
|
+
|
109
115
|
import {
|
110
116
|
EMAIL_REGEX,
|
111
117
|
URL_REGEX,
|
@@ -163,7 +169,10 @@ import {
|
|
163
169
|
ELEMENTS_WHITE_SPACE_REGEX,
|
164
170
|
PARAMETER_ALPHANUMERIC_REGEX,
|
165
171
|
} from './validations/regex';
|
166
|
-
import {
|
172
|
+
import {
|
173
|
+
getFromIndexedDB,
|
174
|
+
saveToIndexedDB,
|
175
|
+
} from './utils/indexDBStore/indexDB';
|
167
176
|
|
168
177
|
export {
|
169
178
|
Button,
|
@@ -275,7 +284,13 @@ export {
|
|
275
284
|
saveToIndexedDB,
|
276
285
|
getFromIndexedDB,
|
277
286
|
rearrangeDragItem,
|
287
|
+
getTreeDetails,
|
288
|
+
handleTreeNodeSect,
|
289
|
+
|
290
|
+
//types
|
291
|
+
TreeNodeProps,
|
278
292
|
|
293
|
+
//Regex
|
279
294
|
EMAIL_REGEX,
|
280
295
|
URL_REGEX,
|
281
296
|
PHONE_REGEX,
|
@@ -0,0 +1,167 @@
|
|
1
|
+
import { useState } from 'react';
|
2
|
+
import { getTreeDetails, TreeNode, TreeDetailsResult } from './getTreeDetails';
|
3
|
+
import React from 'react';
|
4
|
+
|
5
|
+
export default {
|
6
|
+
title: 'Utils/getTreeDetails',
|
7
|
+
component: getTreeDetails,
|
8
|
+
};
|
9
|
+
|
10
|
+
const initialData: TreeNode[] = [
|
11
|
+
{
|
12
|
+
createdBy: 'USR4705',
|
13
|
+
modifiedBy: '--',
|
14
|
+
createdByUname: 'Saqeb',
|
15
|
+
modifiedByUname: '--',
|
16
|
+
createdOn: '2023-05-31T10:54:33.296Z',
|
17
|
+
modifiedOn: '2023-05-31T10:54:33.296Z',
|
18
|
+
state: 'APPROVED',
|
19
|
+
path: '/Root',
|
20
|
+
searchKey: '/PAG1010',
|
21
|
+
key: 'PAG1010',
|
22
|
+
name: 'Root',
|
23
|
+
projectId: 'PJT1006',
|
24
|
+
hierarchy: 0,
|
25
|
+
executionOrder: 0,
|
26
|
+
subContainerCount: 1,
|
27
|
+
resourceCount: 0,
|
28
|
+
totalSubContainerCount: 1,
|
29
|
+
totalResourceCount: 2,
|
30
|
+
totalProjectElementCount: 0,
|
31
|
+
totalSharedElementCount: 0,
|
32
|
+
container: false,
|
33
|
+
localDelete: false,
|
34
|
+
defaultEntity: false,
|
35
|
+
lastResource: false,
|
36
|
+
platform: '',
|
37
|
+
},
|
38
|
+
{
|
39
|
+
createdBy: 'USR4705',
|
40
|
+
modifiedBy: '--',
|
41
|
+
createdByUname: 'Saqeb',
|
42
|
+
modifiedByUname: '--',
|
43
|
+
createdOn: '2023-05-31T10:57:31.721Z',
|
44
|
+
modifiedOn: '2023-05-31T10:57:31.721Z',
|
45
|
+
state: 'APPROVED',
|
46
|
+
path: '/Root/page1',
|
47
|
+
searchKey: '/PAG1010/PAG1011',
|
48
|
+
key: 'PAG1011',
|
49
|
+
name: 'page1',
|
50
|
+
projectId: 'PJT1006',
|
51
|
+
hierarchy: 0,
|
52
|
+
executionOrder: 1,
|
53
|
+
subContainerCount: 0,
|
54
|
+
resourceCount: 3,
|
55
|
+
totalSubContainerCount: 0,
|
56
|
+
totalResourceCount: 1,
|
57
|
+
totalProjectElementCount: 0,
|
58
|
+
totalSharedElementCount: 0,
|
59
|
+
container: false,
|
60
|
+
localDelete: false,
|
61
|
+
defaultEntity: false,
|
62
|
+
lastResource: true,
|
63
|
+
platform: '',
|
64
|
+
},
|
65
|
+
];
|
66
|
+
|
67
|
+
export const InteractivePlayground = () => {
|
68
|
+
const [data, setData] = useState<TreeNode[]>(initialData);
|
69
|
+
const [newData, setNewData] = useState<TreeNode[]>([]);
|
70
|
+
const [action, setAction] = useState<'above' | 'below' | 'expand' | 'collapse' | 'start'>('below');
|
71
|
+
const [index, setIndex] = useState<number | undefined>(undefined);
|
72
|
+
const [result, setResult] = useState<TreeDetailsResult | null>(null);
|
73
|
+
|
74
|
+
const handleGetTreeDetails = () => {
|
75
|
+
try {
|
76
|
+
const treeDetails = getTreeDetails(action, data, newData, index);
|
77
|
+
setData(treeDetails.treeDataList);
|
78
|
+
setResult(treeDetails);
|
79
|
+
} catch (error) {
|
80
|
+
alert(error instanceof Error ? error.message : 'An error occurred');
|
81
|
+
}
|
82
|
+
};
|
83
|
+
|
84
|
+
return (
|
85
|
+
<div>
|
86
|
+
<h1>Interactive Playground for getTreeDetails</h1>
|
87
|
+
|
88
|
+
<div>
|
89
|
+
<label htmlFor="action">Action:</label>
|
90
|
+
<select
|
91
|
+
id="action"
|
92
|
+
value={action}
|
93
|
+
onChange={(e) =>
|
94
|
+
setAction(e.target.value as 'above' | 'below' | 'expand' | 'collapse' | 'start')
|
95
|
+
}
|
96
|
+
>
|
97
|
+
<option value="above">Above</option>
|
98
|
+
<option value="below">Below</option>
|
99
|
+
<option value="expand">Expand</option>
|
100
|
+
<option value="collapse">Collapse</option>
|
101
|
+
<option value="start">Start</option>
|
102
|
+
</select>
|
103
|
+
</div>
|
104
|
+
|
105
|
+
{(action === 'expand' || action === 'collapse') && (
|
106
|
+
<div>
|
107
|
+
<label htmlFor="index">Index (for expand/collapse):</label>
|
108
|
+
<input
|
109
|
+
type="number"
|
110
|
+
id="index"
|
111
|
+
value={index !== undefined ? index : ''}
|
112
|
+
onChange={(e) =>
|
113
|
+
setIndex(e.target.value ? parseInt(e.target.value, 10) : undefined)
|
114
|
+
}
|
115
|
+
disabled={action !== 'expand' && action !== 'collapse'}
|
116
|
+
/>
|
117
|
+
</div>
|
118
|
+
)}
|
119
|
+
|
120
|
+
<div>
|
121
|
+
<label htmlFor="newData">New Data (JSON):</label>
|
122
|
+
<textarea
|
123
|
+
id="newData"
|
124
|
+
value={JSON.stringify(newData, null, 2)}
|
125
|
+
onChange={(e) => {
|
126
|
+
try {
|
127
|
+
setNewData(JSON.parse(e.target.value));
|
128
|
+
} catch {
|
129
|
+
alert('Invalid JSON');
|
130
|
+
}
|
131
|
+
}}
|
132
|
+
/>
|
133
|
+
</div>
|
134
|
+
|
135
|
+
<button onClick={handleGetTreeDetails}>Get Tree Details</button>
|
136
|
+
|
137
|
+
<h2>Result:</h2>
|
138
|
+
{result ? (
|
139
|
+
<div>
|
140
|
+
{result.root && (
|
141
|
+
<>
|
142
|
+
<h3>Root:</h3>
|
143
|
+
<pre>{JSON.stringify(result.root, null, 2)}</pre>
|
144
|
+
</>
|
145
|
+
)}
|
146
|
+
<p>
|
147
|
+
<strong>Next:</strong> {result.next.toString()}
|
148
|
+
</p>
|
149
|
+
<p>
|
150
|
+
<strong>Previous:</strong> {result.previous.toString()}
|
151
|
+
</p>
|
152
|
+
<p>
|
153
|
+
<strong>Start ID:</strong> {result.startId}
|
154
|
+
</p>
|
155
|
+
<p>
|
156
|
+
<strong>End ID:</strong> {result.endId}
|
157
|
+
</p>
|
158
|
+
</div>
|
159
|
+
) : (
|
160
|
+
<p>No result yet. Perform an action to see the details.</p>
|
161
|
+
)}
|
162
|
+
|
163
|
+
<h2>Current Tree Data:</h2>
|
164
|
+
<pre>{JSON.stringify(data, null, 2)}</pre>
|
165
|
+
</div>
|
166
|
+
);
|
167
|
+
};
|
@@ -0,0 +1,65 @@
|
|
1
|
+
import { TreeNodeProps as TreeNode } from '../../ComponentProps/TreeNodeProps';
|
2
|
+
|
3
|
+
export interface TreeDetailsResult {
|
4
|
+
treeDataList: TreeNode[];
|
5
|
+
next: boolean;
|
6
|
+
previous: boolean;
|
7
|
+
startId: string;
|
8
|
+
endId: string;
|
9
|
+
root?: TreeNode;
|
10
|
+
}
|
11
|
+
|
12
|
+
export const getTreeDetails = (
|
13
|
+
action: 'above' | 'below' | 'expand' | 'collapse' | 'start',
|
14
|
+
oldData: TreeNode[],
|
15
|
+
newData: TreeNode[],
|
16
|
+
index?: number
|
17
|
+
): TreeDetailsResult => {
|
18
|
+
let treeDataList: TreeNode[];
|
19
|
+
let root: TreeNode | undefined = undefined;
|
20
|
+
|
21
|
+
switch (action) {
|
22
|
+
case 'above':
|
23
|
+
treeDataList = [...newData, ...oldData].slice(0, 40);
|
24
|
+
break;
|
25
|
+
case 'below':
|
26
|
+
treeDataList = [...oldData, ...newData].slice(0, 40);
|
27
|
+
break;
|
28
|
+
case 'expand':
|
29
|
+
case 'collapse':
|
30
|
+
if (typeof index === 'number') {
|
31
|
+
treeDataList = [...oldData.slice(0, index + 1), ...newData];
|
32
|
+
} else {
|
33
|
+
throw new Error(
|
34
|
+
"Index is required for 'expand' or 'collapse' actions."
|
35
|
+
);
|
36
|
+
}
|
37
|
+
break;
|
38
|
+
case 'start':
|
39
|
+
if (oldData.length > 0) {
|
40
|
+
root = oldData[0];
|
41
|
+
treeDataList = oldData.slice(1);
|
42
|
+
} else {
|
43
|
+
throw new Error('Tree data list is empty, cannot determine root.');
|
44
|
+
}
|
45
|
+
break;
|
46
|
+
default:
|
47
|
+
throw new Error(`Invalid action: ${action}`);
|
48
|
+
}
|
49
|
+
|
50
|
+
if (treeDataList.length === 0 && action !== 'start') {
|
51
|
+
throw new Error('Tree data list is empty.');
|
52
|
+
}
|
53
|
+
|
54
|
+
const firstNode = treeDataList[0] || root!;
|
55
|
+
const lastNode = treeDataList[treeDataList.length - 1]!;
|
56
|
+
|
57
|
+
return {
|
58
|
+
treeDataList,
|
59
|
+
next: !lastNode.lastResource,
|
60
|
+
previous: !firstNode.lastResource,
|
61
|
+
startId: firstNode.key,
|
62
|
+
endId: lastNode.key,
|
63
|
+
root,
|
64
|
+
};
|
65
|
+
};
|
@@ -0,0 +1,195 @@
|
|
1
|
+
import React, { useState } from 'react';
|
2
|
+
import { handleTreeNodeSect, TreeNode } from './handleTreeNodeSelect'; // Ensure this imports the utility function
|
3
|
+
|
4
|
+
export default {
|
5
|
+
title: 'Utils/handleTreeNodeSect',
|
6
|
+
component: handleTreeNodeSect,
|
7
|
+
};
|
8
|
+
|
9
|
+
const initialData: TreeNode[] = [
|
10
|
+
{
|
11
|
+
createdBy: 'USR4705',
|
12
|
+
modifiedBy: '--',
|
13
|
+
createdByUname: 'Saqeb',
|
14
|
+
modifiedByUname: '--',
|
15
|
+
createdOn: '2023-05-31T10:54:33.296Z',
|
16
|
+
modifiedOn: '2023-05-31T10:54:33.296Z',
|
17
|
+
state: 'APPROVED',
|
18
|
+
path: '/Root',
|
19
|
+
searchKey: '/PAG1010',
|
20
|
+
key: 'PAG1010',
|
21
|
+
name: 'Root',
|
22
|
+
projectId: 'PJT1006',
|
23
|
+
hierarchy: 0,
|
24
|
+
executionOrder: 0,
|
25
|
+
subContainerCount: 1,
|
26
|
+
resourceCount: 0,
|
27
|
+
totalSubContainerCount: 1,
|
28
|
+
totalResourceCount: 2,
|
29
|
+
totalProjectElementCount: 0,
|
30
|
+
totalSharedElementCount: 0,
|
31
|
+
container: false,
|
32
|
+
localDelete: false,
|
33
|
+
defaultEntity: false,
|
34
|
+
lastResource: false,
|
35
|
+
platform: '',
|
36
|
+
},
|
37
|
+
{
|
38
|
+
createdBy: 'USR4705',
|
39
|
+
modifiedBy: '--',
|
40
|
+
createdByUname: 'Saqeb',
|
41
|
+
modifiedByUname: '--',
|
42
|
+
createdOn: '2023-05-31T10:57:31.721Z',
|
43
|
+
modifiedOn: '2023-05-31T10:57:31.721Z',
|
44
|
+
state: 'APPROVED',
|
45
|
+
path: '/Root/page1',
|
46
|
+
searchKey: '/PAG1010/PAG1011',
|
47
|
+
parentId: 'PAG1010',
|
48
|
+
parentName: 'Root Page',
|
49
|
+
key: 'PAG1011',
|
50
|
+
name: 'page1',
|
51
|
+
projectId: 'PJT1006',
|
52
|
+
hierarchy: 1,
|
53
|
+
executionOrder: 1,
|
54
|
+
subContainerCount: 0,
|
55
|
+
resourceCount: 3,
|
56
|
+
totalSubContainerCount: 0,
|
57
|
+
totalResourceCount: 1,
|
58
|
+
totalProjectElementCount: 0,
|
59
|
+
totalSharedElementCount: 0,
|
60
|
+
container: false,
|
61
|
+
localDelete: false,
|
62
|
+
defaultEntity: false,
|
63
|
+
lastResource: true,
|
64
|
+
},
|
65
|
+
{
|
66
|
+
createdBy: 'USR4705',
|
67
|
+
modifiedBy: '--',
|
68
|
+
createdByUname: 'Saqeb',
|
69
|
+
modifiedByUname: '--',
|
70
|
+
createdOn: '2023-05-31T11:00:00.000Z',
|
71
|
+
modifiedOn: '2023-05-31T11:00:00.000Z',
|
72
|
+
state: 'APPROVED',
|
73
|
+
path: '/Root/page2',
|
74
|
+
searchKey: '/PAG1010/PAG1012',
|
75
|
+
parentId: 'PAG1010',
|
76
|
+
parentName: 'Root Page',
|
77
|
+
key: 'PAG1012',
|
78
|
+
name: 'page2',
|
79
|
+
projectId: 'PJT1006',
|
80
|
+
hierarchy: 1,
|
81
|
+
executionOrder: 2,
|
82
|
+
subContainerCount: 2,
|
83
|
+
resourceCount: 5,
|
84
|
+
totalSubContainerCount: 2,
|
85
|
+
totalResourceCount: 7,
|
86
|
+
totalProjectElementCount: 0,
|
87
|
+
totalSharedElementCount: 0,
|
88
|
+
container: true,
|
89
|
+
localDelete: false,
|
90
|
+
defaultEntity: false,
|
91
|
+
lastResource: false,
|
92
|
+
},
|
93
|
+
{
|
94
|
+
createdBy: 'USR4705',
|
95
|
+
modifiedBy: '--',
|
96
|
+
createdByUname: 'Saqeb',
|
97
|
+
modifiedByUname: '--',
|
98
|
+
createdOn: '2023-05-31T11:05:00.000Z',
|
99
|
+
modifiedOn: '2023-05-31T11:05:00.000Z',
|
100
|
+
state: 'APPROVED',
|
101
|
+
path: '/Root/page2/subpage1',
|
102
|
+
searchKey: '/PAG1010/PAG1012/PAG1013',
|
103
|
+
parentId: 'PAG1012',
|
104
|
+
parentName: 'page2',
|
105
|
+
key: 'PAG1013',
|
106
|
+
name: 'subpage1',
|
107
|
+
projectId: 'PJT1006',
|
108
|
+
hierarchy: 2,
|
109
|
+
executionOrder: 1,
|
110
|
+
subContainerCount: 0,
|
111
|
+
resourceCount: 2,
|
112
|
+
totalSubContainerCount: 0,
|
113
|
+
totalResourceCount: 2,
|
114
|
+
totalProjectElementCount: 0,
|
115
|
+
totalSharedElementCount: 0,
|
116
|
+
container: false,
|
117
|
+
localDelete: false,
|
118
|
+
defaultEntity: false,
|
119
|
+
lastResource: true,
|
120
|
+
},
|
121
|
+
{
|
122
|
+
createdBy: 'USR4705',
|
123
|
+
modifiedBy: '--',
|
124
|
+
createdByUname: 'Saqeb',
|
125
|
+
modifiedByUname: '--',
|
126
|
+
createdOn: '2023-05-31T11:10:00.000Z',
|
127
|
+
modifiedOn: '2023-05-31T11:10:00.000Z',
|
128
|
+
state: 'APPROVED',
|
129
|
+
path: '/Root/page2/subpage2',
|
130
|
+
searchKey: '/PAG1010/PAG1012/PAG1014',
|
131
|
+
parentId: 'PAG1012',
|
132
|
+
parentName: 'page2',
|
133
|
+
key: 'PAG1014',
|
134
|
+
name: 'subpage2',
|
135
|
+
projectId: 'PJT1006',
|
136
|
+
hierarchy: 2,
|
137
|
+
executionOrder: 2,
|
138
|
+
subContainerCount: 0,
|
139
|
+
resourceCount: 4,
|
140
|
+
totalSubContainerCount: 0,
|
141
|
+
totalResourceCount: 4,
|
142
|
+
totalProjectElementCount: 0,
|
143
|
+
totalSharedElementCount: 0,
|
144
|
+
container: false,
|
145
|
+
localDelete: false,
|
146
|
+
defaultEntity: false,
|
147
|
+
lastResource: true,
|
148
|
+
},
|
149
|
+
// Repeat similar patterns to generate 50 entries, modifying hierarchy, executionOrder, and other attributes as needed.
|
150
|
+
];
|
151
|
+
|
152
|
+
export const InteractiveTreeSelector = () => {
|
153
|
+
const [data, setData] = useState<TreeNode[]>(initialData);
|
154
|
+
const [selectedKey, setSelectedKey] = useState<string>('');
|
155
|
+
const [isChecked, setIsChecked] = useState<boolean>(false);
|
156
|
+
|
157
|
+
const handleUpdateTree = () => {
|
158
|
+
const updatedTree = handleTreeNodeSect(data, selectedKey, isChecked);
|
159
|
+
setData([...updatedTree]);
|
160
|
+
};
|
161
|
+
|
162
|
+
return (
|
163
|
+
<div style={{ fontFamily: 'Arial, sans-serif', padding: '20px' }}>
|
164
|
+
<h1>Interactive Tree Selector</h1>
|
165
|
+
<div>
|
166
|
+
<label htmlFor="nodeKey">Node Key:</label>
|
167
|
+
<input
|
168
|
+
id="nodeKey"
|
169
|
+
type="text"
|
170
|
+
value={selectedKey}
|
171
|
+
onChange={(e) => setSelectedKey(e.target.value)}
|
172
|
+
placeholder="Enter node key"
|
173
|
+
/>
|
174
|
+
</div>
|
175
|
+
<div>
|
176
|
+
<label>
|
177
|
+
<input
|
178
|
+
type="checkbox"
|
179
|
+
checked={isChecked}
|
180
|
+
onChange={(e) => setIsChecked(e.target.checked)}
|
181
|
+
/>
|
182
|
+
Set Checked
|
183
|
+
</label>
|
184
|
+
</div>
|
185
|
+
<button onClick={handleUpdateTree} style={{ marginTop: '10px' }}>
|
186
|
+
Update Tree
|
187
|
+
</button>
|
188
|
+
|
189
|
+
<h2>Tree Data:</h2>
|
190
|
+
<pre style={{ backgroundColor: '#f4f4f4', padding: '10px' }}>
|
191
|
+
{JSON.stringify(data, null, 2)}
|
192
|
+
</pre>
|
193
|
+
</div>
|
194
|
+
);
|
195
|
+
};
|
@@ -0,0 +1,61 @@
|
|
1
|
+
import { TreeNodeProps as TreeNode } from '../../ComponentProps/TreeNodeProps';
|
2
|
+
|
3
|
+
export const handleTreeNodeSect = (
|
4
|
+
data: TreeNode[],
|
5
|
+
key: string,
|
6
|
+
isChecked: boolean | 'partial'
|
7
|
+
): TreeNode[] => {
|
8
|
+
const nodesMap = new Map<string, TreeNode>();
|
9
|
+
|
10
|
+
// Build a map for quick access to nodes by key
|
11
|
+
data.forEach((node) => nodesMap.set(node.key, node));
|
12
|
+
|
13
|
+
// Helper to update child nodes
|
14
|
+
function updateChildren(nodeKey: string, checkedStatus: boolean | 'partial') {
|
15
|
+
for (const node of data) {
|
16
|
+
if (node.parentId === nodeKey) {
|
17
|
+
node.checked = checkedStatus;
|
18
|
+
updateChildren(node.key, checkedStatus);
|
19
|
+
}
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
// Helper to update parent nodes
|
24
|
+
function updateParents(nodeKey: string) {
|
25
|
+
const node = nodesMap.get(nodeKey);
|
26
|
+
if (node && node.parentId) {
|
27
|
+
const parentNode = nodesMap.get(node.parentId);
|
28
|
+
if (parentNode) {
|
29
|
+
const siblings = data.filter(
|
30
|
+
(sibling) => sibling.parentId === parentNode.key
|
31
|
+
);
|
32
|
+
const allChecked = siblings.every(
|
33
|
+
(sibling) => sibling.checked === true
|
34
|
+
);
|
35
|
+
const someChecked = siblings.some(
|
36
|
+
(sibling) => sibling.checked === true || sibling.checked === 'partial'
|
37
|
+
);
|
38
|
+
|
39
|
+
parentNode.checked = allChecked
|
40
|
+
? true
|
41
|
+
: someChecked
|
42
|
+
? 'partial'
|
43
|
+
: false;
|
44
|
+
|
45
|
+
updateParents(parentNode.key);
|
46
|
+
}
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
50
|
+
// Find the target node and update its state
|
51
|
+
const targetNode = nodesMap.get(key);
|
52
|
+
if (targetNode) {
|
53
|
+
targetNode.checked = isChecked;
|
54
|
+
// Update children recursively
|
55
|
+
updateChildren(key, isChecked);
|
56
|
+
// Update parents recursively
|
57
|
+
updateParents(key);
|
58
|
+
}
|
59
|
+
|
60
|
+
return data;
|
61
|
+
};
|