@smarterplan/ngx-smarterplan-locations 0.4.19 → 0.4.21

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 (39) hide show
  1. package/README.md +24 -24
  2. package/esm2022/lib/components/carousel/carousel.component.mjs +3 -3
  3. package/esm2022/lib/components/chevron/chevron.component.mjs +3 -3
  4. package/esm2022/lib/components/detail-location/detail-location.component.mjs +40 -4
  5. package/esm2022/lib/components/form-location/form-location.component.mjs +3 -3
  6. package/esm2022/lib/components/images/images.component.mjs +3 -3
  7. package/esm2022/lib/components/landmark-picker/landmark-picker.component.mjs +3 -3
  8. package/esm2022/lib/components/locations/locations.component.mjs +19 -4
  9. package/esm2022/lib/components/locations/map/map-popup/map-popup.component.mjs +3 -3
  10. package/esm2022/lib/components/locations/map/map.component.mjs +3 -3
  11. package/esm2022/lib/components/models3d/models3d.component.mjs +295 -0
  12. package/esm2022/lib/components/plan-legend/plan-legend.component.mjs +3 -3
  13. package/esm2022/lib/components/plans/calibration/calibration.component.mjs +3 -3
  14. package/esm2022/lib/components/plans/edit-plan/edit-plan.component.mjs +3 -3
  15. package/esm2022/lib/components/plans/plans.component.mjs +3 -3
  16. package/esm2022/lib/components/tab-navigation/tab-navigation.component.mjs +3 -3
  17. package/esm2022/lib/components/visits/visits.component.mjs +45 -12
  18. package/esm2022/lib/components/zones/add-audio-zone/add-audio-zone.component.mjs +3 -3
  19. package/esm2022/lib/components/zones/add-zone/add-zone.component.mjs +3 -3
  20. package/esm2022/lib/components/zones/add-zone/selection/selection.component.mjs +3 -3
  21. package/esm2022/lib/components/zones/add-zone/sweep-plan-selection/sweep-plan-selection.component.mjs +3 -3
  22. package/esm2022/lib/components/zones/zones.component.mjs +3 -3
  23. package/esm2022/lib/helper.service.mjs +1 -1
  24. package/esm2022/lib/ngx-smarterplan-location-routing.module.mjs +3 -1
  25. package/esm2022/lib/ngx-smarterplan-locations.module.mjs +4 -1
  26. package/esm2022/lib/ngx-smarterplan-locations.service.mjs +1 -1
  27. package/esm2022/lib/pipes/count-audio-sweeps.pipe.mjs +1 -1
  28. package/esm2022/lib/radio-button/radio-button.component.mjs +3 -3
  29. package/esm2022/public-api.mjs +1 -1
  30. package/fesm2022/smarterplan-ngx-smarterplan-locations.mjs +424 -56
  31. package/fesm2022/smarterplan-ngx-smarterplan-locations.mjs.map +1 -1
  32. package/lib/components/detail-location/detail-location.component.d.ts +13 -0
  33. package/lib/components/locations/locations.component.d.ts +10 -0
  34. package/lib/components/locations/map/map.component.d.ts +2 -2
  35. package/lib/components/models3d/models3d.component.d.ts +84 -0
  36. package/lib/components/visits/visits.component.d.ts +8 -3
  37. package/lib/components/zones/add-zone/sweep-plan-selection/sweep-plan-selection.component.d.ts +0 -1
  38. package/lib/ngx-smarterplan-locations.module.d.ts +27 -26
  39. package/package.json +2 -2
