@smarterplan/ngx-smarterplan-locations 0.3.4 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/esm2022/lib/components/carousel/carousel.component.mjs +30 -0
  2. package/esm2022/lib/components/chevron/chevron.component.mjs +18 -0
  3. package/esm2022/lib/components/detail-location/detail-location.component.mjs +183 -0
  4. package/{esm2020 → esm2022}/lib/components/form-location/form-location.component.mjs +254 -237
  5. package/esm2022/lib/components/images/images.component.mjs +120 -0
  6. package/esm2022/lib/components/locations/locations.component.mjs +157 -0
  7. package/esm2022/lib/components/locations/map/map-popup/map-popup.component.mjs +72 -0
  8. package/esm2022/lib/components/locations/map/map.component.mjs +92 -0
  9. package/esm2022/lib/components/plan-legend/plan-legend.component.mjs +49 -0
  10. package/esm2022/lib/components/plans/calibration/calibration.component.mjs +494 -0
  11. package/esm2022/lib/components/plans/edit-plan/edit-plan.component.mjs +350 -0
  12. package/{esm2020 → esm2022}/lib/components/plans/plans.component.mjs +243 -225
  13. package/esm2022/lib/components/tab-navigation/tab-navigation.component.mjs +43 -0
  14. package/esm2022/lib/components/visits/visits.component.mjs +294 -0
  15. package/esm2022/lib/components/zones/add-audio-zone/add-audio-zone.component.mjs +250 -0
  16. package/esm2022/lib/components/zones/add-zone/add-zone.component.mjs +333 -0
  17. package/esm2022/lib/components/zones/add-zone/selection/selection.component.mjs +81 -0
  18. package/esm2022/lib/components/zones/add-zone/sweep-plan-selection/sweep-plan-selection.component.mjs +518 -0
  19. package/esm2022/lib/components/zones/zones.component.mjs +291 -0
  20. package/{esm2020 → esm2022}/lib/helper.service.mjs +133 -133
  21. package/esm2022/lib/ngx-smarterplan-location-routing.module.mjs +50 -0
  22. package/esm2022/lib/ngx-smarterplan-locations.module.mjs +124 -0
  23. package/esm2022/lib/ngx-smarterplan-locations.service.mjs +15 -0
  24. package/esm2022/lib/pipes/count-audio-sweeps.pipe.mjs +29 -0
  25. package/esm2022/lib/radio-button/radio-button.component.mjs +28 -0
  26. package/{esm2020 → esm2022}/public-api.mjs +8 -8
  27. package/{esm2020 → esm2022}/smarterplan-ngx-smarterplan-locations.mjs +4 -4
  28. package/{fesm2020 → fesm2022}/smarterplan-ngx-smarterplan-locations.mjs +3959 -3738
  29. package/fesm2022/smarterplan-ngx-smarterplan-locations.mjs.map +1 -0
  30. package/index.d.ts +5 -5
  31. package/lib/components/carousel/carousel.component.d.ts +12 -12
  32. package/lib/components/chevron/chevron.component.d.ts +9 -9
  33. package/lib/components/detail-location/detail-location.component.d.ts +55 -55
  34. package/lib/components/form-location/form-location.component.d.ts +45 -45
  35. package/lib/components/images/images.component.d.ts +33 -33
  36. package/lib/components/locations/locations.component.d.ts +51 -51
  37. package/lib/components/locations/map/map-popup/map-popup.component.d.ts +22 -22
  38. package/lib/components/locations/map/map.component.d.ts +21 -22
  39. package/lib/components/plan-legend/plan-legend.component.d.ts +14 -14
  40. package/lib/components/plans/calibration/calibration.component.d.ts +140 -140
  41. package/lib/components/plans/edit-plan/edit-plan.component.d.ts +55 -55
  42. package/lib/components/plans/plans.component.d.ts +63 -63
  43. package/lib/components/tab-navigation/tab-navigation.component.d.ts +13 -13
  44. package/lib/components/visits/visits.component.d.ts +63 -63
  45. package/lib/components/zones/add-audio-zone/add-audio-zone.component.d.ts +63 -63
  46. package/lib/components/zones/add-zone/add-zone.component.d.ts +69 -69
  47. package/lib/components/zones/add-zone/selection/selection.component.d.ts +44 -44
  48. package/lib/components/zones/add-zone/sweep-plan-selection/sweep-plan-selection.component.d.ts +107 -107
  49. package/lib/components/zones/zones.component.d.ts +73 -73
  50. package/lib/helper.service.d.ts +53 -53
  51. package/lib/ngx-smarterplan-location-routing.module.d.ts +7 -7
  52. package/lib/ngx-smarterplan-locations.module.d.ts +36 -36
  53. package/lib/ngx-smarterplan-locations.service.d.ts +6 -6
  54. package/lib/pipes/count-audio-sweeps.pipe.d.ts +10 -10
  55. package/lib/radio-button/radio-button.component.d.ts +12 -12
  56. package/package.json +13 -19
  57. package/public-api.d.ts +4 -4
  58. package/esm2020/lib/components/carousel/carousel.component.mjs +0 -28
  59. package/esm2020/lib/components/chevron/chevron.component.mjs +0 -18
  60. package/esm2020/lib/components/detail-location/detail-location.component.mjs +0 -168
  61. package/esm2020/lib/components/images/images.component.mjs +0 -107
  62. package/esm2020/lib/components/locations/locations.component.mjs +0 -145
  63. package/esm2020/lib/components/locations/map/map-popup/map-popup.component.mjs +0 -66
  64. package/esm2020/lib/components/locations/map/map.component.mjs +0 -91
  65. package/esm2020/lib/components/plan-legend/plan-legend.component.mjs +0 -47
  66. package/esm2020/lib/components/plans/calibration/calibration.component.mjs +0 -468
  67. package/esm2020/lib/components/plans/edit-plan/edit-plan.component.mjs +0 -324
  68. package/esm2020/lib/components/tab-navigation/tab-navigation.component.mjs +0 -41
  69. package/esm2020/lib/components/visits/visits.component.mjs +0 -275
  70. package/esm2020/lib/components/zones/add-audio-zone/add-audio-zone.component.mjs +0 -230
  71. package/esm2020/lib/components/zones/add-zone/add-zone.component.mjs +0 -315
  72. package/esm2020/lib/components/zones/add-zone/selection/selection.component.mjs +0 -77
  73. package/esm2020/lib/components/zones/add-zone/sweep-plan-selection/sweep-plan-selection.component.mjs +0 -502
  74. package/esm2020/lib/components/zones/zones.component.mjs +0 -268
  75. package/esm2020/lib/ngx-smarterplan-location-routing.module.mjs +0 -49
  76. package/esm2020/lib/ngx-smarterplan-locations.module.mjs +0 -123
  77. package/esm2020/lib/ngx-smarterplan-locations.service.mjs +0 -14
  78. package/esm2020/lib/pipes/count-audio-sweeps.pipe.mjs +0 -27
  79. package/esm2020/lib/radio-button/radio-button.component.mjs +0 -26
  80. package/fesm2015/smarterplan-ngx-smarterplan-locations.mjs +0 -3983
  81. package/fesm2015/smarterplan-ngx-smarterplan-locations.mjs.map +0 -1
  82. package/fesm2020/smarterplan-ngx-smarterplan-locations.mjs.map +0 -1
