@cluetec/ngcx-tree 0.1.0-angular-15 → 1.0.0
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 +56 -23
- package/esm2022/lib/ngcx-tree/ngcx-tree-models.mjs +2 -0
- package/{esm2020 → esm2022}/lib/ngcx-tree/ngcx-tree-node/ngcx-tree-node.component.mjs +4 -4
- package/esm2022/lib/ngcx-tree/ngcx-tree.component.mjs +332 -0
- package/fesm2022/cluetec-ngcx-tree.mjs +409 -0
- package/fesm2022/cluetec-ngcx-tree.mjs.map +1 -0
- package/lib/ngcx-tree/ngcx-tree-models.d.ts +5 -11
- package/lib/ngcx-tree/ngcx-tree-node/ngcx-tree-node.component.d.ts +1 -1
- package/lib/ngcx-tree/ngcx-tree.component.d.ts +42 -36
- package/package.json +11 -15
- package/esm2020/lib/ngcx-tree/ngcx-tree-models.mjs +0 -2
- package/esm2020/lib/ngcx-tree/ngcx-tree.component.mjs +0 -323
- package/fesm2015/cluetec-ngcx-tree.mjs +0 -410
- package/fesm2015/cluetec-ngcx-tree.mjs.map +0 -1
- package/fesm2020/cluetec-ngcx-tree.mjs +0 -400
- package/fesm2020/cluetec-ngcx-tree.mjs.map +0 -1
- /package/{esm2020 → esm2022}/cluetec-ngcx-tree.mjs +0 -0
- /package/{esm2020 → esm2022}/lib/ngcx-tree/ngcx-tree-data.source.mjs +0 -0
- /package/{esm2020 → esm2022}/lib/ngcx-tree/ngcx-tree-utils.mjs +0 -0
- /package/{esm2020 → esm2022}/public-api.mjs +0 -0
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
import { DragDropModule, } from '@angular/cdk/drag-drop';
|
|
2
|
+
import { CdkTreeModule, NestedTreeControl, } from '@angular/cdk/tree';
|
|
3
|
+
import { NgIf } from '@angular/common';
|
|
4
|
+
import { Component, EventEmitter, HostListener, Input, Output, } from '@angular/core';
|
|
5
|
+
import { NgcxTreeDataSource } from './ngcx-tree-data.source';
|
|
6
|
+
import { NgcxTreeNodeComponent } from './ngcx-tree-node/ngcx-tree-node.component';
|
|
7
|
+
import { isParentOf } from './ngcx-tree-utils';
|
|
8
|
+
import * as i0 from "@angular/core";
|
|
9
|
+
import * as i1 from "@angular/cdk/tree";
|
|
10
|
+
import * as i2 from "@angular/cdk/drag-drop";
|
|
11
|
+
export class NgcxTreeComponent {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.nodeMoved = new EventEmitter();
|
|
14
|
+
this.customEvent = new EventEmitter();
|
|
15
|
+
this.clickEvent = new EventEmitter();
|
|
16
|
+
this.selectEvent = new EventEmitter();
|
|
17
|
+
/**
|
|
18
|
+
* Api for finding and selecting node. Extends from the CDK treeControl for expanding/collapsing the tree
|
|
19
|
+
*/
|
|
20
|
+
this.treeControl = new NgcxTreeControl(this, (node) => node.children, {
|
|
21
|
+
trackBy: (node) => node.id,
|
|
22
|
+
});
|
|
23
|
+
this.dataSource = new NgcxTreeDataSource([]);
|
|
24
|
+
this.DropType = DropType;
|
|
25
|
+
this.disable = () => false;
|
|
26
|
+
}
|
|
27
|
+
ngOnInit() {
|
|
28
|
+
this.updateTree();
|
|
29
|
+
}
|
|
30
|
+
ngOnChanges(changes) {
|
|
31
|
+
if (changes['nodes']) {
|
|
32
|
+
if (this.treeControl) {
|
|
33
|
+
// initialized already
|
|
34
|
+
this.updateTree();
|
|
35
|
+
}
|
|
36
|
+
if (this.selectedNode) {
|
|
37
|
+
const selectedNodeId = this.selectedNode.id;
|
|
38
|
+
setTimeout(() => this.treeControl.selectNodeById(selectedNodeId));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
updateTree() {
|
|
43
|
+
const wrapperNodes = this.createWrapperNodes(this.nodes ?? []);
|
|
44
|
+
this.dataSource = new NgcxTreeDataSource(wrapperNodes);
|
|
45
|
+
this.treeControl.dataNodes = this.dataSource.data$.value;
|
|
46
|
+
}
|
|
47
|
+
createWrapperNodes(nodes, parent, depth = 0) {
|
|
48
|
+
const childCount = nodes.length;
|
|
49
|
+
const wrapperNodes = nodes.map((node, idx) => {
|
|
50
|
+
const nodeWrapper = {
|
|
51
|
+
id: node.id,
|
|
52
|
+
data: node,
|
|
53
|
+
isFirstChild: idx === 0,
|
|
54
|
+
isLastChild: idx === childCount - 1,
|
|
55
|
+
index: idx,
|
|
56
|
+
parent: parent,
|
|
57
|
+
depth: depth,
|
|
58
|
+
children: [],
|
|
59
|
+
};
|
|
60
|
+
nodeWrapper.children = node.children
|
|
61
|
+
? this.createWrapperNodes(node.children, nodeWrapper, depth + 1)
|
|
62
|
+
: [];
|
|
63
|
+
return nodeWrapper;
|
|
64
|
+
});
|
|
65
|
+
wrapperNodes.forEach((wrapperNode) => {
|
|
66
|
+
if (!wrapperNode.isLastChild) {
|
|
67
|
+
wrapperNode.next = wrapperNodes[wrapperNode.index + 1];
|
|
68
|
+
}
|
|
69
|
+
if (!wrapperNode.isFirstChild) {
|
|
70
|
+
wrapperNode.previous = wrapperNodes[wrapperNode.index - 1];
|
|
71
|
+
}
|
|
72
|
+
if (this.config?.allowSelection?.(wrapperNode)) {
|
|
73
|
+
wrapperNode.isSelectable = true;
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
return wrapperNodes;
|
|
77
|
+
}
|
|
78
|
+
allowDrop(dropNode, dropType) {
|
|
79
|
+
if (!this.dragging ||
|
|
80
|
+
this.dragging.id === dropNode.id ||
|
|
81
|
+
isParentOf(this.dragging, dropNode)) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
if (dropType == DropType.DROP_INTO &&
|
|
85
|
+
dropNode.id === this.dragging.parent?.id) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
if (dropType == DropType.DROP_AFTER &&
|
|
89
|
+
dropNode.next?.id === this.dragging.id) {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
if (dropType == DropType.DROP_BEFORE &&
|
|
93
|
+
dropNode.previous?.id === this.dragging.id) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
const intoNode = dropType == DropType.DROP_INTO ? dropNode : dropNode.parent;
|
|
97
|
+
if (this.config?.allowDrop) {
|
|
98
|
+
return this.config.allowDrop(this.dragging, intoNode);
|
|
99
|
+
}
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
// prevent drop directly after a node on same level, that is expanded
|
|
103
|
+
sortPredicate() {
|
|
104
|
+
return (index, _drag, drop) => {
|
|
105
|
+
return index == 0 || !this.treeControl.isExpanded(drop.data);
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
disableDrag(node) {
|
|
109
|
+
return this.config?.allowDrag ? !this.config.allowDrag(node) : false;
|
|
110
|
+
}
|
|
111
|
+
keyDownArrowUp(event) {
|
|
112
|
+
if (this.selectedNode) {
|
|
113
|
+
if (!this.selectedNode.isFirstChild) {
|
|
114
|
+
this.selectNode(this.selectedNode.previous);
|
|
115
|
+
}
|
|
116
|
+
else if (this.selectedNode.parent) {
|
|
117
|
+
this.selectNode(this.selectedNode.parent);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
const nodes = this.dataSource.data$.value;
|
|
122
|
+
if (nodes.length > 0) {
|
|
123
|
+
this.selectNode(nodes[nodes.length - 1]);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
event.preventDefault();
|
|
127
|
+
}
|
|
128
|
+
keyDownArrowDown(event) {
|
|
129
|
+
if (this.selectedNode) {
|
|
130
|
+
if (!this.selectedNode.isLastChild) {
|
|
131
|
+
this.selectNode(this.selectedNode.next);
|
|
132
|
+
}
|
|
133
|
+
else if (this.selectedNode.parent?.next) {
|
|
134
|
+
this.selectNode(this.selectedNode.parent.next);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
const nodes = this.dataSource.data$.value;
|
|
139
|
+
if (nodes.length > 0) {
|
|
140
|
+
this.selectNode(nodes[0]);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
event.preventDefault();
|
|
144
|
+
}
|
|
145
|
+
keyDownArrowLeft(event) {
|
|
146
|
+
if (this.selectedNode) {
|
|
147
|
+
if (this.treeControl.isExpanded(this.selectedNode)) {
|
|
148
|
+
this.treeControl.collapse(this.selectedNode);
|
|
149
|
+
}
|
|
150
|
+
else if (this.selectedNode?.parent) {
|
|
151
|
+
this.selectNode(this.selectedNode.parent);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
const nodes = this.dataSource.data$.value;
|
|
156
|
+
if (nodes.length > 0) {
|
|
157
|
+
this.selectNode(nodes[0]);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
event.preventDefault();
|
|
161
|
+
}
|
|
162
|
+
keyDownArrowRight(event) {
|
|
163
|
+
if (this.selectedNode && this.selectedNode.children.length > 0) {
|
|
164
|
+
this.selectNode(this.selectedNode.children[0]);
|
|
165
|
+
}
|
|
166
|
+
else if (!this.selectedNode) {
|
|
167
|
+
const nodes = this.dataSource.data$.value;
|
|
168
|
+
if (nodes.length > 0) {
|
|
169
|
+
this.selectNode(nodes[0]);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
event.preventDefault();
|
|
173
|
+
}
|
|
174
|
+
keyEscapeWhileDragging() {
|
|
175
|
+
if (this.dragging) {
|
|
176
|
+
this.canceledByEsc = true;
|
|
177
|
+
document.dispatchEvent(new Event('mouseup'));
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
handleDragRelease(event) {
|
|
181
|
+
this.dragging = undefined;
|
|
182
|
+
const movedNode = event.source.data;
|
|
183
|
+
const dropZoneId = event.event.target.id;
|
|
184
|
+
if (!dropZoneId) {
|
|
185
|
+
// no valid drop zone
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
const dropZoneInfo = new DropZoneInfo(dropZoneId);
|
|
189
|
+
const toNode = this.treeControl.findNodeById(dropZoneInfo.nodeId);
|
|
190
|
+
if (!toNode) {
|
|
191
|
+
console.error(`node with id '${dropZoneInfo.nodeId}' could not be found`);
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
// dropType undefined can happen if dropped directly without moving
|
|
195
|
+
if (this.canceledByEsc || dropZoneInfo.dropType === undefined) {
|
|
196
|
+
this.canceledByEsc = false;
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
const insertIntoNode = dropZoneInfo.dropType === DropType.DROP_INTO ? toNode : toNode.parent;
|
|
200
|
+
const wrapperList = insertIntoNode?.children ?? this.dataSource.data$.value;
|
|
201
|
+
const addAtNodeIdx = this.findAddIndex(dropZoneInfo, insertIntoNode, wrapperList);
|
|
202
|
+
const removedFromIdx = this.removeElementFromPreviousPosition(movedNode);
|
|
203
|
+
// add element to new Position, subtract one if inserted in same list after the remove position
|
|
204
|
+
(insertIntoNode?.data.children ?? this.nodes).splice(movedNode.parent?.id === insertIntoNode?.id &&
|
|
205
|
+
removedFromIdx < addAtNodeIdx
|
|
206
|
+
? addAtNodeIdx - 1
|
|
207
|
+
: addAtNodeIdx, 0, movedNode.data);
|
|
208
|
+
const afterNodeIdx = addAtNodeIdx - 1;
|
|
209
|
+
const afterNode = afterNodeIdx > -1 && wrapperList.length > afterNodeIdx
|
|
210
|
+
? wrapperList[afterNodeIdx]
|
|
211
|
+
: undefined;
|
|
212
|
+
const beforeNode = addAtNodeIdx > -1 && wrapperList.length > addAtNodeIdx
|
|
213
|
+
? wrapperList[addAtNodeIdx]
|
|
214
|
+
: undefined;
|
|
215
|
+
this.nodeMoved.emit({
|
|
216
|
+
node: movedNode,
|
|
217
|
+
parent: dropZoneInfo.dropType === DropType.DROP_INTO ? toNode : toNode.parent,
|
|
218
|
+
afterNode: afterNode,
|
|
219
|
+
beforeNode: beforeNode,
|
|
220
|
+
});
|
|
221
|
+
this.dataSource = new NgcxTreeDataSource(this.createWrapperNodes(this.nodes));
|
|
222
|
+
this.treeControl.dataNodes = this.dataSource.data$.value;
|
|
223
|
+
}
|
|
224
|
+
findAddIndex(dropZoneInfo, insertIntoNode, insertIntoList) {
|
|
225
|
+
if (insertIntoNode &&
|
|
226
|
+
dropZoneInfo.dropType === DropType.DROP_INTO &&
|
|
227
|
+
!insertIntoNode.data.children) {
|
|
228
|
+
insertIntoNode.data.children = [];
|
|
229
|
+
}
|
|
230
|
+
let addAtNodeIdx = 0;
|
|
231
|
+
if (dropZoneInfo.dropType === DropType.DROP_AFTER ||
|
|
232
|
+
dropZoneInfo.dropType === DropType.DROP_BEFORE) {
|
|
233
|
+
addAtNodeIdx = insertIntoList.findIndex((child) => child.id === dropZoneInfo.nodeId);
|
|
234
|
+
if (dropZoneInfo.dropType === DropType.DROP_AFTER) {
|
|
235
|
+
addAtNodeIdx++;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return addAtNodeIdx;
|
|
239
|
+
}
|
|
240
|
+
removeElementFromPreviousPosition(movedNode) {
|
|
241
|
+
const removeFromList = movedNode.parent?.data.children ?? this.nodes;
|
|
242
|
+
const removeIndex = removeFromList.findIndex((child) => child.id === movedNode.id);
|
|
243
|
+
removeFromList.splice(removeIndex, 1);
|
|
244
|
+
return removeIndex;
|
|
245
|
+
}
|
|
246
|
+
nodeClicked(nodeWrapper) {
|
|
247
|
+
this.clickEvent.emit(nodeWrapper);
|
|
248
|
+
if (nodeWrapper.isSelectable) {
|
|
249
|
+
this.selectedNode =
|
|
250
|
+
nodeWrapper.id === this.selectedNode?.id ? undefined : nodeWrapper;
|
|
251
|
+
this.selectEvent.emit(this.selectedNode);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
selectNode(nodeWrapper) {
|
|
255
|
+
if (!nodeWrapper || nodeWrapper.isSelectable) {
|
|
256
|
+
this.selectedNode = nodeWrapper;
|
|
257
|
+
let expandNode = this.selectedNode?.parent;
|
|
258
|
+
while (expandNode) {
|
|
259
|
+
this.treeControl.expand(expandNode);
|
|
260
|
+
expandNode = expandNode.parent;
|
|
261
|
+
}
|
|
262
|
+
this.selectEvent.emit(this.selectedNode);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.8", ngImport: i0, type: NgcxTreeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
266
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.8", type: NgcxTreeComponent, isStandalone: true, selector: "ngcx-tree", inputs: { nodes: "nodes", config: "config" }, outputs: { nodeMoved: "nodeMoved", customEvent: "customEvent", clickEvent: "clickEvent", selectEvent: "selectEvent" }, host: { listeners: { "window:keydown.escape": "keyEscapeWhileDragging()" } }, usesOnChanges: true, ngImport: i0, template: "<cdk-tree\n #tree\n class=\"ngcx-tree\"\n *ngIf=\"dataSource\"\n [dataSource]=\"dataSource\"\n [treeControl]=\"treeControl\"\n cdkDropListGroup\n [class.dragging]=\"dragging\"\n (keyup.arrowup)=\"keyDownArrowUp($event)\"\n (keydown.arrowdown)=\"keyDownArrowDown($event)\"\n (keydown.arrowleft)=\"keyDownArrowLeft($event)\"\n (keydown.arrowright)=\"keyDownArrowRight($event)\"\n tabindex=\"0\">\n <cdk-nested-tree-node *cdkTreeNodeDef=\"let node\" class=\"tree-node\">\n <div\n cdkDropList\n [id]=\"node.id + '_' + DropType.DROP_AFTER\"\n class=\"tree-node-container-drop-zone after-expanded-node\"\n [class.hide]=\"\n !allowDrop(node, DropType.DROP_AFTER) || !treeControl.isExpanded(node)\n \">\n <div class=\"drop-insert-line\"></div>\n </div>\n <div class=\"tree-node-container\">\n <div\n cdkDropList\n [id]=\"node.id + '_' + DropType.DROP_BEFORE\"\n class=\"tree-node-container-drop-zone before-node\"\n [class.hide]=\"\n !node.isFirstChild || !allowDrop(node, DropType.DROP_BEFORE)\n \">\n <div class=\"drop-insert-line\"></div>\n </div>\n <div\n cdkDropList\n [id]=\"node.id + '_' + DropType.DROP_INTO\"\n class=\"tree-node-container-drop-zone into-node\"\n [class.hide]=\"!allowDrop(node, DropType.DROP_INTO)\"></div>\n <div\n cdkDropList\n [id]=\"node.id + '_' + DropType.DROP_AFTER\"\n class=\"tree-node-container-drop-zone after-node\"\n [class.last]=\"node.isLastChild\"\n [class.hide]=\"\n treeControl.isExpanded(node) || !allowDrop(node, DropType.DROP_AFTER)\n \">\n <div class=\"drop-insert-line\"></div>\n </div>\n <div\n cdkDropList\n [cdkDropListData]=\"node\"\n [cdkDropListEnterPredicate]=\"disable\"\n [cdkDropListSortPredicate]=\"disable\">\n <div\n cdkDrag\n [cdkDragDisabled]=\"disableDrag(node)\"\n [cdkDragData]=\"node\"\n (cdkDragStarted)=\"dragging = node\"\n (cdkDragReleased)=\"handleDragRelease($event)\">\n <div *cdkDragPlaceholder></div>\n <div\n class=\"tree-node-content-container\"\n [class.first]=\"node.isFirstChild\"\n [class.last]=\"node.isLastChild\"\n [class.expanded]=\"treeControl.isExpanded(node)\">\n <ngcx-tree-node\n style=\"width: 100%\"\n [nodeWrapper]=\"node\"\n [isSelected]=\"node.id === selectedNode?.id\"\n [treeControl]=\"treeControl\"\n [treeConfig]=\"config\"\n (customEvent)=\"customEvent.emit($event)\"\n (clickEvent)=\"nodeClicked(node)\"></ngcx-tree-node>\n </div>\n </div>\n <ngcx-tree-node\n *ngIf=\"node.id === dragging?.id\"\n [nodeWrapper]=\"node\"\n [treeControl]=\"treeControl\"\n [treeConfig]=\"config\"></ngcx-tree-node>\n </div>\n </div>\n <div\n *ngIf=\"treeControl.isExpanded(node)\"\n class=\"tree-node-children-container\"\n [class.first]=\"node.isFirstChild\"\n [class.last]=\"node.isLastChild\">\n <div cdkTreeNodeOutlet></div>\n </div>\n </cdk-nested-tree-node>\n</cdk-tree>\n", styles: [".ngcx-tree{height:auto}.ngcx-tree ul,.ngcx-tree li{margin-top:0;margin-bottom:0;list-style-type:none}.tree-node{display:flex;flex-direction:column;position:relative}.tree-node .tree-node{margin-left:20px}.tree-node-container{width:100%;min-height:30px;display:flex;flex-direction:row;justify-content:flex-start;align-items:center;position:relative;cursor:default}.tree-node-container .tree-node-content-container{width:100%}.tree-node-container .cdk-drag{width:100%;display:flex;flex-direction:row;justify-content:flex-start;align-items:center}.tree-node-container-drop-zone{height:100%;left:25px;right:5px;position:absolute;z-index:1;display:flex;justify-content:center;flex-direction:column}.tree-node-container-drop-zone:hover.into-node,.tree-node-container-drop-zone.cdk-drop-list-dragging.into-node{border:1.5px dashed rgba(0,0,0,.5)}.tree-node-container-drop-zone:hover .drop-insert-line,.tree-node-container-drop-zone.cdk-drop-list-dragging .drop-insert-line{border-top:1.5px dashed rgba(0,0,0,.5)}.tree-node-container-drop-zone.hide{height:0!important}.tree-node-container-drop-zone.hide .drop-insert-line{border-top:solid transparent 0px!important}.tree-node-container-drop-zone.before-node{height:20px;z-index:2;top:-10px}.tree-node-container-drop-zone.after-node{height:20px;z-index:3;top:calc(100% - 10px)}.tree-node-container-drop-zone.after-node.last{height:10px}.tree-node-container-drop-zone.after-expanded-node{position:absolute;height:20px;z-index:3;bottom:-10px;display:flex;justify-content:center;flex-direction:column}\n"], dependencies: [{ kind: "ngmodule", type: CdkTreeModule }, { kind: "directive", type: i1.CdkNestedTreeNode, selector: "cdk-nested-tree-node", inputs: ["role", "disabled", "tabIndex"], exportAs: ["cdkNestedTreeNode"] }, { kind: "directive", type: i1.CdkTreeNodeDef, selector: "[cdkTreeNodeDef]", inputs: ["cdkTreeNodeDefWhen"] }, { kind: "component", type: i1.CdkTree, selector: "cdk-tree", inputs: ["dataSource", "treeControl", "trackBy"], exportAs: ["cdkTree"] }, { kind: "directive", type: i1.CdkTreeNodeOutlet, selector: "[cdkTreeNodeOutlet]" }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i2.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i2.CdkDropListGroup, selector: "[cdkDropListGroup]", inputs: ["cdkDropListGroupDisabled"], exportAs: ["cdkDropListGroup"] }, { kind: "directive", type: i2.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i2.CdkDragPlaceholder, selector: "ng-template[cdkDragPlaceholder]", inputs: ["data"] }, { kind: "component", type: NgcxTreeNodeComponent, selector: "ngcx-tree-node", inputs: ["nodeWrapper", "treeControl", "treeConfig", "isSelected"], outputs: ["customEvent", "clickEvent"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); }
|
|
267
|
+
}
|
|
268
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.8", ngImport: i0, type: NgcxTreeComponent, decorators: [{
|
|
269
|
+
type: Component,
|
|
270
|
+
args: [{ selector: 'ngcx-tree', standalone: true, imports: [CdkTreeModule, DragDropModule, NgcxTreeNodeComponent, NgIf], template: "<cdk-tree\n #tree\n class=\"ngcx-tree\"\n *ngIf=\"dataSource\"\n [dataSource]=\"dataSource\"\n [treeControl]=\"treeControl\"\n cdkDropListGroup\n [class.dragging]=\"dragging\"\n (keyup.arrowup)=\"keyDownArrowUp($event)\"\n (keydown.arrowdown)=\"keyDownArrowDown($event)\"\n (keydown.arrowleft)=\"keyDownArrowLeft($event)\"\n (keydown.arrowright)=\"keyDownArrowRight($event)\"\n tabindex=\"0\">\n <cdk-nested-tree-node *cdkTreeNodeDef=\"let node\" class=\"tree-node\">\n <div\n cdkDropList\n [id]=\"node.id + '_' + DropType.DROP_AFTER\"\n class=\"tree-node-container-drop-zone after-expanded-node\"\n [class.hide]=\"\n !allowDrop(node, DropType.DROP_AFTER) || !treeControl.isExpanded(node)\n \">\n <div class=\"drop-insert-line\"></div>\n </div>\n <div class=\"tree-node-container\">\n <div\n cdkDropList\n [id]=\"node.id + '_' + DropType.DROP_BEFORE\"\n class=\"tree-node-container-drop-zone before-node\"\n [class.hide]=\"\n !node.isFirstChild || !allowDrop(node, DropType.DROP_BEFORE)\n \">\n <div class=\"drop-insert-line\"></div>\n </div>\n <div\n cdkDropList\n [id]=\"node.id + '_' + DropType.DROP_INTO\"\n class=\"tree-node-container-drop-zone into-node\"\n [class.hide]=\"!allowDrop(node, DropType.DROP_INTO)\"></div>\n <div\n cdkDropList\n [id]=\"node.id + '_' + DropType.DROP_AFTER\"\n class=\"tree-node-container-drop-zone after-node\"\n [class.last]=\"node.isLastChild\"\n [class.hide]=\"\n treeControl.isExpanded(node) || !allowDrop(node, DropType.DROP_AFTER)\n \">\n <div class=\"drop-insert-line\"></div>\n </div>\n <div\n cdkDropList\n [cdkDropListData]=\"node\"\n [cdkDropListEnterPredicate]=\"disable\"\n [cdkDropListSortPredicate]=\"disable\">\n <div\n cdkDrag\n [cdkDragDisabled]=\"disableDrag(node)\"\n [cdkDragData]=\"node\"\n (cdkDragStarted)=\"dragging = node\"\n (cdkDragReleased)=\"handleDragRelease($event)\">\n <div *cdkDragPlaceholder></div>\n <div\n class=\"tree-node-content-container\"\n [class.first]=\"node.isFirstChild\"\n [class.last]=\"node.isLastChild\"\n [class.expanded]=\"treeControl.isExpanded(node)\">\n <ngcx-tree-node\n style=\"width: 100%\"\n [nodeWrapper]=\"node\"\n [isSelected]=\"node.id === selectedNode?.id\"\n [treeControl]=\"treeControl\"\n [treeConfig]=\"config\"\n (customEvent)=\"customEvent.emit($event)\"\n (clickEvent)=\"nodeClicked(node)\"></ngcx-tree-node>\n </div>\n </div>\n <ngcx-tree-node\n *ngIf=\"node.id === dragging?.id\"\n [nodeWrapper]=\"node\"\n [treeControl]=\"treeControl\"\n [treeConfig]=\"config\"></ngcx-tree-node>\n </div>\n </div>\n <div\n *ngIf=\"treeControl.isExpanded(node)\"\n class=\"tree-node-children-container\"\n [class.first]=\"node.isFirstChild\"\n [class.last]=\"node.isLastChild\">\n <div cdkTreeNodeOutlet></div>\n </div>\n </cdk-nested-tree-node>\n</cdk-tree>\n", styles: [".ngcx-tree{height:auto}.ngcx-tree ul,.ngcx-tree li{margin-top:0;margin-bottom:0;list-style-type:none}.tree-node{display:flex;flex-direction:column;position:relative}.tree-node .tree-node{margin-left:20px}.tree-node-container{width:100%;min-height:30px;display:flex;flex-direction:row;justify-content:flex-start;align-items:center;position:relative;cursor:default}.tree-node-container .tree-node-content-container{width:100%}.tree-node-container .cdk-drag{width:100%;display:flex;flex-direction:row;justify-content:flex-start;align-items:center}.tree-node-container-drop-zone{height:100%;left:25px;right:5px;position:absolute;z-index:1;display:flex;justify-content:center;flex-direction:column}.tree-node-container-drop-zone:hover.into-node,.tree-node-container-drop-zone.cdk-drop-list-dragging.into-node{border:1.5px dashed rgba(0,0,0,.5)}.tree-node-container-drop-zone:hover .drop-insert-line,.tree-node-container-drop-zone.cdk-drop-list-dragging .drop-insert-line{border-top:1.5px dashed rgba(0,0,0,.5)}.tree-node-container-drop-zone.hide{height:0!important}.tree-node-container-drop-zone.hide .drop-insert-line{border-top:solid transparent 0px!important}.tree-node-container-drop-zone.before-node{height:20px;z-index:2;top:-10px}.tree-node-container-drop-zone.after-node{height:20px;z-index:3;top:calc(100% - 10px)}.tree-node-container-drop-zone.after-node.last{height:10px}.tree-node-container-drop-zone.after-expanded-node{position:absolute;height:20px;z-index:3;bottom:-10px;display:flex;justify-content:center;flex-direction:column}\n"] }]
|
|
271
|
+
}], propDecorators: { nodes: [{
|
|
272
|
+
type: Input
|
|
273
|
+
}], config: [{
|
|
274
|
+
type: Input
|
|
275
|
+
}], nodeMoved: [{
|
|
276
|
+
type: Output
|
|
277
|
+
}], customEvent: [{
|
|
278
|
+
type: Output
|
|
279
|
+
}], clickEvent: [{
|
|
280
|
+
type: Output
|
|
281
|
+
}], selectEvent: [{
|
|
282
|
+
type: Output
|
|
283
|
+
}], keyEscapeWhileDragging: [{
|
|
284
|
+
type: HostListener,
|
|
285
|
+
args: ['window:keydown.escape']
|
|
286
|
+
}] } });
|
|
287
|
+
var DropType;
|
|
288
|
+
(function (DropType) {
|
|
289
|
+
DropType["DROP_AFTER"] = "DROP_AFTER";
|
|
290
|
+
DropType["DROP_BEFORE"] = "DROP_BEFORE";
|
|
291
|
+
DropType["DROP_INTO"] = "DROP_INTO";
|
|
292
|
+
})(DropType || (DropType = {}));
|
|
293
|
+
export class NgcxTreeControl extends NestedTreeControl {
|
|
294
|
+
constructor(treeComponent, getChildren, options) {
|
|
295
|
+
super(getChildren, options);
|
|
296
|
+
this.treeComponent = treeComponent;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* select a node by id. the selectEvent is fired afterwards.
|
|
300
|
+
*/
|
|
301
|
+
selectNodeById(id) {
|
|
302
|
+
this.treeComponent.selectNode(this.findNodeById(id));
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* find a node by id.
|
|
306
|
+
*/
|
|
307
|
+
findNodeById(id) {
|
|
308
|
+
return this.findNodeByIdInNodes(this.treeComponent.dataSource.data$.value, id);
|
|
309
|
+
}
|
|
310
|
+
findNodeByIdInNodes(nodes, id) {
|
|
311
|
+
for (const node of nodes) {
|
|
312
|
+
if (node.id === id) {
|
|
313
|
+
return node;
|
|
314
|
+
}
|
|
315
|
+
if (node.children?.length > 0) {
|
|
316
|
+
const foundNode = this.findNodeByIdInNodes(node.children, id);
|
|
317
|
+
if (foundNode) {
|
|
318
|
+
return foundNode;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
return undefined;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
class DropZoneInfo {
|
|
326
|
+
constructor(id) {
|
|
327
|
+
const pos = id.indexOf('_');
|
|
328
|
+
this.nodeId = id.substring(0, pos);
|
|
329
|
+
this.dropType = id.substring(pos + 1);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmdjeC10cmVlLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25nY3gtdHJlZS9zcmMvbGliL25nY3gtdHJlZS9uZ2N4LXRyZWUuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmdjeC10cmVlL3NyYy9saWIvbmdjeC10cmVlL25nY3gtdHJlZS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBSUwsY0FBYyxHQUNmLE1BQU0sd0JBQXdCLENBQUM7QUFDaEMsT0FBTyxFQUNMLGFBQWEsRUFDYixpQkFBaUIsR0FFbEIsTUFBTSxtQkFBbUIsQ0FBQztBQUMzQixPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDdkMsT0FBTyxFQUNMLFNBQVMsRUFDVCxZQUFZLEVBQ1osWUFBWSxFQUNaLEtBQUssRUFHTCxNQUFNLEdBRVAsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFPN0QsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sMkNBQTJDLENBQUM7QUFDbEYsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLG1CQUFtQixDQUFDOzs7O0FBUy9DLE1BQU0sT0FBTyxpQkFBaUI7SUFQOUI7UUFhWSxjQUFTLEdBQUcsSUFBSSxZQUFZLEVBQTZCLENBQUM7UUFDMUQsZ0JBQVcsR0FBRyxJQUFJLFlBQVksRUFBSyxDQUFDO1FBQ3BDLGVBQVUsR0FBRyxJQUFJLFlBQVksRUFBMEIsQ0FBQztRQUN4RCxnQkFBVyxHQUFHLElBQUksWUFBWSxFQUEwQixDQUFDO1FBRW5FOztXQUVHO1FBQ2EsZ0JBQVcsR0FBdUIsSUFBSSxlQUFlLENBQ25FLElBQUksRUFDSixDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFDdkI7WUFDRSxPQUFPLEVB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QyxJQUFJLENBQUMsUUFBUSxHQUFhLEVBQUUsQ0FBQyxTQUFTLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ2xELENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENka0RyYWcsXG4gIENka0RyYWdSZWxlYXNlLFxuICBDZGtEcm9wTGlzdCxcbiAgRHJhZ0Ryb3BNb2R1bGUsXG59IGZyb20gJ0Bhbmd1bGFyL2Nkay9kcmFnLWRyb3AnO1xuaW1wb3J0IHtcbiAgQ2RrVHJlZU1vZHVsZSxcbiAgTmVzdGVkVHJlZUNvbnRyb2wsXG4gIE5lc3RlZFRyZWVDb250cm9sT3B0aW9ucyxcbn0gZnJvbSAnQGFuZ3VsYXIvY2RrL3RyZWUnO1xuaW1wb3J0IHsgTmdJZiB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQge1xuICBDb21wb25lbnQsXG4gIEV2ZW50RW1pdHRlcixcbiAgSG9zdExpc3RlbmVyLFxuICBJbnB1dCxcbiAgT25DaGFuZ2VzLFxuICBPbkluaXQsXG4gIE91dHB1dCxcbiAgU2ltcGxlQ2hhbmdlcyxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBOZ2N4VHJlZURhdGFTb3VyY2UgfSBmcm9tICcuL25nY3gtdHJlZS1kYXRhLnNvdXJjZSc7XG5pbXBvcnQge1xuICBOZ2N4VHJlZUNvbmZpZyxcbiAgTmdjeFRyZWVOb2RlLFxuICBOZ2N4VHJlZU5vZGVNb3ZlZEV2ZW50LFxuICBOZ2N4VHJlZU5vZGVXcmFwcGVyLFxufSBmcm9tICcuL25nY3gtdHJlZS1tb2RlbHMnO1xuaW1wb3J0IHsgTmdjeFRyZWVOb2RlQ29tcG9uZW50IH0gZnJvbSAnLi9uZ2N4LXRyZWUtbm9kZS9uZ2N4LXRyZWUtbm9kZS5jb21wb25lbnQnO1xuaW1wb3J0IHsgaXNQYXJlbnRPZiB9IGZyb20gJy4vbmdjeC10cmVlLXV0aWxzJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmdjeC10cmVlJyxcbiAgdGVtcGxhdGVVcmw6ICduZ2N4LXRyZWUuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnbmdjeC10cmVlLmNvbXBvbmVudC5zY3NzJ10sXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtDZGtUcmVlTW9kdWxlLCBEcmFnRHJvcE1vZHVsZSwgTmdjeFRyZWVOb2RlQ29tcG9uZW50LCBOZ0lmXSxcbn0pXG5leHBvcnQgY2xhc3MgTmdjeFRyZWVDb21wb25lbnQ8VCBleHRlbmRzIE5nY3hUcmVlTm9kZT5cbiAgaW1wbGVtZW50cyBPbkNoYW5nZXMsIE9uSW5pdFxue1xuICBASW5wdXQoKSBub2Rlcz86IE5nY3hUcmVlTm9kZVtdO1xuICBASW5wdXQoKSBjb25maWc/OiBOZ2N4VHJlZUNvbmZpZzxUPjtcblxuICBAT3V0cHV0KCkgbm9kZU1vdmVkID0gbmV3IEV2ZW50RW1pdHRlcjxOZ2N4VHJlZU5vZGVNb3ZlZEV2ZW50PFQ+PigpO1xuICBAT3V0cHV0KCkgY3VzdG9tRXZlbnQgPSBuZXcgRXZlbnRFbWl0dGVyPFQ+KCk7XG4gIEBPdXRwdXQoKSBjbGlja0V2ZW50ID0gbmV3IEV2ZW50RW1pdHRlcjxOZ2N4VHJlZU5vZGVXcmFwcGVyPFQ+PigpO1xuICBAT3V0cHV0KCkgc2VsZWN0RXZlbnQgPSBuZXcgRXZlbnRFbWl0dGVyPE5nY3hUcmVlTm9kZVdyYXBwZXI8VD4+KCk7XG5cbiAgLyoqXG4gICAqIEFwaSBmb3IgZmluZGluZyBhbmQgc2VsZWN0aW5nIG5vZGUuIEV4dGVuZHMgZnJvbSB0aGUgQ0RLIHRyZWVDb250cm9sIGZvciBleHBhbmRpbmcvY29sbGFwc2luZyB0aGUgdHJlZVxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHRyZWVDb250cm9sOiBOZ2N4VHJlZUNvbnRyb2w8VD4gPSBuZXcgTmdjeFRyZWVDb250cm9sPFQ+KFxuICAgIHRoaXMsXG4gICAgKG5vZGUpID0+IG5vZGUuY2hpbGRyZW4sXG4gICAge1xuICAgICAgdHJhY2tCeTogKG5vZGU6IE5nY3hUcmVlTm9kZVdyYXBwZXI8VD4pID0+IG5vZGUuaWQsXG4gICAgfVxuICApO1xuXG4gIGRhdGFTb3VyY2U6IE5nY3hUcmVlRGF0YVNvdXJjZTxOZ2N4VHJlZU5vZGVXcmFwcGVyPFQ+PiA9XG4gICAgbmV3IE5nY3hUcmVlRGF0YVNvdXJjZTxOZ2N4VHJlZU5vZGVXcmFwcGVyPFQ+PihbXSk7XG5cbiAgcHJvdGVjdGVkIGRyYWdnaW5nPzogTmdjeFRyZWVOb2RlV3JhcHBlcjxUPjtcblxuICBwcm90ZWN0ZWQgc2VsZWN0ZWROb2RlPzogTmdjeFRyZWVOb2RlV3JhcHBlcjxUPjtcblxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgRHJvcFR5cGUgPSBEcm9wVHlwZTtcblxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgZGlzYWJsZSA9ICgpID0+IGZhbHNlO1xuXG4gIHByaXZhdGUgY2FuY2VsZWRCeUVzYz86IGJvb2xlYW47XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy51cGRhdGVUcmVlKCk7XG4gIH1cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKSB7XG4gICAgaWYgKGNoYW5nZXNbJ25vZGVzJ10pIHtcbiAgICAgIGlmICh0aGlzLnRyZWVDb250cm9sKSB7XG4gICAgICAgIC8vIGluaXRpYWxpemVkIGFscmVhZHlcbiAgICAgICAgdGhpcy51cGRhdGVUcmVlKCk7XG4gICAgICB9XG4gICAgICBpZiAodGhpcy5zZWxlY3RlZE5vZGUpIHtcbiAgICAgICAgY29uc3Qgc2VsZWN0ZWROb2RlSWQgPSB0aGlzLnNlbGVjdGVkTm9kZS5pZDtcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB0aGlzLnRyZWVDb250cm9sLnNlbGVjdE5vZGVCeUlkKHNlbGVjdGVkTm9kZUlkKSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVUcmVlKCkge1xuICAgIGNvbnN0IHdyYXBwZXJOb2RlcyA9IHRoaXMuY3JlYXRlV3JhcHBlck5vZGVzKHRoaXMubm9kZXMgPz8gW10pO1xuICAgIHRoaXMuZGF0YVNvdXJjZSA9IG5ldyBOZ2N4VHJlZURhdGFTb3VyY2Uod3JhcHBlck5vZGVzKTtcbiAgICB0aGlzLnRyZWVDb250cm9sLmRhdGFOb2RlcyA9IHRoaXMuZGF0YVNvdXJjZS5kYXRhJC52YWx1ZTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlV3JhcHBlck5vZGVzKFxuICAgIG5vZGVzOiBOZ2N4VHJlZU5vZGVbXSxcbiAgICBwYXJlbnQ/OiBOZ2N4VHJlZU5vZGVXcmFwcGVyPFQ+LFxuICAgIGRlcHRoOiBudW1iZXIgPSAwXG4gICk6IE5nY3hUcmVlTm9kZVdyYXBwZXI8VD5bXSB7XG4gICAgY29uc3QgY2hpbGRDb3VudCA9IG5vZGVzLmxlbmd0aDtcbiAgICBjb25zdCB3cmFwcGVyTm9kZXMgPSBub2Rlcy5tYXAoKG5vZGUsIGlkeCkgPT4ge1xuICAgICAgY29uc3Qgbm9kZVdyYXBwZXI6IE5nY3hUcmVlTm9kZVdyYXBwZXI8VD4gPSB7XG4gICAgICAgIGlkOiBub2RlLmlkLFxuICAgICAgICBkYXRhOiA8VD5ub2RlLFxuICAgICAgICBpc0ZpcnN0Q2hpbGQ6IGlkeCA9PT0gMCxcbiAgICAgICAgaXNMYXN0Q2hpbGQ6IGlkeCA9PT0gY2hpbGRDb3VudCAtIDEsXG4gICAgICAgIGluZGV4OiBpZHgsXG4gICAgICAgIHBhcmVudDogcGFyZW50LFxuICAgICAgICBkZXB0aDogZGVwdGgsXG4gICAgICAgIGNoaWxkcmVuOiBbXSxcbiAgICAgIH07XG4gICAgICBub2RlV3JhcHBlci5jaGlsZHJlbiA9IG5vZGUuY2hpbGRyZW5cbiAgICAgICAgPyB0aGlzLmNyZWF0ZVdyYXBwZXJOb2Rlcyhub2RlLmNoaWxkcmVuLCBub2RlV3JhcHBlciwgZGVwdGggKyAxKVxuICAgICAgICA6IFtdO1xuXG4gICAgICByZXR1cm4gbm9kZVdyYXBwZXI7XG4gICAgfSk7XG4gICAgd3JhcHBlck5vZGVzLmZvckVhY2goKHdyYXBwZXJOb2RlKSA9PiB7XG4gICAgICBpZiAoIXdyYXBwZXJOb2RlLmlzTGFzdENoaWxkKSB7XG4gICAgICAgIHdyYXBwZXJOb2RlLm5leHQgPSB3cmFwcGVyTm9kZXNbd3JhcHBlck5vZGUuaW5kZXggKyAxXTtcbiAgICAgIH1cbiAgICAgIGlmICghd3JhcHBlck5vZGUuaXNGaXJzdENoaWxkKSB7XG4gICAgICAgIHdyYXBwZXJOb2RlLnByZXZpb3VzID0gd3JhcHBlck5vZGVzW3dyYXBwZXJOb2RlLmluZGV4IC0gMV07XG4gICAgICB9XG4gICAgICBpZiAodGhpcy5jb25maWc/LmFsbG93U2VsZWN0aW9uPy4od3JhcHBlck5vZGUpKSB7XG4gICAgICAgIHdyYXBwZXJOb2RlLmlzU2VsZWN0YWJsZSA9IHRydWU7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIHdyYXBwZXJOb2RlcztcbiAgfVxuXG4gIHByb3RlY3RlZCBhbGxvd0Ryb3AoXG4gICAgZHJvcE5vZGU6IE5nY3hUcmVlTm9kZVdyYXBwZXI8VD4sXG4gICAgZHJvcFR5cGU6IERyb3BUeXBlXG4gICk6IGJvb2xlYW4ge1xuICAgIGlmIChcbiAgICAgICF0aGlzLmRyYWdnaW5nIHx8XG4gICAgICB0aGlzLmRyYWdnaW5nLmlkID09PSBkcm9wTm9kZS5pZCB8fFxuICAgICAgaXNQYXJlbnRPZih0aGlzLmRyYWdnaW5nLCBkcm9wTm9kZSlcbiAgICApIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgaWYgKFxuICAgICAgZHJvcFR5cGUgPT0gRHJvcFR5cGUuRFJPUF9JTlRPICYmXG4gICAgICBkcm9wTm9kZS5pZCA9PT0gdGhpcy5kcmFnZ2luZy5wYXJlbnQ/LmlkXG4gICAgKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGlmIChcbiAgICAgIGRyb3BUeXBlID09IERyb3BUeXBlLkRST1BfQUZURVIgJiZcbiAgICAgIGRyb3BOb2RlLm5leHQ/LmlkID09PSB0aGlzLmRyYWdnaW5nLmlkXG4gICAgKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGlmIChcbiAgICAgIGRyb3BUeXBlID09IERyb3BUeXBlLkRST1BfQkVGT1JFICYmXG4gICAgICBkcm9wTm9kZS5wcmV2aW91cz8uaWQgPT09IHRoaXMuZHJhZ2dpbmcuaWRcbiAgICApIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBjb25zdCBpbnRvTm9kZSA9XG4gICAgICBkcm9wVHlwZSA9PSBEcm9wVHlwZS5EUk9QX0lOVE8gPyBkcm9wTm9kZSA6IGRyb3BOb2RlLnBhcmVudDtcbiAgICBpZiAodGhpcy5jb25maWc/LmFsbG93RHJvcCkge1xuICAgICAgcmV0dXJuIHRoaXMuY29uZmlnLmFsbG93RHJvcCh0aGlzLmRyYWdnaW5nLCBpbnRvTm9kZSk7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLy8gcHJldmVudCBkcm9wIGRpcmVjdGx5IGFmdGVyIGEgbm9kZSBvbiBzYW1lIGxldmVsLCB0aGF0IGlzIGV4cGFuZGVkXG4gIHByb3RlY3RlZCBzb3J0UHJlZGljYXRlKCk6IChcbiAgICBpbmRleDogbnVtYmVyLFxuICAgIGRyYWc6IENka0RyYWcsXG4gICAgZHJvcDogQ2RrRHJvcExpc3RcbiAgKSA9PiBib29sZWFuIHtcbiAgICByZXR1cm4gKFxuICAgICAgaW5kZXg6IG51bWJlcixcbiAgICAgIF9kcmFnOiBDZGtEcmFnPE5nY3hUcmVlTm9kZVdyYXBwZXI8VD4+LFxuICAgICAgZHJvcDogQ2RrRHJvcExpc3Q8TmdjeFRyZWVOb2RlV3JhcHBlcjxUPj5cbiAgICApID0+IHtcbiAgICAgIHJldHVybiBpbmRleCA9PSAwIHx8ICF0aGlzLnRyZWVDb250cm9sLmlzRXhwYW5kZWQoZHJvcC5kYXRhKTtcbiAgICB9O1xuICB9XG5cbiAgcHJvdGVjdGVkIGRpc2FibGVEcmFnKG5vZGU6IE5nY3hUcmVlTm9kZVdyYXBwZXI8VD4pIHtcbiAgICByZXR1cm4gdGhpcy5jb25maWc/LmFsbG93RHJhZyA/ICF0aGlzLmNvbmZpZy5hbGxvd0RyYWcobm9kZSkgOiBmYWxzZTtcbiAgfVxuXG4gIHByb3RlY3RlZCBrZXlEb3duQXJyb3dVcChldmVudDogRXZlbnQpIHtcbiAgICBpZiAodGhpcy5zZWxlY3RlZE5vZGUpIHtcbiAgICAgIGlmICghdGhpcy5zZWxlY3RlZE5vZGUuaXNGaXJzdENoaWxkKSB7XG4gICAgICAgIHRoaXMuc2VsZWN0Tm9kZSh0aGlzLnNlbGVjdGVkTm9kZS5wcmV2aW91cyk7XG4gICAgICB9IGVsc2UgaWYgKHRoaXMuc2VsZWN0ZWROb2RlLnBhcmVudCkge1xuICAgICAgICB0aGlzLnNlbGVjdE5vZGUodGhpcy5zZWxlY3RlZE5vZGUucGFyZW50KTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3Qgbm9kZXMgPSB0aGlzLmRhdGFTb3VyY2UuZGF0YSQudmFsdWU7XG4gICAgICBpZiAobm9kZXMubGVuZ3RoID4gMCkge1xuICAgICAgICB0aGlzLnNlbGVjdE5vZGUobm9kZXNbbm9kZXMubGVuZ3RoIC0gMV0pO1xuICAgICAgfVxuICAgIH1cbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGtleURvd25BcnJvd0Rvd24oZXZlbnQ6IEV2ZW50KSB7XG4gICAgaWYgKHRoaXMuc2VsZWN0ZWROb2RlKSB7XG4gICAgICBpZiAoIXRoaXMuc2VsZWN0ZWROb2RlLmlzTGFzdENoaWxkKSB7XG4gICAgICAgIHRoaXMuc2VsZWN0Tm9kZSh0aGlzLnNlbGVjdGVkTm9kZS5uZXh0KTtcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5zZWxlY3RlZE5vZGUucGFyZW50Py5uZXh0KSB7XG4gICAgICAgIHRoaXMuc2VsZWN0Tm9kZSh0aGlzLnNlbGVjdGVkTm9kZS5wYXJlbnQubmV4dCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IG5vZGVzID0gdGhpcy5kYXRhU291cmNlLmRhdGEkLnZhbHVlO1xuICAgICAgaWYgKG5vZGVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgdGhpcy5zZWxlY3ROb2RlKG5vZGVzWzBdKTtcbiAgICAgIH1cbiAgICB9XG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBrZXlEb3duQXJyb3dMZWZ0KGV2ZW50OiBFdmVudCkge1xuICAgIGlmICh0aGlzLnNlbGVjdGVkTm9kZSkge1xuICAgICAgaWYgKHRoaXMudHJlZUNvbnRyb2wuaXNFeHBhbmRlZCh0aGlzLnNlbGVjdGVkTm9kZSkpIHtcbiAgICAgICAgdGhpcy50cmVlQ29udHJvbC5jb2xsYXBzZSh0aGlzLnNlbGVjdGVkTm9kZSk7XG4gICAgICB9IGVsc2UgaWYgKHRoaXMuc2VsZWN0ZWROb2RlPy5wYXJlbnQpIHtcbiAgICAgICAgdGhpcy5zZWxlY3ROb2RlKHRoaXMuc2VsZWN0ZWROb2RlLnBhcmVudCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IG5vZGVzID0gdGhpcy5kYXRhU291cmNlLmRhdGEkLnZhbHVlO1xuICAgICAgaWYgKG5vZGVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgdGhpcy5zZWxlY3ROb2RlKG5vZGVzWzBdKTtcbiAgICAgIH1cbiAgICB9XG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBrZXlEb3duQXJyb3dSaWdodChldmVudDogRXZlbnQpIHtcbiAgICBpZiAodGhpcy5zZWxlY3RlZE5vZGUgJiYgdGhpcy5zZWxlY3RlZE5vZGUuY2hpbGRyZW4ubGVuZ3RoID4gMCkge1xuICAgICAgdGhpcy5zZWxlY3ROb2RlKHRoaXMuc2VsZWN0ZWROb2RlLmNoaWxkcmVuWzBdKTtcbiAgICB9IGVsc2UgaWYgKCF0aGlzLnNlbGVjdGVkTm9kZSkge1xuICAgICAgY29uc3Qgbm9kZXMgPSB0aGlzLmRhdGFTb3VyY2UuZGF0YSQudmFsdWU7XG4gICAgICBpZiAobm9kZXMubGVuZ3RoID4gMCkge1xuICAgICAgICB0aGlzLnNlbGVjdE5vZGUobm9kZXNbMF0pO1xuICAgICAgfVxuICAgIH1cbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignd2luZG93OmtleWRvd24uZXNjYXBlJylcbiAgcHJvdGVjdGVkIGtleUVzY2FwZVdoaWxlRHJhZ2dpbmcoKSB7XG4gICAgaWYgKHRoaXMuZHJhZ2dpbmcpIHtcbiAgICAgIHRoaXMuY2FuY2VsZWRCeUVzYyA9IHRydWU7XG4gICAgICBkb2N1bWVudC5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudCgnbW91c2V1cCcpKTtcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgaGFuZGxlRHJhZ1JlbGVhc2UoZXZlbnQ6IENka0RyYWdSZWxlYXNlPE5nY3hUcmVlTm9kZVdyYXBwZXI8VD4+KSB7XG4gICAgdGhpcy5kcmFnZ2luZyA9IHVuZGVmaW5lZDtcbiAgICBjb25zdCBtb3ZlZE5vZGUgPSBldmVudC5zb3VyY2UuZGF0YTtcbiAgICBjb25zdCBkcm9wWm9uZUlkID0gKDxhbnk+ZXZlbnQuZXZlbnQudGFyZ2V0KS5pZDtcbiAgICBpZiAoIWRyb3Bab25lSWQpIHtcbiAgICAgIC8vIG5vIHZhbGlkIGRyb3Agem9uZVxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGRyb3Bab25lSW5mbyA9IG5ldyBEcm9wWm9uZUluZm8oZHJvcFpvbmVJZCk7XG4gICAgY29uc3QgdG9Ob2RlID0gdGhpcy50cmVlQ29udHJvbC5maW5kTm9kZUJ5SWQoZHJvcFpvbmVJbmZvLm5vZGVJZCk7XG4gICAgaWYgKCF0b05vZGUpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoYG5vZGUgd2l0aCBpZCAnJHtkcm9wWm9uZUluZm8ubm9kZUlkfScgY291bGQgbm90IGJlIGZvdW5kYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gZHJvcFR5cGUgdW5kZWZpbmVkIGNhbiBoYXBwZW4gaWYgZHJvcHBlZCBkaXJlY3RseSB3aXRob3V0IG1vdmluZ1xuICAgIGlmICh0aGlzLmNhbmNlbGVkQnlFc2MgfHwgZHJvcFpvbmVJbmZvLmRyb3BUeXBlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMuY2FuY2VsZWRCeUVzYyA9IGZhbHNlO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGluc2VydEludG9Ob2RlID1cbiAgICAgIGRyb3Bab25lSW5mby5kcm9wVHlwZSA9PT0gRHJvcFR5cGUuRFJPUF9JTlRPID8gdG9Ob2RlIDogdG9Ob2RlLnBhcmVudDtcbiAgICBjb25zdCB3cmFwcGVyTGlzdCA9IGluc2VydEludG9Ob2RlPy5jaGlsZHJlbiA/PyB0aGlzLmRhdGFTb3VyY2UuZGF0YSQudmFsdWU7XG4gICAgY29uc3QgYWRkQXROb2RlSWR4ID0gdGhpcy5maW5kQWRkSW5kZXgoXG4gICAgICBkcm9wWm9uZUluZm8sXG4gICAgICBpbnNlcnRJbnRvTm9kZSxcbiAgICAgIHdyYXBwZXJMaXN0XG4gICAgKTtcblxuICAgIGNvbnN0IHJlbW92ZWRGcm9tSWR4ID0gdGhpcy5yZW1vdmVFbGVtZW50RnJvbVByZXZpb3VzUG9zaXRpb24obW92ZWROb2RlKTtcbiAgICAvLyBhZGQgZWxlbWVudCB0byBuZXcgUG9zaXRpb24sIHN1YnRyYWN0IG9uZSBpZiBpbnNlcnRlZCBpbiBzYW1lIGxpc3QgYWZ0ZXIgdGhlIHJlbW92ZSBwb3NpdGlvblxuICAgIChpbnNlcnRJbnRvTm9kZT8uZGF0YS5jaGlsZHJlbiA/PyB0aGlzLm5vZGVzISkuc3BsaWNlKFxuICAgICAgbW92ZWROb2RlLnBhcmVudD8uaWQgPT09IGluc2VydEludG9Ob2RlPy5pZCAmJlxuICAgICAgICByZW1vdmVkRnJvbUlkeCA8IGFkZEF0Tm9kZUlkeFxuICAgICAgICA/IGFkZEF0Tm9kZUlkeCAtIDFcbiAgICAgICAgOiBhZGRBdE5vZGVJZHgsXG4gICAgICAwLFxuICAgICAgbW92ZWROb2RlLmRhdGFcbiAgICApO1xuXG4gICAgY29uc3QgYWZ0ZXJOb2RlSWR4ID0gYWRkQXROb2RlSWR4IC0gMTtcbiAgICBjb25zdCBhZnRlck5vZGUgPVxuICAgICAgYWZ0ZXJOb2RlSWR4ID4gLTEgJiYgd3JhcHBlckxpc3QubGVuZ3RoID4gYWZ0ZXJOb2RlSWR4XG4gICAgICAgID8gd3JhcHBlckxpc3RbYWZ0ZXJOb2RlSWR4XVxuICAgICAgICA6IHVuZGVmaW5lZDtcblxuICAgIGNvbnN0IGJlZm9yZU5vZGUgPVxuICAgICAgYWRkQXROb2RlSWR4ID4gLTEgJiYgd3JhcHBlckxpc3QubGVuZ3RoID4gYWRkQXROb2RlSWR4XG4gICAgICAgID8gd3JhcHBlckxpc3RbYWRkQXROb2RlSWR4XVxuICAgICAgICA6IHVuZGVmaW5lZDtcbiAgICB0aGlzLm5vZGVNb3ZlZC5lbWl0KHtcbiAgICAgIG5vZGU6IG1vdmVkTm9kZSxcbiAgICAgIHBhcmVudDpcbiAgICAgICAgZHJvcFpvbmVJbmZvLmRyb3BUeXBlID09PSBEcm9wVHlwZS5EUk9QX0lOVE8gPyB0b05vZGUgOiB0b05vZGUucGFyZW50LFxuICAgICAgYWZ0ZXJOb2RlOiBhZnRlck5vZGUsXG4gICAgICBiZWZvcmVOb2RlOiBiZWZvcmVOb2RlLFxuICAgIH0pO1xuICAgIHRoaXMuZGF0YVNvdXJjZSA9IG5ldyBOZ2N4VHJlZURhdGFTb3VyY2UoXG4gICAgICB0aGlzLmNyZWF0ZVdyYXBwZXJOb2Rlcyh0aGlzLm5vZGVzISlcbiAgICApO1xuICAgIHRoaXMudHJlZUNvbnRyb2wuZGF0YU5vZGVzID0gdGhpcy5kYXRhU291cmNlLmRhdGEkLnZhbHVlO1xuICB9XG5cbiAgcHJpdmF0ZSBmaW5kQWRkSW5kZXgoXG4gICAgZHJvcFpvbmVJbmZvOiBEcm9wWm9uZUluZm8sXG4gICAgaW5zZXJ0SW50b05vZGU6IE5nY3hUcmVlTm9kZVdyYXBwZXI8VD4gfCB1bmRlZmluZWQsXG4gICAgaW5zZXJ0SW50b0xpc3Q6IE5nY3hUcmVlTm9kZVdyYXBwZXI8VD5bXVxuICApIHtcbiAgICBpZiAoXG4gICAgICBpbnNlcnRJbnRvTm9kZSAmJlxuICAgICAgZHJvcFpvbmVJbmZvLmRyb3BUeXBlID09PSBEcm9wVHlwZS5EUk9QX0lOVE8gJiZcbiAgICAgICFpbnNlcnRJbnRvTm9kZS5kYXRhLmNoaWxkcmVuXG4gICAgKSB7XG4gICAgICBpbnNlcnRJbnRvTm9kZS5kYXRhLmNoaWxkcmVuID0gW107XG4gICAgfVxuICAgIGxldCBhZGRBdE5vZGVJZHggPSAwO1xuICAgIGlmIChcbiAgICAgIGRyb3Bab25lSW5mby5kcm9wVHlwZSA9PT0gRHJvcFR5cGUuRFJPUF9BRlRFUiB8fFxuICAgICAgZHJvcFpvbmVJbmZvLmRyb3BUeXBlID09PSBEcm9wVHlwZS5EUk9QX0JFRk9SRVxuICAgICkge1xuICAgICAgYWRkQXROb2RlSWR4ID0gaW5zZXJ0SW50b0xpc3QuZmluZEluZGV4KFxuICAgICAgICAoY2hpbGQpID0+IGNoaWxkLmlkID09PSBkcm9wWm9uZUluZm8ubm9kZUlkXG4gICAgICApO1xuICAgICAgaWYgKGRyb3Bab25lSW5mby5kcm9wVHlwZSA9PT0gRHJvcFR5cGUuRFJPUF9BRlRFUikge1xuICAgICAgICBhZGRBdE5vZGVJZHgrKztcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGFkZEF0Tm9kZUlkeDtcbiAgfVxuXG4gIHByaXZhdGUgcmVtb3ZlRWxlbWVudEZyb21QcmV2aW91c1Bvc2l0aW9uKFxuICAgIG1vdmVkTm9kZTogTmdjeFRyZWVOb2RlV3JhcHBlcjxUPlxuICApOiBudW1iZXIge1xuICAgIGNvbnN0IHJlbW92ZUZyb21MaXN0ID0gbW92ZWROb2RlLnBhcmVudD8uZGF0YS5jaGlsZHJlbiA/PyB0aGlzLm5vZGVzITtcbiAgICBjb25zdCByZW1vdmVJbmRleCA9IHJlbW92ZUZyb21MaXN0LmZpbmRJbmRleChcbiAgICAgIChjaGlsZDogYW55KSA9PiBjaGlsZC5pZCA9PT0gbW92ZWROb2RlLmlkXG4gICAgKTtcbiAgICByZW1vdmVGcm9tTGlzdC5zcGxpY2UocmVtb3ZlSW5kZXgsIDEpO1xuICAgIHJldHVybiByZW1vdmVJbmRleDtcbiAgfVxuXG4gIG5vZGVDbGlja2VkKG5vZGVXcmFwcGVyOiBOZ2N4VHJlZU5vZGVXcmFwcGVyPFQ+KSB7XG4gICAgdGhpcy5jbGlja0V2ZW50LmVtaXQobm9kZVdyYXBwZXIpO1xuICAgIGlmIChub2RlV3JhcHBlci5pc1NlbGVjdGFibGUpIHtcbiAgICAgIHRoaXMuc2VsZWN0ZWROb2RlID1cbiAgICAgICAgbm9kZVdyYXBwZXIuaWQgPT09IHRoaXMuc2VsZWN0ZWROb2RlPy5pZCA/IHVuZGVmaW5lZCA6IG5vZGVXcmFwcGVyO1xuICAgICAgdGhpcy5zZWxlY3RFdmVudC5lbWl0KHRoaXMuc2VsZWN0ZWROb2RlKTtcbiAgICB9XG4gIH1cblxuICBzZWxlY3ROb2RlKG5vZGVXcmFwcGVyOiBOZ2N4VHJlZU5vZGVXcmFwcGVyPFQ+IHwgdW5kZWZpbmVkKSB7XG4gICAgaWYgKCFub2RlV3JhcHBlciB8fCBub2RlV3JhcHBlci5pc1NlbGVjdGFibGUpIHtcbiAgICAgIHRoaXMuc2VsZWN0ZWROb2RlID0gbm9kZVdyYXBwZXI7XG4gICAgICBsZXQgZXhwYW5kTm9kZSA9IHRoaXMuc2VsZWN0ZWROb2RlPy5wYXJlbnQ7XG4gICAgICB3aGlsZSAoZXhwYW5kTm9kZSkge1xuICAgICAgICB0aGlzLnRyZWVDb250cm9sLmV4cGFuZChleHBhbmROb2RlKTtcbiAgICAgICAgZXhwYW5kTm9kZSA9IGV4cGFuZE5vZGUucGFyZW50O1xuICAgICAgfVxuICAgICAgdGhpcy5zZWxlY3RFdmVudC5lbWl0KHRoaXMuc2VsZWN0ZWROb2RlKTtcbiAgICB9XG4gIH1cbn1cblxuZW51bSBEcm9wVHlwZSB7XG4gIERST1BfQUZURVIgPSAnRFJPUF9BRlRFUicsXG4gIERST1BfQkVGT1JFID0gJ0RST1BfQkVGT1JFJyxcbiAgRFJPUF9JTlRPID0gJ0RST1BfSU5UTycsXG59XG5cbmV4cG9ydCBjbGFzcyBOZ2N4VHJlZUNvbnRyb2w8VCBleHRlbmRzIE5nY3hUcmVlTm9kZT4gZXh0ZW5kcyBOZXN0ZWRUcmVlQ29udHJvbDxcbiAgTmdjeFRyZWVOb2RlV3JhcHBlcjxUPixcbiAgc3RyaW5nXG4+IHtcbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSB0cmVlQ29tcG9uZW50OiBOZ2N4VHJlZUNvbXBvbmVudDxUPixcbiAgICBnZXRDaGlsZHJlbjogKGRhdGFOb2RlOiBOZ2N4VHJlZU5vZGVXcmFwcGVyPFQ+KSA9PiBOZ2N4VHJlZU5vZGVXcmFwcGVyPFQ+W10sXG4gICAgb3B0aW9ucz86IE5lc3RlZFRyZWVDb250cm9sT3B0aW9uczxOZ2N4VHJlZU5vZGVXcmFwcGVyPFQ+LCBzdHJpbmc+XG4gICkge1xuICAgIHN1cGVyKGdldENoaWxkcmVuLCBvcHRpb25zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBzZWxlY3QgYSBub2RlIGJ5IGlkLiB0aGUgc2VsZWN0RXZlbnQgaXMgZmlyZWQgYWZ0ZXJ3YXJkcy5cbiAgICovXG4gIHNlbGVjdE5vZGVCeUlkKGlkOiBzdHJpbmcpIHtcbiAgICB0aGlzLnRyZWVDb21wb25lbnQuc2VsZWN0Tm9kZSh0aGlzLmZpbmROb2RlQnlJZChpZCkpO1xuICB9XG5cbiAgLyoqXG4gICAqIGZpbmQgYSBub2RlIGJ5IGlkLlxuICAgKi9cbiAgZmluZE5vZGVCeUlkKGlkOiBzdHJpbmcpOiBOZ2N4VHJlZU5vZGVXcmFwcGVyPFQ+IHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5maW5kTm9kZUJ5SWRJbk5vZGVzKFxuICAgICAgdGhpcy50cmVlQ29tcG9uZW50LmRhdGFTb3VyY2UuZGF0YSQudmFsdWUsXG4gICAgICBpZFxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIGZpbmROb2RlQnlJZEluTm9kZXMoXG4gICAgbm9kZXM6IE5nY3hUcmVlTm9kZVdyYXBwZXI8VD5bXSxcbiAgICBpZDogc3RyaW5nXG4gICk6IE5nY3hUcmVlTm9kZVdyYXBwZXI8VD4gfCB1bmRlZmluZWQge1xuICAgIGZvciAoY29uc3Qgbm9kZSBvZiBub2Rlcykge1xuICAgICAgaWYgKG5vZGUuaWQgPT09IGlkKSB7XG4gICAgICAgIHJldHVybiBub2RlO1xuICAgICAgfVxuICAgICAgaWYgKG5vZGUuY2hpbGRyZW4/Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgY29uc3QgZm91bmROb2RlID0gdGhpcy5maW5kTm9kZUJ5SWRJbk5vZGVzKG5vZGUuY2hpbGRyZW4sIGlkKTtcbiAgICAgICAgaWYgKGZvdW5kTm9kZSkge1xuICAgICAgICAgIHJldHVybiBmb3VuZE5vZGU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59XG5cbmNsYXNzIERyb3Bab25lSW5mbyB7XG4gIGRyb3BUeXBlOiBEcm9wVHlwZTtcbiAgbm9kZUlkOiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3IoaWQ6IHN0cmluZykge1xuICAgIGNvbnN0IHBvcyA9IGlkLmluZGV4T2YoJ18nKTtcbiAgICB0aGlzLm5vZGVJZCA9IGlkLnN1YnN0cmluZygwLCBwb3MpO1xuICAgIHRoaXMuZHJvcFR5cGUgPSA8RHJvcFR5cGU+aWQuc3Vic3RyaW5nKHBvcyArIDEpO1xuICB9XG59XG4iLCI8Y2RrLXRyZWVcbiAgI3RyZWVcbiAgY2xhc3M9XCJuZ2N4LXRyZWVcIlxuICAqbmdJZj1cImRhdGFTb3VyY2VcIlxuICBbZGF0YVNvdXJjZV09XCJkYXRhU291cmNlXCJcbiAgW3RyZWVDb250cm9sXT1cInRyZWVDb250cm9sXCJcbiAgY2RrRHJvcExpc3RHcm91cFxuICBbY2xhc3MuZHJhZ2dpbmddPVwiZHJhZ2dpbmdcIlxuICAoa2V5dXAuYXJyb3d1cCk9XCJrZXlEb3duQXJyb3dVcCgkZXZlbnQpXCJcbiAgKGtleWRvd24uYXJyb3dkb3duKT1cImtleURvd25BcnJvd0Rvd24oJGV2ZW50KVwiXG4gIChrZXlkb3duLmFycm93bGVmdCk9XCJrZXlEb3duQXJyb3dMZWZ0KCRldmVudClcIlxuICAoa2V5ZG93bi5hcnJvd3JpZ2h0KT1cImtleURvd25BcnJvd1JpZ2h0KCRldmVudClcIlxuICB0YWJpbmRleD1cIjBcIj5cbiAgPGNkay1uZXN0ZWQtdHJlZS1ub2RlICpjZGtUcmVlTm9kZURlZj1cImxldCBub2RlXCIgY2xhc3M9XCJ0cmVlLW5vZGVcIj5cbiAgICA8ZGl2XG4gICAgICBjZGtEcm9wTGlzdFxuICAgICAgW2lkXT1cIm5vZGUuaWQgKyAnXycgKyBEcm9wVHlwZS5EUk9QX0FGVEVSXCJcbiAgICAgIGNsYXNzPVwidHJlZS1ub2RlLWNvbnRhaW5lci1kcm9wLXpvbmUgYWZ0ZXItZXhwYW5kZWQtbm9kZVwiXG4gICAgICBbY2xhc3MuaGlkZV09XCJcbiAgICAgICAgIWFsbG93RHJvcChub2RlLCBEcm9wVHlwZS5EUk9QX0FGVEVSKSB8fCAhdHJlZUNvbnRyb2wuaXNFeHBhbmRlZChub2RlKVxuICAgICAgXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiZHJvcC1pbnNlcnQtbGluZVwiPjwvZGl2PlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJ0cmVlLW5vZGUtY29udGFpbmVyXCI+XG4gICAgICA8ZGl2XG4gICAgICAgIGNka0Ryb3BMaXN0XG4gICAgICAgIFtpZF09XCJub2RlLmlkICsgJ18nICsgRHJvcFR5cGUuRFJPUF9CRUZPUkVcIlxuICAgICAgICBjbGFzcz1cInRyZWUtbm9kZS1jb250YWluZXItZHJvcC16b25lIGJlZm9yZS1ub2RlXCJcbiAgICAgICAgW2NsYXNzLmhpZGVdPVwiXG4gICAgICAgICAgIW5vZGUuaXNGaXJzdENoaWxkIHx8ICFhbGxvd0Ryb3Aobm9kZSwgRHJvcFR5cGUuRFJPUF9CRUZPUkUpXG4gICAgICAgIFwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiZHJvcC1pbnNlcnQtbGluZVwiPjwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2XG4gICAgICAgIGNka0Ryb3BMaXN0XG4gICAgICAgIFtpZF09XCJub2RlLmlkICsgJ18nICsgRHJvcFR5cGUuRFJPUF9JTlRPXCJcbiAgICAgICAgY2xhc3M9XCJ0cmVlLW5vZGUtY29udGFpbmVyLWRyb3Atem9uZSBpbnRvLW5vZGVcIlxuICAgICAgICBbY2xhc3MuaGlkZV09XCIhYWxsb3dEcm9wKG5vZGUsIERyb3BUeXBlLkRST1BfSU5UTylcIj48L2Rpdj5cbiAgICAgIDxkaXZcbiAgICAgICAgY2RrRHJvcExpc3RcbiAgICAgICAgW2lkXT1cIm5vZGUuaWQgKyAnXycgKyBEcm9wVHlwZS5EUk9QX0FGVEVSXCJcbiAgICAgICAgY2xhc3M9XCJ0cmVlLW5vZGUtY29udGFpbmVyLWRyb3Atem9uZSBhZnRlci1ub2RlXCJcbiAgICAgICAgW2NsYXNzLmxhc3RdPVwibm9kZS5pc0xhc3RDaGlsZFwiXG4gICAgICAgIFtjbGFzcy5oaWRlXT1cIlxuICAgICAgICAgIHRyZWVDb250cm9sLmlzRXhwYW5kZWQobm9kZSkgfHwgIWFsbG93RHJvcChub2RlLCBEcm9wVHlwZS5EUk9QX0FGVEVSKVxuICAgICAgICBcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImRyb3AtaW5zZXJ0LWxpbmVcIj48L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdlxuICAgICAgICBjZGtEcm9wTGlzdFxuICAgICAgICBbY2RrRHJvcExpc3REYXRhXT1cIm5vZGVcIlxuICAgICAgICBbY2RrRHJvcExpc3RFbnRlclByZWRpY2F0ZV09XCJkaXNhYmxlXCJcbiAgICAgICAgW2Nka0Ryb3BMaXN0U29ydFByZWRpY2F0ZV09XCJkaXNhYmxlXCI+XG4gICAgICAgIDxkaXZcbiAgICAgICAgICBjZGtEcmFnXG4gICAgICAgICAgW2Nka0RyYWdEaXNhYmxlZF09XCJkaXNhYmxlRHJhZyhub2RlKVwiXG4gICAgICAgICAgW2Nka0RyYWdEYXRhXT1cIm5vZGVcIlxuICAgICAgICAgIChjZGtEcmFnU3RhcnRlZCk9XCJkcmFnZ2luZyA9IG5vZGVcIlxuICAgICAgICAgIChjZGtEcmFnUmVsZWFzZWQpPVwiaGFuZGxlRHJhZ1JlbGVhc2UoJGV2ZW50KVwiPlxuICAgICAgICAgIDxkaXYgKmNka0RyYWdQbGFjZWhvbGRlcj48L2Rpdj5cbiAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICBjbGFzcz1cInRyZWUtbm9kZS1jb250ZW50LWNvbnRhaW5lclwiXG4gICAgICAgICAgICBbY2xhc3MuZmlyc3RdPVwibm9kZS5pc0ZpcnN0Q2hpbGRcIlxuICAgICAgICAgICAgW2NsYXNzLmxhc3RdPVwibm9kZS5pc0xhc3RDaGlsZFwiXG4gICAgICAgICAgICBbY2xhc3MuZXhwYW5kZWRdPVwidHJlZUNvbnRyb2wuaXNFeHBhbmRlZChub2RlKVwiPlxuICAgICAgICAgICAgPG5nY3gtdHJlZS1ub2RlXG4gICAgICAgICAgICAgIHN0eWxlPVwid2lkdGg6IDEwMCVcIlxuICAgICAgICAgICAgICBbbm9kZVdyYXBwZXJdPVwibm9kZVwiXG4gICAgICAgICAgICAgIFtpc1NlbGVjdGVkXT1cIm5vZGUuaWQgPT09IHNlbGVjdGVkTm9kZT8uaWRcIlxuICAgICAgICAgICAgICBbdHJlZUNvbnRyb2xdPVwidHJlZUNvbnRyb2xcIlxuICAgICAgICAgICAgICBbdHJlZUNvbmZpZ109XCJjb25maWdcIlxuICAgICAgICAgICAgICAoY3VzdG9tRXZlbnQpPVwiY3VzdG9tRXZlbnQuZW1pdCgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgKGNsaWNrRXZlbnQpPVwibm9kZUNsaWNrZWQobm9kZSlcIj48L25nY3gtdHJlZS1ub2RlPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPG5nY3gtdHJlZS1ub2RlXG4gICAgICAgICAgKm5nSWY9XCJub2RlLmlkID09PSBkcmFnZ2luZz8uaWRcIlxuICAgICAgICAgIFtub2RlV3JhcHBlcl09XCJub2RlXCJcbiAgICAgICAgICBbdHJlZUNvbnRyb2xdPVwidHJlZUNvbnRyb2xcIlxuICAgICAgICAgIFt0cmVlQ29uZmlnXT1cImNvbmZpZ1wiPjwvbmdjeC10cmVlLW5vZGU+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2XG4gICAgICAqbmdJZj1cInRyZWVDb250cm9sLmlzRXhwYW5kZWQobm9kZSlcIlxuICAgICAgY2xhc3M9XCJ0cmVlLW5vZGUtY2hpbGRyZW4tY29udGFpbmVyXCJcbiAgICAgIFtjbGFzcy5maXJzdF09XCJub2RlLmlzRmlyc3RDaGlsZFwiXG4gICAgICBbY2xhc3MubGFzdF09XCJub2RlLmlzTGFzdENoaWxkXCI+XG4gICAgICA8ZGl2IGNka1RyZWVOb2RlT3V0bGV0PjwvZGl2PlxuICAgIDwvZGl2PlxuICA8L2Nkay1uZXN0ZWQtdHJlZS1ub2RlPlxuPC9jZGstdHJlZT5cbiJdfQ==
|