@limble/limble-tree 0.12.4 → 0.13.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 +149 -149
- package/{esm2015/lib/classes/Branch.js → esm2020/lib/classes/Branch.mjs} +1 -1
- package/{esm2015/lib/classes/DropZone.js → esm2020/lib/classes/DropZone.mjs} +1 -1
- package/{esm2015/lib/classes/DropZoneLocation.js → esm2020/lib/classes/DropZoneLocation.mjs} +1 -1
- package/{esm2015/lib/custom-event-bindings/dragleave-no-change-detect.directive.js → esm2020/lib/custom-event-bindings/dragleave-no-change-detect.directive.mjs} +0 -0
- package/{esm2015/lib/custom-event-bindings/dragover-no-change-detect.directive.js → esm2020/lib/custom-event-bindings/dragover-no-change-detect.directive.mjs} +1 -1
- package/esm2020/lib/drop-zone/drop-zone.component.mjs +75 -0
- package/esm2020/lib/limble-tree-branch/limble-tree-branch.component.mjs +110 -0
- package/esm2020/lib/limble-tree-node/limble-tree-node.component.mjs +467 -0
- package/{esm2015/lib/limble-tree-placeholder/limble-tree-placeholder.component.js → esm2020/lib/limble-tree-placeholder/limble-tree-placeholder.component.mjs} +3 -8
- package/esm2020/lib/limble-tree-root/drop-zone.service.mjs +376 -0
- package/esm2020/lib/limble-tree-root/limble-tree-root.component.mjs +172 -0
- package/{esm2015/lib/limble-tree-root/tree-construction-status.service.js → esm2020/lib/limble-tree-root/tree-construction-status.service.mjs} +1 -1
- package/esm2020/lib/limble-tree-root/tree.service.mjs +297 -0
- package/{esm2015/lib/limble-tree.module.js → esm2020/lib/limble-tree.module.mjs} +5 -5
- package/{esm2015/lib/singletons/component-creator.service.js → esm2020/lib/singletons/component-creator.service.mjs} +1 -1
- package/esm2020/lib/singletons/drag-state.service.mjs +63 -0
- package/esm2020/lib/singletons/global-events.service.mjs +136 -0
- package/{esm2015/lib/util.js → esm2020/lib/util.mjs} +1 -1
- package/{esm2015/limble-limble-tree.js → esm2020/limble-limble-tree.mjs} +0 -0
- package/{esm2015/public-api.js → esm2020/public-api.mjs} +1 -1
- package/fesm2015/limble-limble-tree.mjs +2256 -0
- package/fesm2015/limble-limble-tree.mjs.map +1 -0
- package/{fesm2015/limble-limble-tree.js → fesm2020/limble-limble-tree.mjs} +89 -136
- package/fesm2020/limble-limble-tree.mjs.map +1 -0
- package/{limble-limble-tree.d.ts → index.d.ts} +0 -0
- package/lib/custom-event-bindings/dragleave-no-change-detect.directive.d.ts +1 -1
- package/lib/custom-event-bindings/dragover-no-change-detect.directive.d.ts +1 -1
- package/lib/drop-zone/drop-zone.component.d.ts +1 -1
- package/lib/limble-tree-branch/limble-tree-branch.component.d.ts +1 -1
- package/lib/limble-tree-node/limble-tree-node.component.d.ts +1 -1
- package/lib/limble-tree-placeholder/limble-tree-placeholder.component.d.ts +1 -1
- package/lib/limble-tree-root/limble-tree-root.component.d.ts +1 -1
- package/package.json +22 -9
- package/bundles/limble-limble-tree.umd.js +0 -2910
- package/bundles/limble-limble-tree.umd.js.map +0 -1
- package/esm2015/lib/drop-zone/drop-zone.component.js +0 -81
- package/esm2015/lib/limble-tree-branch/limble-tree-branch.component.js +0 -116
- package/esm2015/lib/limble-tree-node/limble-tree-node.component.js +0 -484
- package/esm2015/lib/limble-tree-root/drop-zone.service.js +0 -377
- package/esm2015/lib/limble-tree-root/limble-tree-root.component.js +0 -178
- package/esm2015/lib/limble-tree-root/tree.service.js +0 -301
- package/esm2015/lib/singletons/drag-state.service.js +0 -64
- package/esm2015/lib/singletons/global-events.service.js +0 -137
- package/fesm2015/limble-limble-tree.js.map +0 -1
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
import { Component, EventEmitter, Input, NgZone, Output, ViewChild, ViewContainerRef } from "@angular/core";
|
|
2
|
-
import { DropZoneService } from "./drop-zone.service";
|
|
3
|
-
import { TreeService } from "./tree.service";
|
|
4
|
-
import { isElementDescendant, isFirefox } from "../util";
|
|
5
|
-
import { first } from "rxjs/operators";
|
|
6
|
-
import { TreeConstructionStatus } from "./tree-construction-status.service";
|
|
7
|
-
import * as i0 from "@angular/core";
|
|
8
|
-
import * as i1 from "./tree.service";
|
|
9
|
-
import * as i2 from "./drop-zone.service";
|
|
10
|
-
import * as i3 from "../singletons/drag-state.service";
|
|
11
|
-
import * as i4 from "../singletons/global-events.service";
|
|
12
|
-
import * as i5 from "../custom-event-bindings/dragover-no-change-detect.directive";
|
|
13
|
-
import * as i6 from "../custom-event-bindings/dragleave-no-change-detect.directive";
|
|
14
|
-
import * as i7 from "@angular/common";
|
|
15
|
-
import * as i8 from "../limble-tree-placeholder/limble-tree-placeholder.component";
|
|
16
|
-
const _c0 = ["host"];
|
|
17
|
-
function LimbleTreeRootComponent_limble_tree_placeholder_1_Template(rf, ctx) { if (rf & 1) {
|
|
18
|
-
i0.ɵɵelement(0, "limble-tree-placeholder");
|
|
19
|
-
} }
|
|
20
|
-
function LimbleTreeRootComponent_ng_template_2_Template(rf, ctx) { }
|
|
21
|
-
export class LimbleTreeRootComponent {
|
|
22
|
-
constructor(treeService, dropZoneService, dragStateService, globalEventsService, ngZone, changeDetectorRef, el) {
|
|
23
|
-
this.treeService = treeService;
|
|
24
|
-
this.dropZoneService = dropZoneService;
|
|
25
|
-
this.dragStateService = dragStateService;
|
|
26
|
-
this.globalEventsService = globalEventsService;
|
|
27
|
-
this.ngZone = ngZone;
|
|
28
|
-
this.changeDetectorRef = changeDetectorRef;
|
|
29
|
-
this.el = el;
|
|
30
|
-
this.treeChange = new EventEmitter();
|
|
31
|
-
this.treeDrop = new EventEmitter();
|
|
32
|
-
this.changesSubscription = this.treeService.changes$.subscribe(() => {
|
|
33
|
-
//"In dev mode, Angular performs an additional check after each change
|
|
34
|
-
//detection run, to ensure the bindings haven’t changed." We use a timeout here
|
|
35
|
-
//to preclude the possibility of causing a binding to update in the parent
|
|
36
|
-
//component after change detection runs but before the additional check.
|
|
37
|
-
//See https://angular.io/errors/NG0100 for details.
|
|
38
|
-
setTimeout(() => {
|
|
39
|
-
this.treeChange.emit();
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
this.dropSubscription = this.treeService.drops$.subscribe((drop) => {
|
|
43
|
-
setTimeout(() => {
|
|
44
|
-
this.treeDrop.emit(drop);
|
|
45
|
-
});
|
|
46
|
-
});
|
|
47
|
-
this.placeholder = false;
|
|
48
|
-
this.treeService.placeholder$.subscribe((value) => {
|
|
49
|
-
this.placeholder = value;
|
|
50
|
-
if (!NgZone.isInAngularZone()) {
|
|
51
|
-
this.changeDetectorRef.detectChanges();
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
ngAfterViewInit() {
|
|
56
|
-
var _a;
|
|
57
|
-
if (((_a = this.options) === null || _a === void 0 ? void 0 : _a.listMode) !== true &&
|
|
58
|
-
(this.itemsPerPage !== undefined || this.page !== undefined)) {
|
|
59
|
-
console.warn("pagination is only allowed in listMode; `itemsPerPage` and `page` inputs will be ignored");
|
|
60
|
-
}
|
|
61
|
-
this.update();
|
|
62
|
-
this.changeDetectorRef.detectChanges();
|
|
63
|
-
this.ngZone.runOutsideAngular(() => {
|
|
64
|
-
//this is for mac os - without this dragover handler drop events aren't firing correctly
|
|
65
|
-
this.el.nativeElement.addEventListener("dragover", (event) => {
|
|
66
|
-
event.preventDefault();
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
ngOnChanges() {
|
|
71
|
-
if (this.host !== undefined && this.data !== undefined) {
|
|
72
|
-
this.update();
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
/** Rebuild the tree */
|
|
76
|
-
update() {
|
|
77
|
-
if (this.host === undefined) {
|
|
78
|
-
throw new Error("Failed to render limble tree. Failure occurred at root.");
|
|
79
|
-
}
|
|
80
|
-
if (this.data === undefined) {
|
|
81
|
-
throw new Error(`limbleTree requires a data object`);
|
|
82
|
-
}
|
|
83
|
-
this.treeService.init(this.host, this.data, this.options, this.itemsPerPage, this.page);
|
|
84
|
-
//We check for firefox here because there is a bug in Firefox that causes the
|
|
85
|
-
//custom scrolling to break. See https://bugzilla.mozilla.org/show_bug.cgi?id=505521#c80
|
|
86
|
-
if (!isFirefox()) {
|
|
87
|
-
this.globalEventsService.addScrolling();
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
dragoverHandler(event) {
|
|
91
|
-
if (event.dataTransfer === null) {
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
event.stopPropagation();
|
|
95
|
-
event.preventDefault();
|
|
96
|
-
event.dataTransfer.dropEffect = "move";
|
|
97
|
-
}
|
|
98
|
-
dragleaveHandler(event) {
|
|
99
|
-
const currentTarget = event.currentTarget;
|
|
100
|
-
const relatedTarget = event.relatedTarget;
|
|
101
|
-
if (!(currentTarget instanceof Node) ||
|
|
102
|
-
!(relatedTarget instanceof Node) ||
|
|
103
|
-
isElementDescendant(currentTarget, relatedTarget) !== false) {
|
|
104
|
-
//event came from deeper in the tree. Ignore it.
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
//Mouse has left the tree, so clear the drop zones
|
|
108
|
-
this.dropZoneService.clearVisibleZones();
|
|
109
|
-
this.changeDetectorRef.detectChanges();
|
|
110
|
-
}
|
|
111
|
-
dropHandler(event) {
|
|
112
|
-
event.stopPropagation();
|
|
113
|
-
if (this.dragStateService.getState() !== "droppable") {
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
const sourceBranch = this.dragStateService.capture();
|
|
117
|
-
if (sourceBranch === undefined) {
|
|
118
|
-
throw new Error("failed to get current branch in dragendHandler");
|
|
119
|
-
}
|
|
120
|
-
const dropZone = this.dropZoneService.getActiveDropZone();
|
|
121
|
-
if (dropZone === null) {
|
|
122
|
-
throw new Error("failed to get active drop zone at drop handler");
|
|
123
|
-
}
|
|
124
|
-
this.treeService.captured = true;
|
|
125
|
-
this.dragStateService.state$
|
|
126
|
-
.pipe(first((message) => message === "idle"))
|
|
127
|
-
.subscribe(() => {
|
|
128
|
-
this.treeService.captured = false;
|
|
129
|
-
});
|
|
130
|
-
this.dropZoneService.clearVisibleZones();
|
|
131
|
-
this.treeService.drop(sourceBranch, dropZone.getFullInsertCoordinates());
|
|
132
|
-
}
|
|
133
|
-
ngOnDestroy() {
|
|
134
|
-
this.changesSubscription.unsubscribe();
|
|
135
|
-
this.dropSubscription.unsubscribe();
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
LimbleTreeRootComponent.ɵfac = function LimbleTreeRootComponent_Factory(t) { return new (t || LimbleTreeRootComponent)(i0.ɵɵdirectiveInject(i1.TreeService), i0.ɵɵdirectiveInject(i2.DropZoneService), i0.ɵɵdirectiveInject(i3.DragStateService), i0.ɵɵdirectiveInject(i4.GlobalEventsService), i0.ɵɵdirectiveInject(i0.NgZone), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i0.ElementRef)); };
|
|
139
|
-
LimbleTreeRootComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: LimbleTreeRootComponent, selectors: [["limble-tree-root"]], viewQuery: function LimbleTreeRootComponent_Query(rf, ctx) { if (rf & 1) {
|
|
140
|
-
i0.ɵɵviewQuery(_c0, 5, ViewContainerRef);
|
|
141
|
-
} if (rf & 2) {
|
|
142
|
-
let _t;
|
|
143
|
-
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.host = _t.first);
|
|
144
|
-
} }, inputs: { data: "data", options: "options", itemsPerPage: "itemsPerPage", page: "page" }, outputs: { treeChange: "treeChange", treeDrop: "treeDrop" }, features: [i0.ɵɵProvidersFeature([TreeService, DropZoneService, TreeConstructionStatus]), i0.ɵɵNgOnChangesFeature], decls: 4, vars: 1, consts: [[1, "tree-event-host", 3, "dragoverNoChangeDetect", "dragleaveNoChangeDetect", "drop"], [4, "ngIf"], ["host", ""]], template: function LimbleTreeRootComponent_Template(rf, ctx) { if (rf & 1) {
|
|
145
|
-
i0.ɵɵelementStart(0, "div", 0);
|
|
146
|
-
i0.ɵɵlistener("dragoverNoChangeDetect", function LimbleTreeRootComponent_Template_div_dragoverNoChangeDetect_0_listener($event) { return ctx.dragoverHandler($event); })("dragleaveNoChangeDetect", function LimbleTreeRootComponent_Template_div_dragleaveNoChangeDetect_0_listener($event) { return ctx.dragleaveHandler($event); })("drop", function LimbleTreeRootComponent_Template_div_drop_0_listener($event) { return ctx.dropHandler($event); });
|
|
147
|
-
i0.ɵɵtemplate(1, LimbleTreeRootComponent_limble_tree_placeholder_1_Template, 1, 0, "limble-tree-placeholder", 1);
|
|
148
|
-
i0.ɵɵtemplate(2, LimbleTreeRootComponent_ng_template_2_Template, 0, 0, "ng-template", null, 2, i0.ɵɵtemplateRefExtractor);
|
|
149
|
-
i0.ɵɵelementEnd();
|
|
150
|
-
} if (rf & 2) {
|
|
151
|
-
i0.ɵɵadvance(1);
|
|
152
|
-
i0.ɵɵproperty("ngIf", ctx.placeholder === true);
|
|
153
|
-
} }, directives: [i5.DragoverNoChangeDetectDirective, i6.DragleaveNoChangeDetectDirective, i7.NgIf, i8.LimbleTreePlaceholderComponent], styles: [""] });
|
|
154
|
-
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(LimbleTreeRootComponent, [{
|
|
155
|
-
type: Component,
|
|
156
|
-
args: [{
|
|
157
|
-
selector: "limble-tree-root",
|
|
158
|
-
templateUrl: "./limble-tree-root.component.html",
|
|
159
|
-
styleUrls: ["./limble-tree-root.component.scss"],
|
|
160
|
-
providers: [TreeService, DropZoneService, TreeConstructionStatus]
|
|
161
|
-
}]
|
|
162
|
-
}], function () { return [{ type: i1.TreeService }, { type: i2.DropZoneService }, { type: i3.DragStateService }, { type: i4.GlobalEventsService }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: i0.ElementRef }]; }, { data: [{
|
|
163
|
-
type: Input
|
|
164
|
-
}], options: [{
|
|
165
|
-
type: Input
|
|
166
|
-
}], itemsPerPage: [{
|
|
167
|
-
type: Input
|
|
168
|
-
}], page: [{
|
|
169
|
-
type: Input
|
|
170
|
-
}], host: [{
|
|
171
|
-
type: ViewChild,
|
|
172
|
-
args: ["host", { read: ViewContainerRef }]
|
|
173
|
-
}], treeChange: [{
|
|
174
|
-
type: Output
|
|
175
|
-
}], treeDrop: [{
|
|
176
|
-
type: Output
|
|
177
|
-
}] }); })();
|
|
178
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGltYmxlLXRyZWUtcm9vdC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9saW1ibGUtdHJlZS9zcmMvbGliL2xpbWJsZS10cmVlLXJvb3QvbGltYmxlLXRyZWUtcm9vdC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9saW1ibGUtdHJlZS9zcmMvbGliL2xpbWJsZS10cmVlLXJvb3QvbGltYmxlLXRyZWUtcm9vdC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBR0osU0FBUyxFQUVULFlBQVksRUFDWixLQUFLLEVBQ0wsTUFBTSxFQUdOLE1BQU0sRUFDTixTQUFTLEVBQ1QsZ0JBQWdCLEVBQ2xCLE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQU10RCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxFQUFFLG1CQUFtQixFQUFFLFNBQVMsRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUd6RCxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDdkMsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sb0NBQW9DLENBQUM7Ozs7Ozs7Ozs7OztJQ3BCekUsMENBRTJCOzs7QUQwQjlCLE1BQU0sT0FBTyx1QkFBdUI7SUFvQmpDLFlBQ29CLFdBQXdCLEVBQ3hCLGVBQWdDLEVBQ2hDLGdCQUFrQyxFQUNsQyxtQkFBd0MsRUFDeEMsTUFBYyxFQUNkLGlCQUFvQyxFQUNwQyxFQUF1QjtRQU52QixnQkFBVyxHQUFYLFdBQVcsQ0FBYTtRQUN4QixvQkFBZSxHQUFmLGVBQWUsQ0FBaUI7UUFDaEMscUJBQWdCLEdBQWhCLGdCQUFnQixDQUFrQjtRQUNsQyx3QkFBbUIsR0FBbkIsbUJBQW1CLENBQXFCO1FBQ3hDLFdBQU0sR0FBTixN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MEI7O3VGRDJCcEIsdUJBQXVCO2NBTm5DLFNBQVM7ZUFBQztnQkFDUixRQUFRLEVBQUUsa0JBQWtCO2dCQUM1QixXQUFXLEVBQUUsbUNBQW1DO2dCQUNoRCxTQUFTLEVBQUUsQ0FBQyxtQ0FBbUMsQ0FBQztnQkFDaEQsU0FBUyxFQUFFLENBQUMsV0FBVyxFQUFFLGVBQWUsRUFBRSxzQkFBc0IsQ0FBQzthQUNuRTsyT0FJVyxJQUFJO2tCQUFaLEtBQUs7WUFDRyxPQUFPO2tCQUFmLEtBQUs7WUFDRyxZQUFZO2tCQUFwQixLQUFLO1lBQ0csSUFBSTtrQkFBWixLQUFLO1lBRWlELElBQUk7a0JBQTFELFNBQVM7bUJBQUMsTUFBTSxFQUFFLEVBQUUsSUFBSSxFQUFFLGdCQUFnQixFQUFFO1lBSTFCLFVBQVU7a0JBQTVCLE1BQU07WUFFWSxRQUFRO2tCQUExQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcclxuICAgQWZ0ZXJWaWV3SW5pdCxcclxuICAgQ2hhbmdlRGV0ZWN0b3JSZWYsXHJcbiAgIENvbXBvbmVudCxcclxuICAgRWxlbWVudFJlZixcclxuICAgRXZlbnRFbWl0dGVyLFxyXG4gICBJbnB1dCxcclxuICAgTmdab25lLFxyXG4gICBPbkNoYW5nZXMsXHJcbiAgIE9uRGVzdHJveSxcclxuICAgT3V0cHV0LFxyXG4gICBWaWV3Q2hpbGQsXHJcbiAgIFZpZXdDb250YWluZXJSZWZcclxufSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xyXG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tIFwicnhqc1wiO1xyXG5pbXBvcnQgeyBEcm9wWm9uZVNlcnZpY2UgfSBmcm9tIFwiLi9kcm9wLXpvbmUuc2VydmljZVwiO1xyXG5pbXBvcnQge1xyXG4gICBMaW1ibGVUcmVlRGF0YSxcclxuICAgTGltYmxlVHJlZU9wdGlvbnMsXHJcbiAgIFRyZWVEcm9wXHJcbn0gZnJvbSBcIi4uL2xpbWJsZS10cmVlLXJvb3QvdHJlZS5zZXJ2aWNlXCI7XHJcbmltcG9ydCB7IFRyZWVTZXJ2aWNlIH0gZnJvbSBcIi4vdHJlZS5zZXJ2aWNlXCI7XHJcbmltcG9ydCB7IGlzRWxlbWVudERlc2NlbmRhbnQsIGlzRmlyZWZveCB9IGZyb20gXCIuLi91dGlsXCI7XHJcbmltcG9ydCB7IERyYWdTdGF0ZVNlcnZpY2UgfSBmcm9tIFwiLi4vc2luZ2xldG9ucy9kcmFnLXN0YXRlLnNlcnZpY2VcIjtcclxuaW1wb3J0IHsgR2xvYmFsRXZlbnRzU2VydmljZSB9IGZyb20gXCIuLi9zaW5nbGV0b25zL2dsb2JhbC1ldmVudHMuc2VydmljZVwiO1xyXG5pbXBvcnQgeyBmaXJzdCB9IGZyb20gXCJyeGpzL29wZXJhdG9yc1wiO1xyXG5pbXBvcnQgeyBUcmVlQ29uc3RydWN0aW9uU3RhdHVzIH0gZnJvbSBcIi4vdHJlZS1jb25zdHJ1Y3Rpb24tc3RhdHVzLnNlcnZpY2VcIjtcclxuXHJcbkBDb21wb25lbnQoe1xyXG4gICBzZWxlY3RvcjogXCJsaW1ibGUtdHJlZS1yb290XCIsXHJcbiAgIHRlbXBsYXRlVXJsOiBcIi4vbGltYmxlLXRyZWUtcm9vdC5jb21wb25lbnQuaHRtbFwiLFxyXG4gICBzdHlsZVVybHM6IFtcIi4vbGltYmxlLXRyZWUtcm9vdC5jb21wb25lbnQuc2Nzc1wiXSxcclxuICAgcHJvdmlkZXJzOiBbVHJlZVNlcnZpY2UsIERyb3Bab25lU2VydmljZSwgVHJlZUNvbnN0cnVjdGlvblN0YXR1c11cclxufSlcclxuZXhwb3J0IGNsYXNzIExpbWJsZVRyZWVSb290Q29tcG9uZW50XHJcbiAgIGltcGxlbWVudHMgQWZ0ZXJWaWV3SW5pdCwgT25DaGFuZ2VzLCBPbkRlc3Ryb3lcclxue1xyXG4gICBASW5wdXQoKSBkYXRhOiBMaW1ibGVUcmVlRGF0YSB8IHVuZGVmaW5lZDtcclxuICAgQElucHV0KCkgb3B0aW9uczogTGltYmxlVHJlZU9wdGlvbnMgfCB1bmRlZmluZWQ7XHJcbiAgIEBJbnB1dCgpIGl0ZW1zUGVyUGFnZTogbnVtYmVyIHwgdW5kZWZpbmVkO1xyXG4gICBASW5wdXQoKSBwYWdlOiBudW1iZXIgfCB1bmRlZmluZWQ7XHJcblxyXG4gICBAVmlld0NoaWxkKFwiaG9zdFwiLCB7IHJlYWQ6IFZpZXdDb250YWluZXJSZWYgfSkgcHJpdmF0ZSBob3N0OlxyXG4gICAgICB8IFZpZXdDb250YWluZXJSZWZcclxuICAgICAgfCB1bmRlZmluZWQ7XHJcblxyXG4gICBAT3V0cHV0KCkgcmVhZG9ubHkgdHJlZUNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8bnVsbD4oKTtcclxuXHJcbiAgIEBPdXRwdXQoKSByZWFkb25seSB0cmVlRHJvcCA9IG5ldyBFdmVudEVtaXR0ZXI8VHJlZURyb3A+KCk7XHJcblxyXG4gICBwcml2YXRlIHJlYWRvbmx5IGNoYW5nZXNTdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbjtcclxuICAgcHJpdmF0ZSByZWFkb25seSBkcm9wU3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb247XHJcbiAgIHB1YmxpYyBwbGFjZWhvbGRlcjogYm9vbGVhbjtcclxuXHJcbiAgIGNvbnN0cnVjdG9yKFxyXG4gICAgICBwcml2YXRlIHJlYWRvbmx5IHRyZWVTZXJ2aWNlOiBUcmVlU2VydmljZSxcclxuICAgICAgcHJpdmF0ZSByZWFkb25seSBkcm9wWm9uZVNlcnZpY2U6IERyb3Bab25lU2VydmljZSxcclxuICAgICAgcHJpdmF0ZSByZWFkb25seSBkcmFnU3RhdGVTZXJ2aWNlOiBEcmFnU3RhdGVTZXJ2aWNlLFxyXG4gICAgICBwcml2YXRlIHJlYWRvbmx5IGdsb2JhbEV2ZW50c1NlcnZpY2U6IEdsb2JhbEV2ZW50c1NlcnZpY2UsXHJcbiAgICAgIHByaXZhdGUgcmVhZG9ubHkgbmdab25lOiBOZ1pvbmUsXHJcbiAgICAgIHByaXZhdGUgcmVhZG9ubHkgY2hhbmdlRGV0ZWN0b3JSZWY6IENoYW5nZURldGVjdG9yUmVmLFxyXG4gICAgICBwcml2YXRlIHJlYWRvbmx5IGVsOiBFbGVtZW50UmVmPEVsZW1lbnQ+XHJcbiAgICkge1xyXG4gICAgICB0aGlzLmNoYW5nZXNTdWJzY3JpcHRpb24gPSB0aGlzLnRyZWVTZXJ2aWNlLmNoYW5nZXMkLnN1YnNjcmliZSgoKSA9PiB7XHJcbiAgICAgICAgIC8vXCJJbiBkZXYgbW9kZSwgQW5ndWxhciBwZXJmb3JtcyBhbiBhZGRpdGlvbmFsIGNoZWNrIGFmdGVyIGVhY2ggY2hhbmdlXHJcbiAgICAgICAgIC8vZGV0ZWN0aW9uIHJ1biwgdG8gZW5zdXJlIHRoZSBiaW5kaW5ncyBoYXZlbuKAmXQgY2hhbmdlZC5cIiBXZSB1c2UgYSB0aW1lb3V0IGhlcmVcclxuICAgICAgICAgLy90byBwcmVjbHVkZSB0aGUgcG9zc2liaWxpdHkgb2YgY2F1c2luZyBhIGJpbmRpbmcgdG8gdXBkYXRlIGluIHRoZSBwYXJlbnRcclxuICAgICAgICAgLy9jb21wb25lbnQgYWZ0ZXIgY2hhbmdlIGRldGVjdGlvbiBydW5zIGJ1dCBiZWZvcmUgdGhlIGFkZGl0aW9uYWwgY2hlY2suXHJcbiAgICAgICAgIC8vU2VlIGh0dHBzOi8vYW5ndWxhci5pby9lcnJvcnMvTkcwMTAwIGZvciBkZXRhaWxzLlxyXG4gICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICAgICAgdGhpcy50cmVlQ2hhbmdlLmVtaXQoKTtcclxuICAgICAgICAgfSk7XHJcbiAgICAgIH0pO1xyXG4gICAgICB0aGlzLmRyb3BTdWJzY3JpcHRpb24gPSB0aGlzLnRyZWVTZXJ2aWNlLmRyb3BzJC5zdWJzY3JpYmUoKGRyb3ApID0+IHtcclxuICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgICAgIHRoaXMudHJlZURyb3AuZW1pdChkcm9wKTtcclxuICAgICAgICAgfSk7XHJcbiAgICAgIH0pO1xyXG4gICAgICB0aGlzLnBsYWNlaG9sZGVyID0gZmFsc2U7XHJcbiAgICAgIHRoaXMudHJlZVNlcnZpY2UucGxhY2Vob2xkZXIkLnN1YnNjcmliZSgodmFsdWUpID0+IHtcclxuICAgICAgICAgdGhpcy5wbGFjZWhvbGRlciA9IHZhbHVlO1xyXG4gICAgICAgICBpZiAoIU5nWm9uZS5pc0luQW5ndWxhclpvbmUoKSkge1xyXG4gICAgICAgICAgICB0aGlzLmNoYW5nZURldGVjdG9yUmVmLmRldGVjdENoYW5nZXMoKTtcclxuICAgICAgICAgfVxyXG4gICAgICB9KTtcclxuICAgfVxyXG5cclxuICAgbmdBZnRlclZpZXdJbml0KCkge1xyXG4gICAgICBpZiAoXHJcbiAgICAgICAgIHRoaXMub3B0aW9ucz8ubGlzdE1vZGUgIT09IHRydWUgJiZcclxuICAgICAgICAgKHRoaXMuaXRlbXNQZXJQYWdlICE9PSB1bmRlZmluZWQgfHwgdGhpcy5wYWdlICE9PSB1bmRlZmluZWQpXHJcbiAgICAgICkge1xyXG4gICAgICAgICBjb25zb2xlLndhcm4oXHJcbiAgICAgICAgICAgIFwicGFnaW5hdGlvbiBpcyBvbmx5IGFsbG93ZWQgaW4gbGlzdE1vZGU7IGBpdGVtc1BlclBhZ2VgIGFuZCBgcGFnZWAgaW5wdXRzIHdpbGwgYmUgaWdub3JlZFwiXHJcbiAgICAgICAgICk7XHJcbiAgICAgIH1cclxuICAgICAgdGhpcy51cGRhdGUoKTtcclxuICAgICAgdGhpcy5jaGFuZ2VEZXRlY3RvclJlZi5kZXRlY3RDaGFuZ2VzKCk7XHJcblxyXG4gICAgICB0aGlzLm5nWm9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XHJcbiAgICAgICAgIC8vdGhpcyBpcyBmb3IgbWFjIG9zIC0gd2l0aG91dCB0aGlzIGRyYWdvdmVyIGhhbmRsZXIgZHJvcCBldmVudHMgYXJlbid0IGZpcmluZyBjb3JyZWN0bHlcclxuICAgICAgICAgdGhpcy5lbC5uYXRpdmVFbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoXCJkcmFnb3ZlclwiLCAoZXZlbnQpID0+IHtcclxuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICAgfSk7XHJcbiAgICAgIH0pO1xyXG4gICB9XHJcblxyXG4gICBuZ09uQ2hhbmdlcygpIHtcclxuICAgICAgaWYgKHRoaXMuaG9zdCAhPT0gdW5kZWZpbmVkICYmIHRoaXMuZGF0YSAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgIHRoaXMudXBkYXRlKCk7XHJcbiAgICAgIH1cclxuICAgfVxyXG5cclxuICAgLyoqIFJlYnVpbGQgdGhlIHRyZWUgKi9cclxuICAgcHVibGljIHVwZGF0ZSgpIHtcclxuICAgICAgaWYgKHRoaXMuaG9zdCA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgIHRocm93IG5ldyBFcnJvcihcclxuICAgICAgICAgICAgXCJGYWlsZWQgdG8gcmVuZGVyIGxpbWJsZSB0cmVlLiBGYWlsdXJlIG9jY3VycmVkIGF0IHJvb3QuXCJcclxuICAgICAgICAgKTtcclxuICAgICAgfVxyXG4gICAgICBpZiAodGhpcy5kYXRhID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBsaW1ibGVUcmVlIHJlcXVpcmVzIGEgZGF0YSBvYmplY3RgKTtcclxuICAgICAgfVxyXG4gICAgICB0aGlzLnRyZWVTZXJ2aWNlLmluaXQoXHJcbiAgICAgICAgIHRoaXMuaG9zdCxcclxuICAgICAgICAgdGhpcy5kYXRhLFxyXG4gICAgICAgICB0aGlzLm9wdGlvbnMsXHJcbiAgICAgICAgIHRoaXMuaXRlbXNQZXJQYWdlLFxyXG4gICAgICAgICB0aGlzLnBhZ2VcclxuICAgICAgKTtcclxuICAgICAgLy9XZSBjaGVjayBmb3IgZmlyZWZveCBoZXJlIGJlY2F1c2UgdGhlcmUgaXMgYSBidWcgaW4gRmlyZWZveCB0aGF0IGNhdXNlcyB0aGVcclxuICAgICAgLy9jdXN0b20gc2Nyb2xsaW5nIHRvIGJyZWFrLiBTZWUgaHR0cHM6Ly9idWd6aWxsYS5tb3ppbGxhLm9yZy9zaG93X2J1Zy5jZ2k/aWQ9NTA1NTIxI2M4MFxyXG4gICAgICBpZiAoIWlzRmlyZWZveCgpKSB7XHJcbiAgICAgICAgIHRoaXMuZ2xvYmFsRXZlbnRzU2VydmljZS5hZGRTY3JvbGxpbmcoKTtcclxuICAgICAgfVxyXG4gICB9XHJcblxyXG4gICBwdWJsaWMgZHJhZ292ZXJIYW5kbGVyKGV2ZW50OiBEcmFnRXZlbnQpIHtcclxuICAgICAgaWYgKGV2ZW50LmRhdGFUcmFuc2ZlciA9PT0gbnVsbCkge1xyXG4gICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XHJcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgIGV2ZW50LmRhdGFUcmFuc2Zlci5kcm9wRWZmZWN0ID0gXCJtb3ZlXCI7XHJcbiAgIH1cclxuXHJcbiAgIHB1YmxpYyBkcmFnbGVhdmVIYW5kbGVyKGV2ZW50OiBEcmFnRXZlbnQpIHtcclxuICAgICAgY29uc3QgY3VycmVudFRhcmdldCA9IGV2ZW50LmN1cnJlbnRUYXJnZXQ7XHJcbiAgICAgIGNvbnN0IHJlbGF0ZWRUYXJnZXQgPSBldmVudC5yZWxhdGVkVGFyZ2V0O1xyXG4gICAgICBpZiAoXHJcbiAgICAgICAgICEoY3VycmVudFRhcmdldCBpbnN0YW5jZW9mIE5vZGUpIHx8XHJcbiAgICAgICAgICEocmVsYXRlZFRhcmdldCBpbnN0YW5jZW9mIE5vZGUpIHx8XHJcbiAgICAgICAgIGlzRWxlbWVudERlc2NlbmRhbnQoY3VycmVudFRhcmdldCwgcmVsYXRlZFRhcmdldCkgIT09IGZhbHNlXHJcbiAgICAgICkge1xyXG4gICAgICAgICAvL2V2ZW50IGNhbWUgZnJvbSBkZWVwZXIgaW4gdGhlIHRyZWUuIElnbm9yZSBpdC5cclxuICAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcbiAgICAgIC8vTW91c2UgaGFzIGxlZnQgdGhlIHRyZWUsIHNvIGNsZWFyIHRoZSBkcm9wIHpvbmVzXHJcbiAgICAgIHRoaXMuZHJvcFpvbmVTZXJ2aWNlLmNsZWFyVmlzaWJsZVpvbmVzKCk7XHJcbiAgICAgIHRoaXMuY2hhbmdlRGV0ZWN0b3JSZWYuZGV0ZWN0Q2hhbmdlcygpO1xyXG4gICB9XHJcblxyXG4gICBwdWJsaWMgZHJvcEhhbmRsZXIoZXZlbnQ6IERyYWdFdmVudCkge1xyXG4gICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcclxuICAgICAgaWYgKHRoaXMuZHJhZ1N0YXRlU2VydmljZS5nZXRTdGF0ZSgpICE9PSBcImRyb3BwYWJsZVwiKSB7XHJcbiAgICAgICAgIHJldHVybjtcclxuICAgICAgfVxyXG4gICAgICBjb25zdCBzb3VyY2VCcmFuY2ggPSB0aGlzLmRyYWdTdGF0ZVNlcnZpY2UuY2FwdHVyZSgpO1xyXG4gICAgICBpZiAoc291cmNlQnJhbmNoID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiZmFpbGVkIHRvIGdldCBjdXJyZW50IGJyYW5jaCBpbiBkcmFnZW5kSGFuZGxlclwiKTtcclxuICAgICAgfVxyXG4gICAgICBjb25zdCBkcm9wWm9uZSA9IHRoaXMuZHJvcFpvbmVTZXJ2aWNlLmdldEFjdGl2ZURyb3Bab25lKCk7XHJcbiAgICAgIGlmIChkcm9wWm9uZSA9PT0gbnVsbCkge1xyXG4gICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJmYWlsZWQgdG8gZ2V0IGFjdGl2ZSBkcm9wIHpvbmUgYXQgZHJvcCBoYW5kbGVyXCIpO1xyXG4gICAgICB9XHJcbiAgICAgIHRoaXMudHJlZVNlcnZpY2UuY2FwdHVyZWQgPSB0cnVlO1xyXG4gICAgICB0aGlzLmRyYWdTdGF0ZVNlcnZpY2Uuc3RhdGUkXHJcbiAgICAgICAgIC5waXBlKGZpcnN0KChtZXNzYWdlKSA9PiBtZXNzYWdlID09PSBcImlkbGVcIikpXHJcbiAgICAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xyXG4gICAgICAgICAgICB0aGlzLnRyZWVTZXJ2aWNlLmNhcHR1cmVkID0gZmFsc2U7XHJcbiAgICAgICAgIH0pO1xyXG4gICAgICB0aGlzLmRyb3Bab25lU2VydmljZS5jbGVhclZpc2libGVab25lcygpO1xyXG4gICAgICB0aGlzLnRyZWVTZXJ2aWNlLmRyb3Aoc291cmNlQnJhbmNoLCBkcm9wWm9uZS5nZXRGdWxsSW5zZXJ0Q29vcmRpbmF0ZXMoKSk7XHJcbiAgIH1cclxuXHJcbiAgIG5nT25EZXN0cm95KCkge1xyXG4gICAgICB0aGlzLmNoYW5nZXNTdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcclxuICAgICAgdGhpcy5kcm9wU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XHJcbiAgIH1cclxufVxyXG4iLCI8ZGl2XHJcbiAgIChkcmFnb3Zlck5vQ2hhbmdlRGV0ZWN0KT1cImRyYWdvdmVySGFuZGxlcigkZXZlbnQpXCJcclxuICAgKGRyYWdsZWF2ZU5vQ2hhbmdlRGV0ZWN0KT1cImRyYWdsZWF2ZUhhbmRsZXIoJGV2ZW50KVwiXHJcbiAgIChkcm9wKT1cImRyb3BIYW5kbGVyKCRldmVudClcIlxyXG4gICBjbGFzcz1cInRyZWUtZXZlbnQtaG9zdFwiXHJcbj5cclxuICAgPGxpbWJsZS10cmVlLXBsYWNlaG9sZGVyXHJcbiAgICAgICpuZ0lmPVwicGxhY2Vob2xkZXIgPT09IHRydWVcIlxyXG4gICA+PC9saW1ibGUtdHJlZS1wbGFjZWhvbGRlcj5cclxuICAgPG5nLXRlbXBsYXRlICNob3N0PjwvbmctdGVtcGxhdGU+XHJcbjwvZGl2PlxyXG4iXX0=
|
|
@@ -1,301 +0,0 @@
|
|
|
1
|
-
import { Injectable } from "@angular/core";
|
|
2
|
-
import { Branch } from "../classes/Branch";
|
|
3
|
-
import { LimbleTreeNodeComponent } from "../limble-tree-node/limble-tree-node.component";
|
|
4
|
-
import { BehaviorSubject, EMPTY, Subject } from "rxjs";
|
|
5
|
-
import { arraysAreEqual } from "../util";
|
|
6
|
-
import { debounce, debounceTime, filter, tap } from "rxjs/operators";
|
|
7
|
-
import * as i0 from "@angular/core";
|
|
8
|
-
import * as i1 from "../singletons/component-creator.service";
|
|
9
|
-
import * as i2 from "./drop-zone.service";
|
|
10
|
-
import * as i3 from "../singletons/drag-state.service";
|
|
11
|
-
import * as i4 from "./tree-construction-status.service";
|
|
12
|
-
/** The default value for the `indent` option */
|
|
13
|
-
export const INDENT = 45;
|
|
14
|
-
export class TreeService {
|
|
15
|
-
constructor(componentCreatorService, dropZoneService, dragStateService, treeConstructionStatus) {
|
|
16
|
-
this.componentCreatorService = componentCreatorService;
|
|
17
|
-
this.dropZoneService = dropZoneService;
|
|
18
|
-
this.dragStateService = dragStateService;
|
|
19
|
-
this.treeConstructionStatus = treeConstructionStatus;
|
|
20
|
-
this.changes$ = new Subject();
|
|
21
|
-
this.drops$ = new Subject();
|
|
22
|
-
this.treeModel = new Branch(null);
|
|
23
|
-
this.placeholder = false;
|
|
24
|
-
this.captured = false;
|
|
25
|
-
this.cleanupSignal$ = new Subject();
|
|
26
|
-
let rebuild = false;
|
|
27
|
-
let treeIsStable = false;
|
|
28
|
-
const treeIsStable$ = this.treeConstructionStatus.stable$.pipe(tap((value) => {
|
|
29
|
-
treeIsStable = value;
|
|
30
|
-
}), filter((value) => value === true));
|
|
31
|
-
this.cleanupSignal$
|
|
32
|
-
.pipe(tap((value) => {
|
|
33
|
-
rebuild = value;
|
|
34
|
-
}), debounce(() => {
|
|
35
|
-
if (treeIsStable === true) {
|
|
36
|
-
//If tree is stable, continue right away
|
|
37
|
-
return EMPTY;
|
|
38
|
-
}
|
|
39
|
-
//If tree is not stable, wait for it to become so.
|
|
40
|
-
return treeIsStable$;
|
|
41
|
-
}),
|
|
42
|
-
//We use this timed debounce to throttle chained destruction of components
|
|
43
|
-
debounceTime(5))
|
|
44
|
-
.subscribe(() => {
|
|
45
|
-
this.cleanup(rebuild);
|
|
46
|
-
rebuild = false;
|
|
47
|
-
});
|
|
48
|
-
this.placeholder$ = new BehaviorSubject(false);
|
|
49
|
-
this.placeholder$.subscribe((value) => {
|
|
50
|
-
this.placeholder = value;
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
drop(source, targetCoordinates) {
|
|
54
|
-
var _a;
|
|
55
|
-
//prep
|
|
56
|
-
const sourceParent = source.getParent();
|
|
57
|
-
if (sourceParent === null) {
|
|
58
|
-
throw new Error("can't drop root of tree");
|
|
59
|
-
}
|
|
60
|
-
const sourceIndex = source.getIndex();
|
|
61
|
-
if (sourceIndex === undefined || sourceIndex === null) {
|
|
62
|
-
throw new Error("Cannot move the hidden root node");
|
|
63
|
-
}
|
|
64
|
-
let targetParentCoordinates;
|
|
65
|
-
let newIndex;
|
|
66
|
-
if (this.placeholder === true) {
|
|
67
|
-
targetParentCoordinates = [];
|
|
68
|
-
newIndex = 0;
|
|
69
|
-
}
|
|
70
|
-
else {
|
|
71
|
-
targetParentCoordinates = [...targetCoordinates];
|
|
72
|
-
newIndex = targetParentCoordinates.pop();
|
|
73
|
-
}
|
|
74
|
-
if (newIndex === undefined) {
|
|
75
|
-
throw new Error("target coordinates are empty");
|
|
76
|
-
}
|
|
77
|
-
const targetParent = this.treeModel.getDescendant(targetParentCoordinates);
|
|
78
|
-
if (targetParent === undefined) {
|
|
79
|
-
throw new Error("could not get to target");
|
|
80
|
-
}
|
|
81
|
-
const target = this.dropZoneService.getDropZone(targetCoordinates);
|
|
82
|
-
const targetIndex = target === null || target === void 0 ? void 0 : target.getLocation().insertIndex;
|
|
83
|
-
const targetHost = target === null || target === void 0 ? void 0 : target.getHost();
|
|
84
|
-
const sourceHost = (_a = this.dragStateService.getData()) === null || _a === void 0 ? void 0 : _a.parentContainer;
|
|
85
|
-
if (this.placeholder === true) {
|
|
86
|
-
this.placeholder$.next(false);
|
|
87
|
-
}
|
|
88
|
-
//Change the treeModel
|
|
89
|
-
targetParent.insertChild(source, newIndex);
|
|
90
|
-
//Prepare to update the view
|
|
91
|
-
if (targetHost === undefined ||
|
|
92
|
-
sourceHost === undefined ||
|
|
93
|
-
targetIndex === undefined) {
|
|
94
|
-
//Hitting this means there is a bug, but not a fatal one.
|
|
95
|
-
//Just render the whole tree again.
|
|
96
|
-
console.warn("Could not perform a precise update. Re-rendering the entire tree instead");
|
|
97
|
-
this.render();
|
|
98
|
-
this.changes$.next(null);
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
//Update the view
|
|
102
|
-
const nodesInSource = sourceHost.length;
|
|
103
|
-
const componentRef = this.componentCreatorService.appendComponent(LimbleTreeNodeComponent, targetHost, newIndex);
|
|
104
|
-
componentRef.instance.branch = source;
|
|
105
|
-
componentRef.instance.parentHost = targetHost;
|
|
106
|
-
if (targetIndex < sourceIndex &&
|
|
107
|
-
sourceHost.length > nodesInSource &&
|
|
108
|
-
arraysAreEqual(sourceParent.getCoordinates(), targetParentCoordinates)) {
|
|
109
|
-
sourceHost.remove(sourceIndex + 1);
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
sourceHost.remove(sourceIndex);
|
|
113
|
-
}
|
|
114
|
-
//Update the tree data
|
|
115
|
-
this.rebuildTreeData();
|
|
116
|
-
//Publish drop data
|
|
117
|
-
this.drops$.next({
|
|
118
|
-
target: source.data,
|
|
119
|
-
oldParent: sourceParent.data,
|
|
120
|
-
oldIndex: sourceIndex,
|
|
121
|
-
newParent: targetParent.data,
|
|
122
|
-
newIndex: newIndex
|
|
123
|
-
});
|
|
124
|
-
this.cleanupSignal$.next(false);
|
|
125
|
-
}
|
|
126
|
-
/** Initializes the service and renders the tree.
|
|
127
|
-
* @param host - The ViewContainerRef into which the tree will be rendered.
|
|
128
|
-
* @param data - The data array that was passed in to LimbleTreeRoot, which is
|
|
129
|
-
* the users' representation of the tree
|
|
130
|
-
* @param options - The options object that was passed in to LimbleTreeRoot
|
|
131
|
-
*/
|
|
132
|
-
init(host, data, options, itemsPerPage, page) {
|
|
133
|
-
this.host = host;
|
|
134
|
-
this.originalData = data;
|
|
135
|
-
this.treeOptions = this.processOptions(options, itemsPerPage, page);
|
|
136
|
-
if (this.treeOptions.listMode === true) {
|
|
137
|
-
let start = this.treeOptions.itemsPerPage * (this.treeOptions.page - 1);
|
|
138
|
-
if (isNaN(start)) {
|
|
139
|
-
//This catches the case where itemsPerPage was not passed by the user,
|
|
140
|
-
//causing `start` to equal infinity*0, which is NaN.
|
|
141
|
-
start = 0;
|
|
142
|
-
}
|
|
143
|
-
const end = start + this.treeOptions.itemsPerPage;
|
|
144
|
-
this.treeData = this.originalData.slice(start, end);
|
|
145
|
-
}
|
|
146
|
-
else {
|
|
147
|
-
this.treeData = [...this.originalData];
|
|
148
|
-
}
|
|
149
|
-
this.render();
|
|
150
|
-
}
|
|
151
|
-
cleanup(rebuild = false) {
|
|
152
|
-
var _a;
|
|
153
|
-
if (rebuild) {
|
|
154
|
-
this.rebuildTreeData();
|
|
155
|
-
}
|
|
156
|
-
if (((_a = this.treeData) === null || _a === void 0 ? void 0 : _a.length) === 0) {
|
|
157
|
-
//We do a full render here because it isn't actually any slower
|
|
158
|
-
//when there are no nodes, and it is a little more straightforward
|
|
159
|
-
this.render();
|
|
160
|
-
}
|
|
161
|
-
else {
|
|
162
|
-
this.changes$.next(null);
|
|
163
|
-
this.dropZoneService.update();
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
/** Renders the entire tree from root to leaves */
|
|
167
|
-
render() {
|
|
168
|
-
if (this.host === undefined ||
|
|
169
|
-
this.treeData === undefined ||
|
|
170
|
-
this.treeOptions === undefined) {
|
|
171
|
-
throw new Error("TreeModel not initialized");
|
|
172
|
-
}
|
|
173
|
-
this.treeConstructionStatus.ready(false);
|
|
174
|
-
this.host.clear();
|
|
175
|
-
this.dropZoneService.restart();
|
|
176
|
-
this.placeholder$.next(false);
|
|
177
|
-
this.treeModel = new Branch(null);
|
|
178
|
-
if (this.treeData.length === 0) {
|
|
179
|
-
//Tree is empty, but we have to to have something there so other trees' items can be dropped into it
|
|
180
|
-
this.placeholder$.next(true);
|
|
181
|
-
}
|
|
182
|
-
else {
|
|
183
|
-
for (const node of this.treeData) {
|
|
184
|
-
const branch = new Branch(node);
|
|
185
|
-
this.treeModel.appendChild(branch);
|
|
186
|
-
}
|
|
187
|
-
for (const branch of this.treeModel.getChildren()) {
|
|
188
|
-
const componentRef = this.componentCreatorService.appendComponent(LimbleTreeNodeComponent, this.host);
|
|
189
|
-
componentRef.instance.branch = branch;
|
|
190
|
-
componentRef.instance.parentHost = this.host;
|
|
191
|
-
//The LimbleTreeNodeComponent will (indirectly) call the `renderBranch` method of this service to render
|
|
192
|
-
//its own children
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
this.treeConstructionStatus.ready(true);
|
|
196
|
-
this.changes$.next(null);
|
|
197
|
-
this.dropZoneService.init(this.treeModel, this.treeOptions);
|
|
198
|
-
}
|
|
199
|
-
/** Renders a branch of the tree and all of its descendants */
|
|
200
|
-
renderBranch(host, branch) {
|
|
201
|
-
var _a, _b;
|
|
202
|
-
if (this.treeModel === undefined) {
|
|
203
|
-
throw new Error("TreeModel not initialized");
|
|
204
|
-
}
|
|
205
|
-
host.clear();
|
|
206
|
-
branch.clearChildren();
|
|
207
|
-
for (const node of (_b = (_a = branch.data) === null || _a === void 0 ? void 0 : _a.nodes) !== null && _b !== void 0 ? _b : []) {
|
|
208
|
-
const newBranch = new Branch(node);
|
|
209
|
-
branch.appendChild(newBranch);
|
|
210
|
-
const componentRef = this.componentCreatorService.appendComponent(LimbleTreeNodeComponent, host);
|
|
211
|
-
componentRef.instance.branch = newBranch;
|
|
212
|
-
componentRef.instance.parentHost = host;
|
|
213
|
-
//The LimbleTreeNodeComponent will (indirectly) call the `renderBranch` method of this service to render
|
|
214
|
-
//its own children
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
processOptions(options = {}, itemsPerPage = Infinity, page = 1) {
|
|
218
|
-
var _a, _b, _c, _d, _e;
|
|
219
|
-
if (options.listMode === true &&
|
|
220
|
-
options.allowNesting !== undefined &&
|
|
221
|
-
options.allowNesting !== false) {
|
|
222
|
-
console.warn("The value of `allowNesting` will be ignored; it must be false when `listMode` is true");
|
|
223
|
-
}
|
|
224
|
-
const result = {
|
|
225
|
-
defaultComponent: options.defaultComponent,
|
|
226
|
-
indent: (_a = options.indent) !== null && _a !== void 0 ? _a : INDENT,
|
|
227
|
-
allowNesting: options.listMode !== true && ((_b = options.allowNesting) !== null && _b !== void 0 ? _b : true),
|
|
228
|
-
allowDragging: (_c = options.allowDragging) !== null && _c !== void 0 ? _c : true,
|
|
229
|
-
allowDrop: (_d = options.allowDrop) !== null && _d !== void 0 ? _d : (() => true),
|
|
230
|
-
listMode: (_e = options.listMode) !== null && _e !== void 0 ? _e : false,
|
|
231
|
-
itemsPerPage: options.listMode ? itemsPerPage : undefined,
|
|
232
|
-
page: options.listMode ? page : undefined
|
|
233
|
-
};
|
|
234
|
-
return result;
|
|
235
|
-
}
|
|
236
|
-
rebuildTreeData() {
|
|
237
|
-
if (this.originalData === undefined ||
|
|
238
|
-
this.treeData === undefined ||
|
|
239
|
-
this.treeOptions === undefined ||
|
|
240
|
-
this.host === undefined) {
|
|
241
|
-
throw new Error("Tree data not initialized");
|
|
242
|
-
}
|
|
243
|
-
this.treeData = [];
|
|
244
|
-
for (const branch of this.treeModel.getChildren()) {
|
|
245
|
-
this.treeData.push(this.rebuildBranch(branch));
|
|
246
|
-
}
|
|
247
|
-
if (this.treeOptions.listMode === true &&
|
|
248
|
-
this.treeOptions.itemsPerPage < Infinity) {
|
|
249
|
-
const itemsPerPage = this.treeOptions.itemsPerPage;
|
|
250
|
-
const start = itemsPerPage * (this.treeOptions.page - 1);
|
|
251
|
-
this.originalData.splice(start, itemsPerPage, ...this.treeData);
|
|
252
|
-
if (this.treeData.length !== itemsPerPage) {
|
|
253
|
-
let action = false;
|
|
254
|
-
if (this.treeData.length < itemsPerPage &&
|
|
255
|
-
start + itemsPerPage <= this.originalData.length) {
|
|
256
|
-
//The current page does not have enough nodes. Add some to the view from the next page.
|
|
257
|
-
const count = itemsPerPage - this.treeData.length;
|
|
258
|
-
for (let index = itemsPerPage - 1; index < itemsPerPage + count - 1; index++) {
|
|
259
|
-
const branch = new Branch(this.originalData[start + index]);
|
|
260
|
-
this.treeModel.appendChild(branch);
|
|
261
|
-
const componentRef = this.componentCreatorService.appendComponent(LimbleTreeNodeComponent, this.host);
|
|
262
|
-
componentRef.instance.branch = branch;
|
|
263
|
-
componentRef.instance.parentHost = this.host;
|
|
264
|
-
}
|
|
265
|
-
action = true;
|
|
266
|
-
}
|
|
267
|
-
else if (this.treeData.length > itemsPerPage) {
|
|
268
|
-
//The current page has too many nodes. Remove some of them from the view.
|
|
269
|
-
const count = this.treeData.length - itemsPerPage;
|
|
270
|
-
for (let index = itemsPerPage + count - 1; index >= itemsPerPage; index--) {
|
|
271
|
-
this.treeModel.removeChild(index);
|
|
272
|
-
this.host.remove(index);
|
|
273
|
-
}
|
|
274
|
-
action = true;
|
|
275
|
-
}
|
|
276
|
-
if (action === true) {
|
|
277
|
-
const end = start + itemsPerPage;
|
|
278
|
-
this.treeData = this.originalData.slice(start, end);
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
else {
|
|
283
|
-
this.originalData.length = 0;
|
|
284
|
-
this.originalData.push(...this.treeData);
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
rebuildBranch(branch) {
|
|
288
|
-
const temp = branch.data;
|
|
289
|
-
temp.nodes = [];
|
|
290
|
-
for (const child of branch.getChildren()) {
|
|
291
|
-
temp.nodes.push(this.rebuildBranch(child));
|
|
292
|
-
}
|
|
293
|
-
return temp;
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
TreeService.ɵfac = function TreeService_Factory(t) { return new (t || TreeService)(i0.ɵɵinject(i1.ComponentCreatorService), i0.ɵɵinject(i2.DropZoneService), i0.ɵɵinject(i3.DragStateService), i0.ɵɵinject(i4.TreeConstructionStatus)); };
|
|
297
|
-
TreeService.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: TreeService, factory: TreeService.ɵfac });
|
|
298
|
-
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TreeService, [{
|
|
299
|
-
type: Injectable
|
|
300
|
-
}], function () { return [{ type: i1.ComponentCreatorService }, { type: i2.DropZoneService }, { type: i3.DragStateService }, { type: i4.TreeConstructionStatus }]; }, null); })();
|
|
301
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJlZS5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbGltYmxlLXRyZWUvc3JjL2xpYi9saW1ibGUtdHJlZS1yb290L3RyZWUuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUEwQixNQUFNLGVBQWUsQ0FBQztBQUduRSxPQUFPLEVBQUUsTUFBTSxFQUFxQixNQUFNLG1CQUFtQixDQUFDO0FBQzlELE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLGdEQUFnRCxDQUFDO0FBRXpGLE9BQU8sRUFBRSxlQUFlLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUN2RCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ3pDLE9BQU8sRUFBRSxRQUFRLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQzs7Ozs7O0FBK0RyRSxnREFBZ0Q7QUFDaEQsTUFBTSxDQUFDLE1BQU0sTUFBTSxHQUFHLEVBQUUsQ0FBQztBQWtEekIsTUFBTSxPQUFPLFdBQVc7SUFjckIsWUFDb0IsdUJBQWdELEVBQ2hELGVBQWdDLEVBQ2hDLGdCQUFrQyxFQUNsQyxzQkFBOEM7UUFIOUMsNEJBQXVCLEdBQXZCLHVCQUF1QixDQUF5QjtRQUNoRCxvQkFBZSxHQUFmLGVBQWUsQ0FBaUI7UUFDaEMscUJBQWdCLEdBQWhCLGdCQUFnQixDQUFrQjtRQUNsQywyQkFBc0IsR0FBdEIsc0JBQXNCLENBQXdCO1FBRS9ELElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxPQUFPLEVBQUUsQ0FBQztRQUM5QixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksT0FBTyxFQUFFLENBQUM7UUFDNUIsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNsQyxJQUFJLENBQUMs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QUFDLFdBQVcsRUFBRSxFQUFFO1lBQ3ZDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztTQUM3QztRQUNELE9BQU8sSUFBSSxDQUFDO0lBQ2YsQ0FBQzs7c0VBOVZTLFdBQVc7aUVBQVgsV0FBVyxXQUFYLFdBQVc7dUZBQVgsV0FBVztjQUR2QixVQUFVIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSwgVHlwZSwgVmlld0NvbnRhaW5lclJlZiB9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XHJcbmltcG9ydCB7IENvbXBvbmVudENyZWF0b3JTZXJ2aWNlIH0gZnJvbSBcIi4uL3NpbmdsZXRvbnMvY29tcG9uZW50LWNyZWF0b3Iuc2VydmljZVwiO1xyXG5pbXBvcnQgeyBEcm9wWm9uZVNlcnZpY2UgfSBmcm9tIFwiLi9kcm9wLXpvbmUuc2VydmljZVwiO1xyXG5pbXBvcnQgeyBCcmFuY2gsIEJyYW5jaENvb3JkaW5hdGVzIH0gZnJvbSBcIi4uL2NsYXNzZXMvQnJhbmNoXCI7XHJcbmltcG9ydCB7IExpbWJsZVRyZWVOb2RlQ29tcG9uZW50IH0gZnJvbSBcIi4uL2xpbWJsZS10cmVlLW5vZGUvbGltYmxlLXRyZWUtbm9kZS5jb21wb25lbnRcIjtcclxuaW1wb3J0IHsgRHJhZ1N0YXRlU2VydmljZSB9IGZyb20gXCIuLi9zaW5nbGV0b25zL2RyYWctc3RhdGUuc2VydmljZVwiO1xyXG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIEVNUFRZLCBTdWJqZWN0IH0gZnJvbSBcInJ4anNcIjtcclxuaW1wb3J0IHsgYXJyYXlzQXJlRXF1YWwgfSBmcm9tIFwiLi4vdXRpbFwiO1xyXG5pbXBvcnQgeyBkZWJvdW5jZSwgZGVib3VuY2VUaW1lLCBmaWx0ZXIsIHRhcCB9IGZyb20gXCJyeGpzL29wZXJhdG9yc1wiO1xyXG5pbXBvcnQgeyBUcmVlQ29uc3RydWN0aW9uU3RhdHVzIH0gZnJvbSBcIi4vdHJlZS1jb25zdHJ1Y3Rpb24tc3RhdHVzLnNlcnZpY2VcIjtcclxuXHJcbi8qKiBBbiBvYmplY3QgZGVzY3JpYmluZyBhIG5vZGUgb2YgdGhlIHRyZWUgKi9cclxuZXhwb3J0IGludGVyZmFjZSBMaW1ibGVUcmVlTm9kZSB7XHJcbiAgIC8qKiBBIGxpc3Qgb2Ygbm9kZXMgdG8gYmUgcmVuZGVyZWQgXCJ1bmRlclwiIHRoaXMgb25lLCBvbmUgbGV2ZWwgZGVlcGVyIGluIHRoZSB0cmVlLiAqL1xyXG4gICBub2Rlcz86IExpbWJsZVRyZWVEYXRhO1xyXG4gICAvLyAvKiogQSBjdXN0b20gZGF0YSBvYmplY3QgdGhhdCB3aWxsIGJlIHBhc3NlZCBpbnRvIHRoZSBjb21wb25lbnQgYXMgYW4gYElucHV0KClgIGJpbmRpbmcgY2FsbGVkIGBub2RlRGF0YWAgKi9cclxuICAgLy8gZGF0YTogdW5rbm93bjtcclxuICAgLyoqIEFuIG9iamVjdCB0aGF0IGRlc2NyaWJlcyB0aGUgY29tcG9uZW50IHdoaWNoIHdpbGwgcmVwcmVzZW50IHRoaXMgbm9kZSBpbiB0aGUgdmlzdWFsIHRyZWUgKi9cclxuICAgY29tcG9uZW50PzogQ29tcG9uZW50T2JqO1xyXG4gICBjb2xsYXBzZWQ/OiBib29sZWFuO1xyXG4gICBbaW5kZXg6IHN0cmluZ106IHVua25vd247XHJcbn1cclxuXHJcbi8qKiBBbiBvYmplY3QgdGhhdCB0aGUgbGltYmxlLXRyZWUtcm9vdCBjb21wb25lbnQgdXNlcyB0byBidWlsZCB0aGUgdHJlZSAqL1xyXG5leHBvcnQgdHlwZSBMaW1ibGVUcmVlRGF0YSA9IEFycmF5PExpbWJsZVRyZWVOb2RlPjtcclxuXHJcbi8qKiBBIGdyb3VwIG9mIHNldHRpbmdzIGZvciBjaGFuZ2luZyB0aGUgZnVuY3Rpb25hbGl0eSBvZiB0aGUgdHJlZSAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIExpbWJsZVRyZWVPcHRpb25zIHtcclxuICAgLyoqIFRoZSBjb21wb25lbnQgb2JqZWN0IHRvIHVzZSBpZiBvbmUgaXMgbm90IHNwZWNpZmllZCBmb3IgYSBwYXJ0aWN1bGFyIG5vZGUgKi9cclxuICAgZGVmYXVsdENvbXBvbmVudD86IENvbXBvbmVudE9iajtcclxuICAgLyoqIFRoZSBudW1iZXIgb2YgcGl4ZWxzIHRvIGluZGVudCBlYWNoIGxldmVsIG9mIHRoZSB0cmVlLiBEZWZhdWx0cyB0byA0NSAqL1xyXG4gICBpbmRlbnQ/OiBudW1iZXI7XHJcbiAgIC8qKlxyXG4gICAgKiBXaGV0aGVyIHRvIGFsbG93IFwibmVzdGluZ1wiIChwbGFjaW5nIGEgbm9kZSBvbmUgbGV2ZWwgZGVlcGVyIHRoYW4gY3VycmVudGx5IGV4aXN0cyBvbiB0aGUgYnJhbmNoKS5cclxuICAgICogV2hlbiB0aGlzIGlzIGEgYm9vbGVhbiwgaXQgYXBwbGllcyB0byBhbGwgbm9kZXMuIFdoZW4gdGhpcyBpcyBhIGZ1bmN0aW9uLCB0aGUgbm9kZSBpbiBxdWVzdGlvblxyXG4gICAgKiBpcyBwYXNzZWQgaW4uIERlZmF1bHRzIHRvIHRydWUuXHJcbiAgICAqL1xyXG4gICBhbGxvd05lc3Rpbmc/OiBib29sZWFuIHwgKChub2RlRGF0YTogTGltYmxlVHJlZU5vZGUpID0+IGJvb2xlYW4pO1xyXG4gICAvKipcclxuICAgICogV2hldGhlciB0byBhbGxvdyBhIG5vZGUgdG8gYmUgZHJhZ2dlZC4gV2hlbiB0aGlzIGlzIGEgYm9vbGVhbiwgaXQgYXBwbGllcyB0byBhbGwgbm9kZXMuIFdoZW4gdGhpc1xyXG4gICAgKiBpcyBhIGZ1bmN0aW9uLCB0aGUgbm9kZSBpbiBxdWVzdGlvbiBpcyBwYXNzZWQgaW4uIERlZmF1bHRzIHRvIHRydWUuXHJcbiAgICAqL1xyXG4gICBhbGxvd0RyYWdnaW5nPzogYm9vbGVhbiB8ICgobm9kZURhdGE6IExpbWJsZVRyZWVOb2RlKSA9PiBib29sZWFuKTtcclxuICAgLyoqIEEgY2FsbGJhY2sgdG8gZGV0ZXJtaW5lIHdoZXRoZXIgYSBzb3VyY2VOb2RlIGNhbiBiZSBkcm9wcGVkIGF0IGEgcGFydGljdWxhciBsb2NhdGlvbi4gKi9cclxuICAgYWxsb3dEcm9wPzogKFxyXG4gICAgICBzb3VyY2VOb2RlOiBMaW1ibGVUcmVlTm9kZSxcclxuICAgICAgcHJvcG9zZWRQYXJlbnQ6IExpbWJsZVRyZWVOb2RlIHwgbnVsbCxcclxuICAgICAgcHJvcG9zZWRJbmRleDogbnVtYmVyXHJcbiAgICkgPT4gYm9vbGVhbjtcclxuICAgLyoqIFdoZW4gc2V0IHRvIHRydWUsIGxpc3QgbW9kZSB3aWxsIGVuZm9yY2UgYSBmbGF0IHRyZWUgc3RydWN0dXJlLCBtZWFuaW5nIHRoZXJlXHJcbiAgICAqIGNhbiBvbmx5IGJlIG9uZSBsZXZlbCBvZiB0aGUgdHJlZS4gYGFsbG93TmVzdGluZ2AgaXMgYXV0b21hdGljYWxseSBzZXQgdG8gYGZhbHNlYFxyXG4gICAgKiBhbmQgYW55IGNoaWxkcmVuIHdpbGwgYmUgZGVsZXRlZC5cclxuICAgICpcclxuICAgICogVGhpcyBtb2RlIGNhbiBiZSB1c2VkIHdoZW4gdGhlIHNhbWUgZHluYW1pYyBkcmFnIGFuZCBkcm9wIGZ1bmN0aW9uYWxpdHkgb2ZcclxuICAgICogdGhlIHRyZWUgaXMgZGVzaXJlZCwgYnV0IHRoZSB0cmVlIHN0cnVjdHVyZSBpdHNlbGYgaXMgbm90IG5lY2Vzc2FyeS4gVGhpc1xyXG4gICAgKiBhbHNvIG9wZW5zIHVwIHRoZSBwYWdpbmF0aW9uIEFQSSBvbiB0aGUgbGltYmxlLXRyZWUtcm9vdCBjb21wb25lbnQuIFNlZSB0aGVcclxuICAgICogUkVBRE1FIGZvciBkZXRhaWxzIG9uIHBhZ2luYXRpb24uXHJcbiAgICAqL1xyXG4gICBsaXN0TW9kZT86IGJvb2xlYW47XHJcbn1cclxuXHJcbi8qKiBBbiBvYmplY3QgdGhhdCByZWZlcmVuY2VzIHRoZSBjb21wb25lbnQgdG8gYmUgcmVuZGVyZWQgYW5kIGl0cyBiaW5kaW5ncyAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIENvbXBvbmVudE9iaiB7XHJcbiAgIC8qKiBUaGUgY29tcG9uZW50IGNsYXNzICovXHJcbiAgIGNsYXNzOiBUeXBlPHVua25vd24+O1xyXG4gICAvKiogVGhlIGJpbmRpbmdzIChpbnB1dHMgYW5kIG91dHB1dHMpIG9mIHRoZSBjbGFzcyAqL1xyXG4gICBiaW5kaW5ncz86IHtcclxuICAgICAgW2luZGV4OiBzdHJpbmddOiB1bmtub3duO1xyXG4gICB9O1xyXG59XHJcblxyXG4vKiogVGhlIGRlZmF1bHQgdmFsdWUgZm9yIHRoZSBgaW5kZW50YCBvcHRpb24gKi9cclxuZXhwb3J0IGNvbnN0IElOREVOVCA9IDQ1O1xyXG5cclxuLyoqIEFuIG9wdGlvbnMgb2JqZWN0IHdpdGggZGVmYXVsdCB2YWx1ZXMgbG9hZGVkIHdoZXJlIGFwcGxpY2FibGUgKi9cclxuZXhwb3J0IGludGVyZmFjZSBQcm9jZXNzZWRPcHRpb25zQmFzZSBleHRlbmRzIExpbWJsZVRyZWVPcHRpb25zIHtcclxuICAgZGVmYXVsdENvbXBvbmVudD86IENvbXBvbmVudE9iajtcclxuICAgaW5kZW50OiBudW1iZXI7XHJcbiAgIGFsbG93TmVzdGluZzogYm9vbGVhbiB8ICgobm9kZURhdGE6IExpbWJsZVRyZWVOb2RlKSA9PiBib29sZWFuKTtcclxuICAgYWxsb3dEcmFnZ2luZzogYm9vbGVhbiB8ICgobm9kZURhdGE6IExpbWJsZVRyZWVOb2RlKSA9PiBib29sZWFuKTtcclxuICAgYWxsb3dEcm9wOiAoXHJcbiAgICAgIHNvdXJjZU5vZGU6IExpbWJsZVRyZWVOb2RlLFxyXG4gICAgICBwcm9wb3NlZFBhcmVudDogTGltYmxlVHJlZU5vZGUgfCBudWxsLFxyXG4gICAgICBwcm9wb3NlZEluZGV4OiBudW1iZXJcclxuICAgKSA9PiBib29sZWFuO1xyXG4gICBsaXN0TW9kZTogYm9vbGVhbjtcclxuICAgaXRlbXNQZXJQYWdlOiBudW1iZXIgfCB1bmRlZmluZWQ7XHJcbiAgIHBhZ2U6IG51bWJlciB8IHVuZGVmaW5lZDtcclxufVxyXG5cclxuZXhwb3J0IGludGVyZmFjZSBQcm9jZXNzZWRPcHRpb25zV2l0aFBhZ2luYXRpb24gZXh0ZW5kcyBQcm9jZXNzZWRPcHRpb25zQmFzZSB7XHJcbiAgIGxpc3RNb2RlOiB0cnVlO1xyXG4gICBpdGVtc1BlclBhZ2U6IG51bWJlcjtcclxuICAgcGFnZTogbnVtYmVyO1xyXG59XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIFByb2Nlc3NlZE9wdGlvbnNXaXRob3V0UGFnaW5hdGlvblxyXG4gICBleHRlbmRzIFByb2Nlc3NlZE9wdGlvbnNCYXNlIHtcclxuICAgbGlzdE1vZGU6IGZhbHNlO1xyXG4gICBpdGVtc1BlclBhZ2U6IHVuZGVmaW5lZDtcclxuICAgcGFnZTogdW5kZWZpbmVkO1xyXG59XHJcblxyXG5leHBvcnQgdHlwZSBQcm9jZXNzZWRPcHRpb25zID1cclxuICAgfCBQcm9jZXNzZWRPcHRpb25zV2l0aFBhZ2luYXRpb25cclxuICAgfCBQcm9jZXNzZWRPcHRpb25zV2l0aG91dFBhZ2luYXRpb247XHJcblxyXG4vKiogdGhlIHZhbHVlIGVtaXR0ZWQgZnJvbSB0aGUgcm9vdCBjb21wb25lbnQgYWZ0ZXIgYSBub2RlIGlzIGRyb3BwZWQgKi9cclxuZXhwb3J0IGludGVyZmFjZSBUcmVlRHJvcCB7XHJcbiAgIC8qKiBUaGUgbm9kZSB0aGF0IHdhcyBkcm9wcGVkICovXHJcbiAgIHRhcmdldDogTGltYmxlVHJlZU5vZGU7XHJcbiAgIC8qKiB0aGUgdGFyZ2V0J3MgcGFyZW50IGJlZm9yZSB0aGUgZHJhZyBhbmQgZHJvcCwgb3IgbnVsbCBpZiBpdCB3YXMgYSB0b3AtbGV2ZWwgbm9kZSAqL1xyXG4gICBvbGRQYXJlbnQ6IExpbWJsZVRyZWVOb2RlIHwgbnVsbDtcclxuICAgLyoqIHRoZSBpbmRleCBvZiB0aGUgbm9kZSBiZWZvcmUgdGhlIGRyYWcgYW5kIGRyb3AgcmVsYXRpdmUgdG8gaXRzIG9sZCBzaWJsaW5ncyAqL1xyXG4gICBvbGRJbmRleDogbnVtYmVyO1xyXG4gICAvKiogdGhlIHRhcmdldCdzIHBhcmVudCBhZnRlciB0aGUgZHJhZyBhbmQgZHJvcCwgb3IgbnVsbCBpZiBpdCBpcyBub3cgYSB0b3AtbGV2ZWwgbm9kZSAqL1xyXG4gICBuZXdQYXJlbnQ6IExpbWJsZVRyZWVOb2RlIHwgbnVsbDtcclxuICAgLyoqIHRoZSBpbmRleCBvZiB0aGUgbm9kZSBhZnRlciB0aGUgZHJhZyBhbmQgZHJvcCByZWxhdGl2ZSB0byBpdHMgbmV3IHNpYmxpbmdzICovXHJcbiAgIG5ld0luZGV4OiBudW1iZXI7XHJcbn1cclxuXHJcbkBJbmplY3RhYmxlKClcclxuZXhwb3J0IGNsYXNzIFRyZWVTZXJ2aWNlIHtcclxuICAgcHVibGljIHJlYWRvbmx5IGNoYW5nZXMkOiBTdWJqZWN0PG51bGw+O1xyXG4gICBwdWJsaWMgcmVhZG9ubHkgZHJvcHMkOiBTdWJqZWN0PFRyZWVEcm9wPjtcclxuICAgcHVibGljIGhvc3Q6IFZpZXdDb250YWluZXJSZWYgfCB1bmRlZmluZWQ7XHJcbiAgIHB1YmxpYyB0cmVlRGF0YTogTGltYmxlVHJlZURhdGEgfCB1bmRlZmluZWQ7XHJcbiAgIC8qKiBUaGlzIHNob3VsZCBuZXZlciBiZSByZWFzc2lnbmVkLiBJdCBpcyBhc3NpZ25lZCBpbiBpbml0KCkgYW5kIG5vIHdoZXJlIGVsc2UuIFdlIG5lZWQgdG8ga2VlcCB0aGUgcmVmZXJlbmNlIGZyb20gYnJlYWtpbmcuICovXHJcbiAgIHByaXZhdGUgb3JpZ2luYWxEYXRhOiBMaW1ibGVUcmVlRGF0YSB8IHVuZGVmaW5lZDtcclxuICAgcHVibGljIHRyZWVPcHRpb25zOiBQcm9jZXNzZWRPcHRpb25zIHwgdW5kZWZpbmVkO1xyXG4gICBwdWJsaWMgdHJlZU1vZGVsOiBCcmFuY2g8YW55PjtcclxuICAgcHJpdmF0ZSBwbGFjZWhvbGRlcjogYm9vbGVhbjtcclxuICAgcHVibGljIGNhcHR1cmVkOiBib29sZWFuO1xyXG4gICBwdWJsaWMgcmVhZG9ubHkgY2xlYW51cFNpZ25hbCQ6IFN1YmplY3Q8Ym9vbGVhbj47XHJcbiAgIHB1YmxpYyBwbGFjZWhvbGRlciQ6IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPjtcclxuXHJcbiAgIGNvbnN0cnVjdG9yKFxyXG4gICAgICBwcml2YXRlIHJlYWRvbmx5IGNvbXBvbmVudENyZWF0b3JTZXJ2aWNlOiBDb21wb25lbnRDcmVhdG9yU2VydmljZSxcclxuICAgICAgcHJpdmF0ZSByZWFkb25seSBkcm9wWm9uZVNlcnZpY2U6IERyb3Bab25lU2VydmljZSxcclxuICAgICAgcHJpdmF0ZSByZWFkb25seSBkcmFnU3RhdGVTZXJ2aWNlOiBEcmFnU3RhdGVTZXJ2aWNlLFxyXG4gICAgICBwcml2YXRlIHJlYWRvbmx5IHRyZWVDb25zdHJ1Y3Rpb25TdGF0dXM6IFRyZWVDb25zdHJ1Y3Rpb25TdGF0dXNcclxuICAgKSB7XHJcbiAgICAgIHRoaXMuY2hhbmdlcyQgPSBuZXcgU3ViamVjdCgpO1xyXG4gICAgICB0aGlzLmRyb3BzJCA9IG5ldyBTdWJqZWN0KCk7XHJcbiAgICAgIHRoaXMudHJlZU1vZGVsID0gbmV3IEJyYW5jaChudWxsKTtcclxuICAgICAgdGhpcy5wbGFjZWhvbGRlciA9IGZhbHNlO1xyXG4gICAgICB0aGlzLmNhcHR1cmVkID0gZmFsc2U7XHJcbiAgICAgIHRoaXMuY2xlYW51cFNpZ25hbCQgPSBuZXcgU3ViamVjdCgpO1xyXG4gICAgICBsZXQgcmVidWlsZCA9IGZhbHNlO1xyXG4gICAgICBsZXQgdHJlZUlzU3RhYmxlID0gZmFsc2U7XHJcbiAgICAgIGNvbnN0IHRyZWVJc1N0YWJsZSQgPSB0aGlzLnRyZWVDb25zdHJ1Y3Rpb25TdGF0dXMuc3RhYmxlJC5waXBlKFxyXG4gICAgICAgICB0YXAoKHZhbHVlKSA9PiB7XHJcbiAgICAgICAgICAgIHRyZWVJc1N0YWJsZSA9IHZhbHVlO1xyXG4gICAgICAgICB9KSxcclxuICAgICAgICAgZmlsdGVyKCh2YWx1ZSkgPT4gdmFsdWUgPT09IHRydWUpXHJcbiAgICAgICk7XHJcbiAgICAgIHRoaXMuY2xlYW51cFNpZ25hbCRcclxuICAgICAgICAgLnBpcGUoXHJcbiAgICAgICAgICAgIHRhcCgodmFsdWUpID0+IHtcclxuICAgICAgICAgICAgICAgcmVidWlsZCA9IHZhbHVlO1xyXG4gICAgICAgICAgICB9KSxcclxuICAgICAgICAgICAgZGVib3VuY2UoKCkgPT4ge1xyXG4gICAgICAgICAgICAgICBpZiAodHJlZUlzU3RhYmxlID09PSB0cnVlKSB7XHJcbiAgICAgICAgICAgICAgICAgIC8vSWYgdHJlZSBpcyBzdGFibGUsIGNvbnRpbnVlIHJpZ2h0IGF3YXlcclxuICAgICAgICAgICAgICAgICAgcmV0dXJuIEVNUFRZO1xyXG4gICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgIC8vSWYgdHJlZSBpcyBub3Qgc3RhYmxlLCB3YWl0IGZvciBpdCB0byBiZWNvbWUgc28uXHJcbiAgICAgICAgICAgICAgIHJldHVybiB0cmVlSXNTdGFibGUkO1xyXG4gICAgICAgICAgICB9KSxcclxuICAgICAgICAgICAgLy9XZSB1c2UgdGhpcyB0aW1lZCBkZWJvdW5jZSB0byB0aHJvdHRsZSBjaGFpbmVkIGRlc3RydWN0aW9uIG9mIGNvbXBvbmVudHNcclxuICAgICAgICAgICAgZGVib3VuY2VUaW1lKDUpXHJcbiAgICAgICAgIClcclxuICAgICAgICAgLnN1YnNjcmliZSgoKSA9PiB7XHJcbiAgICAgICAgICAgIHRoaXMuY2xlYW51cChyZWJ1aWxkKTtcclxuICAgICAgICAgICAgcmVidWlsZCA9IGZhbHNlO1xyXG4gICAgICAgICB9KTtcclxuICAgICAgdGhpcy5wbGFjZWhvbGRlciQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+KGZhbHNlKTtcclxuICAgICAgdGhpcy5wbGFjZWhvbGRlciQuc3Vic2NyaWJlKCh2YWx1ZSkgPT4ge1xyXG4gICAgICAgICB0aGlzLnBsYWNlaG9sZGVyID0gdmFsdWU7XHJcbiAgICAgIH0pO1xyXG4gICB9XHJcblxyXG4gICBwdWJsaWMgZHJvcChzb3VyY2U6IEJyYW5jaDxhbnk+LCB0YXJnZXRDb29yZGluYXRlczogQnJhbmNoQ29vcmRpbmF0ZXMpIHtcclxuICAgICAgLy9wcmVwXHJcbiAgICAgIGNvbnN0IHNvdXJjZVBhcmVudCA9IHNvdXJjZS5nZXRQYXJlbnQoKTtcclxuICAgICAgaWYgKHNvdXJjZVBhcmVudCA9PT0gbnVsbCkge1xyXG4gICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJjYW4ndCBkcm9wIHJvb3Qgb2YgdHJlZVwiKTtcclxuICAgICAgfVxyXG4gICAgICBjb25zdCBzb3VyY2VJbmRleCA9IHNvdXJjZS5nZXRJbmRleCgpO1xyXG4gICAgICBpZiAoc291cmNlSW5kZXggPT09IHVuZGVmaW5lZCB8fCBzb3VyY2VJbmRleCA9PT0gbnVsbCkge1xyXG4gICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYW5ub3QgbW92ZSB0aGUgaGlkZGVuIHJvb3Qgbm9kZVwiKTtcclxuICAgICAgfVxyXG4gICAgICBsZXQgdGFyZ2V0UGFyZW50Q29vcmRpbmF0ZXM6IEJyYW5jaENvb3JkaW5hdGVzO1xyXG4gICAgICBsZXQgbmV3SW5kZXg6IG51bWJlciB8IHVuZGVmaW5lZDtcclxuICAgICAgaWYgKHRoaXMucGxhY2Vob2xkZXIgPT09IHRydWUpIHtcclxuICAgICAgICAgdGFyZ2V0UGFyZW50Q29vcmRpbmF0ZXMgPSBbXTtcclxuICAgICAgICAgbmV3SW5kZXggPSAwO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgICB0YXJnZXRQYXJlbnRDb29yZGluYXRlcyA9IFsuLi50YXJnZXRDb29yZGluYXRlc107XHJcbiAgICAgICAgIG5ld0luZGV4ID0gdGFyZ2V0UGFyZW50Q29vcmRpbmF0ZXMucG9wKCk7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKG5ld0luZGV4ID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwidGFyZ2V0IGNvb3JkaW5hdGVzIGFyZSBlbXB0eVwiKTtcclxuICAgICAgfVxyXG4gICAgICBjb25zdCB0YXJnZXRQYXJlbnQgPSB0aGlzLnRyZWVNb2RlbC5nZXREZXNjZW5kYW50KFxyXG4gICAgICAgICB0YXJnZXRQYXJlbnRDb29yZGluYXRlc1xyXG4gICAgICApO1xyXG4gICAgICBpZiAodGFyZ2V0UGFyZW50ID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiY291bGQgbm90IGdldCB0byB0YXJnZXRcIik7XHJcbiAgICAgIH1cclxuICAgICAgY29uc3QgdGFyZ2V0ID0gdGhpcy5kcm9wWm9uZVNlcnZpY2UuZ2V0RHJvcFpvbmUodGFyZ2V0Q29vcmRpbmF0ZXMpO1xyXG4gICAgICBjb25zdCB0YXJnZXRJbmRleCA9IHRhcmdldD8uZ2V0TG9jYXRpb24oKS5pbnNlcnRJbmRleDtcclxuICAgICAgY29uc3QgdGFyZ2V0SG9zdCA9IHRhcmdldD8uZ2V0SG9zdCgpO1xyXG4gICAgICBjb25zdCBzb3VyY2VIb3N0ID0gdGhpcy5kcmFnU3RhdGVTZXJ2aWNlLmdldERhdGEoKT8ucGFyZW50Q29udGFpbmVyO1xyXG4gICAgICBpZiAodGhpcy5wbGFjZWhvbGRlciA9PT0gdHJ1ZSkge1xyXG4gICAgICAgICB0aGlzLnBsYWNlaG9sZGVyJC5uZXh0KGZhbHNlKTtcclxuICAgICAgfVxyXG4gICAgICAvL0NoYW5nZSB0aGUgdHJlZU1vZGVsXHJcbiAgICAgIHRhcmdldFBhcmVudC5pbnNlcnRDaGlsZChzb3VyY2UsIG5ld0luZGV4KTtcclxuICAgICAgLy9QcmVwYXJlIHRvIHVwZGF0ZSB0aGUgdmlld1xyXG4gICAgICBpZiAoXHJcbiAgICAgICAgIHRhcmdldEhvc3QgPT09IHVuZGVmaW5lZCB8fFxyXG4gICAgICAgICBzb3VyY2VIb3N0ID09PSB1bmRlZmluZWQgfHxcclxuICAgICAgICAgdGFyZ2V0SW5kZXggPT09IHVuZGVmaW5lZFxyXG4gICAgICApIHtcclxuICAgICAgICAgLy9IaXR0aW5nIHRoaXMgbWVhbnMgdGhlcmUgaXMgYSBidWcsIGJ1dCBub3QgYSBmYXRhbCBvbmUuXHJcbiAgICAgICAgIC8vSnVzdCByZW5kZXIgdGhlIHdob2xlIHRyZWUgYWdhaW4uXHJcbiAgICAgICAgIGNvbnNvbGUud2FybihcclxuICAgICAgICAgICAgXCJDb3VsZCBub3QgcGVyZm9ybSBhIHByZWNpc2UgdXBkYXRlLiBSZS1yZW5kZXJpbmcgdGhlIGVudGlyZSB0cmVlIGluc3RlYWRcIlxyXG4gICAgICAgICApO1xyXG4gICAgICAgICB0aGlzLnJlbmRlcigpO1xyXG4gICAgICAgICB0aGlzLmNoYW5nZXMkLm5leHQobnVsbCk7XHJcbiAgICAgICAgIHJldHVybjtcclxuICAgICAgfVxyXG4gICAgICAvL1VwZGF0ZSB0aGUgdmlld1xyXG4gICAgICBjb25zdCBub2Rlc0luU291cmNlID0gc291cmNlSG9zdC5sZW5ndGg7XHJcbiAgICAgIGNvbnN0IGNvbXBvbmVudFJlZiA9IHRoaXMuY29tcG9uZW50Q3JlYXRvclNlcnZpY2UuYXBwZW5kQ29tcG9uZW50KFxyXG4gICAgICAgICBMaW1ibGVUcmVlTm9kZUNvbXBvbmVudCxcclxuICAgICAgICAgdGFyZ2V0SG9zdCxcclxuICAgICAgICAgbmV3SW5kZXhcclxuICAgICAgKTtcclxuICAgICAgY29tcG9uZW50UmVmLmluc3RhbmNlLmJyYW5jaCA9IHNvdXJjZTtcclxuICAgICAgY29tcG9uZW50UmVmLmluc3RhbmNlLnBhcmVudEhvc3QgPSB0YXJnZXRIb3N0O1xyXG4gICAgICBpZiAoXHJcbiAgICAgICAgIHRhcmdldEluZGV4IDwgc291cmNlSW5kZXggJiZcclxuICAgICAgICAgc291cmNlSG9zdC5sZW5ndGggPiBub2Rlc0luU291cmNlICYmXHJcbiAgICAgICAgIGFycmF5c0FyZUVxdWFsKHNvdXJjZVBhcmVudC5nZXRDb29yZGluYXRlcygpLCB0YXJnZXRQYXJlbnRDb29yZGluYXRlcylcclxuICAgICAgKSB7XHJcbiAgICAgICAgIHNvdXJjZUhvc3QucmVtb3ZlKHNvdXJjZUluZGV4ICsgMSk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgIHNvdXJjZUhvc3QucmVtb3ZlKHNvdXJjZUluZGV4KTtcclxuICAgICAgfVxyXG4gICAgICAvL1VwZGF0ZSB0aGUgdHJlZSBkYXRhXHJcbiAgICAgIHRoaXMucmVidWlsZFRyZWVEYXRhKCk7XHJcbiAgICAgIC8vUHVibGlzaCBkcm9wIGRhdGFcclxuICAgICAgdGhpcy5kcm9wcyQubmV4dCh7XHJcbiAgICAgICAgIHRhcmdldDogc291cmNlLmRhdGEsXHJcbiAgICAgICAgIG9sZFBhcmVudDogc291cmNlUGFyZW50LmRhdGEgYXMgTGltYmxlVHJlZU5vZGUsXHJcbiAgICAgICAgIG9sZEluZGV4OiBzb3VyY2VJbmRleCxcclxuICAgICAgICAgbmV3UGFyZW50OiB0YXJnZXRQYXJlbnQuZGF0YSxcclxuICAgICAgICAgbmV3SW5kZXg6IG5ld0luZGV4XHJcbiAgICAgIH0pO1xyXG4gICAgICB0aGlzLmNsZWFudXBTaWduYWwkLm5leHQoZmFsc2UpO1xyXG4gICB9XHJcblxyXG4gICAvKiogSW5pdGlhbGl6ZXMgdGhlIHNlcnZpY2UgYW5kIHJlbmRlcnMgdGhlIHRyZWUuXHJcbiAgICAqIEBwYXJhbSBob3N0IC0gVGhlIFZpZXdDb250YWluZXJSZWYgaW50byB3aGljaCB0aGUgdHJlZSB3aWxsIGJlIHJlbmRlcmVkLlxyXG4gICAgKiBAcGFyYW0gZGF0YSAtIFRoZSBkYXRhIGFycmF5IHRoYXQgd2FzIHBhc3NlZCBpbiB0byBMaW1ibGVUcmVlUm9vdCwgd2hpY2ggaXNcclxuICAgICogdGhlIHVzZXJzJyByZXByZXNlbnRhdGlvbiBvZiB0aGUgdHJlZVxyXG4gICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBvcHRpb25zIG9iamVjdCB0aGF0IHdhcyBwYXNzZWQgaW4gdG8gTGltYmxlVHJlZVJvb3RcclxuICAgICovXHJcbiAgIHB1YmxpYyBpbml0KFxyXG4gICAgICBob3N0OiBWaWV3Q29udGFpbmVyUmVmLFxyXG4gICAgICBkYXRhOiBMaW1ibGVUcmVlRGF0YSxcclxuICAgICAgb3B0aW9ucz86IExpbWJsZVRyZWVPcHRpb25zLFxyXG4gICAgICBpdGVtc1BlclBhZ2U/OiBudW1iZXIsXHJcbiAgICAgIHBhZ2U/OiBudW1iZXJcclxuICAgKTogdm9pZCB7XHJcbiAgICAgIHRoaXMuaG9zdCA9IGhvc3Q7XHJcbiAgICAgIHRoaXMub3JpZ2luYWxEYXRhID0gZGF0YTtcclxuICAgICAgdGhpcy50cmVlT3B0aW9ucyA9IHRoaXMucHJvY2Vzc09wdGlvbnMob3B0aW9ucywgaXRlbXNQZXJQYWdlLCBwYWdlKTtcclxuICAgICAgaWYgKHRoaXMudHJlZU9wdGlvbnMubGlzdE1vZGUgPT09IHRydWUpIHtcclxuICAgICAgICAgbGV0IHN0YXJ0ID1cclxuICAgICAgICAgICAgdGhpcy50cmVlT3B0aW9ucy5pdGVtc1BlclBhZ2UgKiAodGhpcy50cmVlT3B0aW9ucy5wYWdlIC0gMSk7XHJcbiAgICAgICAgIGlmIChpc05hTihzdGFydCkpIHtcclxuICAgICAgICAgICAgLy9UaGlzIGNhdGNoZXMgdGhlIGNhc2Ugd2hlcmUgaXRlbXNQZXJQYWdlIHdhcyBub3QgcGFzc2VkIGJ5IHRoZSB1c2VyLFxyXG4gICAgICAgICAgICAvL2NhdXNpbmcgYHN0YXJ0YCB0byBlcXVhbCBpbmZpbml0eSowLCB3aGljaCBpcyBOYU4uXHJcbiAgICAgICAgICAgIHN0YXJ0ID0gMDtcclxuICAgICAgICAgfVxyXG4gICAgICAgICBjb25zdCBlbmQgPSBzdGFydCArIHRoaXMudHJlZU9wdGlvbnMuaXRlbXNQZXJQYWdlO1xyXG4gICAgICAgICB0aGlzLnRyZWVEYXRhID0gdGhpcy5vcmlnaW5hbERhdGEuc2xpY2Uoc3RhcnQsIGVuZCk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgIHRoaXMudHJlZURhdGEgPSBbLi4udGhpcy5vcmlnaW5hbERhdGFdO1xyXG4gICAgICB9XHJcbiAgICAgIHRoaXMucmVuZGVyKCk7XHJcbiAgIH1cclxuXHJcbiAgIHByaXZhdGUgY2xlYW51cChyZWJ1aWxkID0gZmFsc2UpOiB2b2lkIHtcclxuICAgICAgaWYgKHJlYnVpbGQpIHtcclxuICAgICAgICAgdGhpcy5yZWJ1aWxkVHJlZURhdGEoKTtcclxuICAgICAgfVxyXG4gICAgICBpZiAodGhpcy50cmVlRGF0YT8ubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgIC8vV2UgZG8gYSBmdWxsIHJlbmRlciBoZXJlIGJlY2F1c2UgaXQgaXNuJ3QgYWN0dWFsbHkgYW55IHNsb3dlclxyXG4gICAgICAgICAvL3doZW4gdGhlcmUgYXJlIG5vIG5vZGVzLCBhbmQgaXQgaXMgYSBsaXR0bGUgbW9yZSBzdHJhaWdodGZvcndhcmRcclxuICAgICAgICAgdGhpcy5yZW5kZXIoKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgdGhpcy5jaGFuZ2VzJC5uZXh0KG51bGwpO1xyXG4gICAgICAgICB0aGlzLmRyb3Bab25lU2VydmljZS51cGRhdGUoKTtcclxuICAgICAgfVxyXG4gICB9XHJcblxyXG4gICAvKiogUmVuZGVycyB0aGUgZW50aXJlIHRyZWUgZnJvbSByb290IHRvIGxlYXZlcyAqL1xyXG4gICBwcml2YXRlIHJlbmRlcigpIHtcclxuICAgICAgaWYgKFxyXG4gICAgICAgICB0aGlzLmhvc3QgPT09IHVuZGVmaW5lZCB8fFxyXG4gICAgICAgICB0aGlzLnRyZWVEYXRhID09PSB1bmRlZmluZWQgfHxcclxuICAgICAgICAgdGhpcy50cmVlT3B0aW9ucyA9PT0gdW5kZWZpbmVkXHJcbiAgICAgICkge1xyXG4gICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUcmVlTW9kZWwgbm90IGluaXRpYWxpemVkXCIpO1xyXG4gICAgICB9XHJcbiAgICAgIHRoaXMudHJlZUNvbnN0cnVjdGlvblN0YXR1cy5yZWFkeShmYWxzZSk7XHJcbiAgICAgIHRoaXMuaG9zdC5jbGVhcigpO1xyXG4gICAgICB0aGlzLmRyb3Bab25lU2VydmljZS5yZXN0YXJ0KCk7XHJcbiAgICAgIHRoaXMucGxhY2Vob2xkZXIkLm5leHQoZmFsc2UpO1xyXG4gICAgICB0aGlzLnRyZWVNb2RlbCA9IG5ldyBCcmFuY2gobnVsbCk7XHJcbiAgICAgIGlmICh0aGlzLnRyZWVEYXRhLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAvL1RyZWUgaXMgZW1wdHksIGJ1dCB3ZSBoYXZlIHRvIHRvIGhhdmUgc29tZXRoaW5nIHRoZXJlIHNvIG90aGVyIHRyZWVzJyBpdGVtcyBjYW4gYmUgZHJvcHBlZCBpbnRvIGl0XHJcbiAgICAgICAgIHRoaXMucGxhY2Vob2xkZXIkLm5leHQodHJ1ZSk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgIGZvciAoY29uc3Qgbm9kZSBvZiB0aGlzLnRyZWVEYXRhKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGJyYW5jaCA9IG5ldyBCcmFuY2gobm9kZSk7XHJcbiAgICAgICAgICAgIHRoaXMudHJlZU1vZGVsLmFwcGVuZENoaWxkKGJyYW5jaCk7XHJcbiAgICAgICAgIH1cclxuICAgICAgICAgZm9yIChjb25zdCBicmFuY2ggb2YgdGhpcy50cmVlTW9kZWwuZ2V0Q2hpbGRyZW4oKSkge1xyXG4gICAgICAgICAgICBjb25zdCBjb21wb25lbnRSZWYgPSB0aGlzLmNvbXBvbmVudENyZWF0b3JTZXJ2aWNlLmFwcGVuZENvbXBvbmVudDxMaW1ibGVUcmVlTm9kZUNvbXBvbmVudD4oXHJcbiAgICAgICAgICAgICAgIExpbWJsZVRyZWVOb2RlQ29tcG9uZW50LFxyXG4gICAgICAgICAgICAgICB0aGlzLmhvc3RcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgY29tcG9uZW50UmVmLmluc3RhbmNlLmJyYW5jaCA9IGJyYW5jaDtcclxuICAgICAgICAgICAgY29tcG9uZW50UmVmLmluc3RhbmNlLnBhcmVudEhvc3QgPSB0aGlzLmhvc3Q7XHJcbiAgICAgICAgICAgIC8vVGhlIExpbWJsZVRyZWVOb2RlQ29tcG9uZW50IHdpbGwgKGluZGlyZWN0bHkpIGNhbGwgdGhlIGByZW5kZXJCcmFuY2hgIG1ldGhvZCBvZiB0aGlzIHNlcnZpY2UgdG8gcmVuZGVyXHJcbiAgICAgICAgICAgIC8vaXRzIG93biBjaGlsZHJlblxyXG4gICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgdGhpcy50cmVlQ29uc3RydWN0aW9uU3RhdHVzLnJlYWR5KHRydWUpO1xyXG4gICAgICB0aGlzLmNoYW5nZXMkLm5leHQobnVsbCk7XHJcbiAgICAgIHRoaXMuZHJvcFpvbmVTZXJ2aWNlLmluaXQodGhpcy50cmVlTW9kZWwsIHRoaXMudHJlZU9wdGlvbnMpO1xyXG4gICB9XHJcblxyXG4gICAvKiogUmVuZGVycyBhIGJyYW5jaCBvZiB0aGUgdHJlZSBhbmQgYWxsIG9mIGl0cyBkZXNjZW5kYW50cyAqL1xyXG4gICBwdWJsaWMgcmVuZGVyQnJhbmNoKGhvc3Q6IFZpZXdDb250YWluZXJSZWYsIGJyYW5jaDogQnJhbmNoPGFueT4pIHtcclxuICAgICAgaWYgKHRoaXMudHJlZU1vZGVsID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVHJlZU1vZGVsIG5vdCBpbml0aWFsaXplZFwiKTtcclxuICAgICAgfVxyXG4gICAgICBob3N0LmNsZWFyKCk7XHJcbiAgICAgIGJyYW5jaC5jbGVhckNoaWxkcmVuKCk7XHJcbiAgICAgIGZvciAoY29uc3Qgbm9kZSBvZiBicmFuY2guZGF0YT8ubm9kZXMgPz8gW10pIHtcclxuICAgICAgICAgY29uc3QgbmV3QnJhbmNoID0gbmV3IEJyYW5jaChub2RlKTtcclxuICAgICAgICAgYnJhbmNoLmFwcGVuZENoaWxkKG5ld0JyYW5jaCk7XHJcbiAgICAgICAgIGNvbnN0IGNvbXBvbmVudFJlZiA9IHRoaXMuY29tcG9uZW50Q3JlYXRvclNlcnZpY2UuYXBwZW5kQ29tcG9uZW50PExpbWJsZVRyZWVOb2RlQ29tcG9uZW50PihcclxuICAgICAgICAgICAgTGltYmxlVHJlZU5vZGVDb21wb25lbnQsXHJcbiAgICAgICAgICAgIGhvc3RcclxuICAgICAgICAgKTtcclxuICAgICAgICAgY29tcG9uZW50UmVmLmluc3RhbmNlLmJyYW5jaCA9IG5ld0JyYW5jaDtcclxuICAgICAgICAgY29tcG9uZW50UmVmLmluc3RhbmNlLnBhcmVudEhvc3QgPSBob3N0O1xyXG4gICAgICAgICAvL1RoZSBMaW1ibGVUcmVlTm9kZUNvbXBvbmVudCB3aWxsIChpbmRpcmVjdGx5KSBjYWxsIHRoZSBgcmVuZGVyQnJhbmNoYCBtZXRob2Qgb2YgdGhpcyBzZXJ2aWNlIHRvIHJlbmRlclxyXG4gICAgICAgICAvL2l0cyBvd24gY2hpbGRyZW5cclxuICAgICAgfVxyXG4gICB9XHJcblxyXG4gICBwcml2YXRlIHByb2Nlc3NPcHRpb25zKFxyXG4gICAgICBvcHRpb25zOiBMaW1ibGVUcmVlT3B0aW9ucyA9IHt9LFxyXG4gICAgICBpdGVtc1BlclBhZ2U6IG51bWJlciA9IEluZmluaXR5LFxyXG4gICAgICBwYWdlOiBudW1iZXIgPSAxXHJcbiAgICk6IFByb2Nlc3NlZE9wdGlvbnMge1xyXG4gICAgICBpZiAoXHJcbiAgICAgICAgIG9wdGlvbnMubGlzdE1vZGUgPT09IHRydWUgJiZcclxuICAgICAgICAgb3B0aW9ucy5hbGxvd05lc3RpbmcgIT09IHVuZGVmaW5lZCAmJlxyXG4gICAgICAgICBvcHRpb25zLmFsbG93TmVzdGluZyAhPT0gZmFsc2VcclxuICAgICAgKSB7XHJcbiAgICAgICAgIGNvbnNvbGUud2FybihcclxuICAgICAgICAgICAgXCJUaGUgdmFsdWUgb2YgYGFsbG93TmVzdGluZ2Agd2lsbCBiZSBpZ25vcmVkOyBpdCBtdXN0IGJlIGZhbHNlIHdoZW4gYGxpc3RNb2RlYCBpcyB0cnVlXCJcclxuICAgICAgICAgKTtcclxuICAgICAgfVxyXG4gICAgICBjb25zdCByZXN1bHQ6IFByb2Nlc3NlZE9wdGlvbnNCYXNlID0ge1xyXG4gICAgICAgICBkZWZhdWx0Q29tcG9uZW50OiBvcHRpb25zLmRlZmF1bHRDb21wb25lbnQsXHJcbiAgICAgICAgIGluZGVudDogb3B0aW9ucy5pbmRlbnQgPz8gSU5ERU5ULFxyXG4gICAgICAgICBhbGxvd05lc3Rpbmc6XHJcbiAgICAgICAgICAgIG9wdGlvbnMubGlzdE1vZGUgIT09IHRydWUgJiYgKG9wdGlvbnMuYWxsb3dOZXN0aW5nID8/IHRydWUpLFxyXG4gICAgICAgICBhbGxvd0RyYWdnaW5nOiBvcHRpb25zLmFsbG93RHJhZ2dpbmcgPz8gdHJ1ZSxcclxuICAgICAgICAgYWxsb3dEcm9wOiBvcHRpb25zLmFsbG93RHJvcCA/PyAoKCkgPT4gdHJ1ZSksXHJcbiAgICAgICAgIGxpc3RNb2RlOiBvcHRpb25zLmxpc3RNb2RlID8/IGZhbHNlLFxyXG4gICAgICAgICBpdGVtc1BlclBhZ2U6IG9wdGlvbnMubGlzdE1vZGUgPyBpdGVtc1BlclBhZ2UgOiB1bmRlZmluZWQsXHJcbiAgICAgICAgIHBhZ2U6IG9wdGlvbnMubGlzdE1vZGUgPyBwYWdlIDogdW5kZWZpbmVkXHJcbiAgICAgIH07XHJcbiAgICAgIHJldHVybiByZXN1bHQgYXMgUHJvY2Vzc2VkT3B0aW9ucztcclxuICAgfVxyXG5cclxuICAgcHJpdmF0ZSByZWJ1aWxkVHJlZURhdGEoKTogdm9pZCB7XHJcbiAgICAgIGlmIChcclxuICAgICAgICAgdGhpcy5vcmlnaW5hbERhdGEgPT09IHVuZGVmaW5lZCB8fFxyXG4gICAgICAgICB0aGlzLnRyZWVEYXRhID09PSB1bmRlZmluZWQgfHxcclxuICAgICAgICAgdGhpcy50cmVlT3B0aW9ucyA9PT0gdW5kZWZpbmVkIHx8XHJcbiAgICAgICAgIHRoaXMuaG9zdCA9PT0gdW5kZWZpbmVkXHJcbiAgICAgICkge1xyXG4gICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUcmVlIGRhdGEgbm90IGluaXRpYWxpemVkXCIpO1xyXG4gICAgICB9XHJcbiAgICAgIHRoaXMudHJlZURhdGEgPSBbXTtcclxuICAgICAgZm9yIChjb25zdCBicmFuY2ggb2YgdGhpcy50cmVlTW9kZWwuZ2V0Q2hpbGRyZW4oKSkge1xyXG4gICAgICAgICB0aGlzLnRyZWVEYXRhLnB1c2godGhpcy5yZWJ1aWxkQnJhbmNoKGJyYW5jaCkpO1xyXG4gICAgICB9XHJcbiAgICAgIGlmIChcclxuICAgICAgICAgdGhpcy50cmVlT3B0aW9ucy5saXN0TW9kZSA9PT0gdHJ1ZSAmJlxyXG4gICAgICAgICB0aGlzLnRyZWVPcHRpb25zLml0ZW1zUGVyUGFnZSA8IEluZmluaXR5XHJcbiAgICAgICkge1xyXG4gICAgICAgICBjb25zdCBpdGVtc1BlclBhZ2UgPSB0aGlzLnRyZWVPcHRpb25zLml0ZW1zUGVyUGFnZTtcclxuICAgICAgICAgY29uc3Qgc3RhcnQgPSBpdGVtc1BlclBhZ2UgKiAodGhpcy50cmVlT3B0aW9ucy5wYWdlIC0gMSk7XHJcbiAgICAgICAgIHRoaXMub3JpZ2luYWxEYXRhLnNwbGljZShzdGFydCwgaXRlbXNQZXJQYWdlLCAuLi50aGlzLnRyZWVEYXRhKTtcclxuICAgICAgICAgaWYgKHRoaXMudHJlZURhdGEubGVuZ3RoICE9PSBpdGVtc1BlclBhZ2UpIHtcclxuICAgICAgICAgICAgbGV0IGFjdGlvbiA9IGZhbHNlO1xyXG4gICAgICAgICAgICBpZiAoXHJcbiAgICAgICAgICAgICAgIHRoaXMudHJlZURhdGEubGVuZ3RoIDwgaXRlbXNQZXJQYWdlICYmXHJcbiAgICAgICAgICAgICAgIHN0YXJ0ICsgaXRlbXNQZXJQYWdlIDw9IHRoaXMub3JpZ2luYWxEYXRhLmxlbmd0aFxyXG4gICAgICAgICAgICApIHtcclxuICAgICAgICAgICAgICAgLy9UaGUgY3VycmVudCBwYWdlIGRvZXMgbm90IGhhdmUgZW5vdWdoIG5vZGVzLiBBZGQgc29tZSB0byB0aGUgdmlldyBmcm9tIHRoZSBuZXh0IHBhZ2UuXHJcbiAgICAgICAgICAgICAgIGNvbnN0IGNvdW50ID0gaXRlbXNQZXJQYWdlIC0gdGhpcy50cmVlRGF0YS5sZW5ndGg7XHJcbiAgICAgICAgICAgICAgIGZvciAoXHJcbiAgICAgICAgICAgICAgICAgIGxldCBpbmRleCA9IGl0ZW1zUGVyUGFnZSAtIDE7XHJcbiAgICAgICAgICAgICAgICAgIGluZGV4IDwgaXRlbXNQZXJQYWdlICsgY291bnQgLSAxO1xyXG4gICAgICAgICAgICAgICAgICBpbmRleCsrXHJcbiAgICAgICAgICAgICAgICkge1xyXG4gICAgICAgICAgICAgICAgICBjb25zdCBicmFuY2ggPSBuZXcgQnJhbmNoKHRoaXMub3JpZ2luYWxEYXRhW3N0YXJ0ICsgaW5kZXhdKTtcclxuICAgICAgICAgICAgICAgICAgdGhpcy50cmVlTW9kZWwuYXBwZW5kQ2hpbGQoYnJhbmNoKTtcclxuICAgICAgICAgICAgICAgICAgY29uc3QgY29tcG9uZW50UmVmID0gdGhpcy5jb21wb25lbnRDcmVhdG9yU2VydmljZS5hcHBlbmRDb21wb25lbnQ8TGltYmxlVHJlZU5vZGVDb21wb25lbnQ+KFxyXG4gICAgICAgICAgICAgICAgICAgICBMaW1ibGVUcmVlTm9kZUNvbXBvbmVudCxcclxuICAgICAgICAgICAgICAgICAgICAgdGhpcy5ob3N0XHJcbiAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgIGNvbXBvbmVudFJlZi5pbnN0YW5jZS5icmFuY2ggPSBicmFuY2g7XHJcbiAgICAgICAgICAgICAgICAgIGNvbXBvbmVudFJlZi5pbnN0YW5jZS5wYXJlbnRIb3N0ID0gdGhpcy5ob3N0O1xyXG4gICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgIGFjdGlvbiA9IHRydWU7XHJcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy50cmVlRGF0YS5sZW5ndGggPiBpdGVtc1BlclBhZ2UpIHtcclxuICAgICAgICAgICAgICAgLy9UaGUgY3VycmVudCBwYWdlIGhhcyB0b28gbWFueSBub2Rlcy4gUmVtb3ZlIHNvbWUgb2YgdGhlbSBmcm9tIHRoZSB2aWV3LlxyXG4gICAgICAgICAgICAgICBjb25zdCBjb3VudCA9IHRoaXMudHJlZURhdGEubGVuZ3RoIC0gaXRlbXNQZXJQYWdlO1xyXG4gICAgICAgICAgICAgICBmb3IgKFxyXG4gICAgICAgICAgICAgICAgICBsZXQgaW5kZXggPSBpdGVtc1BlclBhZ2UgKyBjb3VudCAtIDE7XHJcbiAgICAgICAgICAgICAgICAgIGluZGV4ID49IGl0ZW1zUGVyUGFnZTtcclxuICAgICAgICAgICAgICAgICAgaW5kZXgtLVxyXG4gICAgICAgICAgICAgICApIHtcclxuICAgICAgICAgICAgICAgICAgdGhpcy50cmVlTW9kZWwucmVtb3ZlQ2hpbGQoaW5kZXgpO1xyXG4gICAgICAgICAgICAgICAgICB0aGlzLmhvc3QucmVtb3ZlKGluZGV4KTtcclxuICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICBhY3Rpb24gPSB0cnVlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmIChhY3Rpb24gPT09IHRydWUpIHtcclxuICAgICAgICAgICAgICAgY29uc3QgZW5kID0gc3RhcnQgKyBpdGVtc1BlclBhZ2U7XHJcbiAgICAgICAgICAgICAgIHRoaXMudHJlZURhdGEgPSB0aGlzLm9yaWdpbmFsRGF0YS5zbGljZShzdGFydCwgZW5kKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICB9XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgIHRoaXMub3JpZ2luYWxEYXRhLmxlbmd0aCA9IDA7XHJcbiAgICAgICAgIHRoaXMub3JpZ2luYWxEYXRhLnB1c2goLi4udGhpcy50cmVlRGF0YSk7XHJcbiAgICAgIH1cclxuICAgfVxyXG5cclxuICAgcHJpdmF0ZSByZWJ1aWxkQnJhbmNoKGJyYW5jaDogQnJhbmNoPGFueT4pOiBMaW1ibGVUcmVlTm9kZSB7XHJcbiAgICAgIGNvbnN0IHRlbXA6IExpbWJsZVRyZWVOb2RlID0gYnJhbmNoLmRhdGE7XHJcbiAgICAgIHRlbXAubm9kZXMgPSBbXTtcclxuICAgICAgZm9yIChjb25zdCBjaGlsZCBvZiBicmFuY2guZ2V0Q2hpbGRyZW4oKSkge1xyXG4gICAgICAgICB0ZW1wLm5vZGVzLnB1c2godGhpcy5yZWJ1aWxkQnJhbmNoKGNoaWxkKSk7XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIHRlbXA7XHJcbiAgIH1cclxufVxyXG4iXX0=
|