@@ -0,0 +1,333 @@
1
+ import { Component, EventEmitter, Input, Output } from '@angular/core';
2
+ import { Validators, } from '@angular/forms';
3
+ import * as i0 from "@angular/core";
4
+ import * as i1 from "@angular/forms";
5
+ import * as i2 from "@smarterplan/ngx-smarterplan-core";
6
+ import * as i3 from "@angular/common";
7
+ import * as i4 from "../../carousel/carousel.component";
8
+ import * as i5 from "./sweep-plan-selection/sweep-plan-selection.component";
9
+ import * as i6 from "@ngx-translate/core";
10
+ class AddZoneComponent {
11
+ fb;
12
+ zoneService;
13
+ layerService;
14
+ userService;
15
+ navigationService;
16
+ zoneEdit;
17
+ spaceID;
18
+ images360;
19
+ navigationIDs;
20
+ zones;
21
+ newZoneDataFromEditor;
22
+ updatedZone = new EventEmitter();
23
+ chosenPlan;
24
+ isMuseumVisit = false;
25
+ defaultZone;
26
+ parentZones = [];
27
+ carouselIsVisible = false;
28
+ zoneForm;
29
+ isSubmitted = false;
30
+ currentScanShowing;
31
+ chosenScans = [];
32
+ layers;
33
+ fromPlan = false;
34
+ chosenScansOnPlan = [];
35
+ currentOrgId;
36
+ zoneInitialNavCount = 0;
37
+ zoneIsMatterportFloor = false;
38
+ multipleFloors = false;
39
+ constructor(fb, zoneService, layerService, userService, navigationService) {
40
+ this.fb = fb;
41
+ this.zoneService = zoneService;
42
+ this.layerService = layerService;
43
+ this.userService = userService;
44
+ this.navigationService = navigationService;
45
+ }
46
+ async ngOnInit() {
47
+ this.parentZones = this.zones.filter((zone) => zone.layer && zone.layer.name === 'FLOOR');
48
+ if (!this.defaultZone) {
49
+ this.defaultZone = this.getDefaultZone();
50
+ }
51
+ this.parentZones.unshift(this.defaultZone);
52
+ await this.updateLayers();
53
+ this.initZoneForm();
54
+ }
55
+ async updateLayers() {
56
+ this.currentOrgId = this.userService.currentOrganisation(this.spaceID).id;
57
+ const layers = await this.layerService.getLayerForOrganisation(this.currentOrgId);
58
+ // filter out layers created by the system
59
+ this.layers = layers.filter((l) => l.name !== 'BUILDING' && l.name !== 'FLOOR');
60
+ }
61
+ async initZoneForm() {
62
+ if (this.zoneEdit) {
63
+ if (this.zoneEdit.metadata) {
64
+ const metadata = JSON.parse(this.zoneEdit.metadata);
65
+ this.zoneIsMatterportFloor = metadata.hasOwnProperty('matterportFloorSequence');
66
+ }
67
+ const isVirtual = this.zoneService.zoneIsVirtual(this.zoneEdit);
68
+ if (!isVirtual) {
69
+ await this.loadNavigations();
70
+ }
71
+ this.isMuseumVisit = this.zoneEdit.isMuseumVisitZone === true;
72
+ this.multipleFloors = this.zoneEdit.isMultipleFloorZone === true;
73
+ this.zoneForm = this.fb.group({
74
+ id: this.zoneEdit.id,
75
+ name: [this.zoneEdit.name, [Validators.required]],
76
+ code_ref: this.zoneEdit.code_ref ? this.zoneEdit.code_ref : null,
77
+ layerID: this.zoneEdit.layer ? this.zoneEdit.layer.id : null,
78
+ surface: this.zoneEdit.surface ? this.zoneEdit.surface : 0,
79
+ parentID: this.zoneEdit.parentID,
80
+ parent: { value: this.zoneEdit.parent.name, disabled: true },
81
+ newLayer: [null, [this.layerNameValidator()]],
82
+ isMuseumVisitZone: this.isMuseumVisit,
83
+ startSweepID: this.zoneEdit.startSweepID,
84
+ });
85
+ this.onChangeMultipleFloors();
86
+ }
87
+ else {
88
+ this.zoneForm = this.fb.group({
89
+ name: [
90
+ this.newZoneDataFromEditor ? this.newZoneDataFromEditor.name : '',
91
+ [Validators.required],
92
+ ],
93
+ code_ref: null,
94
+ layerID: null,
95
+ surface: 0,
96
+ parentID: this.defaultZone.id,
97
+ newLayer: [null, [this.layerNameValidator()]],
98
+ isMuseumVisitZone: this.isMuseumVisit,
99
+ startSweepID: null,
100
+ });
101
+ }
102
+ }
103
+ async onSubmitZone() {
104
+ this.isSubmitted = true;
105
+ if (!this.zoneForm.valid) {
106
+ return;
107
+ }
108
+ const formValue = this.zoneForm.getRawValue(); //because we need values of disables controls as well
109
+ if (formValue.newLayer) {
110
+ await this.createLayer(formValue.newLayer).then((layer) => {
111
+ formValue.layerID = layer.id;
112
+ });
113
+ }
114
+ const zoneInput = {
115
+ name: formValue.name,
116
+ surface: Math.round(formValue.surface * 100) / 100,
117
+ spaceID: this.spaceID,
118
+ layerID: formValue.layerID,
119
+ parentID: formValue.parentID,
120
+ isMuseumVisitZone: this.isMuseumVisit,
121
+ isMultipleFloorZone: this.multipleFloors,
122
+ sweepIDs: [],
123
+ startSweepID: formValue.startSweepID,
124
+ };
125
+ if (formValue.code_ref) {
126
+ zoneInput.code_ref = formValue.code_ref;
127
+ }
128
+ try {
129
+ this.zoneForm = null;
130
+ this.isSubmitted = false;
131
+ if (this.zoneEdit) {
132
+ const zoneUpdate = zoneInput;
133
+ zoneUpdate.sweepIDs = this.zoneEdit.sweepIDs;
134
+ zoneUpdate.id = formValue.id;
135
+ await this.setSweepsAndNodeForZoneInput(zoneUpdate);
136
+ await this.zoneService.updateZone(zoneUpdate);
137
+ this.zoneEdit = null;
138
+ this.updatedZone.emit(zoneUpdate.id);
139
+ }
140
+ else {
141
+ await this.setSweepsAndNodeForZoneInput(zoneInput);
142
+ if (!zoneInput.parentID) {
143
+ // set building as parent
144
+ zoneInput.parentID = this.defaultZone.id;
145
+ }
146
+ await this.zoneService.create(zoneInput).then((zoneCreated) => {
147
+ this.updatedZone.emit(zoneCreated.id);
148
+ });
149
+ }
150
+ }
151
+ catch (error) {
152
+ console.error(error);
153
+ }
154
+ }
155
+ onCancel() {
156
+ this.isSubmitted = false;
157
+ this.zoneForm = null;
158
+ this.chosenScansOnPlan = [];
159
+ this.chosenScans = [];
160
+ this.updatedZone.emit(false);
161
+ }
162
+ get name() {
163
+ return this.zoneForm.get('name');
164
+ }
165
+ get newLayer() {
166
+ return this.zoneForm.get('newLayer');
167
+ }
168
+ toggleCarousel() {
169
+ this.carouselIsVisible = true;
170
+ this.chosenScansOnPlan = [];
171
+ }
172
+ togglePlan() {
173
+ this.fromPlan = true;
174
+ this.chosenScans = [];
175
+ }
176
+ onAddScan() {
177
+ if (!this.chosenScans.includes(this.currentScanShowing)) {
178
+ // console.log("adding scan", this.currentScanShowing);
179
+ this.chosenScans.push(this.currentScanShowing);
180
+ }
181
+ else {
182
+ alert('Scan already added!');
183
+ }
184
+ }
185
+ onRemoveScanImage(scan) {
186
+ const index = this.chosenScans.indexOf(scan);
187
+ this.chosenScans.splice(index, 1);
188
+ }
189
+ onRemoveScanPlan(scan) {
190
+ const index = this.chosenScansOnPlan.indexOf(scan);
191
+ this.chosenScansOnPlan.splice(index, 1);
192
+ }
193
+ async setSweepsAndNodeForZoneInput(zoneInput) {
194
+ if (this.chosenScans.length > 0 &&
195
+ this.chosenScans.length !== this.zoneInitialNavCount &&
196
+ !this.fromPlan) {
197
+ // if we chose scans from the carousel
198
+ const sweepIDs = [];
199
+ this.chosenScans.map(async (scan) => {
200
+ const imageUuid = this.images360[scan].filename.split('_')[0];
201
+ const sweepID = this.navigationIDs.find((nav) => {
202
+ return nav.includes(imageUuid);
203
+ });
204
+ if (sweepID) {
205
+ sweepIDs.push(sweepID);
206
+ }
207
+ });
208
+ zoneInput.sweepIDs = sweepIDs;
209
+ }
210
+ else {
211
+ // we are not coming from gallery choice
212
+ if (this.chosenScansOnPlan.length > 0) {
213
+ zoneInput.sweepIDs = this.chosenScansOnPlan;
214
+ }
215
+ }
216
+ if (zoneInput.sweepIDs && zoneInput.sweepIDs.length > 0) {
217
+ const navForSweep = await this.navigationService.getNavigationsForMatterportIDForSpace(zoneInput.sweepIDs[0], this.spaceID);
218
+ zoneInput.nodeIDs = [navForSweep[0].nodeID];
219
+ }
220
+ }
221
+ async createLayer(name) {
222
+ return this.layerService.createLayerForOrganisation(name, this.currentOrgId);
223
+ }
224
+ async loadNavigations() {
225
+ if (this.zoneEdit.sweepIDs.length > 0) {
226
+ this.zoneInitialNavCount = this.zoneEdit.sweepIDs.length;
227
+ const navList = [];
228
+ const scansZoneEdit = [];
229
+ await Promise.all(this.zoneEdit.sweepIDs.map(async (sweepID) => {
230
+ scansZoneEdit.push(sweepID);
231
+ const index = this.images360.findIndex((im) => {
232
+ return im.filename.includes(sweepID.slice(0, 8));
233
+ });
234
+ if (index !== -1) {
235
+ navList.push(index);
236
+ }
237
+ }));
238
+ this.chosenScans = navList;
239
+ this.chosenScansOnPlan = scansZoneEdit;
240
+ return Promise.resolve();
241
+ }
242
+ return Promise.resolve();
243
+ }
244
+ // iniPlanForDraw() {
245
+ // this.togglePlan();
246
+ // setTimeout(() => {
247
+ // this.onPlanClick();
248
+ // }, 500);
249
+ // }
250
+ /**
251
+ * Adds all sweeps of the space
252
+ */
253
+ onAddAll() {
254
+ const defaultZone = this.getDefaultZone();
255
+ if (defaultZone) {
256
+ this.chosenScansOnPlan = defaultZone.sweepIDs;
257
+ this.zoneForm.get('parentID').setValue(defaultZone.id);
258
+ this.zoneForm.get('parentID').disable();
259
+ this.multipleFloors = true;
260
+ }
261
+ }
262
+ getDefaultZone() {
263
+ return this.zones.find((zone) => zone.layer &&
264
+ zone.layer.name === 'BUILDING' &&
265
+ zone.sweepIDs &&
266
+ zone.sweepIDs.length > 0);
267
+ }
268
+ /**
269
+ * Multiple floors
270
+ */
271
+ onChangeMultipleFloors() {
272
+ if (this.multipleFloors) {
273
+ const defaultZone = this.getDefaultZone();
274
+ if (defaultZone) {
275
+ this.zoneForm.get('parentID').setValue(defaultZone.id);
276
+ this.zoneForm.get('parentID').disable();
277
+ }
278
+ }
279
+ else {
280
+ this.zoneForm.get('parentID').enable();
281
+ }
282
+ }
283
+ onSelectedSweepsFromPlan(result) {
284
+ if (result) {
285
+ if (result.sweeps) {
286
+ this.chosenScansOnPlan = result.sweeps;
287
+ }
288
+ if (result.startSweepID) {
289
+ this.zoneForm.controls.startSweepID.setValue(result.startSweepID);
290
+ }
291
+ }
292
+ this.fromPlan = false;
293
+ }
294
+ layerNameValidator() {
295
+ return (control) => {
296
+ if (!control.value) {
297
+ return null;
298
+ }
299
+ const forbidden = this.layers
300
+ .map((l) => l.name.toLowerCase())
301
+ .includes(control.value.toLowerCase());
302
+ return forbidden ? { forbiddenName: { value: control.value } } : null;
303
+ };
304
+ }
305
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AddZoneComponent, deps: [{ token: i1.UntypedFormBuilder }, { token: i2.ZoneService }, { token: i2.LayerService }, { token: i2.BaseUserService }, { token: i2.NavigationService }], target: i0.ɵɵFactoryTarget.Component });
306
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: AddZoneComponent, selector: "lib-add-zone", inputs: { zoneEdit: "zoneEdit", spaceID: "spaceID", images360: "images360", navigationIDs: "navigationIDs", zones: "zones", newZoneDataFromEditor: "newZoneDataFromEditor", chosenPlan: "chosenPlan", isMuseumVisit: "isMuseumVisit", defaultZone: "defaultZone" }, outputs: { updatedZone: "updatedZone" }, ngImport: i0, template: "<div class=\"main-container\" *ngIf=\"zoneForm\">\r\n <div class=\"col-7\">\r\n <form (ngSubmit)=\"onSubmitZone()\" [formGroup]=\"zoneForm\">\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Name' | translate}} *</label>\r\n <div class=\"col-sm-10\">\r\n <input type=\"text\" class=\"form-control\" required formControlName=\"name\">\r\n <!-- <div class=\"invalid-feedback\">\r\n {{'A name is required' | translate}}\r\n </div> -->\r\n </div>\r\n </div>\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'codeRef' | translate}}</label>\r\n <div class=\"col-sm-10\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"code_ref\">\r\n </div>\r\n </div>\r\n <div class=\"mb-3 row\" *ngIf=\"!isMuseumVisit && !zoneIsMatterportFloor\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Type of zone' | translate}}</label>\r\n <div class=\"col-sm-10\">\r\n <select class=\"form-control\" formControlName=\"layerID\">\r\n <option value=\"null\" selected disabled hidden> {{ zoneEdit && zoneEdit.layer ?\r\n zoneEdit.layer.name : 'Choose type'}}</option>\r\n <option *ngFor=\"let layer of layers\" [value]=\"layer.id\">\r\n {{ layer.name }}\r\n </option>\r\n </select>\r\n <p class=\"mt-1 new-type-text\">{{'or add new type of zone' | translate }}</p>\r\n <input type=\"text\" class=\"form-control new-type-input\" formControlName=\"newLayer\">\r\n <div *ngIf=\"newLayer.invalid && (newLayer.dirty || newLayer.touched)\" class=\"text-danger\">\r\n <div *ngIf=\"newLayer.errors?.['forbiddenName']\">\r\n {{'Layer exists already' | translate}}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <!--If Editing Zone possibility to assign it to museum itinerary-->\r\n <div class=\"mb-3 row\" *ngIf=\"zoneEdit && !zoneIsMatterportFloor\">\r\n <label class=\"col-sm-2 col-form-label\">{{ 'Museum Itinerary' | translate }}</label>\r\n <div class=\"col-sm-10\">\r\n <input class=\"checkbox-apply mt-3\" type=\"checkbox\" [(ngModel)]=\"isMuseumVisit\"\r\n [ngModelOptions]=\"{standalone: true}\">\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\" *ngIf=\"!zoneEdit || zoneEdit.isMultipleFloorZone\">\r\n <label class=\"col-sm-2 col-form-label\">{{ 'Multiple Floors' | translate }}</label>\r\n <div class=\"col-sm-10\">\r\n <input class=\"checkbox-apply mt-3\" type=\"checkbox\" [(ngModel)]=\"multipleFloors\"\r\n [disabled]=\"zoneEdit !== undefined && zoneEdit !== null\" (change)=\"onChangeMultipleFloors()\"\r\n [ngModelOptions]=\"{standalone: true}\">\r\n <div class='text-danger' *ngIf=\"zoneEdit\">\r\n {{'cannotChangeMultifloor' | translate}}\r\n </div>\r\n </div>\r\n\r\n </div>\r\n\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Surface' | translate}}</label>\r\n <div class=\"col-sm-10\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"surface\">\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\" *ngIf=\"!zoneIsMatterportFloor\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Parent zone' | translate}}</label>\r\n <div class=\"col-sm-10\">\r\n <input *ngIf=\"zoneEdit\" type=\"text\" class=\"form-control\" formControlName=\"parent\">\r\n <div class=\"text-danger\" *ngIf=\"zoneEdit\">\r\n {{'cannotChangeParent' | translate}}\r\n </div>\r\n <select *ngIf=\"!zoneEdit\" class=\"form-control\" formControlName=\"parentID\">\r\n <option *ngFor=\"let zone of parentZones\" [ngValue]=\"zone.id\">\r\n {{ zone.name }}\r\n </option>\r\n </select>\r\n\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\" style=\"max-height: 200px; overflow: auto;\" *ngIf=\"!zoneIsMatterportFloor\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Scan Points' | translate}}</label>\r\n <!-- <p class=\"col-sm-2\" *ngIf=\"zoneEdit\">{{ zoneEdit.sweepIDs.length }} scans</p> -->\r\n <p class=\"col\" *ngIf=\"chosenScansOnPlan.length === 0 && chosenScans.length === 0\">\r\n {{'No scan points chosen' | translate}}</p>\r\n <div class=\"col-sm-5\" *ngIf=\"chosenScansOnPlan && chosenScansOnPlan.length > 0\">\r\n <p>{{ chosenScansOnPlan.length }} {{'scan points chosen' | translate}}</p>\r\n <!-- <div *ngFor=\"let scan of chosenScansOnPlan\">\r\n <div class=\"row\">\r\n <p class=\"me-2\">{{ scan | slice:0:8 }}</p>\r\n <div (click)=\"onRemoveScanPlan(scan)\" [style.cursor]=\"'pointer'\">\r\n <span class=\"iconify\" data-icon=\"mdi:trash-can-outline\"></span>\r\n </div>\r\n </div>\r\n </div> -->\r\n </div>\r\n <div class=\"col-sm-5\" *ngIf=\"carouselIsVisible && chosenScans && chosenScans.length > 0\">\r\n <p>{{ chosenScans.length }} {{'scan points chosen' | translate}}</p>\r\n <div *ngFor=\"let scan of chosenScans\">\r\n <div class=\"row\">\r\n <p class=\"me-2\">{{ images360[scan].filename }}</p>\r\n <div (click)=\"onRemoveScanImage(scan)\" [style.cursor]=\"'pointer'\">\r\n <span class=\"iconify\" data-icon=\"mdi:trash-can-outline\"></span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"row mb-3 mt-3\" *ngIf=\"!zoneIsMatterportFloor\">\r\n <div class=\"col\">\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2\"\r\n (click)=\"togglePlan()\">{{'Choose scan points on plan' |\r\n translate}}</button>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"toggleCarousel()\"\r\n [disabled]=\"fromPlan || !images360 || images360.length === 0\">\r\n {{'Choose scan points from gallery' | translate}}</button>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"onAddAll()\"\r\n [disabled]=\"fromPlan || !images360 || images360.length === 0\">\r\n {{'add-all-scans' | translate}}</button>\r\n </div>\r\n </div>\r\n\r\n <!-- <div class=\"mb-3 row\">\r\n <label class=\"col-sm-3 col-form-label\">{{'No visible scan points' | translate}}</label>\r\n <div class=\"col-sm-3\">\r\n <input class=\"checkbox-apply mt-3\" type=\"checkbox\" [(ngModel)]=\"noScanPoints\"\r\n [ngModelOptions]=\"{standalone: true}\">\r\n </div>\r\n </div> -->\r\n\r\n <div *ngIf=\"carouselIsVisible\" class=\"mb-2\">\r\n <lib-carousel *ngIf=\"images360 && images360.length > 0\" [images]=\"images360\"\r\n (currentScan)=\"currentScanShowing=$event\"></lib-carousel>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2 mt-3\"\r\n (click)=\"onAddScan()\">{{'Add to zone' | translate}}</button>\r\n </div>\r\n <div class=\"mt-3\">\r\n <button type=\"submit\" class=\"btn btn-primary rounded-pill me-2\"\r\n [disabled]=\"fromPlan || !zoneForm.valid\">{{'Save' | translate}}</button>\r\n <button type=\"button\" (click)=\"onCancel()\" class=\"btn btn-outline-primary rounded-pill me-2\">\r\n {{'Cancel' | translate}}</button>\r\n </div>\r\n </form>\r\n </div>\r\n <div class=\"edit-plan\" *ngIf=\"fromPlan\">\r\n <lib-sweep-plan-selection style=\"width: 100%;\" [newZoneData]=\"newZoneDataFromEditor\" [spaceID]=\"spaceID\"\r\n [multipleFloors]=\"multipleFloors\" [inputZone]=\"zoneEdit\"\r\n (sweepsSelected)=\"onSelectedSweepsFromPlan($event)\"></lib-sweep-plan-selection>\r\n </div>\r\n</div>", styles: [".main-container{display:flex;flex-direction:column}.edit-plan{display:flex;margin:8px 0}.form-range{width:100%}h2{color:var(--smarterplan-primary);padding:0}.col-form-label{margin-bottom:1rem}.btn-outline-primary{margin-right:1rem}.new-type-input{margin-bottom:1rem}.new-type-text{margin-bottom:.5rem}.row{margin:0}p{margin:0;padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px)}button{min-width:80px}\n"], dependencies: [{ kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i4.CarouselComponent, selector: "lib-carousel", inputs: ["images"], outputs: ["currentScan"] }, { kind: "component", type: i5.SweepPlanSelectionComponent, selector: "lib-sweep-plan-selection", inputs: ["spaceID", "chosenScansOnPlan", "newZoneData", "occupiedSweeps", "unavailableSweeps", "editingAudioZone", "inputZone", "multipleFloors"], outputs: ["sweepsSelected"] }, { kind: "pipe", type: i6.TranslatePipe, name: "translate" }] });
307
+ }
308
+ export { AddZoneComponent };
309
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AddZoneComponent, decorators: [{
310
+ type: Component,
311
+ args: [{ selector: 'lib-add-zone', template: "<div class=\"main-container\" *ngIf=\"zoneForm\">\r\n <div class=\"col-7\">\r\n <form (ngSubmit)=\"onSubmitZone()\" [formGroup]=\"zoneForm\">\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Name' | translate}} *</label>\r\n <div class=\"col-sm-10\">\r\n <input type=\"text\" class=\"form-control\" required formControlName=\"name\">\r\n <!-- <div class=\"invalid-feedback\">\r\n {{'A name is required' | translate}}\r\n </div> -->\r\n </div>\r\n </div>\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'codeRef' | translate}}</label>\r\n <div class=\"col-sm-10\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"code_ref\">\r\n </div>\r\n </div>\r\n <div class=\"mb-3 row\" *ngIf=\"!isMuseumVisit && !zoneIsMatterportFloor\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Type of zone' | translate}}</label>\r\n <div class=\"col-sm-10\">\r\n <select class=\"form-control\" formControlName=\"layerID\">\r\n <option value=\"null\" selected disabled hidden> {{ zoneEdit && zoneEdit.layer ?\r\n zoneEdit.layer.name : 'Choose type'}}</option>\r\n <option *ngFor=\"let layer of layers\" [value]=\"layer.id\">\r\n {{ layer.name }}\r\n </option>\r\n </select>\r\n <p class=\"mt-1 new-type-text\">{{'or add new type of zone' | translate }}</p>\r\n <input type=\"text\" class=\"form-control new-type-input\" formControlName=\"newLayer\">\r\n <div *ngIf=\"newLayer.invalid && (newLayer.dirty || newLayer.touched)\" class=\"text-danger\">\r\n <div *ngIf=\"newLayer.errors?.['forbiddenName']\">\r\n {{'Layer exists already' | translate}}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <!--If Editing Zone possibility to assign it to museum itinerary-->\r\n <div class=\"mb-3 row\" *ngIf=\"zoneEdit && !zoneIsMatterportFloor\">\r\n <label class=\"col-sm-2 col-form-label\">{{ 'Museum Itinerary' | translate }}</label>\r\n <div class=\"col-sm-10\">\r\n <input class=\"checkbox-apply mt-3\" type=\"checkbox\" [(ngModel)]=\"isMuseumVisit\"\r\n [ngModelOptions]=\"{standalone: true}\">\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\" *ngIf=\"!zoneEdit || zoneEdit.isMultipleFloorZone\">\r\n <label class=\"col-sm-2 col-form-label\">{{ 'Multiple Floors' | translate }}</label>\r\n <div class=\"col-sm-10\">\r\n <input class=\"checkbox-apply mt-3\" type=\"checkbox\" [(ngModel)]=\"multipleFloors\"\r\n [disabled]=\"zoneEdit !== undefined && zoneEdit !== null\" (change)=\"onChangeMultipleFloors()\"\r\n [ngModelOptions]=\"{standalone: true}\">\r\n <div class='text-danger' *ngIf=\"zoneEdit\">\r\n {{'cannotChangeMultifloor' | translate}}\r\n </div>\r\n </div>\r\n\r\n </div>\r\n\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Surface' | translate}}</label>\r\n <div class=\"col-sm-10\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"surface\">\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\" *ngIf=\"!zoneIsMatterportFloor\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Parent zone' | translate}}</label>\r\n <div class=\"col-sm-10\">\r\n <input *ngIf=\"zoneEdit\" type=\"text\" class=\"form-control\" formControlName=\"parent\">\r\n <div class=\"text-danger\" *ngIf=\"zoneEdit\">\r\n {{'cannotChangeParent' | translate}}\r\n </div>\r\n <select *ngIf=\"!zoneEdit\" class=\"form-control\" formControlName=\"parentID\">\r\n <option *ngFor=\"let zone of parentZones\" [ngValue]=\"zone.id\">\r\n {{ zone.name }}\r\n </option>\r\n </select>\r\n\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\" style=\"max-height: 200px; overflow: auto;\" *ngIf=\"!zoneIsMatterportFloor\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Scan Points' | translate}}</label>\r\n <!-- <p class=\"col-sm-2\" *ngIf=\"zoneEdit\">{{ zoneEdit.sweepIDs.length }} scans</p> -->\r\n <p class=\"col\" *ngIf=\"chosenScansOnPlan.length === 0 && chosenScans.length === 0\">\r\n {{'No scan points chosen' | translate}}</p>\r\n <div class=\"col-sm-5\" *ngIf=\"chosenScansOnPlan && chosenScansOnPlan.length > 0\">\r\n <p>{{ chosenScansOnPlan.length }} {{'scan points chosen' | translate}}</p>\r\n <!-- <div *ngFor=\"let scan of chosenScansOnPlan\">\r\n <div class=\"row\">\r\n <p class=\"me-2\">{{ scan | slice:0:8 }}</p>\r\n <div (click)=\"onRemoveScanPlan(scan)\" [style.cursor]=\"'pointer'\">\r\n <span class=\"iconify\" data-icon=\"mdi:trash-can-outline\"></span>\r\n </div>\r\n </div>\r\n </div> -->\r\n </div>\r\n <div class=\"col-sm-5\" *ngIf=\"carouselIsVisible && chosenScans && chosenScans.length > 0\">\r\n <p>{{ chosenScans.length }} {{'scan points chosen' | translate}}</p>\r\n <div *ngFor=\"let scan of chosenScans\">\r\n <div class=\"row\">\r\n <p class=\"me-2\">{{ images360[scan].filename }}</p>\r\n <div (click)=\"onRemoveScanImage(scan)\" [style.cursor]=\"'pointer'\">\r\n <span class=\"iconify\" data-icon=\"mdi:trash-can-outline\"></span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"row mb-3 mt-3\" *ngIf=\"!zoneIsMatterportFloor\">\r\n <div class=\"col\">\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2\"\r\n (click)=\"togglePlan()\">{{'Choose scan points on plan' |\r\n translate}}</button>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"toggleCarousel()\"\r\n [disabled]=\"fromPlan || !images360 || images360.length === 0\">\r\n {{'Choose scan points from gallery' | translate}}</button>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"onAddAll()\"\r\n [disabled]=\"fromPlan || !images360 || images360.length === 0\">\r\n {{'add-all-scans' | translate}}</button>\r\n </div>\r\n </div>\r\n\r\n <!-- <div class=\"mb-3 row\">\r\n <label class=\"col-sm-3 col-form-label\">{{'No visible scan points' | translate}}</label>\r\n <div class=\"col-sm-3\">\r\n <input class=\"checkbox-apply mt-3\" type=\"checkbox\" [(ngModel)]=\"noScanPoints\"\r\n [ngModelOptions]=\"{standalone: true}\">\r\n </div>\r\n </div> -->\r\n\r\n <div *ngIf=\"carouselIsVisible\" class=\"mb-2\">\r\n <lib-carousel *ngIf=\"images360 && images360.length > 0\" [images]=\"images360\"\r\n (currentScan)=\"currentScanShowing=$event\"></lib-carousel>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2 mt-3\"\r\n (click)=\"onAddScan()\">{{'Add to zone' | translate}}</button>\r\n </div>\r\n <div class=\"mt-3\">\r\n <button type=\"submit\" class=\"btn btn-primary rounded-pill me-2\"\r\n [disabled]=\"fromPlan || !zoneForm.valid\">{{'Save' | translate}}</button>\r\n <button type=\"button\" (click)=\"onCancel()\" class=\"btn btn-outline-primary rounded-pill me-2\">\r\n {{'Cancel' | translate}}</button>\r\n </div>\r\n </form>\r\n </div>\r\n <div class=\"edit-plan\" *ngIf=\"fromPlan\">\r\n <lib-sweep-plan-selection style=\"width: 100%;\" [newZoneData]=\"newZoneDataFromEditor\" [spaceID]=\"spaceID\"\r\n [multipleFloors]=\"multipleFloors\" [inputZone]=\"zoneEdit\"\r\n (sweepsSelected)=\"onSelectedSweepsFromPlan($event)\"></lib-sweep-plan-selection>\r\n </div>\r\n</div>", styles: [".main-container{display:flex;flex-direction:column}.edit-plan{display:flex;margin:8px 0}.form-range{width:100%}h2{color:var(--smarterplan-primary);padding:0}.col-form-label{margin-bottom:1rem}.btn-outline-primary{margin-right:1rem}.new-type-input{margin-bottom:1rem}.new-type-text{margin-bottom:.5rem}.row{margin:0}p{margin:0;padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px)}button{min-width:80px}\n"] }]
312
+ }], ctorParameters: function () { return [{ type: i1.UntypedFormBuilder }, { type: i2.ZoneService }, { type: i2.LayerService }, { type: i2.BaseUserService }, { type: i2.NavigationService }]; }, propDecorators: { zoneEdit: [{
313
+ type: Input
314
+ }], spaceID: [{
315
+ type: Input
316
+ }], images360: [{
317
+ type: Input
318
+ }], navigationIDs: [{
319
+ type: Input
320
+ }], zones: [{
321
+ type: Input
322
+ }], newZoneDataFromEditor: [{
323
+ type: Input
324
+ }], updatedZone: [{
325
+ type: Output
326
+ }], chosenPlan: [{
327
+ type: Input
328
+ }], isMuseumVisit: [{
329
+ type: Input
330
+ }], defaultZone: [{
331
+ type: Input
332
+ }] } });
333
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWRkLXpvbmUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWxvY2F0aW9ucy9zcmMvbGliL2NvbXBvbmVudHMvem9uZXMvYWRkLXpvbmUvYWRkLXpvbmUuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWxvY2F0aW9ucy9zcmMvbGliL2NvbXBvbmVudHMvem9uZXMvYWRkLXpvbmUvYWRkLXpvbmUuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFVLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMvRSxPQUFPLEVBR0wsVUFBVSxHQUlYLE1BQU0sZ0JBQWdCLENBQUM7Ozs7Ozs7O0FBVXhCLE1BS2EsZ0JBQWdCO0lBZ0RqQjtJQUNBO0lBQ0E7SUFDQTtJQUNBO0lBbkRELFFBQVEsQ0FBTztJQUVmLE9BQU8sQ0FBUztJQUVoQixTQUFTLENBQXVDO0lBRWhELGFBQWEsQ0FBVztJQUV4QixLQUFLLENBQVM7SUFFZCxxQkFBcUIsQ0FBTTtJQUUxQixXQUFXLEdBQUcsSUFBSSxZQUFZLEVBQU8sQ0FBQztJQUV2QyxVQUFVLENBQU87SUFFakIsYUFBYSxHQUFZLEtBQUssQ0FBQztJQUUvQixXQUFXLENBQU87SUFFM0IsV0FBVyxHQUFXLEVBQUUsQ0FBQztJQUV6QixpQkFBaUIsR0FBRyxLQUFLLENBQUM7SUFFMUIsUUFBUSxDQUFtQjtJQUUzQixXQUFXLEdBQUcsS0FBSyxDQUFDO0lBRXBCLGtCQUFrQixDQUFTO0lBRTNCLFdBQVcsR0FBYSxFQUFFLENBQUM7SUFFM0IsTUFBTSxDQUFVO0lBRWhCLFFBQVEsR0FBWSxLQUFLLENBQUM7SUFFMUIsaUJBQWlCLEdBQWEsRUFBRSxDQUFDO0lBRWpDLFlB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LE9BQU8sQ0FBQyxLQUFLLEVBQUU7Z0JBQ2xCLE9BQU8sSUFBSSxDQUFDO2FBQ2I7WUFDRCxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsTUFBTTtpQkFDMUIsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO2lCQUNoQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1lBQ3pDLE9BQU8sU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLGFBQWEsRUFBRSxFQUFFLEtBQUssRUFBRSxPQUFPLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1FBQ3hFLENBQUMsQ0FBQztJQUNKLENBQUM7d0dBaFdVLGdCQUFnQjs0RkFBaEIsZ0JBQWdCLGlXQ3ZCN0IsaXZTQXdKTTs7U0RqSU8sZ0JBQWdCOzRGQUFoQixnQkFBZ0I7a0JBTDVCLFNBQVM7K0JBQ0UsY0FBYzs0TkFLZixRQUFRO3NCQUFoQixLQUFLO2dCQUVHLE9BQU87c0JBQWYsS0FBSztnQkFFRyxTQUFTO3NCQUFqQixLQUFLO2dCQUVHLGFBQWE7c0JBQXJCLEtBQUs7Z0JBRUcsS0FBSztzQkFBYixLQUFLO2dCQUVHLHFCQUFxQjtzQkFBN0IsS0FBSztnQkFFSSxXQUFXO3NCQUFwQixNQUFNO2dCQUVFLFVBQVU7c0JBQWxCLEtBQUs7Z0JBRUcsYUFBYTtzQkFBckIsS0FBSztnQkFFRyxXQUFXO3NCQUFuQixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBFdmVudEVtaXR0ZXIsIElucHV0LCBPbkluaXQsIE91dHB1dCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQge1xyXG4gIFVudHlwZWRGb3JtR3JvdXAsXHJcbiAgVW50eXBlZEZvcm1CdWlsZGVyLFxyXG4gIFZhbGlkYXRvcnMsXHJcbiAgQWJzdHJhY3RDb250cm9sLFxyXG4gIFZhbGlkYXRvckZuLFxyXG4gIFZhbGlkYXRpb25FcnJvcnMsXHJcbn0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xyXG5pbXBvcnQge1xyXG4gIFpvbmUsXHJcbiAgUGxhbixcclxuICBMYXllcixcclxuICBab25lU2VydmljZSxcclxuICBMYXllclNlcnZpY2UsXHJcbiAgQmFzZVVzZXJTZXJ2aWNlLFxyXG4gIE5hdmlnYXRpb25TZXJ2aWNlLFxyXG59IGZyb20gJ0BzbWFydGVycGxhbi9uZ3gtc21hcnRlcnBsYW4tY29yZSc7XHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnbGliLWFkZC16b25lJyxcclxuICB0ZW1wbGF0ZVVybDogJy4vYWRkLXpvbmUuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsczogWycuL2FkZC16b25lLmNvbXBvbmVudC5zY3NzJ10sXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBBZGRab25lQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcclxuICBASW5wdXQoKSB6b25lRWRpdDogWm9uZTtcclxuXHJcbiAgQElucHV0KCkgc3BhY2VJRDogc3RyaW5nO1xyXG5cclxuICBASW5wdXQoKSBpbWFnZXMzNjA6IHsgcGF0aDogc3RyaW5nOyBmaWxlbmFtZTogc3RyaW5nIH1bXTtcclxuXHJcbiAgQElucHV0KCkgbmF2aWdhdGlvbklEczogc3RyaW5nW107XHJcblxyXG4gIEBJbnB1dCgpIHpvbmVzOiBab25lW107XHJcblxyXG4gIEBJbnB1dCgpIG5ld1pvbmVEYXRhRnJvbUVkaXRvcjogYW55O1xyXG5cclxuICBAT3V0cHV0KCkgdXBkYXRlZFpvbmUgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcclxuXHJcbiAgQElucHV0KCkgY2hvc2VuUGxhbjogUGxhbjtcclxuXHJcbiAgQElucHV0KCkgaXNNdXNldW1WaXNpdDogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICBASW5wdXQoKSBkZWZhdWx0Wm9uZTogWm9uZTtcclxuXHJcbiAgcGFyZW50Wm9uZXM6IFpvbmVbXSA9IFtdO1xyXG5cclxuICBjYXJvdXNlbElzVmlzaWJsZSA9IGZhbHNlO1xyXG5cclxuICB6b25lRm9ybTogVW50eXBlZEZvcm1Hcm91cDtcclxuXHJcbiAgaXNTdWJtaXR0ZWQgPSBmYWxzZTtcclxuXHJcbiAgY3VycmVudFNjYW5TaG93aW5nOiBudW1iZXI7XHJcblxyXG4gIGNob3NlblNjYW5zOiBudW1iZXJbXSA9IFtdO1xyXG5cclxuICBsYXllcnM6IExheWVyW107XHJcblxyXG4gIGZyb21QbGFuOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gIGNob3NlblNjYW5zT25QbGFuOiBzdHJpbmdbXSA9IFtdO1xyXG5cclxuICBjdXJyZW50T3JnSWQ6IHN0cmluZztcclxuXHJcbiAgem9uZUluaXRpYWxOYXZDb3VudCA9IDA7XHJcblxyXG4gIHpvbmVJc01hdHRlcnBvcnRGbG9vciA9IGZhbHNlO1xyXG5cclxuICBtdWx0aXBsZUZsb29ycyA9IGZhbHNlO1xyXG5cclxuICBjb25zdHJ1Y3RvcihcclxuICAgIHByaXZhdGUgZmI6IFVudHlwZWRGb3JtQnVpbGRlcixcclxuICAgIHByaXZhdGUgem9uZVNlcnZpY2U6IFpvbmVTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSBsYXllclNlcnZpY2U6IExheWVyU2VydmljZSxcclxuICAgIHByaXZhdGUgdXNlclNlcnZpY2U6IEJhc2VVc2VyU2VydmljZSxcclxuICAgIHByaXZhdGUgbmF2aWdhdGlvblNlcnZpY2U6IE5hdmlnYXRpb25TZXJ2aWNlXHJcbiAgKSB7IH1cclxuXHJcbiAgYXN5bmMgbmdPbkluaXQoKSB7XHJcbiAgICB0aGlzLnBhcmVudFpvbmVzID0gdGhpcy56b25lcy5maWx0ZXIoXHJcbiAgICAgICh6b25lKSA9PiB6b25lLmxheWVyICYmIHpvbmUubGF5ZXIubmFtZSA9PT0gJ0ZMT09SJ1xyXG4gICAgKTtcclxuICAgIGlmICghdGhpcy5kZWZhdWx0Wm9uZSkge1xyXG4gICAgICB0aGlzLmRlZmF1bHRab25lID0gdGhpcy5nZXREZWZhdWx0Wm9uZSgpO1xyXG4gICAgfVxyXG4gICAgdGhpcy5wYXJlbnRab25lcy51bnNoaWZ0KHRoaXMuZGVmYXVsdFpvbmUpO1xyXG4gICAgYXdhaXQgdGhpcy51cGRhdGVMYXllcnMoKTtcclxuICAgIHRoaXMuaW5pdFpvbmVGb3JtKCk7XHJcbiAgfVxyXG5cclxuICBhc3luYyB1cGRhdGVMYXllcnMoKSB7XHJcbiAgICB0aGlzLmN1cnJlbnRPcmdJZCA9IHRoaXMudXNlclNlcnZpY2UuY3VycmVudE9yZ2FuaXNhdGlvbih0aGlzLnNwYWNlSUQpLmlkO1xyXG4gICAgY29uc3QgbGF5ZXJzID0gYXdhaXQgdGhpcy5sYXllclNlcnZpY2UuZ2V0TGF5ZXJGb3JPcmdhbmlzYXRpb24oXHJcbiAgICAgIHRoaXMuY3VycmVudE9yZ0lkXHJcbiAgICApO1xyXG4gICAgLy8gZmlsdGVyIG91dCBsYXllcnMgY3JlYXRlZCBieSB0aGUgc3lzdGVtXHJcbiAgICB0aGlzLmxheWVycyA9IGxheWVycy5maWx0ZXIoXHJcbiAgICAgIChsKSA9PiBsLm5hbWUgIT09ICdCVUlMRElORycgJiYgbC5uYW1lICE9PSAnRkxPT1InXHJcbiAgICApO1xyXG4gIH1cclxuXHJcbiAgYXN5bmMgaW5pdFpvbmVGb3JtKCkge1xyXG4gICAgaWYgKHRoaXMuem9uZUVkaXQpIHtcclxuICAgICAgaWYgKHRoaXMuem9uZUVkaXQubWV0YWRhdGEpIHtcclxuICAgICAgICBjb25zdCBtZXRhZGF0YSA9IEpTT04ucGFyc2UodGhpcy56b25lRWRpdC5tZXRhZGF0YSk7XHJcbiAgICAgICAgdGhpcy56b25lSXNNYXR0ZXJwb3J0Rmxvb3IgPSBtZXRhZGF0YS5oYXNPd25Qcm9wZXJ0eShcclxuICAgICAgICAgICdtYXR0ZXJwb3J0Rmxvb3JTZXF1ZW5jZSdcclxuICAgICAgICApO1xyXG4gICAgICB9XHJcbiAgICAgIGNvbnN0IGlzVmlydHVhbCA9IHRoaXMuem9uZVNlcnZpY2Uuem9uZUlzVmlydHVhbCh0aGlzLnpvbmVFZGl0KTtcclxuICAgICAgaWYgKCFpc1ZpcnR1YWwpIHtcclxuICAgICAgICBhd2FpdCB0aGlzLmxvYWROYXZpZ2F0aW9ucygpO1xyXG4gICAgICB9XHJcbiAgICAgIHRoaXMuaXNNdXNldW1WaXNpdCA9IHRoaXMuem9uZUVkaXQuaXNNdXNldW1WaXNpdFpvbmUgPT09IHRydWU7XHJcbiAgICAgIHRoaXMubXVsdGlwbGVGbG9vcnMgPSB0aGlzLnpvbmVFZGl0LmlzTXVsdGlwbGVGbG9vclpvbmUgPT09IHRydWU7XHJcbiAgICAgIHRoaXMuem9uZUZvcm0gPSB0aGlzLmZiLmdyb3VwKHtcclxuICAgICAgICBpZDogdGhpcy56b25lRWRpdC5pZCxcclxuICAgICAgICBuYW1lOiBbdGhpcy56b25lRWRpdC5uYW1lLCBbVmFsaWRhdG9ycy5yZXF1aXJlZF1dLFxyXG4gICAgICAgIGNvZGVfcmVmOiB0aGlzLnpvbmVFZGl0LmNvZGVfcmVmID8gdGhpcy56b25lRWRpdC5jb2RlX3JlZiA6IG51bGwsXHJcbiAgICAgICAgbGF5ZXJJRDogdGhpcy56b25lRWRpdC5sYXllciA/IHRoaXMuem9uZUVkaXQubGF5ZXIuaWQgOiBudWxsLFxyXG4gICAgICAgIHN1cmZhY2U6IHRoaXMuem9uZUVkaXQuc3VyZmFjZSA/IHRoaXMuem9uZUVkaXQuc3VyZmFjZSA6IDAsXHJcbiAgICAgICAgcGFyZW50SUQ6IHRoaXMuem9uZUVkaXQucGFyZW50SUQsXHJcbiAgICAgICAgcGFyZW50OiB7IHZhbHVlOiB0aGlzLnpvbmVFZGl0LnBhcmVudC5uYW1lLCBkaXNhYmxlZDogdHJ1ZSB9LFxyXG4gICAgICAgIG5ld0xheWVyOiBbbnVsbCwgW3RoaXMubGF5ZXJOYW1lVmFsaWRhdG9yKCldXSxcclxuICAgICAgICBpc011c2V1bVZpc2l0Wm9uZTogdGhpcy5pc011c2V1bVZpc2l0LFxyXG4gICAgICAgIHN0YXJ0U3dlZXBJRDogdGhpcy56b25lRWRpdC5zdGFydFN3ZWVwSUQsXHJcbiAgICAgIH0pO1xyXG4gICAgICB0aGlzLm9uQ2hhbmdlTXVsdGlwbGVGbG9vcnMoKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuem9uZUZvcm0gPSB0aGlzLmZiLmdyb3VwKHtcclxuICAgICAgICBuYW1lOiBbXHJcbiAgICAgICAgICB0aGlzLm5ld1pvbmVEYXRhRnJvbUVkaXRvciA/IHRoaXMubmV3Wm9uZURhdGFGcm9tRWRpdG9yLm5hbWUgOiAnJyxcclxuICAgICAgICAgIFtWYWxpZGF0b3JzLnJlcXVpcmVkXSxcclxuICAgICAgICBdLFxyXG4gICAgICAgIGNvZGVfcmVmOiBudWxsLFxyXG4gICAgICAgIGxheWVySUQ6IG51bGwsXHJcbiAgICAgICAgc3VyZmFjZTogMCxcclxuICAgICAgICBwYXJlbnRJRDogdGhpcy5kZWZhdWx0Wm9uZS5pZCxcclxuICAgICAgICBuZXdMYXllcjogW251bGwsIFt0aGlzLmxheWVyTmFtZVZhbGlkYXRvcigpXV0sXHJcbiAgICAgICAgaXNNdXNldW1WaXNpdFpvbmU6IHRoaXMuaXNNdXNldW1WaXNpdCxcclxuICAgICAgICBzdGFydFN3ZWVwSUQ6IG51bGwsXHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgYXN5bmMgb25TdWJtaXRab25lKCkge1xyXG4gICAgdGhpcy5pc1N1Ym1pdHRlZCA9IHRydWU7XHJcbiAgICBpZiAoIXRoaXMuem9uZUZvcm0udmFsaWQpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgY29uc3QgZm9ybVZhbHVlID0gdGhpcy56b25lRm9ybS5nZXRSYXdWYWx1ZSgpOyAvL2JlY2F1c2Ugd2UgbmVlZCB2YWx1ZXMgb2YgZGlzYWJsZXMgY29udHJvbHMgYXMgd2VsbFxyXG4gICAgaWYgKGZvcm1WYWx1ZS5uZXdMYXllcikge1xyXG4gICAgICBhd2FpdCB0aGlzLmNyZWF0ZUxheWVyKGZvcm1WYWx1ZS5uZXdMYXllcikudGhlbigobGF5ZXIpID0+IHtcclxuICAgICAgICBmb3JtVmFsdWUubGF5ZXJJRCA9IGxheWVyLmlkO1xyXG4gICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCB6b25lSW5wdXQgPSB7XHJcbiAgICAgIG5hbWU6IGZvcm1WYWx1ZS5uYW1lLFxyXG4gICAgICBzdXJmYWNlOiBNYXRoLnJvdW5kKGZvcm1WYWx1ZS5zdXJmYWNlICogMTAwKSAvIDEwMCxcclxuICAgICAgc3BhY2VJRDogdGhpcy5zcGFjZUlELFxyXG4gICAgICBsYXllcklEOiBmb3JtVmFsdWUubGF5ZXJJRCxcclxuICAgICAgcGFyZW50SUQ6IGZvcm1WYWx1ZS5wYXJlbnRJRCxcclxuICAgICAgaXNNdXNldW1WaXNpdFpvbmU6IHRoaXMuaXNNdXNldW1WaXNpdCxcclxuICAgICAgaXNNdWx0aXBsZUZsb29yWm9uZTogdGhpcy5tdWx0aXBsZUZsb29ycyxcclxuICAgICAgc3dlZXBJRHM6IFtdLFxyXG4gICAgICBzdGFydFN3ZWVwSUQ6IGZvcm1WYWx1ZS5zdGFydFN3ZWVwSUQsXHJcbiAgICB9IGFzIFpvbmU7XHJcblxyXG4gICAgaWYgKGZvcm1WYWx1ZS5jb2RlX3JlZikge1xyXG4gICAgICB6b25lSW5wdXQuY29kZV9yZWYgPSBmb3JtVmFsdWUuY29kZV9yZWY7XHJcbiAgICB9XHJcblxyXG4gICAgdHJ5IHtcclxuICAgICAgdGhpcy56b25lRm9ybSA9IG51bGw7XHJcbiAgICAgIHRoaXMuaXNTdWJtaXR0ZWQgPSBmYWxzZTtcclxuICAgICAgaWYgKHRoaXMuem9uZUVkaXQpIHtcclxuICAgICAgICBjb25zdCB6b25lVXBkYXRlID0gem9uZUlucHV0O1xyXG4gICAgICAgIHpvbmVVcGRhdGUuc3dlZXBJRHMgPSB0aGlzLnpvbmVFZGl0LnN3ZWVwSURzO1xyXG4gICAgICAgIHpvbmVVcGRhdGUuaWQgPSBmb3JtVmFsdWUuaWQ7XHJcbiAgICAgICAgYXdhaXQgdGhpcy5zZXRTd2VlcHNBbmROb2RlRm9yWm9uZUlucHV0KHpvbmVVcGRhdGUpO1xyXG4gICAgICAgIGF3YWl0IHRoaXMuem9uZVNlcnZpY2UudXBkYXRlWm9uZSh6b25lVXBkYXRlKTtcclxuICAgICAgICB0aGlzLnpvbmVFZGl0ID0gbnVsbDtcclxuICAgICAgICB0aGlzLnVwZGF0ZWRab25lLmVtaXQoem9uZVVwZGF0ZS5pZCk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgYXdhaXQgdGhpcy5zZXRTd2VlcHNBbmROb2RlRm9yWm9uZUlucHV0KHpvbmVJbnB1dCk7XHJcbiAgICAgICAgaWYgKCF6b25lSW5wdXQucGFyZW50SUQpIHtcclxuICAgICAgICAgIC8vIHNldCBidWlsZGluZyBhcyBwYXJlbnRcclxuICAgICAgICAgIHpvbmVJbnB1dC5wYXJlbnRJRCA9IHRoaXMuZGVmYXVsdFpvbmUuaWQ7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGF3YWl0IHRoaXMuem9uZVNlcnZpY2UuY3JlYXRlKHpvbmVJbnB1dCkudGhlbigoem9uZUNyZWF0ZWQpID0+IHtcclxuICAgICAgICAgIHRoaXMudXBkYXRlZFpvbmUuZW1pdCh6b25lQ3JlYXRlZC5pZCk7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH1cclxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XHJcbiAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgb25DYW5jZWwoKSB7XHJcbiAgICB0aGlzLmlzU3VibWl0dGVkID0gZmFsc2U7XHJcbiAgICB0aGlzLnpvbmVGb3JtID0gbnVsbDtcclxuICAgIHRoaXMuY2hvc2VuU2NhbnNPblBsYW4gPSBbXTtcclxuICAgIHRoaXMuY2hvc2VuU2NhbnMgPSBbXTtcclxuICAgIHRoaXMudXBkYXRlZFpvbmUuZW1pdChmYWxzZSk7XHJcbiAgfVxyXG5cclxuICBnZXQgbmFtZSgpOiBBYnN0cmFjdENvbnRyb2wge1xyXG4gICAgcmV0dXJuIHRoaXMuem9uZUZvcm0uZ2V0KCduYW1lJyk7XHJcbiAgfVxyXG5cclxuICBnZXQgbmV3TGF5ZXIoKTogQWJzdHJhY3RDb250cm9sIHtcclxuICAgIHJldHVybiB0aGlzLnpvbmVGb3JtLmdldCgnbmV3TGF5ZXInKTtcclxuICB9XHJcblxyXG4gIHRvZ2dsZUNhcm91c2VsKCkge1xyXG4gICAgdGhpcy5jYXJvdXNlbElzVmlzaWJsZSA9IHRydWU7XHJcbiAgICB0aGlzLmNob3NlblNjYW5zT25QbGFuID0gW107XHJcbiAgfVxyXG5cclxuICB0b2dnbGVQbGFuKCkge1xyXG4gICAgdGhpcy5mcm9tUGxhbiA9IHRydWU7XHJcbiAgICB0aGlzLmNob3NlblNjYW5zID0gW107XHJcbiAgfVxyXG5cclxuICBvbkFkZFNjYW4oKSB7XHJcbiAgICBpZiAoIXRoaXMuY2hvc2VuU2NhbnMuaW5jbHVkZXModGhpcy5jdXJyZW50U2NhblNob3dpbmcpKSB7XHJcbiAgICAgIC8vIGNvbnNvbGUubG9nKFwiYWRkaW5nIHNjYW5cIiwgdGhpcy5jdXJyZW50U2NhblNob3dpbmcpO1xyXG4gICAgICB0aGlzLmNob3NlblNjYW5zLnB1c2godGhpcy5jdXJyZW50U2NhblNob3dpbmcpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgYWxlcnQoJ1NjYW4gYWxyZWFkeSBhZGRlZCEnKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIG9uUmVtb3ZlU2NhbkltYWdlKHNjYW46IGFueSkge1xyXG4gICAgY29uc3QgaW5kZXggPSB0aGlzLmNob3NlblNjYW5zLmluZGV4T2Yoc2Nhbik7XHJcbiAgICB0aGlzLmNob3NlblNjYW5zLnNwbGljZShpbmRleCwgMSk7XHJcbiAgfVxyXG5cclxuICBvblJlbW92ZVNjYW5QbGFuKHNjYW46IGFueSkge1xyXG4gICAgY29uc3QgaW5kZXggPSB0aGlzLmNob3NlblNjYW5zT25QbGFuLmluZGV4T2Yoc2Nhbik7XHJcbiAgICB0aGlzLmNob3NlblNjYW5zT25QbGFuLnNwbGljZShpbmRleCwgMSk7XHJcbiAgfVxyXG5cclxuICBhc3luYyBzZXRTd2VlcHNBbmROb2RlRm9yWm9uZUlucHV0KHpvbmVJbnB1dDogWm9uZSkge1xyXG4gICAgaWYgKFxyXG4gICAgICB0aGlzLmNob3NlblNjYW5zLmxlbmd0aCA+IDAgJiZcclxuICAgICAgdGhpcy5jaG9zZW5TY2Fucy5sZW5ndGggIT09IHRoaXMuem9uZUluaXRpYWxOYXZDb3VudCAmJlxyXG4gICAgICAhdGhpcy5mcm9tUGxhblxyXG4gICAgKSB7XHJcbiAgICAgIC8vIGlmIHdlIGNob3NlIHNjYW5zIGZyb20gdGhlIGNhcm91c2VsXHJcbiAgICAgIGNvbnN0IHN3ZWVwSURzOiBzdHJpbmdbXSA9IFtdO1xyXG4gICAgICB0aGlzLmNob3NlblNjYW5zLm1hcChhc3luYyAoc2NhbikgPT4ge1xyXG4gICAgICAgIGNvbnN0IGltYWdlVXVpZCA9IHRoaXMuaW1hZ2VzMzYwW3NjYW5dLmZpbGVuYW1lLnNwbGl0KCdfJylbMF07XHJcbiAgICAgICAgY29uc3Qgc3dlZXBJRCA9IHRoaXMubmF2aWdhdGlvbklEcy5maW5kKChuYXYpID0+IHtcclxuICAgICAgICAgIHJldHVybiBuYXYuaW5jbHVkZXMoaW1hZ2VVdWlkKTtcclxuICAgICAgICB9KTtcclxuICAgICAgICBpZiAoc3dlZXBJRCkge1xyXG4gICAgICAgICAgc3dlZXBJRHMucHVzaChzd2VlcElEKTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gICAgICB6b25lSW5wdXQuc3dlZXBJRHMgPSBzd2VlcElEcztcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIC8vIHdlIGFyZSBub3QgY29taW5nIGZyb20gZ2FsbGVyeSBjaG9pY2VcclxuICAgICAgaWYgKHRoaXMuY2hvc2VuU2NhbnNPblBsYW4ubGVuZ3RoID4gMCkge1xyXG4gICAgICAgIHpvbmVJbnB1dC5zd2VlcElEcyA9IHRoaXMuY2hvc2VuU2NhbnNPblBsYW47XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBpZiAoem9uZUlucHV0LnN3ZWVwSURzICYmIHpvbmVJbnB1dC5zd2VlcElEcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgIGNvbnN0IG5hdkZvclN3ZWVwID1cclxuICAgICAgICBhd2FpdCB0aGlzLm5hdmlnYXRpb25TZXJ2aWNlLmdldE5hdmlnYXRpb25zRm9yTWF0dGVycG9ydElERm9yU3BhY2UoXHJcbiAgICAgICAgICB6b25lSW5wdXQuc3dlZXBJRHNbMF0sXHJcbiAgICAgICAgICB0aGlzLnNwYWNlSURcclxuICAgICAgICApO1xyXG4gICAgICB6b25lSW5wdXQubm9kZUlEcyA9IFtuYXZGb3JTd2VlcFswXS5ub2RlSURdO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgYXN5bmMgY3JlYXRlTGF5ZXIobmFtZTogc3RyaW5nKTogUHJvbWlzZTxMYXllcj4ge1xyXG4gICAgcmV0dXJuIHRoaXMubGF5ZXJTZXJ2aWNlLmNyZWF0ZUxheWVyRm9yT3JnYW5pc2F0aW9uKFxyXG4gICAgICBuYW1lLFxyXG4gICAgICB0aGlzLmN1cnJlbnRPcmdJZFxyXG4gICAgKTtcclxuICB9XHJcblxyXG4gIGFzeW5jIGxvYWROYXZpZ2F0aW9ucygpOiBQcm9taXNlPGFueT4ge1xyXG4gICAgaWYgKHRoaXMuem9uZUVkaXQuc3dlZXBJRHMubGVuZ3RoID4gMCkge1xyXG4gICAgICB0aGlzLnpvbmVJbml0aWFsTmF2Q291bnQgPSB0aGlzLnpvbmVFZGl0LnN3ZWVwSURzLmxlbmd0aDtcclxuICAgICAgY29uc3QgbmF2TGlzdDogbnVtYmVyW10gPSBbXTtcclxuICAgICAgY29uc3Qgc2NhbnNab25lRWRpdDogc3RyaW5nW10gPSBbXTtcclxuICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXHJcbiAgICAgICAgdGhpcy56b25lRWRpdC5zd2VlcElEcy5tYXAoYXN5bmMgKHN3ZWVwSUQ6IHN0cmluZykgPT4ge1xyXG4gICAgICAgICAgc2NhbnNab25lRWRpdC5wdXNoKHN3ZWVwSUQpO1xyXG4gICAgICAgICAgY29uc3QgaW5kZXggPSB0aGlzLmltYWdlczM2MC5maW5kSW5kZXgoKGltKSA9PiB7XHJcbiAgICAgICAgICAgIHJldHVybiBpbS5maWxlbmFtZS5pbmNsdWRlcyhzd2VlcElELnNsaWNlKDAsIDgpKTtcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgaWYgKGluZGV4ICE9PSAtMSkge1xyXG4gICAgICAgICAgICBuYXZMaXN0LnB1c2goaW5kZXgpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0pXHJcbiAgICAgICk7XHJcbiAgICAgIHRoaXMuY2hvc2VuU2NhbnMgPSBuYXZMaXN0O1xyXG4gICAgICB0aGlzLmNob3NlblNjYW5zT25QbGFuID0gc2NhbnNab25lRWRpdDtcclxuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xyXG4gIH1cclxuXHJcbiAgLy8gaW5pUGxhbkZvckRyYXcoKSB7XHJcbiAgLy8gICAgIHRoaXMudG9nZ2xlUGxhbigpO1xyXG4gIC8vICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAvLyAgICAgICAgIHRoaXMub25QbGFuQ2xpY2soKTtcclxuICAvLyAgICAgfSwgNTAwKTtcclxuICAvLyB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEFkZHMgYWxsIHN3ZWVwcyBvZiB0aGUgc3BhY2VcclxuICAgKi9cclxuICBvbkFkZEFsbCgpIHtcclxuICAgIGNvbnN0IGRlZmF1bHRab25lID0gdGhpcy5nZXREZWZhdWx0Wm9uZSgpO1xyXG4gICAgaWYgKGRlZmF1bHRab25lKSB7XHJcbiAgICAgIHRoaXMuY2hvc2VuU2NhbnNPblBsYW4gPSBkZWZhdWx0Wm9uZS5zd2VlcElEcztcclxuICAgICAgdGhpcy56b25lRm9ybS5nZXQoJ3BhcmVudElEJykuc2V0VmFsdWUoZGVmYXVsdFpvbmUuaWQpO1xyXG4gICAgICB0aGlzLnpvbmVGb3JtLmdldCgncGFyZW50SUQnKS5kaXNhYmxlKCk7XHJcbiAgICAgIHRoaXMubXVsdGlwbGVGbG9vcnMgPSB0cnVlO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgZ2V0RGVmYXVsdFpvbmUoKTogWm9uZSB7XHJcbiAgICByZXR1cm4gdGhpcy56b25lcy5maW5kKFxyXG4gICAgICAoem9uZSkgPT5cclxuICAgICAgICB6b25lLmxheWVyICYmXHJcbiAgICAgICAgem9uZS5sYXllci5uYW1lID09PSAnQlVJTERJTkcnICYmXHJcbiAgICAgICAgem9uZS5zd2VlcElEcyAmJlxyXG4gICAgICAgIHpvbmUuc3dlZXBJRHMubGVuZ3RoID4gMFxyXG4gICAgKTtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogTXVsdGlwbGUgZmxvb3JzXHJcbiAgICovXHJcbiAgb25DaGFuZ2VNdWx0aXBsZUZsb29ycygpIHtcclxuICAgIGlmICh0aGlzLm11bHRpcGxlRmxvb3JzKSB7XHJcbiAgICAgIGNvbnN0IGRlZmF1bHRab25lID0gdGhpcy5nZXREZWZhdWx0Wm9uZSgpO1xyXG4gICAgICBpZiAoZGVmYXVsdFpvbmUpIHtcclxuICAgICAgICB0aGlzLnpvbmVGb3JtLmdldCgncGFyZW50SUQnKS5zZXRWYWx1ZShkZWZhdWx0Wm9uZS5pZCk7XHJcbiAgICAgICAgdGhpcy56b25lRm9ybS5nZXQoJ3BhcmVudElEJykuZGlzYWJsZSgpO1xyXG4gICAgICB9XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLnpvbmVGb3JtLmdldCgncGFyZW50SUQnKS5lbmFibGUoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIG9uU2VsZWN0ZWRTd2VlcHNGcm9tUGxhbihyZXN1bHQ6IHsgc3dlZXBzOiBzdHJpbmdbXTsgc3RhcnRTd2VlcElEOiBzdHJpbmcgfSkge1xyXG4gICAgaWYgKHJlc3VsdCkge1xyXG4gICAgICBpZiAocmVzdWx0LnN3ZWVwcykge1xyXG4gICAgICAgIHRoaXMuY2hvc2VuU2NhbnNPblBsYW4gPSByZXN1bHQuc3dlZXBzO1xyXG4gICAgICB9XHJcbiAgICAgIGlmIChyZXN1bHQuc3RhcnRTd2VlcElEKSB7XHJcbiAgICAgICAgdGhpcy56b25lRm9ybS5jb250cm9scy5zdGFydFN3ZWVwSUQuc2V0VmFsdWUocmVzdWx0LnN0YXJ0U3dlZXBJRCk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHRoaXMuZnJvbVBsYW4gPSBmYWxzZTtcclxuICB9XHJcblxyXG4gIGxheWVyTmFtZVZhbGlkYXRvcigpOiBWYWxpZGF0b3JGbiB7XHJcbiAgICByZXR1cm4gKGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCk6IFZhbGlkYXRpb25FcnJvcnMgfCBudWxsID0+IHtcclxuICAgICAgaWYgKCFjb250cm9sLnZhbHVlKSB7XHJcbiAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICAgIH1cclxuICAgICAgY29uc3QgZm9yYmlkZGVuID0gdGhpcy5sYXllcnNcclxuICAgICAgICAubWFwKChsKSA9PiBsLm5hbWUudG9Mb3dlckNhc2UoKSlcclxuICAgICAgICAuaW5jbHVkZXMoY29udHJvbC52YWx1ZS50b0xvd2VyQ2FzZSgpKTtcclxuICAgICAgcmV0dXJuIGZvcmJpZGRlbiA/IHsgZm9yYmlkZGVuTmFtZTogeyB2YWx1ZTogY29udHJvbC52YWx1ZSB9IH0gOiBudWxsO1xyXG4gICAgfTtcclxuICB9XHJcbn1cclxuIiwiPGRpdiBjbGFzcz1cIm1haW4tY29udGFpbmVyXCIgKm5nSWY9XCJ6b25lRm9ybVwiPlxyXG4gICAgPGRpdiBjbGFzcz1cImNvbC03XCI+XHJcbiAgICAgICAgPGZvcm0gKG5nU3VibWl0KT1cIm9uU3VibWl0Wm9uZSgpXCIgW2Zvcm1Hcm91cF09XCJ6b25lRm9ybVwiPlxyXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWItMyByb3dcIj5cclxuICAgICAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImNvbC1zbS0yIGNvbC1mb3JtLWxhYmVsXCI+e3snTmFtZScgfCB0cmFuc2xhdGV9fSAqPC9sYWJlbD5cclxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtc20tMTBcIj5cclxuICAgICAgICAgICAgICAgICAgICA8aW5wdXQgdHlwZT1cInRleHRcIiBjbGFzcz1cImZvcm0tY29udHJvbFwiIHJlcXVpcmVkIGZvcm1Db250cm9sTmFtZT1cIm5hbWVcIj5cclxuICAgICAgICAgICAgICAgICAgICA8IS0tIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHt7J0EgbmFtZSBpcyByZXF1aXJlZCcgfCB0cmFuc2xhdGV9fVxyXG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PiAtLT5cclxuICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1iLTMgcm93XCI+XHJcbiAgICAgICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJjb2wtc20tMiBjb2wtZm9ybS1sYWJlbFwiPnt7J2NvZGVSZWYnIHwgdHJhbnNsYXRlfX08L2xhYmVsPlxyXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNvbC1zbS0xMFwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxpbnB1dCB0eXBlPVwidGV4dFwiIGNsYXNzPVwiZm9ybS1jb250cm9sXCIgZm9ybUNvbnRyb2xOYW1lPVwiY29kZV9yZWZcIj5cclxuICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1iLTMgcm93XCIgKm5nSWY9XCIhaXNNdXNldW1WaXNpdCAmJiAhem9uZUlzTWF0dGVycG9ydEZsb29yXCI+XHJcbiAgICAgICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJjb2wtc20tMiBjb2wtZm9ybS1sYWJlbFwiPnt7J1R5cGUgb2Ygem9uZScgfCB0cmFuc2xhdGV9fTwvbGFiZWw+XHJcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLXNtLTEwXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPHNlbGVjdCBjbGFzcz1cImZvcm0tY29udHJvbFwiIGZvcm1Db250cm9sTmFtZT1cImxheWVySURcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiB2YWx1ZT1cIm51bGxcIiBzZWxlY3RlZCBkaXNhYmxlZCBoaWRkZW4+IHt7IHpvbmVFZGl0ICYmIHpvbmVFZGl0LmxheWVyID9cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHpvbmVFZGl0LmxheWVyLm5hbWUgOiAnQ2hvb3NlIHR5cGUnfX08L29wdGlvbj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiAqbmdGb3I9XCJsZXQgbGF5ZXIgb2YgbGF5ZXJzXCIgW3ZhbHVlXT1cImxheWVyLmlkXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7eyBsYXllci5uYW1lIH19XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvb3B0aW9uPlxyXG4gICAgICAgICAgICAgICAgICAgIDwvc2VsZWN0PlxyXG4gICAgICAgICAgICAgICAgICAgIDxwIGNsYXNzPVwibXQtMSBuZXctdHlwZS10ZXh0XCI+e3snb3IgYWRkIG5ldyB0eXBlIG9mIHpvbmUnIHwgdHJhbnNsYXRlIH19PC9wPlxyXG4gICAgICAgICAgICAgICAgICAgIDxpbnB1dCB0eXBlPVwidGV4dFwiIGNsYXNzPVwiZm9ybS1jb250cm9sIG5ldy10eXBlLWlucHV0XCIgZm9ybUNvbnRyb2xOYW1lPVwibmV3TGF5ZXJcIj5cclxuICAgICAgICAgICAgICAgICAgICA8ZGl2ICpuZ0lmPVwibmV3TGF5ZXIuaW52YWxpZCAmJiAobmV3TGF5ZXIuZGlydHkgfHwgbmV3TGF5ZXIudG91Y2hlZClcIiBjbGFzcz1cInRleHQtZGFuZ2VyXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgKm5nSWY9XCJuZXdMYXllci5lcnJvcnM/LlsnZm9yYmlkZGVuTmFtZSddXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7eydMYXllciBleGlzdHMgYWxyZWFkeScgfCB0cmFuc2xhdGV9fVxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgPCEtLUlmIEVkaXRpbmcgWm9uZSBwb3NzaWJpbGl0eSB0byBhc3NpZ24gaXQgdG8gbXVzZXVtIGl0aW5lcmFyeS0tPlxyXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWItMyByb3dcIiAqbmdJZj1cInpvbmVFZGl0ICYmICF6b25lSXNNYXR0ZXJwb3J0Rmxvb3JcIj5cclxuICAgICAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImNvbC1zbS0yIGNvbC1mb3JtLWxhYmVsXCI+e3sgJ011c2V1bSBJdGluZXJhcnknIHwgdHJhbnNsYXRlIH19PC9sYWJlbD5cclxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtc20tMTBcIj5cclxuICAgICAgICAgICAgICAgICAgICA8aW5wdXQgY2xhc3M9XCJjaGVja2JveC1hcHBseSBtdC0zXCIgdHlwZT1cImNoZWNrYm94XCIgWyhuZ01vZGVsKV09XCJpc011c2V1bVZpc2l0XCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgW25nTW9kZWxPcHRpb25zXT1cIntzdGFuZGFsb25lOiB0cnVlfVwiPlxyXG4gICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1iLTMgcm93XCIgKm5nSWY9XCIhem9uZUVkaXQgfHwgem9uZUVkaXQuaXNNdWx0aXBsZUZsb29yWm9uZVwiPlxyXG4gICAgICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwiY29sLXNtLTIgY29sLWZvcm0tbGFiZWxcIj57eyAnTXVsdGlwbGUgRmxvb3JzJyB8IHRyYW5zbGF0ZSB9fTwvbGFiZWw+XHJcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLXNtLTEwXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPGlucHV0IGNsYXNzPVwiY2hlY2tib3gtYXBwbHkgbXQtM1wiIHR5cGU9XCJjaGVja2JveFwiIFsobmdNb2RlbCldPVwibXVsdGlwbGVGbG9vcnNcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiem9uZUVkaXQgIT09IHVuZGVmaW5lZCAmJiB6b25lRWRpdCAhPT0gbnVsbFwiIChjaGFuZ2UpPVwib25DaGFuZ2VNdWx0aXBsZUZsb29ycygpXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgW25nTW9kZWxPcHRpb25zXT1cIntzdGFuZGFsb25lOiB0cnVlfVwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9J3RleHQtZGFuZ2VyJyAqbmdJZj1cInpvbmVFZGl0XCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHt7J2Nhbm5vdENoYW5nZU11bHRpZmxvb3InIHwgdHJhbnNsYXRlfX1cclxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgICAgICAgPC9kaXY+XHJcblxyXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWItMyByb3dcIj5cclxuICAgICAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImNvbC1zbS0yIGNvbC1mb3JtLWxhYmVsXCI+e3snU3VyZmFjZScgfCB0cmFuc2xhdGV9fTwvbGFiZWw+XHJcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLXNtLTEwXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJ0ZXh0XCIgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIiBmb3JtQ29udHJvbE5hbWU9XCJzdXJmYWNlXCI+XHJcbiAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgPC9kaXY+XHJcblxyXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWItMyByb3dcIiAqbmdJZj1cIiF6b25lSXNNYXR0ZXJwb3J0Rmxvb3JcIj5cclxuICAgICAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImNvbC1zbS0yIGNvbC1mb3JtLWxhYmVsXCI+e3snUGFyZW50IHpvbmUnIHwgdHJhbnNsYXRlfX08L2xhYmVsPlxyXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNvbC1zbS0xMFwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxpbnB1dCAqbmdJZj1cInpvbmVFZGl0XCIgdHlwZT1cInRleHRcIiBjbGFzcz1cImZvcm0tY29udHJvbFwiIGZvcm1Db250cm9sTmFtZT1cInBhcmVudFwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0ZXh0LWRhbmdlclwiICpuZ0lmPVwiem9uZUVkaXRcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAge3snY2Fubm90Q2hhbmdlUGFyZW50JyB8IHRyYW5zbGF0ZX19XHJcbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgPHNlbGVjdCAqbmdJZj1cIiF6b25lRWRpdFwiIGNsYXNzPVwiZm9ybS1jb250cm9sXCIgZm9ybUNvbnRyb2xOYW1lPVwicGFyZW50SURcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiAqbmdGb3I9XCJsZXQgem9uZSBvZiBwYXJlbnRab25lc1wiIFtuZ1ZhbHVlXT1cInpvbmUuaWRcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7IHpvbmUubmFtZSB9fVxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8L29wdGlvbj5cclxuICAgICAgICAgICAgICAgICAgICA8L3NlbGVjdD5cclxuXHJcbiAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgPC9kaXY+XHJcblxyXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWItMyByb3dcIiBzdHlsZT1cIm1heC1oZWlnaHQ6IDIwMHB4OyBvdmVyZmxvdzogYXV0bztcIiAqbmdJZj1cIiF6b25lSXNNYXR0ZXJwb3J0Rmxvb3JcIj5cclxuICAgICAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImNvbC1zbS0yIGNvbC1mb3JtLWxhYmVsXCI+e3snU2NhbiBQb2ludHMnIHwgdHJhbnNsYXRlfX08L2xhYmVsPlxyXG4gICAgICAgICAgICAgICAgPCEtLSA8cCBjbGFzcz1cImNvbC1zbS0yXCIgKm5nSWY9XCJ6b25lRWRpdFwiPnt7IHpvbmVFZGl0LnN3ZWVwSURzLmxlbmd0aCB9fSBzY2FuczwvcD4gLS0+XHJcbiAgICAgICAgICAgICAgICA8cCBjbGFzcz1cImNvbFwiICpuZ0lmPVwiY2hvc2VuU2NhbnNPblBsYW4ubGVuZ3RoID09PSAwICYmIGNob3NlblNjYW5zLmxlbmd0aCA9PT0gMFwiPlxyXG4gICAgICAgICAgICAgICAgICAgIHt7J05vIHNjYW4gcG9pbnRzIGNob3NlbicgfCB0cmFuc2xhdGV9fTwvcD5cclxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtc20tNVwiICpuZ0lmPVwiY2hvc2VuU2NhbnNPblBsYW4gJiYgY2hvc2VuU2NhbnNPblBsYW4ubGVuZ3RoID4gMFwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxwPnt7IGNob3NlblNjYW5zT25QbGFuLmxlbmd0aCB9fSB7eydzY2FuIHBvaW50cyBjaG9zZW4nIHwgdHJhbnNsYXRlfX08L3A+XHJcbiAgICAgICAgICAgICAgICAgICAgPCEtLSA8ZGl2ICpuZ0Zvcj1cImxldCBzY2FuIG9mIGNob3NlblNjYW5zT25QbGFuXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJyb3dcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwIGNsYXNzPVwibWUtMlwiPnt7IHNjYW4gfCBzbGljZTowOjggfX08L3A+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IChjbGljayk9XCJvblJlbW92ZVNjYW5QbGFuKHNjYW4pXCIgW3N0eWxlLmN1cnNvcl09XCIncG9pbnRlcidcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImljb25pZnlcIiBkYXRhLWljb249XCJtZGk6dHJhc2gtY2FuLW91dGxpbmVcIj48L3NwYW4+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+IC0tPlxyXG4gICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLXNtLTVcIiAqbmdJZj1cImNhcm91c2VsSXNWaXNpYmxlICYmIGNob3NlblNjYW5zICYmIGNob3NlblNjYW5zLmxlbmd0aCA+IDBcIj5cclxuICAgICAgICAgICAgICAgICAgICA8cD57eyBjaG9zZW5TY2Fucy5sZW5ndGggfX0ge3snc2NhbiBwb2ludHMgY2hvc2VuJyB8IHRyYW5zbGF0ZX19PC9wPlxyXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgKm5nRm9yPVwibGV0IHNjYW4gb2YgY2hvc2VuU2NhbnNcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInJvd1wiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPHAgY2xhc3M9XCJtZS0yXCI+e3sgaW1hZ2VzMzYwW3NjYW5dLmZpbGVuYW1lIH19PC9wPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiAoY2xpY2spPVwib25SZW1vdmVTY2FuSW1hZ2Uoc2NhbilcIiBbc3R5bGUuY3Vyc29yXT1cIidwb2ludGVyJ1wiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiaWNvbmlmeVwiIGRhdGEtaWNvbj1cIm1kaTp0cmFzaC1jYW4tb3V0bGluZVwiPjwvc3Bhbj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJyb3cgbWItMyBtdC0zXCIgKm5nSWY9XCIhem9uZUlzTWF0dGVycG9ydEZsb29yXCI+XHJcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY29sXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidG4gYnRuLW91dGxpbmUtcHJpbWFyeSByb3VuZGVkLXBpbGwgbWUtMlwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJ0b2dnbGVQbGFuKClcIj57eydDaG9vc2Ugc2NhbiBwb2ludHMgb24gcGxhbicgfFxyXG4gICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2xhdGV9fTwvYnV0dG9uPlxyXG4gICAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYnRuIGJ0bi1vdXRsaW5lLXByaW1hcnkgcm91bmRlZC1waWxsIG1lLTJcIiAoY2xpY2spPVwidG9nZ2xlQ2Fyb3VzZWwoKVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJmcm9tUGxhbiB8fCAhaW1hZ2VzMzYwIHx8IGltYWdlczM2MC5sZW5ndGggPT09IDBcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAge3snQ2hvb3NlIHNjYW4gcG9pbnRzIGZyb20gZ2FsbGVyeScgfCB0cmFuc2xhdGV9fTwvYnV0dG9uPlxyXG4gICAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYnRuIGJ0bi1vdXRsaW5lLXByaW1hcnkgcm91bmRlZC1waWxsIG1lLTJcIiAoY2xpY2spPVwib25BZGRBbGwoKVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJmcm9tUGxhbiB8fCAhaW1hZ2VzMzYwIHx8IGltYWdlczM2MC5sZW5ndGggPT09IDBcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAge3snYWRkLWFsbC1zY2FucycgfCB0cmFuc2xhdGV9fTwvYnV0dG9uPlxyXG4gICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgICAgICAgPCEtLSA8ZGl2IGNsYXNzPVwibWItMyByb3dcIj5cclxuICAgICAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImNvbC1zbS0zIGNvbC1mb3JtLWxhYmVsXCI+e3snTm8gdmlzaWJsZSBzY2FuIHBvaW50cycgfCB0cmFuc2xhdGV9fTwvbGFiZWw+XHJcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLXNtLTNcIj5cclxuICAgICAgICAgICAgICAgICAgICA8aW5wdXQgY2xhc3M9XCJjaGVja2JveC1hcHBseSBtdC0zXCIgdHlwZT1cImNoZWNrYm94XCIgWyhuZ01vZGVsKV09XCJub1NjYW5Qb2ludHNcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBbbmdNb2RlbE9wdGlvbnNdPVwie3N0YW5kYWxvbmU6IHRydWV9XCI+XHJcbiAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgPC9kaXY+IC0tPlxyXG5cclxuICAgICAgICAgICAgPGRpdiAqbmdJZj1cImNhcm91c2VsSXNWaXNpYmxlXCIgY2xhc3M9XCJtYi0yXCI+XHJcbiAgICAgICAgICAgICAgICA8bGliLWNhcm91c2VsICpuZ0lmPVwiaW1hZ2VzMzYwICYmIGltYWdlczM2MC5sZW5ndGggPiAwXCIgW2ltYWdlc109XCJpbWFnZXMzNjBcIlxyXG4gICAgICAgICAgICAgICAgICAgIChjdXJyZW50U2Nhbik9XCJjdXJyZW50U2NhblNob3dpbmc9JGV2ZW50XCI+PC9saWItY2Fyb3VzZWw+XHJcbiAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJ0biBidG4tb3V0bGluZS1wcmltYXJ5IHJvdW5kZWQtcGlsbCBtZS0yIG10LTNcIlxyXG4gICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJvbkFkZFNjYW4oKVwiPnt7J0FkZCB0byB6b25lJyB8IHRyYW5zbGF0ZX19PC9idXR0b24+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwibXQtM1wiPlxyXG4gICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPVwic3VibWl0XCIgY2xhc3M9XCJidG4gYnRuLXByaW1hcnkgcm91bmRlZC1waWxsIG1lLTJcIlxyXG4gICAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJmcm9tUGxhbiB8fCAhem9uZUZvcm0udmFsaWRcIj57eydTYXZlJyB8IHRyYW5zbGF0ZX19PC9idXR0b24+XHJcbiAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiAoY2xpY2spPVwib25DYW5jZWwoKVwiIGNsYXNzPVwiYnRuIGJ0bi1vdXRsaW5lLXByaW1hcnkgcm91bmRlZC1waWxsIG1lLTJcIj5cclxuICAgICAgICAgICAgICAgICAgICB7eydDYW5jZWwnIHwgdHJhbnNsYXRlfX08L2J1dHRvbj5cclxuICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgPC9mb3JtPlxyXG4gICAgPC9kaXY+XHJcbiAgICA8ZGl2IGNsYXNzPVwiZWRpdC1wbGFuXCIgKm5nSWY9XCJmcm9tUGxhblwiPlxyXG4gICAgICAgIDxsaWItc3dlZXAtcGxhbi1zZWxlY3Rpb24gc3R5bGU9XCJ3aWR0aDogMTAwJTtcIiBbbmV3Wm9uZURhdGFdPVwibmV3Wm9uZURhdGFGcm9tRWRpdG9yXCIgW3NwYWNlSURdPVwic3BhY2VJRFwiXHJcbiAgICAgICAgICAgIFttdWx0aXBsZUZsb29yc109XCJtdWx0aXBsZUZsb29yc1wiIFtpbnB1dFpvbmVdPVwiem9uZUVkaXRcIlxyXG4gICAgICAgICAgICAoc3dlZXBzU2VsZWN0ZWQpPVwib25TZWxlY3RlZFN3ZWVwc0Zyb21QbGFuKCRldmVudClcIj48L2xpYi1zd2VlcC1wbGFuLXNlbGVjdGlvbj5cclxuICAgIDwvZGl2PlxyXG48L2Rpdj4iXX0=
@@ -0,0 +1,81 @@
1
+ import { Component, EventEmitter, Output } from '@angular/core';
2
+ import * as i0 from "@angular/core";
3
+ class SelectionComponent {
4
+ constructor() { }
5
+ /**Emit a new selection */
6
+ onSelectionChanged = new EventEmitter();
7
+ /**Zone wich you can use a selection inside, must have the class ".selectZone" */
8
+ selectionableZone;
9
+ /**HtmlElement use to display the selected zone (blue) */
10
+ selectionElement;
11
+ isMousedown = false;
12
+ selection = { startX: 0, startY: 0, endX: 0, endY: 0 };
13
+ selectionRectangle = { top: 0, left: 0, width: 0, height: 0 };
14
+ ngOnInit() {
15
+ this.selectionableZone = document.querySelector(".selectZone");
16
+ this.selectionElement = document.querySelector("#selection");
17
+ this.selectionableZone.addEventListener("mousedown", this.mousedown.bind(this));
18
+ this.selectionableZone.addEventListener("mousemove", this.mousemove.bind(this));
19
+ this.selectionableZone.addEventListener("mouseup", this.mouseup.bind(this));
20
+ }
21
+ /**
22
+ * Update the current selection
23
+ * Will update the selectionRectangle and Selection HTML element
24
+ * @param shouldEmit if true an event will be emitted through onSelectionChanged (true by default)
25
+ */
26
+ updateSelectionElement(shouldEmit = true) {
27
+ this.selectionRectangle.width = Math.abs(this.selection.endX - this.selection.startX);
28
+ this.selectionRectangle.height = Math.abs(this.selection.endY - this.selection.startY);
29
+ this.selectionRectangle.top = Math.min(this.selection.endY, this.selection.startY);
30
+ this.selectionRectangle.left = Math.min(this.selection.endX, this.selection.startX);
31
+ this.selectionElement.style.top = `${this.selectionRectangle.top}px`;
32
+ this.selectionElement.style.left = `${this.selectionRectangle.left}px`;
33
+ this.selectionElement.style.width = `${this.selectionRectangle.width}px`;
34
+ this.selectionElement.style.height = `${this.selectionRectangle.height}px`;
35
+ if (shouldEmit) {
36
+ this.onSelectionChanged.emit(this.selectionRectangle);
37
+ }
38
+ }
39
+ /**
40
+ * Trigger when mouse is press down on selectionableZone
41
+ * @param event
42
+ */
43
+ mousedown(event) {
44
+ if (event.button !== 2) { /**Selection with the right click, so ignore all other event */
45
+ return;
46
+ }
47
+ this.isMousedown = true;
48
+ this.selection = { startY: event.clientY, startX: event.clientX, endX: event.clientX, endY: event.clientY };
49
+ this.updateSelectionElement();
50
+ }
51
+ /**
52
+ * Trigger when mouse is release on selectionableZone
53
+ * @param event
54
+ */
55
+ mouseup(event) {
56
+ this.isMousedown = false;
57
+ this.selection = { startX: 0, startY: 0, endX: 0, endY: 0 };
58
+ this.updateSelectionElement(false);
59
+ }
60
+ /**
61
+ * Trigger when mouse is moving on selectionableZone
62
+ * @param event
63
+ */
64
+ mousemove(event) {
65
+ if (this.isMousedown) {
66
+ this.selection.endX = event.clientX;
67
+ this.selection.endY = event.clientY;
68
+ this.updateSelectionElement();
69
+ }
70
+ }
71
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SelectionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
72
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: SelectionComponent, selector: "lib-selection", outputs: { onSelectionChanged: "onSelectionChanged" }, ngImport: i0, template: "<ng-content></ng-content>\r\n\r\n<div id=\"selection\"></div>", styles: ["#selection{will-change:top,left,width,height;top:0;left:0;position:fixed;display:block;margin-top:0;margin-left:0;width:0px;height:0px;background:#53b6bb4d;border-radius:.15em;border:.15em solid rgba(83,182,187,.8);pointer-events:none}\n"] });
73
+ }
74
+ export { SelectionComponent };
75
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SelectionComponent, decorators: [{
76
+ type: Component,
77
+ args: [{ selector: 'lib-selection', template: "<ng-content></ng-content>\r\n\r\n<div id=\"selection\"></div>", styles: ["#selection{will-change:top,left,width,height;top:0;left:0;position:fixed;display:block;margin-top:0;margin-left:0;width:0px;height:0px;background:#53b6bb4d;border-radius:.15em;border:.15em solid rgba(83,182,187,.8);pointer-events:none}\n"] }]
78
+ }], ctorParameters: function () { return []; }, propDecorators: { onSelectionChanged: [{
79
+ type: Output
80
+ }] } });
81
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VsZWN0aW9uLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1zbWFydGVycGxhbi1sb2NhdGlvbnMvc3JjL2xpYi9jb21wb25lbnRzL3pvbmVzL2FkZC16b25lL3NlbGVjdGlvbi9zZWxlY3Rpb24uY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWxvY2F0aW9ucy9zcmMvbGliL2NvbXBvbmVudHMvem9uZXMvYWRkLXpvbmUvc2VsZWN0aW9uL3NlbGVjdGlvbi5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBVSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7O0FBR3hFLE1BS2Esa0JBQWtCO0lBQzNCLGdCQUFjLENBQUM7SUFFZiwwQkFBMEI7SUFDaEIsa0JBQWtCLEdBQUcsSUFBSSxZQUFZLEVBQWEsQ0FBQztJQUU3RCxpRkFBaUY7SUFDakYsaUJBQWlCLENBQWU7SUFFaEMseURBQXlEO0lBQ3pELGdCQUFnQixDQUFlO0lBRS9CLFdBQVcsR0FBYSxLQUFLLENBQUM7SUFFOUIsU0FBUyxHQUFHLEVBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLENBQUMsRUFBQyxDQUFDO0lBRXJELGtCQUFrQixHQUFlLEVBQUMsR0FBRyxFQUFHLENBQUMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsTUFBTSxFQUFFLENBQUMsRUFBQyxDQUFDO0lBRXpFLFFBQVE7UUFDSixJQUFJLENBQUMsaUJBQWlCLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUUvRCxJQUFJLENBQUMsZ0JBQWdCLEdB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QUFFLE1BQU0sRUFBRyxDQUFDLEVBQUUsSUFBSSxFQUFDLENBQUMsRUFBRSxJQUFJLEVBQUMsQ0FBQyxFQUFDLENBQUM7UUFDekQsSUFBSSxDQUFDLHNCQUFzQixDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3ZDLENBQUM7SUFFRDs7O09BR0c7SUFDSCxTQUFTLENBQUMsS0FBa0I7UUFDeEIsSUFBRyxJQUFJLENBQUMsV0FBVyxFQUFDO1lBQ2hCLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUM7WUFDcEMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQztZQUNwQyxJQUFJLENBQUMsc0JBQXNCLEVBQUUsQ0FBQztTQUNqQztJQUNMLENBQUM7d0dBcEZRLGtCQUFrQjs0RkFBbEIsa0JBQWtCLDRHQ1IvQiwrREFFMEI7O1NETWIsa0JBQWtCOzRGQUFsQixrQkFBa0I7a0JBTDlCLFNBQVM7K0JBQ0UsZUFBZTswRUFRYixrQkFBa0I7c0JBQTNCLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgT25Jbml0LCBPdXRwdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgUmVjdGFuZ2xlIH0gZnJvbSAnLi4vLi4vLi4vLi4vaGVscGVyLnNlcnZpY2UnO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdsaWItc2VsZWN0aW9uJyxcclxuICB0ZW1wbGF0ZVVybDogJy4vc2VsZWN0aW9uLmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybHM6IFsnLi9zZWxlY3Rpb24uY29tcG9uZW50LnNjc3MnXVxyXG59KVxyXG5leHBvcnQgY2xhc3MgU2VsZWN0aW9uQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcclxuICAgIGNvbnN0cnVjdG9yKCl7fVxyXG5cclxuICAgIC8qKkVtaXQgYSBuZXcgc2VsZWN0aW9uICovXHJcbiAgICBAT3V0cHV0KCkgb25TZWxlY3Rpb25DaGFuZ2VkID0gbmV3IEV2ZW50RW1pdHRlcjxSZWN0YW5nbGU+KCk7XHJcblxyXG4gICAgLyoqWm9uZSB3aWNoIHlvdSBjYW4gdXNlIGEgc2VsZWN0aW9uIGluc2lkZSwgbXVzdCBoYXZlIHRoZSBjbGFzcyBcIi5zZWxlY3Rab25lXCIgKi9cclxuICAgIHNlbGVjdGlvbmFibGVab25lIDogSFRNTEVsZW1lbnQ7XHJcblxyXG4gICAgLyoqSHRtbEVsZW1lbnQgdXNlIHRvIGRpc3BsYXkgdGhlIHNlbGVjdGVkIHpvbmUgKGJsdWUpICovXHJcbiAgICBzZWxlY3Rpb25FbGVtZW50IDogSFRNTEVsZW1lbnQ7XHJcblxyXG4gICAgaXNNb3VzZWRvd24gOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gICAgc2VsZWN0aW9uID0ge3N0YXJ0WDogMCwgc3RhcnRZOiAwLCBlbmRYOiAwLCBlbmRZOiAwfTtcclxuXHJcbiAgICBzZWxlY3Rpb25SZWN0YW5nbGUgOiBSZWN0YW5nbGUgPSB7dG9wIDogMCwgbGVmdDogMCwgd2lkdGg6IDAsIGhlaWdodDogMH07XHJcblxyXG4gICAgbmdPbkluaXQoKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5zZWxlY3Rpb25hYmxlWm9uZSA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIuc2VsZWN0Wm9uZVwiKTtcclxuXHJcbiAgICAgICAgdGhpcy5zZWxlY3Rpb25FbGVtZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiNzZWxlY3Rpb25cIik7XHJcblxyXG4gICAgICAgIHRoaXMuc2VsZWN0aW9uYWJsZVpvbmUuYWRkRXZlbnRMaXN0ZW5lcihcIm1vdXNlZG93blwiLHRoaXMubW91c2Vkb3duLmJpbmQodGhpcykpO1xyXG5cclxuICAgICAgICB0aGlzLnNlbGVjdGlvbmFibGVab25lLmFkZEV2ZW50TGlzdGVuZXIoXCJtb3VzZW1vdmVcIix0aGlzLm1vdXNlbW92ZS5iaW5kKHRoaXMpKTtcclxuXHJcbiAgICAgICAgdGhpcy5zZWxlY3Rpb25hYmxlWm9uZS5hZGRFdmVudExpc3RlbmVyKFwibW91c2V1cFwiLHRoaXMubW91c2V1cC5iaW5kKHRoaXMpKTtcclxuICAgIH1cclxuICAgIFxyXG4gICAgLyoqXHJcbiAgICAgKiBVcGRhdGUgdGhlIGN1cnJlbnQgc2VsZWN0aW9uXHJcbiAgICAgKiBXaWxsIHVwZGF0ZSB0aGUgc2VsZWN0aW9uUmVjdGFuZ2xlIGFuZCBTZWxlY3Rpb24gSFRNTCBlbGVtZW50XHJcbiAgICAgKiBAcGFyYW0gc2hvdWxkRW1pdCBpZiB0cnVlIGFuIGV2ZW50IHdpbGwgYmUgZW1pdHRlZCB0aHJvdWdoIG9uU2VsZWN0aW9uQ2hhbmdlZCAodHJ1ZSBieSBkZWZhdWx0KVxyXG4gICAgICovXHJcbiAgICB1cGRhdGVTZWxlY3Rpb25FbGVtZW50KHNob3VsZEVtaXQ9dHJ1ZSl7XHJcbiAgICAgICAgdGhpcy5zZWxlY3Rpb25SZWN0YW5nbGUud2lkdGggPSBNYXRoLmFicyh0aGlzLnNlbGVjdGlvbi5lbmRYIC0gdGhpcy5zZWxlY3Rpb24uc3RhcnRYKTtcclxuICAgICAgICB0aGlzLnNlbGVjdGlvblJlY3RhbmdsZS5oZWlnaHQgPSBNYXRoLmFicyh0aGlzLnNlbGVjdGlvbi5lbmRZIC0gdGhpcy5zZWxlY3Rpb24uc3RhcnRZKTtcclxuICAgICAgICB0aGlzLnNlbGVjdGlvblJlY3RhbmdsZS50b3AgPSBNYXRoLm1pbih0aGlzLnNlbGVjdGlvbi5lbmRZLCB0aGlzLnNlbGVjdGlvbi5zdGFydFkpO1xyXG4gICAgICAgIHRoaXMuc2VsZWN0aW9uUmVjdGFuZ2xlLmxlZnQgPSBNYXRoLm1pbih0aGlzLnNlbGVjdGlvbi5lbmRYLCB0aGlzLnNlbGVjdGlvbi5zdGFydFgpO1xyXG5cclxuICAgICAgICB0aGlzLnNlbGVjdGlvbkVsZW1lbnQuc3R5bGUudG9wID0gYCR7dGhpcy5zZWxlY3Rpb25SZWN0YW5nbGUudG9wfXB4YDtcclxuICAgICAgICB0aGlzLnNlbGVjdGlvbkVsZW1lbnQuc3R5bGUubGVmdCA9IGAke3RoaXMuc2VsZWN0aW9uUmVjdGFuZ2xlLmxlZnR9cHhgO1xyXG4gICAgICAgIHRoaXMuc2VsZWN0aW9uRWxlbWVudC5zdHlsZS53aWR0aCA9IGAke3RoaXMuc2VsZWN0aW9uUmVjdGFuZ2xlLndpZHRofXB4YDtcclxuICAgICAgICB0aGlzLnNlbGVjdGlvbkVsZW1lbnQuc3R5bGUuaGVpZ2h0ID0gYCR7dGhpcy5zZWxlY3Rpb25SZWN0YW5nbGUuaGVpZ2h0fXB4YDtcclxuXHJcbiAgICAgICAgaWYoc2hvdWxkRW1pdCl7XHJcbiAgICAgICAgICAgIHRoaXMub25TZWxlY3Rpb25DaGFuZ2VkLmVtaXQodGhpcy5zZWxlY3Rpb25SZWN0YW5nbGUpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFRyaWdnZXIgd2hlbiBtb3VzZSBpcyBwcmVzcyBkb3duIG9uIHNlbGVjdGlvbmFibGVab25lXHJcbiAgICAgKiBAcGFyYW0gZXZlbnQgXHJcbiAgICAgKi9cclxuICAgIG1vdXNlZG93bihldmVudCA6IE1vdXNlRXZlbnQpe1xyXG4gICAgICAgIGlmKGV2ZW50LmJ1dHRvbiAhPT0gMil7IC8qKlNlbGVjdGlvbiB3aXRoIHRoZSByaWdodCBjbGljaywgc28gaWdub3JlIGFsbCBvdGhlciBldmVudCAqL1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMuaXNNb3VzZWRvd24gPSB0cnVlO1xyXG4gICAgICAgIHRoaXMuc2VsZWN0aW9uID0ge3N0YXJ0WSA6IGV2ZW50LmNsaWVudFksIHN0YXJ0WCA6IGV2ZW50LmNsaWVudFgsIGVuZFg6ZXZlbnQuY2xpZW50WCwgZW5kWTpldmVudC5jbGllbnRZfTtcclxuICAgICAgICB0aGlzLnVwZGF0ZVNlbGVjdGlvbkVsZW1lbnQoKTsgICAgICAgIFxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVHJpZ2dlciB3aGVuIG1vdXNlIGlzIHJlbGVhc2Ugb24gc2VsZWN0aW9uYWJsZVpvbmVcclxuICAgICAqIEBwYXJhbSBldmVudCBcclxuICAgICAqL1xyXG4gICAgbW91c2V1cChldmVudCA6IE1vdXNlRXZlbnQpe1xyXG4gICAgICAgIHRoaXMuaXNNb3VzZWRvd24gPSBmYWxzZTtcclxuICAgICAgICB0aGlzLnNlbGVjdGlvbiA9IHtzdGFydFggOjAsIHN0YXJ0WSA6IDAsIGVuZFg6MCwgZW5kWTowfTtcclxuICAgICAgICB0aGlzLnVwZGF0ZVNlbGVjdGlvbkVsZW1lbnQoZmFsc2UpOyAgICAgICAgXHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUcmlnZ2VyIHdoZW4gbW91c2UgaXMgbW92aW5nIG9uIHNlbGVjdGlvbmFibGVab25lXHJcbiAgICAgKiBAcGFyYW0gZXZlbnQgXHJcbiAgICAgKi9cclxuICAgIG1vdXNlbW92ZShldmVudCA6IE1vdXNlRXZlbnQpe1xyXG4gICAgICAgIGlmKHRoaXMuaXNNb3VzZWRvd24pe1xyXG4gICAgICAgICAgICB0aGlzLnNlbGVjdGlvbi5lbmRYID0gZXZlbnQuY2xpZW50WDtcclxuICAgICAgICAgICAgdGhpcy5zZWxlY3Rpb24uZW5kWSA9IGV2ZW50LmNsaWVudFk7XHJcbiAgICAgICAgICAgIHRoaXMudXBkYXRlU2VsZWN0aW9uRWxlbWVudCgpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbn1cclxuIiwiPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxyXG5cclxuPGRpdiBpZD1cInNlbGVjdGlvblwiPjwvZGl2PiJdfQ==