This repository has been archived by the owner on Dec 18, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 12
/
tree-node-helper.ts
188 lines (172 loc) · 5.37 KB
/
tree-node-helper.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/**
* Copyright 2019 The Hyve B.V.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
import {GbTreeNode} from '../models/tree-node-models/gb-tree-node';
import {VisualAttribute} from '../models/tree-node-models/visual-attribute';
export class TreeNodeHelper {
public static VALID_TREE_NODE_TYPES = [
'NUMERIC',
'CATEGORICAL',
'CATEGORICAL_OPTION',
'DATE',
'STUDY',
'TEXT',
'HIGH_DIMENSIONAL',
'UNKNOWN'
];
/**
* For a tree node, this function selects its parent nodes recursively.
*
* It should be used, when selecting a tree node programmatically.
* Reason: the PrimeNg library does not handle selecting of a parent node,
* when the selection of the node is not triggered by a mouse click event.
*
* @param parent a parent node of a selected node
* @param selectedNodes array of currently selected nodes
*/
public static updateParentNodesSelectionRecursively(parent: GbTreeNode, selectedNodes: GbTreeNode[]) {
if (parent === undefined) {
return;
}
parent.partialSelected = false;
if (parent.children.every((child: GbTreeNode) => selectedNodes.includes(child))) {
this.addNodeToSelectedNodes(parent, selectedNodes);
} else {
this.removeNodeFromSelectedNodes(parent, selectedNodes);
if (parent.children.some((child: GbTreeNode) =>
(selectedNodes.includes(child) || child.partialSelected === true))) {
parent.partialSelected = true;
}
}
this.updateParentNodesSelectionRecursively(parent.parent, selectedNodes);
}
/**
* For a tree node, this function updates all of its children by setting the node as their parent.
*
* This is required for the tree nodes checkboxes update.
* @param node
*/
public static updateParentForAllChildren(node: GbTreeNode) {
node.children.forEach((child) => {
if (child) {
child.parent = node
}
});
}
/**
* Helper function for deselecting a tree node.
*
* @param node deselected node
* @param selectedNodes current tree nodes selection
*/
public static removeNodeFromSelectedNodes(node: GbTreeNode, selectedNodes: GbTreeNode[]) {
const index = selectedNodes.indexOf(node, 0);
if (index > -1) {
selectedNodes.splice(index, 1);
}
}
/**
* Helper function for selecting a tree node.
*
* @param node selected node
* @param selectedNodes current tree nodes selection
*/
public static addNodeToSelectedNodes(node: GbTreeNode, selectedNodes: GbTreeNode[]) {
selectedNodes.push(node);
}
/**
* Create a deep copy of a forest
* @param nodes
*/
public static copyTreeNodes(nodes: GbTreeNode[]): GbTreeNode[] {
let nodesCopy = [];
for (let node of nodes) {
let parent = node.parent;
let children = node.children;
node.parent = null;
node.children = null;
let nodeCopy = JSON.parse(JSON.stringify(node));
if (children) {
nodeCopy.children = this.copyTreeNodes(children);
}
nodesCopy.push(nodeCopy);
node.parent = parent;
node.children = children;
}
return nodesCopy;
}
/**
* Copy the given treenode upward, i.e. excluding its children
* @param {TreeNode} node
* @returns {TreeNode}
*/
public static copyTreeNodeUpward(node: GbTreeNode): GbTreeNode {
let nodeCopy: GbTreeNode = {};
let parentCopy = null;
for (let key in node) {
if (key === 'parent') {
parentCopy = this.copyTreeNodeUpward(node[key]);
} else if (key !== 'children') {
nodeCopy[key] = JSON.parse(JSON.stringify(node[key]));
}
}
if (parentCopy) {
nodeCopy.parent = parentCopy;
}
return nodeCopy;
}
/**
* Returns the depth of a tree node based on the full name (path)
* if it exists, null if the node is null.
* @param node
*/
public static depthOfTreeNode(node: GbTreeNode): number {
return node.fullName ? node.fullName.split('\\').length - 2 : null;
}
/**
* Check if a tree node is a concept node
* @param {TreeNode} node
* @returns {boolean}
*/
public static isVariableNode(node: GbTreeNode): boolean {
const type = node.type;
return (type === 'NUMERIC' ||
type === 'CATEGORICAL' ||
type === 'CATEGORICAL_OPTION' ||
type === 'DATE' ||
type === 'HIGH_DIMENSIONAL' ||
type === 'TEXT')
}
public static flattenTreeNodes(nodes: GbTreeNode[], flattened: GbTreeNode[]) {
for (let node of nodes) {
flattened.push(node);
if (node.children) {
this.flattenTreeNodes(node.children, flattened);
}
}
}
public static getAllVariablesFromTreeNode(node: GbTreeNode, variables: GbTreeNode[]) {
if (node.children) {
for (let child of node.children) {
this.getAllVariablesFromTreeNode(child, variables);
}
} else if (this.isVariableNode(node)) {
variables.push(node);
}
}
/**
* Check if a tree node is a study node
* @param {TreeNode} node
* @returns {boolean}
*/
public static isTreeNodeStudy(node: GbTreeNode): boolean {
return node.type ? node.type === 'STUDY' : false;
}
public static isTreeNodeLeaf(node: GbTreeNode): boolean {
return node.visualAttributes ? node.visualAttributes.includes(VisualAttribute.LEAF) : false;
}
}