@@ -0,0 +1,295 @@
1
+ import { Component, ViewChild } from '@angular/core';
2
+ import { Validators, } from '@angular/forms';
3
+ import { ModalDismissReasons } from '@ng-bootstrap/ng-bootstrap';
4
+ import { CaptureViewer, uploadFileToS3WithProgress, } from '@smarterplan/ngx-smarterplan-core';
5
+ import { Subject } from 'rxjs';
6
+ import * as i0 from "@angular/core";
7
+ import * as i1 from "@angular/forms";
8
+ import * as i2 from "@angular/router";
9
+ import * as i3 from "@ng-bootstrap/ng-bootstrap";
10
+ import * as i4 from "@smarterplan/ngx-smarterplan-core";
11
+ import * as i5 from "@ngx-translate/core";
12
+ import * as i6 from "@angular/common";
13
+ import * as i7 from "../tab-navigation/tab-navigation.component";
14
+ import * as i8 from "../chevron/chevron.component";
15
+ /**
16
+ * Admin screen for the 3D models a site can be visited with.
17
+ *
18
+ * These are stored the same way Matterport visits are - a Capture plus a Node - with the viewer set
19
+ * to THREEJS and the .glb's S3 key in the node's model3D. Sharing the storage is what lets a site
20
+ * carry several models and what makes tags follow the same POI records in either viewer; the split
21
+ * here is only in the form: a 3D model is a name and a file, where a Matterport visit is a model ID
22
+ * and capture details. Placement and alignment are not asked for here - the viewer's alignment tool
23
+ * writes them into the capture's metadata once someone calibrates against a real scene.
24
+ */
25
+ export class Models3dComponent {
26
+ fb;
27
+ route;
28
+ router;
29
+ modalService;
30
+ spaceService;
31
+ visitService;
32
+ captureService;
33
+ nodeService;
34
+ threejsImportService;
35
+ validatorsService;
36
+ translate;
37
+ content;
38
+ menuItems = [];
39
+ currentSpace;
40
+ spaceId;
41
+ /** Only the visits captured as 3D models; Matterport ones stay on the Virtual Visits screen. */
42
+ models = [];
43
+ modelForm;
44
+ modelIndexDetails = -1;
45
+ isEditing = false;
46
+ isProcessing = false;
47
+ submitted = false;
48
+ errorMessage = null;
49
+ modalReference;
50
+ destroy$ = new Subject();
51
+ constructor(fb, route, router, modalService, spaceService, visitService, captureService, nodeService, threejsImportService, validatorsService, translate) {
52
+ this.fb = fb;
53
+ this.route = route;
54
+ this.router = router;
55
+ this.modalService = modalService;
56
+ this.spaceService = spaceService;
57
+ this.visitService = visitService;
58
+ this.captureService = captureService;
59
+ this.nodeService = nodeService;
60
+ this.threejsImportService = threejsImportService;
61
+ this.validatorsService = validatorsService;
62
+ this.translate = translate;
63
+ }
64
+ async ngOnInit() {
65
+ this.spaceId = this.route.snapshot.paramMap.get('id');
66
+ await this.reload();
67
+ }
68
+ ngOnDestroy() {
69
+ this.destroy$.next(true);
70
+ this.destroy$.complete();
71
+ }
72
+ async reload() {
73
+ this.currentSpace = await this.spaceService.getSpace(this.spaceId);
74
+ this.setupMenuItems();
75
+ const visits = await this.visitService.getVisitsForSpaceForUser(this.spaceId);
76
+ this.models = (visits ?? []).filter((visit) => visit.viewer === CaptureViewer.THREEJS);
77
+ }
78
+ setupMenuItems() {
79
+ this.menuItems = [
80
+ { label: 'Locations', url: '/localisation' },
81
+ { label: this.currentSpace.name, url: `/localisation/${this.currentSpace.id}` },
82
+ { label: '3D Models', url: `/localisation/${this.currentSpace.id}/models3d` },
83
+ ];
84
+ }
85
+ onGoBack() {
86
+ this.router.navigate(['/dashboard/localisation', this.spaceId]);
87
+ }
88
+ onToggleDetail(index) {
89
+ this.modelIndexDetails = index === this.modelIndexDetails ? -1 : index;
90
+ }
91
+ onAdd() {
92
+ this.initForm();
93
+ this.menuItems.push({ label: 'New' });
94
+ }
95
+ onEdit(model) {
96
+ this.initForm(model);
97
+ this.isEditing = true;
98
+ this.menuItems.push({ label: model.name });
99
+ }
100
+ onCancel() {
101
+ this.modelForm = null;
102
+ this.isEditing = false;
103
+ this.submitted = false;
104
+ this.errorMessage = null;
105
+ this.setupMenuItems();
106
+ }
107
+ initForm(input = null) {
108
+ this.submitted = false;
109
+ this.errorMessage = null;
110
+ if (input) {
111
+ this.modelForm = this.fb.group({
112
+ captureID: input.captureID,
113
+ nodeID: input.node.id,
114
+ name: [input.name, [Validators.required]],
115
+ modelKey: [input.model3d, [Validators.required]],
116
+ });
117
+ }
118
+ else {
119
+ this.modelForm = this.fb.group({
120
+ name: [null, [Validators.required]],
121
+ modelKey: [null, [Validators.required]],
122
+ });
123
+ }
124
+ }
125
+ /** Upload progress as a percentage, or null when nothing is uploading. */
126
+ uploadPercent = null;
127
+ uploadedFileName = null;
128
+ /**
129
+ * Uploads the chosen .glb and puts the resulting key on the form.
130
+ *
131
+ * Storage.put authenticates with the signed-in user's session rather than separate S3
132
+ * credentials, so anyone who can reach this screen can upload - which is what makes picking a
133
+ * file a better ask than typing a key someone else had to produce.
134
+ */
135
+ async onFileSelected(event) {
136
+ const input = event.target;
137
+ const file = input.files?.[0];
138
+ if (!file) {
139
+ return;
140
+ }
141
+ const name = file.name.toLowerCase();
142
+ if (!name.endsWith('.glb') && !name.endsWith('.gltf')) {
143
+ this.errorMessage = this.translate.instant('Only .glb or .gltf files can be used as a 3D model.');
144
+ input.value = '';
145
+ return;
146
+ }
147
+ this.errorMessage = null;
148
+ this.uploadPercent = 0;
149
+ this.uploadedFileName = file.name;
150
+ try {
151
+ const key = await uploadFileToS3WithProgress(`models3d/${this.spaceId}/`, file, (fraction) => {
152
+ this.uploadPercent = Math.round(fraction * 100);
153
+ });
154
+ this.modelForm.patchValue({ modelKey: key });
155
+ // Name the model after the file when the field is still empty, so the common case needs
156
+ // no extra typing.
157
+ if (!this.modelForm.value.name) {
158
+ this.modelForm.patchValue({ name: file.name.replace(/\.(glb|gltf)$/i, '') });
159
+ }
160
+ }
161
+ catch (error) {
162
+ this.errorMessage = this.describeError(error);
163
+ this.uploadedFileName = null;
164
+ }
165
+ finally {
166
+ this.uploadPercent = null;
167
+ }
168
+ }
169
+ /** Validation error for the .glb key, or null. */
170
+ get modelKeyError() {
171
+ return this.threejsImportService.validateModelKey(this.modelForm?.value.modelKey);
172
+ }
173
+ async onSubmit() {
174
+ this.submitted = true;
175
+ this.errorMessage = null;
176
+ if (!this.modelForm.valid || this.modelKeyError) {
177
+ return;
178
+ }
179
+ const formValue = this.modelForm.value;
180
+ const capture = {
181
+ viewer: CaptureViewer.THREEJS,
182
+ takenAt: Date.now(),
183
+ spaceID: this.currentSpace.id,
184
+ };
185
+ this.isProcessing = true;
186
+ try {
187
+ if (this.isEditing) {
188
+ capture.id = formValue.captureID;
189
+ // metadata is left untouched on edit: the alignment tool writes the visit's tag
190
+ // transform there, and resending the form's idea of it would wipe that.
191
+ await this.captureService.updateCapture(capture);
192
+ await this.nodeService.updateNode({
193
+ id: formValue.nodeID,
194
+ model3D: formValue.modelKey,
195
+ metadata: formValue.name,
196
+ });
197
+ }
198
+ else {
199
+ await this.createModel(formValue);
200
+ }
201
+ await this.reload();
202
+ this.onCancel();
203
+ }
204
+ catch (error) {
205
+ // The most likely failure is the backend rejecting the THREEJS enum value, which has not
206
+ // shipped yet - say so rather than leaving an empty screen.
207
+ this.errorMessage = this.describeError(error);
208
+ }
209
+ finally {
210
+ this.isProcessing = false;
211
+ }
212
+ }
213
+ /** Creates the capture, its node, and the zone/plan/navigation the viewer needs. */
214
+ async createModel(formValue) {
215
+ const capture = await this.captureService.createCapture({
216
+ viewer: CaptureViewer.THREEJS,
217
+ takenAt: Date.now(),
218
+ spaceID: this.currentSpace.id,
219
+ });
220
+ if (!capture) {
221
+ throw new Error('Could not create the capture for this 3D model.');
222
+ }
223
+ const node = await this.nodeService.createNode({
224
+ model3D: formValue.modelKey,
225
+ captureID: capture.id,
226
+ metadata: formValue.name,
227
+ });
228
+ await this.threejsImportService.importData(this.spaceId, null, false, node, true);
229
+ }
230
+ async onDelete(model) {
231
+ this.modalReference = this.modalService.open(this.content);
232
+ try {
233
+ await this.modalReference.result;
234
+ }
235
+ catch {
236
+ return; // dismissed
237
+ }
238
+ this.isProcessing = true;
239
+ try {
240
+ await this.nodeService.deleteNode(model.node.id);
241
+ await this.captureService.deleteCapture(model.captureID);
242
+ await this.reload();
243
+ }
244
+ catch (error) {
245
+ this.errorMessage = this.describeError(error);
246
+ }
247
+ finally {
248
+ this.isProcessing = false;
249
+ }
250
+ }
251
+ /**
252
+ * Turns whatever was thrown into something readable.
253
+ *
254
+ * AppSync rejections arrive as { errors: [{ message }] } with no `message` of their own, so the
255
+ * obvious `error.message ?? String(error)` renders them as "[object Object]" - which hides
256
+ * exactly the cases worth reading, like the backend refusing an enum value it does not know.
257
+ */
258
+ describeError(error) {
259
+ if (typeof error === 'string') {
260
+ return error;
261
+ }
262
+ const graphQlErrors = error?.errors;
263
+ if (Array.isArray(graphQlErrors) && graphQlErrors.length > 0) {
264
+ return graphQlErrors.map((e) => e?.message ?? JSON.stringify(e)).join(' | ');
265
+ }
266
+ if (error?.message) {
267
+ return error.message;
268
+ }
269
+ try {
270
+ return JSON.stringify(error);
271
+ }
272
+ catch {
273
+ return String(error);
274
+ }
275
+ }
276
+ getDismissReason(reason) {
277
+ if (reason === ModalDismissReasons.ESC) {
278
+ return 'by pressing ESC';
279
+ }
280
+ if (reason === ModalDismissReasons.BACKDROP_CLICK) {
281
+ return 'by clicking on a backdrop';
282
+ }
283
+ return `with: ${reason}`;
284
+ }
285
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: Models3dComponent, deps: [{ token: i1.UntypedFormBuilder }, { token: i2.ActivatedRoute }, { token: i2.Router }, { token: i3.NgbModal }, { token: i4.SpaceService }, { token: i4.VisitService }, { token: i4.CaptureService }, { token: i4.NodeService }, { token: i4.ThreeJsImportService }, { token: i4.ValidatorsService }, { token: i5.TranslateService }], target: i0.ɵɵFactoryTarget.Component });
286
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: Models3dComponent, selector: "lib-models3d", viewQueries: [{ propertyName: "content", first: true, predicate: ["content"], descendants: true, static: true }], ngImport: i0, template: "<div class=\"container-fluid\" class=\"dashboard-tab\">\n <div class=\"m-3\">\n <lib-tab-navigation [menuItems]='menuItems' (onGoBack)=\"onGoBack()\"></lib-tab-navigation>\n </div>\n\n <div class=\"row main-form-container\">\n <div class=\"col-md-6 form-container\">\n\n <!-- List -->\n <ul class=\"list-group list-group-flush\" *ngIf=\"!modelForm\">\n <li class=\"list-group-item list-group-item-action\" *ngFor=\"let model of models; index as index\">\n <div class=\"d-flex justify-content-between align-items-center\" (click)=\"onToggleDetail(index)\">\n {{ model.name ? model.name : model.model3d }}\n <lib-chevron [conditionShowing]=\"index == modelIndexDetails\"></lib-chevron>\n </div>\n <div *ngIf=\"index == modelIndexDetails\">\n <ul class=\"list-group list-group-flush\">\n <li class=\"list-group-item bg-transparent\">{{'Name' | translate}} :\n {{ model.name ? model.name : ('Not provided' | translate) }}</li>\n <li class=\"list-group-item bg-transparent\">{{'3D model file' | translate}} :\n {{ model.model3d }}</li>\n <li class=\"list-group-item bg-transparent\">{{'Surface' | translate}}, m<sup>2</sup> :\n {{ model.surface ? model.surface : ('Not provided' | translate) }}</li>\n <li class=\"list-group-item bg-transparent\">{{'Initial placement' | translate}} :\n {{ model.captureMetadata ? model.captureMetadata : ('Automatic' | translate) }}</li>\n </ul>\n\n <lib-loader *ngIf=\"isProcessing\"></lib-loader>\n\n <div class=\"action-button-container mt-3\">\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2\"\n [disabled]=\"isProcessing\" (click)=\"onEdit(model)\">{{'Edit' | translate}}</button>\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\"\n [disabled]=\"isProcessing\" (click)=\"onDelete(model)\">{{'Delete' | translate}}</button>\n </div>\n </div>\n </li>\n </ul>\n\n <!-- An empty list with a button under it reads as \"nothing here\" and the button gets\n missed. With nothing to list, the action is the whole screen. -->\n <div *ngIf=\"!modelForm && models.length === 0\" class=\"text-center py-5\">\n <p class=\"text-muted\">{{'No 3D model yet for this location.' | translate}}</p>\n <button type=\"button\" class=\"btn btn-primary rounded-pill\"\n (click)=\"onAdd()\">{{'Add a 3D model' | translate}}</button>\n </div>\n\n <div class=\"action-button-container mt-3\" *ngIf=\"!modelForm && models.length > 0\">\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\"\n (click)=\"onAdd()\">{{'Add a 3D model' | translate}}</button>\n </div>\n\n <!-- Form -->\n <form *ngIf=\"modelForm\" [formGroup]=\"modelForm\" (ngSubmit)=\"onSubmit()\">\n <div class=\"mb-3 row\">\n <label class=\"col-sm-3 col-form-label\">{{'Name' | translate}} *</label>\n <div class=\"col-sm-9\">\n <input type=\"text\" class=\"form-control\" formControlName=\"name\"\n [class.is-invalid]=\"submitted && modelForm.controls['name'].invalid\">\n </div>\n </div>\n\n <div class=\"mb-3 row\">\n <label class=\"col-sm-3 col-form-label\">{{'3D model file' | translate}} *</label>\n <div class=\"col-sm-9\">\n <!-- styles.scss hides every input[type=file] app-wide; the convention here is a\n styled label wrapping the hidden input, as on the profile screen. -->\n <label for=\"model3d-file\" class=\"btn btn-outline-primary rounded-pill\">\n <input type=\"file\" id=\"model3d-file\" accept=\".glb,.gltf\"\n [disabled]=\"uploadPercent !== null\" (change)=\"onFileSelected($event)\">\n {{'Choose a file' | translate}}\n </label>\n <span *ngIf=\"uploadedFileName && uploadPercent === null\" class=\"ms-2\">{{uploadedFileName}}</span>\n\n <div *ngIf=\"uploadPercent !== null\" class=\"mt-2\">\n <div class=\"progress\" style=\"height: 6px;\" role=\"progressbar\"\n [attr.aria-valuenow]=\"uploadPercent\" aria-valuemin=\"0\" aria-valuemax=\"100\">\n <div class=\"progress-bar\" style=\"transition: none;\"\n [style.width.%]=\"uploadPercent\"></div>\n </div>\n <div class=\"form-text\">{{'Uploading' | translate}} {{uploadedFileName}} \u2014 {{uploadPercent}}%</div>\n </div>\n\n <div *ngIf=\"uploadPercent === null && modelForm.value.modelKey\" class=\"form-text text-success\">\n {{ modelForm.value.modelKey }}\n </div>\n\n <div *ngIf=\"submitted && modelKeyError\" class=\"text-danger\">\n {{ modelKeyError | translate }}\n </div>\n </div>\n </div>\n\n <ngb-alert *ngIf=\"errorMessage\" type=\"danger\" [dismissible]=\"false\">\n {{ errorMessage }}\n </ngb-alert>\n\n <lib-loader *ngIf=\"isProcessing\"></lib-loader>\n\n <div class=\"action-button-container mt-3\">\n <button type=\"submit\" class=\"btn btn-outline-primary rounded-pill me-2\"\n [disabled]=\"isProcessing\">{{'Save' | translate}}</button>\n <button type=\"button\" class=\"btn btn-outline-secondary rounded-pill\"\n [disabled]=\"isProcessing\" (click)=\"onCancel()\">{{'Cancel' | translate}}</button>\n </div>\n </form>\n </div>\n </div>\n</div>\n\n<ng-template #content let-modal>\n <div class=\"modal-header\">\n <h4 class=\"modal-title\">{{'Delete' | translate}}</h4>\n </div>\n <div class=\"modal-body\">\n <p>{{'This 3D model will be removed from this location.' | translate}}</p>\n </div>\n <div class=\"modal-footer\">\n <button type=\"button\" class=\"btn btn-outline-secondary rounded-pill\"\n (click)=\"modal.dismiss()\">{{'Cancel' | translate}}</button>\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\"\n (click)=\"modal.close('confirmed')\">{{'Delete' | translate}}</button>\n </div>\n</ng-template>\n", dependencies: [{ kind: "component", type: i3.NgbAlert, selector: "ngb-alert", inputs: ["animation", "dismissible", "type"], outputs: ["closed"], exportAs: ["ngbAlert"] }, { kind: "directive", type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { 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.LoaderComponent, selector: "lib-loader", inputs: ["useLogo", "color"] }, { kind: "component", type: i7.TabNavigationComponent, selector: "lib-tab-navigation", inputs: ["menuItems"], outputs: ["onGoBack"] }, { kind: "component", type: i8.ChevronComponent, selector: "lib-chevron", inputs: ["conditionShowing"] }, { kind: "pipe", type: i5.TranslatePipe, name: "translate" }] });
287
+ }
288
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: Models3dComponent, decorators: [{
289
+ type: Component,
290
+ args: [{ selector: 'lib-models3d', template: "<div class=\"container-fluid\" class=\"dashboard-tab\">\n <div class=\"m-3\">\n <lib-tab-navigation [menuItems]='menuItems' (onGoBack)=\"onGoBack()\"></lib-tab-navigation>\n </div>\n\n <div class=\"row main-form-container\">\n <div class=\"col-md-6 form-container\">\n\n <!-- List -->\n <ul class=\"list-group list-group-flush\" *ngIf=\"!modelForm\">\n <li class=\"list-group-item list-group-item-action\" *ngFor=\"let model of models; index as index\">\n <div class=\"d-flex justify-content-between align-items-center\" (click)=\"onToggleDetail(index)\">\n {{ model.name ? model.name : model.model3d }}\n <lib-chevron [conditionShowing]=\"index == modelIndexDetails\"></lib-chevron>\n </div>\n <div *ngIf=\"index == modelIndexDetails\">\n <ul class=\"list-group list-group-flush\">\n <li class=\"list-group-item bg-transparent\">{{'Name' | translate}} :\n {{ model.name ? model.name : ('Not provided' | translate) }}</li>\n <li class=\"list-group-item bg-transparent\">{{'3D model file' | translate}} :\n {{ model.model3d }}</li>\n <li class=\"list-group-item bg-transparent\">{{'Surface' | translate}}, m<sup>2</sup> :\n {{ model.surface ? model.surface : ('Not provided' | translate) }}</li>\n <li class=\"list-group-item bg-transparent\">{{'Initial placement' | translate}} :\n {{ model.captureMetadata ? model.captureMetadata : ('Automatic' | translate) }}</li>\n </ul>\n\n <lib-loader *ngIf=\"isProcessing\"></lib-loader>\n\n <div class=\"action-button-container mt-3\">\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2\"\n [disabled]=\"isProcessing\" (click)=\"onEdit(model)\">{{'Edit' | translate}}</button>\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\"\n [disabled]=\"isProcessing\" (click)=\"onDelete(model)\">{{'Delete' | translate}}</button>\n </div>\n </div>\n </li>\n </ul>\n\n <!-- An empty list with a button under it reads as \"nothing here\" and the button gets\n missed. With nothing to list, the action is the whole screen. -->\n <div *ngIf=\"!modelForm && models.length === 0\" class=\"text-center py-5\">\n <p class=\"text-muted\">{{'No 3D model yet for this location.' | translate}}</p>\n <button type=\"button\" class=\"btn btn-primary rounded-pill\"\n (click)=\"onAdd()\">{{'Add a 3D model' | translate}}</button>\n </div>\n\n <div class=\"action-button-container mt-3\" *ngIf=\"!modelForm && models.length > 0\">\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\"\n (click)=\"onAdd()\">{{'Add a 3D model' | translate}}</button>\n </div>\n\n <!-- Form -->\n <form *ngIf=\"modelForm\" [formGroup]=\"modelForm\" (ngSubmit)=\"onSubmit()\">\n <div class=\"mb-3 row\">\n <label class=\"col-sm-3 col-form-label\">{{'Name' | translate}} *</label>\n <div class=\"col-sm-9\">\n <input type=\"text\" class=\"form-control\" formControlName=\"name\"\n [class.is-invalid]=\"submitted && modelForm.controls['name'].invalid\">\n </div>\n </div>\n\n <div class=\"mb-3 row\">\n <label class=\"col-sm-3 col-form-label\">{{'3D model file' | translate}} *</label>\n <div class=\"col-sm-9\">\n <!-- styles.scss hides every input[type=file] app-wide; the convention here is a\n styled label wrapping the hidden input, as on the profile screen. -->\n <label for=\"model3d-file\" class=\"btn btn-outline-primary rounded-pill\">\n <input type=\"file\" id=\"model3d-file\" accept=\".glb,.gltf\"\n [disabled]=\"uploadPercent !== null\" (change)=\"onFileSelected($event)\">\n {{'Choose a file' | translate}}\n </label>\n <span *ngIf=\"uploadedFileName && uploadPercent === null\" class=\"ms-2\">{{uploadedFileName}}</span>\n\n <div *ngIf=\"uploadPercent !== null\" class=\"mt-2\">\n <div class=\"progress\" style=\"height: 6px;\" role=\"progressbar\"\n [attr.aria-valuenow]=\"uploadPercent\" aria-valuemin=\"0\" aria-valuemax=\"100\">\n <div class=\"progress-bar\" style=\"transition: none;\"\n [style.width.%]=\"uploadPercent\"></div>\n </div>\n <div class=\"form-text\">{{'Uploading' | translate}} {{uploadedFileName}} \u2014 {{uploadPercent}}%</div>\n </div>\n\n <div *ngIf=\"uploadPercent === null && modelForm.value.modelKey\" class=\"form-text text-success\">\n {{ modelForm.value.modelKey }}\n </div>\n\n <div *ngIf=\"submitted && modelKeyError\" class=\"text-danger\">\n {{ modelKeyError | translate }}\n </div>\n </div>\n </div>\n\n <ngb-alert *ngIf=\"errorMessage\" type=\"danger\" [dismissible]=\"false\">\n {{ errorMessage }}\n </ngb-alert>\n\n <lib-loader *ngIf=\"isProcessing\"></lib-loader>\n\n <div class=\"action-button-container mt-3\">\n <button type=\"submit\" class=\"btn btn-outline-primary rounded-pill me-2\"\n [disabled]=\"isProcessing\">{{'Save' | translate}}</button>\n <button type=\"button\" class=\"btn btn-outline-secondary rounded-pill\"\n [disabled]=\"isProcessing\" (click)=\"onCancel()\">{{'Cancel' | translate}}</button>\n </div>\n </form>\n </div>\n </div>\n</div>\n\n<ng-template #content let-modal>\n <div class=\"modal-header\">\n <h4 class=\"modal-title\">{{'Delete' | translate}}</h4>\n </div>\n <div class=\"modal-body\">\n <p>{{'This 3D model will be removed from this location.' | translate}}</p>\n </div>\n <div class=\"modal-footer\">\n <button type=\"button\" class=\"btn btn-outline-secondary rounded-pill\"\n (click)=\"modal.dismiss()\">{{'Cancel' | translate}}</button>\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\"\n (click)=\"modal.close('confirmed')\">{{'Delete' | translate}}</button>\n </div>\n</ng-template>\n" }]
291
+ }], ctorParameters: () => [{ type: i1.UntypedFormBuilder }, { type: i2.ActivatedRoute }, { type: i2.Router }, { type: i3.NgbModal }, { type: i4.SpaceService }, { type: i4.VisitService }, { type: i4.CaptureService }, { type: i4.NodeService }, { type: i4.ThreeJsImportService }, { type: i4.ValidatorsService }, { type: i5.TranslateService }], propDecorators: { content: [{
292
+ type: ViewChild,
293
+ args: ['content', { static: true }]
294
+ }] } });
295
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kZWxzM2QuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWxvY2F0aW9ucy9zcmMvbGliL2NvbXBvbmVudHMvbW9kZWxzM2QvbW9kZWxzM2QuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWxvY2F0aW9ucy9zcmMvbGliL2NvbXBvbmVudHMvbW9kZWxzM2QvbW9kZWxzM2QuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBVSxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDN0QsT0FBTyxFQUdILFVBQVUsR0FDYixNQUFNLGdCQUFnQixDQUFDO0FBRXhCLE9BQU8sRUFBWSxtQkFBbUIsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQzNFLE9BQU8sRUFTSCxhQUFhLEVBSWIsMEJBQTBCLEdBQzdCLE1BQU0sbUNBQW1DLENBQUM7QUFFM0MsT0FBTyxFQUFFLE9BQU8sRUFBYSxNQUFNLE1BQU0sQ0FBQzs7Ozs7Ozs7OztBQUUxQzs7Ozs7Ozs7O0dBU0c7QUFLSCxNQUFNLE9BQU8saUJBQWlCO0lBNkJkO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDQTtJQUNEO0lBQ0M7SUF0QzRCLE9BQU8sQ0FBQztJQUVoRCxTQUFTLEdBQWUsRUFBRSxDQUFDO0lBRTNCLFlBQVksQ0FBUTtJQUVwQixPQUFPLENBQVM7SUFFaEIsZ0dBQWdHO0lBQ2hHLE1BQU0sR0FBWSxFQUFFLENBQUM7SUFFckIsU0FBUyxDQUFtQjtJQUU1QixpQkFBaUIsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUV2QixTQUFTLEdBQUcsS0FBSyxDQUFDO0lBRWxCLFlBQVksR0FBRyxLQUFLLENBQUM7SUFFckIsU0FBUyxHQUFHLEtBQUssQ0FBQztJQUVsQixZQUFZ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QUFNLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDekIsQ0FBQztJQUNMLENBQUM7SUFFRCxnQkFBZ0IsQ0FBQyxNQUFXO1FBQ3hCLElBQUksTUFBTSxLQUFLLG1CQUFtQixDQUFDLEdBQUcsRUFBRSxDQUFDO1lBQ3JDLE9BQU8saUJBQWlCLENBQUM7UUFDN0IsQ0FBQztRQUNELElBQUksTUFBTSxLQUFLLG1CQUFtQixDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQ2hELE9BQU8sMkJBQTJCLENBQUM7UUFDdkMsQ0FBQztRQUNELE9BQU8sU0FBUyxNQUFNLEVBQUUsQ0FBQztJQUM3QixDQUFDO3dHQWxTUSxpQkFBaUI7NEZBQWpCLGlCQUFpQixzS0N4QzlCLHF0T0E0SEE7OzRGRHBGYSxpQkFBaUI7a0JBSjdCLFNBQVM7K0JBQ0ksY0FBYzsrV0FJZ0IsT0FBTztzQkFBOUMsU0FBUzt1QkFBQyxTQUFTLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQsIFZpZXdDaGlsZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgICBVbnR5cGVkRm9ybUdyb3VwLFxuICAgIFVudHlwZWRGb3JtQnVpbGRlcixcbiAgICBWYWxpZGF0b3JzLFxufSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBBY3RpdmF0ZWRSb3V0ZSwgUm91dGVyIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IE5nYk1vZGFsLCBNb2RhbERpc21pc3NSZWFzb25zIH0gZnJvbSAnQG5nLWJvb3RzdHJhcC9uZy1ib290c3RyYXAnO1xuaW1wb3J0IHtcbiAgICBOb2RlLFxuICAgIFZpc2l0LFxuICAgIE1lbnVJdGVtLFxuICAgIFRocmVlSnNJbXBvcnRTZXJ2aWNlLFxuICAgIENhcHR1cmVTZXJ2aWNlLFxuICAgIE5vZGVTZXJ2aWNlLFxuICAgIFNwYWNlU2VydmljZSxcbiAgICBWaXNpdFNlcnZpY2UsXG4gICAgQ2FwdHVyZVZpZXdlcixcbiAgICBDYXB0dXJlLFxuICAgIFNwYWNlLFxuICAgIFZhbGlkYXRvcnNTZXJ2aWNlLFxuICAgIHVwbG9hZEZpbGVUb1MzV2l0aFByb2dyZXNzLFxufSBmcm9tICdAc21hcnRlcnBsYW4vbmd4LXNtYXJ0ZXJwbGFuLWNvcmUnO1xuaW1wb3J0IHsgVHJhbnNsYXRlU2VydmljZSB9IGZyb20gJ0BuZ3gtdHJhbnNsYXRlL2NvcmUnO1xuaW1wb3J0IHsgU3ViamVjdCwgdGFrZVVudGlsIH0gZnJvbSAncnhqcyc7XG5cbi8qKlxuICogQWRtaW4gc2NyZWVuIGZvciB0aGUgM0QgbW9kZWxzIGEgc2l0ZSBjYW4gYmUgdmlzaXRlZCB3aXRoLlxuICpcbiAqIFRoZXNlIGFyZSBzdG9yZWQgdGhlIHNhbWUgd2F5IE1hdHRlcnBvcnQgdmlzaXRzIGFyZSAtIGEgQ2FwdHVyZSBwbHVzIGEgTm9kZSAtIHdpdGggdGhlIHZpZXdlciBzZXRcbiAqIHRvIFRIUkVFSlMgYW5kIHRoZSAuZ2xiJ3MgUzMga2V5IGluIHRoZSBub2RlJ3MgbW9kZWwzRC4gU2hhcmluZyB0aGUgc3RvcmFnZSBpcyB3aGF0IGxldHMgYSBzaXRlXG4gKiBjYXJyeSBzZXZlcmFsIG1vZGVscyBhbmQgd2hhdCBtYWtlcyB0YWdzIGZvbGxvdyB0aGUgc2FtZSBQT0kgcmVjb3JkcyBpbiBlaXRoZXIgdmlld2VyOyB0aGUgc3BsaXRcbiAqIGhlcmUgaXMgb25seSBpbiB0aGUgZm9ybTogYSAzRCBtb2RlbCBpcyBhIG5hbWUgYW5kIGEgZmlsZSwgd2hlcmUgYSBNYXR0ZXJwb3J0IHZpc2l0IGlzIGEgbW9kZWwgSURcbiAqIGFuZCBjYXB0dXJlIGRldGFpbHMuIFBsYWNlbWVudCBhbmQgYWxpZ25tZW50IGFyZSBub3QgYXNrZWQgZm9yIGhlcmUgLSB0aGUgdmlld2VyJ3MgYWxpZ25tZW50IHRvb2xcbiAqIHdyaXRlcyB0aGVtIGludG8gdGhlIGNhcHR1cmUncyBtZXRhZGF0YSBvbmNlIHNvbWVvbmUgY2FsaWJyYXRlcyBhZ2FpbnN0IGEgcmVhbCBzY2VuZS5cbiAqL1xuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6ICdsaWItbW9kZWxzM2QnLFxuICAgIHRlbXBsYXRlVXJsOiAnLi9tb2RlbHMzZC5jb21wb25lbnQuaHRtbCcsXG59KVxuZXhwb3J0IGNsYXNzIE1vZGVsczNkQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcbiAgICBAVmlld0NoaWxkKCdjb250ZW50JywgeyBzdGF0aWM6IHRydWUgfSkgY29udGVudDtcblxuICAgIG1lbnVJdGVtczogTWVudUl0ZW1bXSA9IFtdO1xuXG4gICAgY3VycmVudFNwYWNlOiBTcGFjZTtcblxuICAgIHNwYWNlSWQ6IHN0cmluZztcblxuICAgIC8qKiBPbmx5IHRoZSB2aXNpdHMgY2FwdHVyZWQgYXMgM0QgbW9kZWxzOyBNYXR0ZXJwb3J0IG9uZXMgc3RheSBvbiB0aGUgVmlydHVhbCBWaXNpdHMgc2NyZWVuLiAqL1xuICAgIG1vZGVsczogVmlzaXRbXSA9IFtdO1xuXG4gICAgbW9kZWxGb3JtOiBVbnR5cGVkRm9ybUdyb3VwO1xuXG4gICAgbW9kZWxJbmRleERldGFpbHMgPSAtMTtcblxuICAgIGlzRWRpdGluZyA9IGZhbHNlO1xuXG4gICAgaXNQcm9jZXNzaW5nID0gZmFsc2U7XG5cbiAgICBzdWJtaXR0ZWQgPSBmYWxzZTtcblxuICAgIGVycm9yTWVzc2FnZTogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG5cbiAgICBtb2RhbFJlZmVyZW5jZTogYW55O1xuXG4gICAgZGVzdHJveSQgPSBuZXcgU3ViamVjdCgpO1xuXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIHByaXZhdGUgZmI6IFVudHlwZWRGb3JtQnVpbGRlcixcbiAgICAgICAgcHJpdmF0ZSByb3V0ZTogQWN0aXZhdGVkUm91dGUsXG4gICAgICAgIHByaXZhdGUgcm91dGVyOiBSb3V0ZXIsXG4gICAgICAgIHByaXZhdGUgbW9kYWxTZXJ2aWNlOiBOZ2JNb2RhbCxcbiAgICAgICAgcHJpdmF0ZSBzcGFjZVNlcnZpY2U6IFNwYWNlU2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSB2aXNpdFNlcnZpY2U6IFZpc2l0U2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSBjYXB0dXJlU2VydmljZTogQ2FwdHVyZVNlcnZpY2UsXG4gICAgICAgIHByaXZhdGUgbm9kZVNlcnZpY2U6IE5vZGVTZXJ2aWNlLFxuICAgICAgICBwcml2YXRlIHRocmVlanNJbXBvcnRTZXJ2aWNlOiBUaHJlZUpzSW1wb3J0U2VydmljZSxcbiAgICAgICAgcHVibGljIHZhbGlkYXRvcnNTZXJ2aWNlOiBWYWxpZGF0b3JzU2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSB0cmFuc2xhdGU6IFRyYW5zbGF0ZVNlcnZpY2UsXG4gICAgKSB7fVxuXG4gICAgYXN5bmMgbmdPbkluaXQoKSB7XG4gICAgICAgIHRoaXMuc3BhY2VJZCA9IHRoaXMucm91dGUuc25hcHNob3QucGFyYW1NYXAuZ2V0KCdpZCcpO1xuICAgICAgICBhd2FpdCB0aGlzLnJlbG9hZCgpO1xuICAgIH1cblxuICAgIG5nT25EZXN0cm95KCkge1xuICAgICAgICB0aGlzLmRlc3Ryb3kkLm5leHQodHJ1ZSk7XG4gICAgICAgIHRoaXMuZGVzdHJveSQuY29tcGxldGUoKTtcbiAgICB9XG5cbiAgICBhc3luYyByZWxvYWQoKSB7XG4gICAgICAgIHRoaXMuY3VycmVudFNwYWNlID0gYXdhaXQgdGhpcy5zcGFjZVNlcnZpY2UuZ2V0U3BhY2UodGhpcy5zcGFjZUlkKTtcbiAgICAgICAgdGhpcy5zZXR1cE1lbnVJdGVtcygpO1xuICAgICAgICBjb25zdCB2aXNpdHMgPSBhd2FpdCB0aGlzLnZpc2l0U2VydmljZS5nZXRWaXNpdHNGb3JTcGFjZUZvclVzZXIodGhpcy5zcGFjZUlkKTtcbiAgICAgICAgdGhpcy5tb2RlbHMgPSAodmlzaXRzID8/IFtdKS5maWx0ZXIoKHZpc2l0KSA9PiB2aXNpdC52aWV3ZXIgPT09IENhcHR1cmVWaWV3ZXIuVEhSRUVKUyk7XG4gICAgfVxuXG4gICAgc2V0dXBNZW51SXRlbXMoKSB7XG4gICAgICAgIHRoaXMubWVudUl0ZW1zID0gW1xuICAgICAgICAgICAgeyBsYWJlbDogJ0xvY2F0aW9ucycsIHVybDogJy9sb2NhbGlzYXRpb24nIH0sXG4gICAgICAgICAgICB7IGxhYmVsOiB0aGlzLmN1cnJlbnRTcGFjZS5uYW1lLCB1cmw6IGAvbG9jYWxpc2F0aW9uLyR7dGhpcy5jdXJyZW50U3BhY2UuaWR9YCB9LFxuICAgICAgICAgICAgeyBsYWJlbDogJzNEIE1vZGVscycsIHVybDogYC9sb2NhbGlzYXRpb24vJHt0aGlzLmN1cnJlbnRTcGFjZS5pZH0vbW9kZWxzM2RgIH0sXG4gICAgICAgIF07XG4gICAgfVxuXG4gICAgb25Hb0JhY2soKSB7XG4gICAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFsnL2Rhc2hib2FyZC9sb2NhbGlzYXRpb24nLCB0aGlzLnNwYWNlSWRdKTtcbiAgICB9XG5cbiAgICBvblRvZ2dsZURldGFpbChpbmRleDogbnVtYmVyKSB7XG4gICAgICAgIHRoaXMubW9kZWxJbmRleERldGFpbHMgPSBpbmRleCA9PT0gdGhpcy5tb2RlbEluZGV4RGV0YWlscyA/IC0xIDogaW5kZXg7XG4gICAgfVxuXG4gICAgb25BZGQoKSB7XG4gICAgICAgIHRoaXMuaW5pdEZvcm0oKTtcbiAgICAgICAgdGhpcy5tZW51SXRlbXMucHVzaCh7IGxhYmVsOiAnTmV3JyB9KTtcbiAgICB9XG5cbiAgICBvbkVkaXQobW9kZWw6IFZpc2l0KSB7XG4gICAgICAgIHRoaXMuaW5pdEZvcm0obW9kZWwpO1xuICAgICAgICB0aGlzLmlzRWRpdGluZyA9IHRydWU7XG4gICAgICAgIHRoaXMubWVudUl0ZW1zLnB1c2goeyBsYWJlbDogbW9kZWwubmFtZSB9KTtcbiAgICB9XG5cbiAgICBvbkNhbmNlbCgpIHtcbiAgICAgICAgdGhpcy5tb2RlbEZvcm0gPSBudWxsO1xuICAgICAgICB0aGlzLmlzRWRpdGluZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLnN1Ym1pdHRlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLmVycm9yTWVzc2FnZSA9IG51bGw7XG4gICAgICAgIHRoaXMuc2V0dXBNZW51SXRlbXMoKTtcbiAgICB9XG5cbiAgICBpbml0Rm9ybShpbnB1dDogVmlzaXQgPSBudWxsKSB7XG4gICAgICAgIHRoaXMuc3VibWl0dGVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuZXJyb3JNZXNzYWdlID0gbnVsbDtcbiAgICAgICAgaWYgKGlucHV0KSB7XG4gICAgICAgICAgICB0aGlzLm1vZGVsRm9ybSA9IHRoaXMuZmIuZ3JvdXAoe1xuICAgICAgICAgICAgICAgIGNhcHR1cmVJRDogaW5wdXQuY2FwdHVyZUlELFxuICAgICAgICAgICAgICAgIG5vZGVJRDogaW5wdXQubm9kZS5pZCxcbiAgICAgICAgICAgICAgICBuYW1lOiBbaW5wdXQubmFtZSwgW1ZhbGlkYXRvcnMucmVxdWlyZWRdXSxcbiAgICAgICAgICAgICAgICBtb2RlbEtleTogW2lucHV0Lm1vZGVsM2QsIFtWYWxpZGF0b3JzLnJlcXVpcmVkXV0sXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMubW9kZWxGb3JtID0gdGhpcy5mYi5ncm91cCh7XG4gICAgICAgICAgICAgICAgbmFtZTogW251bGwsIFtWYWxpZGF0b3JzLnJlcXVpcmVkXV0sXG4gICAgICAgICAgICAgICAgbW9kZWxLZXk6IFtudWxsLCBbVmFsaWRhdG9ycy5yZXF1aXJlZF1dLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKiogVXBsb2FkIHByb2dyZXNzIGFzIGEgcGVyY2VudGFnZSwgb3IgbnVsbCB3aGVuIG5vdGhpbmcgaXMgdXBsb2FkaW5nLiAqL1xuICAgIHVwbG9hZFBlcmNlbnQ6IG51bWJlciB8IG51bGwgPSBudWxsO1xuXG4gICAgdXBsb2FkZWRGaWxlTmFtZTogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG5cbiAgICAvKipcbiAgICAgKiBVcGxvYWRzIHRoZSBjaG9zZW4gLmdsYiBhbmQgcHV0cyB0aGUgcmVzdWx0aW5nIGtleSBvbiB0aGUgZm9ybS5cbiAgICAgKlxuICAgICAqIFN0b3JhZ2UucHV0IGF1dGhlbnRpY2F0ZXMgd2l0aCB0aGUgc2lnbmVkLWluIHVzZXIncyBzZXNzaW9uIHJhdGhlciB0aGFuIHNlcGFyYXRlIFMzXG4gICAgICogY3JlZGVudGlhbHMsIHNvIGFueW9uZSB3aG8gY2FuIHJlYWNoIHRoaXMgc2NyZWVuIGNhbiB1cGxvYWQgLSB3aGljaCBpcyB3aGF0IG1ha2VzIHBpY2tpbmcgYVxuICAgICAqIGZpbGUgYSBiZXR0ZXIgYXNrIHRoYW4gdHlwaW5nIGEga2V5IHNvbWVvbmUgZWxzZSBoYWQgdG8gcHJvZHVjZS5cbiAgICAgKi9cbiAgICBhc3luYyBvbkZpbGVTZWxlY3RlZChldmVudDogRXZlbnQpIHtcbiAgICAgICAgY29uc3QgaW5wdXQgPSBldmVudC50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudDtcbiAgICAgICAgY29uc3QgZmlsZSA9IGlucHV0LmZpbGVzPy5bMF07XG4gICAgICAgIGlmICghZmlsZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgbmFtZSA9IGZpbGUubmFtZS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICBpZiAoIW5hbWUuZW5kc1dpdGgoJy5nbGInKSAmJiAhbmFtZS5lbmRzV2l0aCgnLmdsdGYnKSkge1xuICAgICAgICAgICAgdGhpcy5lcnJvck1lc3NhZ2UgPSB0aGlzLnRyYW5zbGF0ZS5pbnN0YW50KCdPbmx5IC5nbGIgb3IgLmdsdGYgZmlsZXMgY2FuIGJlIHVzZWQgYXMgYSAzRCBtb2RlbC4nKTtcbiAgICAgICAgICAgIGlucHV0LnZhbHVlID0gJyc7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmVycm9yTWVzc2FnZSA9IG51bGw7XG4gICAgICAgIHRoaXMudXBsb2FkUGVyY2VudCA9IDA7XG4gICAgICAgIHRoaXMudXBsb2FkZWRGaWxlTmFtZSA9IGZpbGUubmFtZTtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3Qga2V5ID0gYXdhaXQgdXBsb2FkRmlsZVRvUzNXaXRoUHJvZ3Jlc3MoXG4gICAgICAgICAgICAgICAgYG1vZGVsczNkLyR7dGhpcy5zcGFjZUlkfS9gLFxuICAgICAgICAgICAgICAgIGZpbGUsXG4gICAgICAgICAgICAgICAgKGZyYWN0aW9uKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudXBsb2FkUGVyY2VudCA9IE1hdGgucm91bmQoZnJhY3Rpb24gKiAxMDApO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgdGhpcy5tb2RlbEZvcm0ucGF0Y2hWYWx1ZSh7IG1vZGVsS2V5OiBrZXkgfSk7XG4gICAgICAgICAgICAvLyBOYW1lIHRoZSBtb2RlbCBhZnRlciB0aGUgZmlsZSB3aGVuIHRoZSBmaWVsZCBpcyBzdGlsbCBlbXB0eSwgc28gdGhlIGNvbW1vbiBjYXNlIG5lZWRzXG4gICAgICAgICAgICAvLyBubyBleHRyYSB0eXBpbmcuXG4gICAgICAgICAgICBpZiAoIXRoaXMubW9kZWxGb3JtLnZhbHVlLm5hbWUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm1vZGVsRm9ybS5wYXRjaFZhbHVlKHsgbmFtZTogZmlsZS5uYW1lLnJlcGxhY2UoL1xcLihnbGJ8Z2x0ZikkL2ksICcnKSB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIHRoaXMuZXJyb3JNZXNzYWdlID0gdGhpcy5kZXNjcmliZUVycm9yKGVycm9yKTtcbiAgICAgICAgICAgIHRoaXMudXBsb2FkZWRGaWxlTmFtZSA9IG51bGw7XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgICB0aGlzLnVwbG9hZFBlcmNlbnQgPSBudWxsO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqIFZhbGlkYXRpb24gZXJyb3IgZm9yIHRoZSAuZ2xiIGtleSwgb3IgbnVsbC4gKi9cbiAgICBnZXQgbW9kZWxLZXlFcnJvcigpOiBzdHJpbmcgfCBudWxsIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudGhyZWVqc0ltcG9ydFNlcnZpY2UudmFsaWRhdGVNb2RlbEtleSh0aGlzLm1vZGVsRm9ybT8udmFsdWUubW9kZWxLZXkpO1xuICAgIH1cblxuICAgIGFzeW5jIG9uU3VibWl0KCkge1xuICAgICAgICB0aGlzLnN1Ym1pdHRlZCA9IHRydWU7XG4gICAgICAgIHRoaXMuZXJyb3JNZXNzYWdlID0gbnVsbDtcblxuICAgICAgICBpZiAoIXRoaXMubW9kZWxGb3JtLnZhbGlkIHx8IHRoaXMubW9kZWxLZXlFcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZm9ybVZhbHVlID0gdGhpcy5tb2RlbEZvcm0udmFsdWU7XG4gICAgICAgIGNvbnN0IGNhcHR1cmUgPSB7XG4gICAgICAgICAgICB2aWV3ZXI6IENhcHR1cmVWaWV3ZXIuVEhSRUVKUyxcbiAgICAgICAgICAgIHRha2VuQXQ6IERhdGUubm93KCksXG4gICAgICAgICAgICBzcGFjZUlEOiB0aGlzLmN1cnJlbnRTcGFjZS5pZCxcbiAgICAgICAgfSBhcyBDYXB0dXJlO1xuXG4gICAgICAgIHRoaXMuaXNQcm9jZXNzaW5nID0gdHJ1ZTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmICh0aGlzLmlzRWRpdGluZykge1xuICAgICAgICAgICAgICAgIGNhcHR1cmUuaWQgPSBmb3JtVmFsdWUuY2FwdHVyZUlEO1xuICAgICAgICAgICAgICAgIC8vIG1ldGFkYXRhIGlzIGxlZnQgdW50b3VjaGVkIG9uIGVkaXQ6IHRoZSBhbGlnbm1lbnQgdG9vbCB3cml0ZXMgdGhlIHZpc2l0J3MgdGFnXG4gICAgICAgICAgICAgICAgLy8gdHJhbnNmb3JtIHRoZXJlLCBhbmQgcmVzZW5kaW5nIHRoZSBmb3JtJ3MgaWRlYSBvZiBpdCB3b3VsZCB3aXBlIHRoYXQuXG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5jYXB0dXJlU2VydmljZS51cGRhdGVDYXB0dXJlKGNhcHR1cmUpO1xuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMubm9kZVNlcnZpY2UudXBkYXRlTm9kZSh7XG4gICAgICAgICAgICAgICAgICAgIGlkOiBmb3JtVmFsdWUubm9kZUlELFxuICAgICAgICAgICAgICAgICAgICBtb2RlbDNEOiBmb3JtVmFsdWUubW9kZWxLZXksXG4gICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiBmb3JtVmFsdWUubmFtZSxcbiAgICAgICAgICAgICAgICB9IGFzIE5vZGUpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLmNyZWF0ZU1vZGVsKGZvcm1WYWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhd2FpdCB0aGlzLnJlbG9hZCgpO1xuICAgICAgICAgICAgdGhpcy5vbkNhbmNlbCgpO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgLy8gVGhlIG1vc3QgbGlrZWx5IGZhaWx1cmUgaXMgdGhlIGJhY2tlbmQgcmVqZWN0aW5nIHRoZSBUSFJFRUpTIGVudW0gdmFsdWUsIHdoaWNoIGhhcyBub3RcbiAgICAgICAgICAgIC8vIHNoaXBwZWQgeWV0IC0gc2F5IHNvIHJhdGhlciB0aGFuIGxlYXZpbmcgYW4gZW1wdHkgc2NyZWVuLlxuICAgICAgICAgICAgdGhpcy5lcnJvck1lc3NhZ2UgPSB0aGlzLmRlc2NyaWJlRXJyb3IoZXJyb3IpO1xuICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgdGhpcy5pc1Byb2Nlc3NpbmcgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKiBDcmVhdGVzIHRoZSBjYXB0dXJlLCBpdHMgbm9kZSwgYW5kIHRoZSB6b25lL3BsYW4vbmF2aWdhdGlvbiB0aGUgdmlld2VyIG5lZWRzLiAqL1xuICAgIHByaXZhdGUgYXN5bmMgY3JlYXRlTW9kZWwoZm9ybVZhbHVlOiBhbnkpIHtcbiAgICAgICAgY29uc3QgY2FwdHVyZSA9IGF3YWl0IHRoaXMuY2FwdHVyZVNlcnZpY2UuY3JlYXRlQ2FwdHVyZSh7XG4gICAgICAgICAgICB2aWV3ZXI6IENhcHR1cmVWaWV3ZXIuVEhSRUVKUyxcbiAgICAgICAgICAgIHRha2VuQXQ6IERhdGUubm93KCksXG4gICAgICAgICAgICBzcGFjZUlEOiB0aGlzLmN1cnJlbnRTcGFjZS5pZCxcbiAgICAgICAgfSBhcyBDYXB0dXJlKTtcblxuICAgICAgICBpZiAoIWNhcHR1cmUpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ291bGQgbm90IGNyZWF0ZSB0aGUgY2FwdHVyZSBmb3IgdGhpcyAzRCBtb2RlbC4nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IG5vZGUgPSBhd2FpdCB0aGlzLm5vZGVTZXJ2aWNlLmNyZWF0ZU5vZGUoe1xuICAgICAgICAgICAgbW9kZWwzRDogZm9ybVZhbHVlLm1vZGVsS2V5LFxuICAgICAgICAgICAgY2FwdHVyZUlEOiBjYXB0dXJlLmlkLFxuICAgICAgICAgICAgbWV0YWRhdGE6IGZvcm1WYWx1ZS5uYW1lLFxuICAgICAgICB9IGFzIE5vZGUpO1xuXG4gICAgICAgIGF3YWl0IHRoaXMudGhyZWVqc0ltcG9ydFNlcnZpY2UuaW1wb3J0RGF0YShcbiAgICAgICAgICAgIHRoaXMuc3BhY2VJZCxcbiAgICAgICAgICAgIG51bGwsXG4gICAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICAgIG5vZGUsXG4gICAgICAgICAgICB0cnVlLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIGFzeW5jIG9uRGVsZXRlKG1vZGVsOiBWaXNpdCkge1xuICAgICAgICB0aGlzLm1vZGFsUmVmZXJlbmNlID0gdGhpcy5tb2RhbFNlcnZpY2Uub3Blbih0aGlzLmNvbnRlbnQpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5tb2RhbFJlZmVyZW5jZS5yZXN1bHQ7XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgcmV0dXJuOyAvLyBkaXNtaXNzZWRcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuaXNQcm9jZXNzaW5nID0gdHJ1ZTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMubm9kZVNlcnZpY2UuZGVsZXRlTm9kZShtb2RlbC5ub2RlLmlkKTtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuY2FwdHVyZVNlcnZpY2UuZGVsZXRlQ2FwdHVyZShtb2RlbC5jYXB0dXJlSUQpO1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5yZWxvYWQoKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIHRoaXMuZXJyb3JNZXNzYWdlID0gdGhpcy5kZXNjcmliZUVycm9yKGVycm9yKTtcbiAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgIHRoaXMuaXNQcm9jZXNzaW5nID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUdXJucyB3aGF0ZXZlciB3YXMgdGhyb3duIGludG8gc29tZXRoaW5nIHJlYWRhYmxlLlxuICAgICAqXG4gICAgICogQXBwU3luYyByZWplY3Rpb25zIGFycml2ZSBhcyB7IGVycm9yczogW3sgbWVzc2FnZSB9XSB9IHdpdGggbm8gYG1lc3NhZ2VgIG9mIHRoZWlyIG93biwgc28gdGhlXG4gICAgICogb2J2aW91cyBgZXJyb3IubWVzc2FnZSA/PyBTdHJpbmcoZXJyb3IpYCByZW5kZXJzIHRoZW0gYXMgXCJbb2JqZWN0IE9iamVjdF1cIiAtIHdoaWNoIGhpZGVzXG4gICAgICogZXhhY3RseSB0aGUgY2FzZXMgd29ydGggcmVhZGluZywgbGlrZSB0aGUgYmFja2VuZCByZWZ1c2luZyBhbiBlbnVtIHZhbHVlIGl0IGRvZXMgbm90IGtub3cuXG4gICAgICovXG4gICAgcHJpdmF0ZSBkZXNjcmliZUVycm9yKGVycm9yOiBhbnkpOiBzdHJpbmcge1xuICAgICAgICBpZiAodHlwZW9mIGVycm9yID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgcmV0dXJuIGVycm9yO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGdyYXBoUWxFcnJvcnMgPSBlcnJvcj8uZXJyb3JzO1xuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShncmFwaFFsRXJyb3JzKSAmJiBncmFwaFFsRXJyb3JzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHJldHVybiBncmFwaFFsRXJyb3JzLm1hcCgoZTogYW55KSA9PiBlPy5tZXNzYWdlID8/IEpTT04uc3RyaW5naWZ5KGUpKS5qb2luKCcgfCAnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZXJyb3I/Lm1lc3NhZ2UpIHtcbiAgICAgICAgICAgIHJldHVybiBlcnJvci5tZXNzYWdlO1xuICAgICAgICB9XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoZXJyb3IpO1xuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgIHJldHVybiBTdHJpbmcoZXJyb3IpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZ2V0RGlzbWlzc1JlYXNvbihyZWFzb246IGFueSk6IHN0cmluZyB7XG4gICAgICAgIGlmIChyZWFzb24gPT09IE1vZGFsRGlzbWlzc1JlYXNvbnMuRVNDKSB7XG4gICAgICAgICAgICByZXR1cm4gJ2J5IHByZXNzaW5nIEVTQyc7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJlYXNvbiA9PT0gTW9kYWxEaXNtaXNzUmVhc29ucy5CQUNLRFJPUF9DTElDSykge1xuICAgICAgICAgICAgcmV0dXJuICdieSBjbGlja2luZyBvbiBhIGJhY2tkcm9wJztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYHdpdGg6ICR7cmVhc29ufWA7XG4gICAgfVxufVxuIiwiPGRpdiBjbGFzcz1cImNvbnRhaW5lci1mbHVpZFwiIGNsYXNzPVwiZGFzaGJvYXJkLXRhYlwiPlxuICAgIDxkaXYgY2xhc3M9XCJtLTNcIj5cbiAgICAgICAgPGxpYi10YWItbmF2aWdhdGlvbiBbbWVudUl0ZW1zXT0nbWVudUl0ZW1zJyAob25Hb0JhY2spPVwib25Hb0JhY2soKVwiPjwvbGliLXRhYi1uYXZpZ2F0aW9uPlxuICAgIDwvZGl2PlxuXG4gICAgPGRpdiBjbGFzcz1cInJvdyBtYWluLWZvcm0tY29udGFpbmVyXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtbWQtNiBmb3JtLWNvbnRhaW5lclwiPlxuXG4gICAgICAgICAgICA8IS0tIExpc3QgLS0+XG4gICAgICAgICAgICA8dWwgY2xhc3M9XCJsaXN0LWdyb3VwIGxpc3QtZ3JvdXAtZmx1c2hcIiAqbmdJZj1cIiFtb2RlbEZvcm1cIj5cbiAgICAgICAgICAgICAgICA8bGkgY2xhc3M9XCJsaXN0LWdyb3VwLWl0ZW0gbGlzdC1ncm91cC1pdGVtLWFjdGlvblwiICpuZ0Zvcj1cImxldCBtb2RlbCBvZiBtb2RlbHM7IGluZGV4IGFzIGluZGV4XCI+XG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkLWZsZXgganVzdGlmeS1jb250ZW50LWJldHdlZW4gYWxpZ24taXRlbXMtY2VudGVyXCIgKGNsaWNrKT1cIm9uVG9nZ2xlRGV0YWlsKGluZGV4KVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAge3sgbW9kZWwubmFtZSA/IG1vZGVsLm5hbWUgOiBtb2RlbC5tb2RlbDNkIH19XG4gICAgICAgICAgICAgICAgICAgICAgICA8bGliLWNoZXZyb24gW2NvbmRpdGlvblNob3dpbmddPVwiaW5kZXggPT0gbW9kZWxJbmRleERldGFpbHNcIj48L2xpYi1jaGV2cm9uPlxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiAqbmdJZj1cImluZGV4ID09IG1vZGVsSW5kZXhEZXRhaWxzXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8dWwgY2xhc3M9XCJsaXN0LWdyb3VwIGxpc3QtZ3JvdXAtZmx1c2hcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGkgY2xhc3M9XCJsaXN0LWdyb3VwLWl0ZW0gYmctdHJhbnNwYXJlbnRcIj57eydOYW1lJyB8IHRyYW5zbGF0ZX19IDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge3sgbW9kZWwubmFtZSA/IG1vZGVsLm5hbWUgOiAoJ05vdCBwcm92aWRlZCcgfCB0cmFuc2xhdGUpIH19PC9saT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGkgY2xhc3M9XCJsaXN0LWdyb3VwLWl0ZW0gYmctdHJhbnNwYXJlbnRcIj57eyczRCBtb2RlbCBmaWxlJyB8IHRyYW5zbGF0ZX19IDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge3sgbW9kZWwubW9kZWwzZCB9fTwvbGk+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGxpIGNsYXNzPVwibGlzdC1ncm91cC1pdGVtIGJnLXRyYW5zcGFyZW50XCI+e3snU3VyZmFjZScgfCB0cmFuc2xhdGV9fSwgbTxzdXA+Mjwvc3VwPiA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7IG1vZGVsLnN1cmZhY2UgPyBtb2RlbC5zdXJmYWNlIDogKCdOb3QgcHJvdmlkZWQnIHwgdHJhbnNsYXRlKSB9fTwvbGk+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGxpIGNsYXNzPVwibGlzdC1ncm91cC1pdGVtIGJnLXRyYW5zcGFyZW50XCI+e3snSW5pdGlhbCBwbGFjZW1lbnQnIHwgdHJhbnNsYXRlfX0gOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7eyBtb2RlbC5jYXB0dXJlTWV0YWRhdGEgPyBtb2RlbC5jYXB0dXJlTWV0YWRhdGEgOiAoJ0F1dG9tYXRpYycgfCB0cmFuc2xhdGUpIH19PC9saT5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvdWw+XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxsaWItbG9hZGVyICpuZ0lmPVwiaXNQcm9jZXNzaW5nXCI+PC9saWItbG9hZGVyPlxuXG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYWN0aW9uLWJ1dHRvbi1jb250YWluZXIgbXQtM1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYnRuIGJ0bi1vdXRsaW5lLXByaW1hcnkgcm91bmRlZC1waWxsIG1lLTJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiaXNQcm9jZXNzaW5nXCIgKGNsaWNrKT1cIm9uRWRpdChtb2RlbClcIj57eydFZGl0JyB8IHRyYW5zbGF0ZX19PC9idXR0b24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidG4gYnRuLW91dGxpbmUtcHJpbWFyeSByb3VuZGVkLXBpbGxcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiaXNQcm9jZXNzaW5nXCIgKGNsaWNrKT1cIm9uRGVsZXRlKG1vZGVsKVwiPnt7J0RlbGV0ZScgfCB0cmFuc2xhdGV9fTwvYnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIDwvbGk+XG4gICAgICAgICAgICA8L3VsPlxuXG4gICAgICAgICAgICA8IS0tIEFuIGVtcHR5IGxpc3Qgd2l0aCBhIGJ1dHRvbiB1bmRlciBpdCByZWFkcyBhcyBcIm5vdGhpbmcgaGVyZVwiIGFuZCB0aGUgYnV0dG9uIGdldHNcbiAgICAgICAgICAgICAgICAgbWlzc2VkLiBXaXRoIG5vdGhpbmcgdG8gbGlzdCwgdGhlIGFjdGlvbiBpcyB0aGUgd2hvbGUgc2NyZWVuLiAtLT5cbiAgICAgICAgICAgIDxkaXYgKm5nSWY9XCIhbW9kZWxGb3JtICYmIG1vZGVscy5sZW5ndGggPT09IDBcIiBjbGFzcz1cInRleHQtY2VudGVyIHB5LTVcIj5cbiAgICAgICAgICAgICAgICA8cCBjbGFzcz1cInRleHQtbXV0ZWRcIj57eydObyAzRCBtb2RlbCB5ZXQgZm9yIHRoaXMgbG9jYXRpb24uJyB8IHRyYW5zbGF0ZX19PC9wPlxuICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYnRuIGJ0bi1wcmltYXJ5IHJvdW5kZWQtcGlsbFwiXG4gICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJvbkFkZCgpXCI+e3snQWRkIGEgM0QgbW9kZWwnIHwgdHJhbnNsYXRlfX08L2J1dHRvbj5cbiAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYWN0aW9uLWJ1dHRvbi1jb250YWluZXIgbXQtM1wiICpuZ0lmPVwiIW1vZGVsRm9ybSAmJiBtb2RlbHMubGVuZ3RoID4gMFwiPlxuICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYnRuIGJ0bi1vdXRsaW5lLXByaW1hcnkgcm91bmRlZC1waWxsXCJcbiAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cIm9uQWRkKClcIj57eydBZGQgYSAzRCBtb2RlbCcgfCB0cmFuc2xhdGV9fTwvYnV0dG9uPlxuICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgIDwhLS0gRm9ybSAtLT5cbiAgICAgICAgICAgIDxmb3JtICpuZ0lmPVwibW9kZWxGb3JtXCIgW2Zvcm1Hcm91cF09XCJtb2RlbEZvcm1cIiAobmdTdWJtaXQpPVwib25TdWJtaXQoKVwiPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtYi0zIHJvd1wiPlxuICAgICAgICAgICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJjb2wtc20tMyBjb2wtZm9ybS1sYWJlbFwiPnt7J05hbWUnIHwgdHJhbnNsYXRlfX0gKjwvbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtc20tOVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJ0ZXh0XCIgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIiBmb3JtQ29udHJvbE5hbWU9XCJuYW1lXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbY2xhc3MuaXMtaW52YWxpZF09XCJzdWJtaXR0ZWQgJiYgbW9kZWxGb3JtLmNvbnRyb2xzWyduYW1lJ10uaW52YWxpZFwiPlxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtYi0zIHJvd1wiPlxuICAgICAgICAgICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJjb2wtc20tMyBjb2wtZm9ybS1sYWJlbFwiPnt7JzNEIG1vZGVsIGZpbGUnIHwgdHJhbnNsYXRlfX0gKjwvbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtc20tOVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPCEtLSBzdHlsZXMuc2NzcyBoaWRlcyBldmVyeSBpbnB1dFt0eXBlPWZpbGVdIGFwcC13aWRlOyB0aGUgY29udmVudGlvbiBoZXJlIGlzIGFcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3R5bGVkIGxhYmVsIHdyYXBwaW5nIHRoZSBoaWRkZW4gaW5wdXQsIGFzIG9uIHRoZSBwcm9maWxlIHNjcmVlbi4gLS0+XG4gICAgICAgICAgICAgICAgICAgICAgICA8bGFiZWwgZm9yPVwibW9kZWwzZC1maWxlXCIgY2xhc3M9XCJidG4gYnRuLW91dGxpbmUtcHJpbWFyeSByb3VuZGVkLXBpbGxcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgdHlwZT1cImZpbGVcIiBpZD1cIm1vZGVsM2QtZmlsZVwiIGFjY2VwdD1cIi5nbGIsLmdsdGZcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwidXBsb2FkUGVyY2VudCAhPT0gbnVsbFwiIChjaGFuZ2UpPVwib25GaWxlU2VsZWN0ZWQoJGV2ZW50KVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7J0Nob29zZSBhIGZpbGUnIHwgdHJhbnNsYXRlfX1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiAqbmdJZj1cInVwbG9hZGVkRmlsZU5hbWUgJiYgdXBsb2FkUGVyY2VudCA9PT0gbnVsbFwiIGNsYXNzPVwibXMtMlwiPnt7dXBsb2FkZWRGaWxlTmFtZX19PC9zcGFuPlxuXG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2ICpuZ0lmPVwidXBsb2FkUGVyY2VudCAhPT0gbnVsbFwiIGNsYXNzPVwibXQtMlwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJwcm9ncmVzc1wiIHN0eWxlPVwiaGVpZ2h0OiA2cHg7XCIgcm9sZT1cInByb2dyZXNzYmFyXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2F0dHIuYXJpYS12YWx1ZW5vd109XCJ1cGxvYWRQZXJjZW50XCIgYXJpYS12YWx1ZW1pbj1cIjBcIiBhcmlhLXZhbHVlbWF4PVwiMTAwXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJwcm9ncmVzcy1iYXJcIiBzdHlsZT1cInRyYW5zaXRpb246IG5vbmU7XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtzdHlsZS53aWR0aC4lXT1cInVwbG9hZFBlcmNlbnRcIj48L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZm9ybS10ZXh0XCI+e3snVXBsb2FkaW5nJyB8IHRyYW5zbGF0ZX19IHt7dXBsb2FkZWRGaWxlTmFtZX19IOKAlCB7e3VwbG9hZFBlcmNlbnR9fSU8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2ICpuZ0lmPVwidXBsb2FkUGVyY2VudCA9PT0gbnVsbCAmJiBtb2RlbEZvcm0udmFsdWUubW9kZWxLZXlcIiBjbGFzcz1cImZvcm0tdGV4dCB0ZXh0LXN1Y2Nlc3NcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7eyBtb2RlbEZvcm0udmFsdWUubW9kZWxLZXkgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2ICpuZ0lmPVwic3VibWl0dGVkICYmIG1vZGVsS2V5RXJyb3JcIiBjbGFzcz1cInRleHQtZGFuZ2VyXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge3sgbW9kZWxLZXlFcnJvciB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgICAgICAgPG5nYi1hbGVydCAqbmdJZj1cImVycm9yTWVzc2FnZVwiIHR5cGU9XCJkYW5nZXJcIiBbZGlzbWlzc2libGVdPVwiZmFsc2VcIj5cbiAgICAgICAgICAgICAgICAgICAge3sgZXJyb3JNZXNzYWdlIH19XG4gICAgICAgICAgICAgICAgPC9uZ2ItYWxlcnQ+XG5cbiAgICAgICAgICAgICAgICA8bGliLWxvYWRlciAqbmdJZj1cImlzUHJvY2Vzc2luZ1wiPjwvbGliLWxvYWRlcj5cblxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJhY3Rpb24tYnV0dG9uLWNvbnRhaW5lciBtdC0zXCI+XG4gICAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT1cInN1Ym1pdFwiIGNsYXNzPVwiYnRuIGJ0bi1vdXRsaW5lLXByaW1hcnkgcm91bmRlZC1waWxsIG1lLTJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cImlzUHJvY2Vzc2luZ1wiPnt7J1NhdmUnIHwgdHJhbnNsYXRlfX08L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidG4gYnRuLW91dGxpbmUtc2Vjb25kYXJ5IHJvdW5kZWQtcGlsbFwiXG4gICAgICAgICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiaXNQcm9jZXNzaW5nXCIgKGNsaWNrKT1cIm9uQ2FuY2VsKClcIj57eydDYW5jZWwnIHwgdHJhbnNsYXRlfX08L2J1dHRvbj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDwvZm9ybT5cbiAgICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG48L2Rpdj5cblxuPG5nLXRlbXBsYXRlICNjb250ZW50IGxldC1tb2RhbD5cbiAgICA8ZGl2IGNsYXNzPVwibW9kYWwtaGVhZGVyXCI+XG4gICAgICAgIDxoNCBjbGFzcz1cIm1vZGFsLXRpdGxlXCI+e3snRGVsZXRlJyB8IHRyYW5zbGF0ZX19PC9oND5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwibW9kYWwtYm9keVwiPlxuICAgICAgICA8cD57eydUaGlzIDNEIG1vZGVsIHdpbGwgYmUgcmVtb3ZlZCBmcm9tIHRoaXMgbG9jYXRpb24uJyB8IHRyYW5zbGF0ZX19PC9wPlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJtb2RhbC1mb290ZXJcIj5cbiAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidG4gYnRuLW91dGxpbmUtc2Vjb25kYXJ5IHJvdW5kZWQtcGlsbFwiXG4gICAgICAgICAgICAoY2xpY2spPVwibW9kYWwuZGlzbWlzcygpXCI+e3snQ2FuY2VsJyB8IHRyYW5zbGF0ZX19PC9idXR0b24+XG4gICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYnRuIGJ0bi1vdXRsaW5lLXByaW1hcnkgcm91bmRlZC1waWxsXCJcbiAgICAgICAgICAgIChjbGljayk9XCJtb2RhbC5jbG9zZSgnY29uZmlybWVkJylcIj57eydEZWxldGUnIHwgdHJhbnNsYXRlfX08L2J1dHRvbj5cbiAgICA8L2Rpdj5cbjwvbmctdGVtcGxhdGU+XG4iXX0=
@@ -37,12 +37,12 @@ export class PlanLegendComponent {
37
37
  }
38
38
  }
39
39
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PlanLegendComponent, deps: [{ token: i1.TranslateService }], target: i0.ɵɵFactoryTarget.Component });
40
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: PlanLegendComponent, selector: "lib-plan-legend", inputs: { isAudioZone: "isAudioZone" }, ngImport: i0, template: "<div class=\"mt-3 ms-3\" class=\"legendContainer\">\r\n <h5>{{\"legend.title\" | translate}}</h5>\r\n <div class=\"legendBox\">\r\n <div class=\"legendRow\" *ngFor=\"let elemnt of buttonsToRender\">\r\n <button class=\"legendIcon\" [ngStyle] = \"{'background-image': elemnt.url}\"></button>\r\n <span>{{elemnt.text}}</span>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".legendContainer{padding:1rem;border:solid var(--smarterplan-primary) 2px;border-radius:6px;width:100%;margin-bottom:.5rem;background:#fff}.legendContainer .legendBox{display:flex;flex-direction:row;justify-content:center;flex-wrap:wrap}.legendContainer .legendBox .legendRow{display:flex;flex-direction:row;align-items:center}.legendContainer .legendBox .legendRow .legendIcon{width:2.5rem;height:2.5rem;background-repeat:no-repeat;background-size:cover;border:none;background-color:transparent;margin-right:.5rem;cursor:auto}.legendContainer .legendBox .legendRow span{margin-right:1rem;cursor:auto}.legendContainer .legendBox .legendRow h5{cursor:auto}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }] });
40
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: PlanLegendComponent, selector: "lib-plan-legend", inputs: { isAudioZone: "isAudioZone" }, ngImport: i0, template: "<div class=\"mt-3 ms-3\" class=\"legendContainer\">\n <h5>{{\"legend.title\" | translate}}</h5>\n <div class=\"legendBox\">\n <div class=\"legendRow\" *ngFor=\"let elemnt of buttonsToRender\">\n <button class=\"legendIcon\" [ngStyle] = \"{'background-image': elemnt.url}\"></button>\n <span>{{elemnt.text}}</span>\n </div>\n </div>\n</div>\n", styles: [".legendContainer{padding:1rem;border:solid var(--smarterplan-primary) 2px;border-radius:6px;width:100%;margin-bottom:.5rem;background:#fff}.legendContainer .legendBox{display:flex;flex-direction:row;justify-content:center;flex-wrap:wrap}.legendContainer .legendBox .legendRow{display:flex;flex-direction:row;align-items:center}.legendContainer .legendBox .legendRow .legendIcon{width:2.5rem;height:2.5rem;background-repeat:no-repeat;background-size:cover;border:none;background-color:transparent;margin-right:.5rem;cursor:auto}.legendContainer .legendBox .legendRow span{margin-right:1rem;cursor:auto}.legendContainer .legendBox .legendRow h5{cursor:auto}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }] });
41
41
  }
42
42
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PlanLegendComponent, decorators: [{
43
43
  type: Component,
44
- args: [{ selector: 'lib-plan-legend', template: "<div class=\"mt-3 ms-3\" class=\"legendContainer\">\r\n <h5>{{\"legend.title\" | translate}}</h5>\r\n <div class=\"legendBox\">\r\n <div class=\"legendRow\" *ngFor=\"let elemnt of buttonsToRender\">\r\n <button class=\"legendIcon\" [ngStyle] = \"{'background-image': elemnt.url}\"></button>\r\n <span>{{elemnt.text}}</span>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".legendContainer{padding:1rem;border:solid var(--smarterplan-primary) 2px;border-radius:6px;width:100%;margin-bottom:.5rem;background:#fff}.legendContainer .legendBox{display:flex;flex-direction:row;justify-content:center;flex-wrap:wrap}.legendContainer .legendBox .legendRow{display:flex;flex-direction:row;align-items:center}.legendContainer .legendBox .legendRow .legendIcon{width:2.5rem;height:2.5rem;background-repeat:no-repeat;background-size:cover;border:none;background-color:transparent;margin-right:.5rem;cursor:auto}.legendContainer .legendBox .legendRow span{margin-right:1rem;cursor:auto}.legendContainer .legendBox .legendRow h5{cursor:auto}\n"] }]
44
+ args: [{ selector: 'lib-plan-legend', template: "<div class=\"mt-3 ms-3\" class=\"legendContainer\">\n <h5>{{\"legend.title\" | translate}}</h5>\n <div class=\"legendBox\">\n <div class=\"legendRow\" *ngFor=\"let elemnt of buttonsToRender\">\n <button class=\"legendIcon\" [ngStyle] = \"{'background-image': elemnt.url}\"></button>\n <span>{{elemnt.text}}</span>\n </div>\n </div>\n</div>\n", styles: [".legendContainer{padding:1rem;border:solid var(--smarterplan-primary) 2px;border-radius:6px;width:100%;margin-bottom:.5rem;background:#fff}.legendContainer .legendBox{display:flex;flex-direction:row;justify-content:center;flex-wrap:wrap}.legendContainer .legendBox .legendRow{display:flex;flex-direction:row;align-items:center}.legendContainer .legendBox .legendRow .legendIcon{width:2.5rem;height:2.5rem;background-repeat:no-repeat;background-size:cover;border:none;background-color:transparent;margin-right:.5rem;cursor:auto}.legendContainer .legendBox .legendRow span{margin-right:1rem;cursor:auto}.legendContainer .legendBox .legendRow h5{cursor:auto}\n"] }]
45
45
  }], ctorParameters: () => [{ type: i1.TranslateService }], propDecorators: { isAudioZone: [{
46
46
  type: Input
47
47
  }] } });
48
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGxhbi1sZWdlbmQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWxvY2F0aW9ucy9zcmMvbGliL2NvbXBvbmVudHMvcGxhbi1sZWdlbmQvcGxhbi1sZWdlbmQuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWxvY2F0aW9ucy9zcmMvbGliL2NvbXBvbmVudHMvcGxhbi1sZWdlbmQvcGxhbi1sZWdlbmQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBVSxLQUFLLEVBQWMsTUFBTSxlQUFlLENBQUM7Ozs7QUFRckUsTUFBTSxPQUFPLG1CQUFtQjtJQVFwQjtJQVBELFdBQVcsR0FBWSxLQUFLLENBQUM7SUFFdEMsZUFBZSxHQUFHLEVBQUUsQ0FBQztJQUVyQixXQUFXLEdBQUcsRUFBRSxDQUFDO0lBRWpCLFlBQ1UsU0FBMkI7UUFBM0IsY0FBUyxHQUFULFNBQVMsQ0FBa0I7SUFDbEMsQ0FBQztJQUVKLEtBQUssQ0FBQyxRQUFRO1FBQ1osSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFBO0lBQ2YsQ0FBQztJQUVELEtBQUssQ0FBQyxNQUFNO1FBQ1YsSUFBSSxDQUFDLGVBQWUsR0FBRztZQUNyQjtnQkFDRSxHQUFHLEVBQUUsaUZBQWlGO2dCQUN0RixJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDO2FBQzdDO1lBQ0Q7Z0JBQ0UsR0FBRyxFQUFFLDZGQUE2RjtnQkFDbEcsSUFBSSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQzthQUMzQztTQUNGLENBQUE7UUFDRCxJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUNuQixJQUFJLFdBQVcsR0FBRyxDQUFDO29CQUNqQixHQUFHLEVBQUUsK0ZBQStGO29CQUNwRyxJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDO2lCQUM3QztnQkFDRDtvQkFDRSxHQUFHLEVBQUUsa0ZBQWtGO29CQUN2RixJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFDO2lCQUM5QyxDQUFDLENBQUE7WUFDRixJQUFJLENBQUMsZUFBZSxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFBO1FBQ25FLENBQUM7SUFDSCxDQUFDO3dHQXJDVSxtQkFBbUI7NEZBQW5CLG1CQUFtQiwrRkNSaEMsc1pBU0E7OzRGRERhLG1CQUFtQjtrQkFML0IsU0FBUzsrQkFDRSxpQkFBaUI7cUZBS2xCLFdBQVc7c0JBQW5CLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIE9uSW5pdCwgSW5wdXQsIE9uQ2hhbmdlcyAgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgVHJhbnNsYXRlU2VydmljZSB9IGZyb20gXCJAbmd4LXRyYW5zbGF0ZS9jb3JlXCI7XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogJ2xpYi1wbGFuLWxlZ2VuZCcsXHJcbiAgdGVtcGxhdGVVcmw6ICcuL3BsYW4tbGVnZW5kLmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybHM6IFsnLi9wbGFuLWxlZ2VuZC5jb21wb25lbnQuc2NzcyddXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBQbGFuTGVnZW5kQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcclxuICBASW5wdXQoKSBpc0F1ZGlvWm9uZT86Ym9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICBidXR0b25zVG9SZW5kZXIgPSBbXTtcclxuXHJcbiAgY29sb3JUb1RleHQgPSB7fTtcclxuXHJcbiAgY29uc3RydWN0b3IoXHJcbiAgICBwcml2YXRlIHRyYW5zbGF0ZTogVHJhbnNsYXRlU2VydmljZSxcclxuICApIHt9XHJcblxyXG4gIGFzeW5jIG5nT25Jbml0KCkge1xyXG4gICAgdGhpcy5yZW5kZXIoKVxyXG4gIH1cclxuXHJcbiAgYXN5bmMgcmVuZGVyKCkge1xyXG4gICAgdGhpcy5idXR0b25zVG9SZW5kZXIgPSBbXHJcbiAgICAgIHtcclxuICAgICAgICB1cmw6IGB1cmwoXCJodHRwczovL2FwaS5pY29uaWZ5LmRlc2lnbi9tZGk6YWRqdXN0LnN2Zz9jb2xvcj1ncmVlbiZoZWlnaHQ9MTcmd2lkdGg9MTdcIilgLFxyXG4gICAgICAgIHRleHQ6IHRoaXMudHJhbnNsYXRlLmluc3RhbnQoXCJsZWdlbmQuZ3JlZW5cIilcclxuICAgICAgfSxcclxuICAgICAge1xyXG4gICAgICAgIHVybDogYHVybChcImh0dHBzOi8vYXBpLmljb25pZnkuZGVzaWduL21kaTpjbG9zZS1jaXJjbGUtb3V0bGluZS5zdmc/Y29sb3I9cmVkJmhlaWdodD0xNyZ3aWR0aD0xN1wiKWAsXHJcbiAgICAgICAgdGV4dDogdGhpcy50cmFuc2xhdGUuaW5zdGFudChcImxlZ2VuZC5yZWRcIilcclxuICAgICAgfVxyXG4gICAgXVxyXG4gICAgaWYgKHRoaXMuaXNBdWRpb1pvbmUpIHtcclxuICAgICAgICBsZXQgYXVkaW9Qb2ludHMgPSBbe1xyXG4gICAgICAgICAgdXJsOiBgdXJsKFwiaHR0cHM6Ly9hcGkuaWNvbmlmeS5kZXNpZ24vbWRpOmNsb3NlLWNpcmNsZS1vdXRsaW5lLnN2Zz9jb2xvcj1ibGFjayZoZWlnaHQ9MTcmd2lkdGg9MTdcIilgLFxyXG4gICAgICAgICAgdGV4dDogdGhpcy50cmFuc2xhdGUuaW5zdGFudChcImxlZ2VuZC5ibGFja1wiKVxyXG4gICAgICAgIH0sXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgdXJsOiBgdXJsKFwiaHR0cHM6Ly9hcGkuaWNvbmlmeS5kZXNpZ24vbWRpOmFkanVzdC5zdmc/Y29sb3I9b3JhbmdlJmhlaWdodD0xNyZ3aWR0aD0xN1wiKWAsXHJcbiAgICAgICAgICB0ZXh0OiB0aGlzLnRyYW5zbGF0ZS5pbnN0YW50KFwibGVnZW5kLm9yYW5nZVwiKVxyXG4gICAgICAgIH1dXHJcbiAgICAgICAgdGhpcy5idXR0b25zVG9SZW5kZXIgPSB0aGlzLmJ1dHRvbnNUb1JlbmRlci5jb25jYXQoYXVkaW9Qb2ludHMpXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvL3N0eWxlQnV0dG9uKGVsZW1lbnQsIFN3ZWVwU3RhdGUuRElTQUJMRUQpO1xyXG5cclxufVxyXG4iLCI8ZGl2IGNsYXNzPVwibXQtMyBtcy0zXCIgY2xhc3M9XCJsZWdlbmRDb250YWluZXJcIj5cclxuICAgIDxoNT57e1wibGVnZW5kLnRpdGxlXCIgfCB0cmFuc2xhdGV9fTwvaDU+XHJcbiAgICA8ZGl2IGNsYXNzPVwibGVnZW5kQm94XCI+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cImxlZ2VuZFJvd1wiICpuZ0Zvcj1cImxldCBlbGVtbnQgb2YgYnV0dG9uc1RvUmVuZGVyXCI+XHJcbiAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJsZWdlbmRJY29uXCIgW25nU3R5bGVdID0gXCJ7J2JhY2tncm91bmQtaW1hZ2UnOiBlbGVtbnQudXJsfVwiPjwvYnV0dG9uPlxyXG4gICAgICAgICAgICA8c3Bhbj57e2VsZW1udC50ZXh0fX08L3NwYW4+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICA8L2Rpdj5cclxuPC9kaXY+XHJcbiJdfQ==
48
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGxhbi1sZWdlbmQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWxvY2F0aW9ucy9zcmMvbGliL2NvbXBvbmVudHMvcGxhbi1sZWdlbmQvcGxhbi1sZWdlbmQuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWxvY2F0aW9ucy9zcmMvbGliL2NvbXBvbmVudHMvcGxhbi1sZWdlbmQvcGxhbi1sZWdlbmQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBVSxLQUFLLEVBQWMsTUFBTSxlQUFlLENBQUM7Ozs7QUFRckUsTUFBTSxPQUFPLG1CQUFtQjtJQVFwQjtJQVBELFdBQVcsR0FBWSxLQUFLLENBQUM7SUFFdEMsZUFBZSxHQUFHLEVBQUUsQ0FBQztJQUVyQixXQUFXLEdBQUcsRUFBRSxDQUFDO0lBRWpCLFlBQ1UsU0FBMkI7UUFBM0IsY0FBUyxHQUFULFNBQVMsQ0FBa0I7SUFDbEMsQ0FBQztJQUVKLEtBQUssQ0FBQyxRQUFRO1FBQ1osSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFBO0lBQ2YsQ0FBQztJQUVELEtBQUssQ0FBQyxNQUFNO1FBQ1YsSUFBSSxDQUFDLGVBQWUsR0FBRztZQUNyQjtnQkFDRSxHQUFHLEVBQUUsaUZBQWlGO2dCQUN0RixJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDO2FBQzdDO1lBQ0Q7Z0JBQ0UsR0FBRyxFQUFFLDZGQUE2RjtnQkFDbEcsSUFBSSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQzthQUMzQztTQUNGLENBQUE7UUFDRCxJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUNuQixJQUFJLFdBQVcsR0FBRyxDQUFDO29CQUNqQixHQUFHLEVBQUUsK0ZBQStGO29CQUNwRyxJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDO2lCQUM3QztnQkFDRDtvQkFDRSxHQUFHLEVBQUUsa0ZBQWtGO29CQUN2RixJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFDO2lCQUM5QyxDQUFDLENBQUE7WUFDRixJQUFJLENBQUMsZUFBZSxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFBO1FBQ25FLENBQUM7SUFDSCxDQUFDO3dHQXJDVSxtQkFBbUI7NEZBQW5CLG1CQUFtQiwrRkNSaEMsb1lBU0E7OzRGRERhLG1CQUFtQjtrQkFML0IsU0FBUzsrQkFDRSxpQkFBaUI7cUZBS2xCLFdBQVc7c0JBQW5CLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIE9uSW5pdCwgSW5wdXQsIE9uQ2hhbmdlcyAgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFRyYW5zbGF0ZVNlcnZpY2UgfSBmcm9tIFwiQG5neC10cmFuc2xhdGUvY29yZVwiO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdsaWItcGxhbi1sZWdlbmQnLFxuICB0ZW1wbGF0ZVVybDogJy4vcGxhbi1sZWdlbmQuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9wbGFuLWxlZ2VuZC5jb21wb25lbnQuc2NzcyddXG59KVxuZXhwb3J0IGNsYXNzIFBsYW5MZWdlbmRDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xuICBASW5wdXQoKSBpc0F1ZGlvWm9uZT86Ym9vbGVhbiA9IGZhbHNlO1xuXG4gIGJ1dHRvbnNUb1JlbmRlciA9IFtdO1xuXG4gIGNvbG9yVG9UZXh0ID0ge307XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSB0cmFuc2xhdGU6IFRyYW5zbGF0ZVNlcnZpY2UsXG4gICkge31cblxuICBhc3luYyBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLnJlbmRlcigpXG4gIH1cblxuICBhc3luYyByZW5kZXIoKSB7XG4gICAgdGhpcy5idXR0b25zVG9SZW5kZXIgPSBbXG4gICAgICB7XG4gICAgICAgIHVybDogYHVybChcImh0dHBzOi8vYXBpLmljb25pZnkuZGVzaWduL21kaTphZGp1c3Quc3ZnP2NvbG9yPWdyZWVuJmhlaWdodD0xNyZ3aWR0aD0xN1wiKWAsXG4gICAgICAgIHRleHQ6IHRoaXMudHJhbnNsYXRlLmluc3RhbnQoXCJsZWdlbmQuZ3JlZW5cIilcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIHVybDogYHVybChcImh0dHBzOi8vYXBpLmljb25pZnkuZGVzaWduL21kaTpjbG9zZS1jaXJjbGUtb3V0bGluZS5zdmc/Y29sb3I9cmVkJmhlaWdodD0xNyZ3aWR0aD0xN1wiKWAsXG4gICAgICAgIHRleHQ6IHRoaXMudHJhbnNsYXRlLmluc3RhbnQoXCJsZWdlbmQucmVkXCIpXG4gICAgICB9XG4gICAgXVxuICAgIGlmICh0aGlzLmlzQXVkaW9ab25lKSB7XG4gICAgICAgIGxldCBhdWRpb1BvaW50cyA9IFt7XG4gICAgICAgICAgdXJsOiBgdXJsKFwiaHR0cHM6Ly9hcGkuaWNvbmlmeS5kZXNpZ24vbWRpOmNsb3NlLWNpcmNsZS1vdXRsaW5lLnN2Zz9jb2xvcj1ibGFjayZoZWlnaHQ9MTcmd2lkdGg9MTdcIilgLFxuICAgICAgICAgIHRleHQ6IHRoaXMudHJhbnNsYXRlLmluc3RhbnQoXCJsZWdlbmQuYmxhY2tcIilcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIHVybDogYHVybChcImh0dHBzOi8vYXBpLmljb25pZnkuZGVzaWduL21kaTphZGp1c3Quc3ZnP2NvbG9yPW9yYW5nZSZoZWlnaHQ9MTcmd2lkdGg9MTdcIilgLFxuICAgICAgICAgIHRleHQ6IHRoaXMudHJhbnNsYXRlLmluc3RhbnQoXCJsZWdlbmQub3JhbmdlXCIpXG4gICAgICAgIH1dXG4gICAgICAgIHRoaXMuYnV0dG9uc1RvUmVuZGVyID0gdGhpcy5idXR0b25zVG9SZW5kZXIuY29uY2F0KGF1ZGlvUG9pbnRzKVxuICAgIH1cbiAgfVxuXG4gIC8vc3R5bGVCdXR0b24oZWxlbWVudCwgU3dlZXBTdGF0ZS5ESVNBQkxFRCk7XG5cbn1cbiIsIjxkaXYgY2xhc3M9XCJtdC0zIG1zLTNcIiBjbGFzcz1cImxlZ2VuZENvbnRhaW5lclwiPlxuICAgIDxoNT57e1wibGVnZW5kLnRpdGxlXCIgfCB0cmFuc2xhdGV9fTwvaDU+XG4gICAgPGRpdiBjbGFzcz1cImxlZ2VuZEJveFwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwibGVnZW5kUm93XCIgKm5nRm9yPVwibGV0IGVsZW1udCBvZiBidXR0b25zVG9SZW5kZXJcIj5cbiAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJsZWdlbmRJY29uXCIgW25nU3R5bGVdID0gXCJ7J2JhY2tncm91bmQtaW1hZ2UnOiBlbGVtbnQudXJsfVwiPjwvYnV0dG9uPlxuICAgICAgICAgICAgPHNwYW4+e3tlbGVtbnQudGV4dH19PC9zcGFuPlxuICAgICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbjwvZGl2PlxuIl19