@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.
- package/README.md +24 -24
- package/esm2022/lib/components/carousel/carousel.component.mjs +3 -3
- package/esm2022/lib/components/chevron/chevron.component.mjs +3 -3
- package/esm2022/lib/components/detail-location/detail-location.component.mjs +40 -4
- package/esm2022/lib/components/form-location/form-location.component.mjs +3 -3
- package/esm2022/lib/components/images/images.component.mjs +3 -3
- package/esm2022/lib/components/landmark-picker/landmark-picker.component.mjs +3 -3
- package/esm2022/lib/components/locations/locations.component.mjs +19 -4
- package/esm2022/lib/components/locations/map/map-popup/map-popup.component.mjs +3 -3
- package/esm2022/lib/components/locations/map/map.component.mjs +3 -3
- package/esm2022/lib/components/models3d/models3d.component.mjs +295 -0
- package/esm2022/lib/components/plan-legend/plan-legend.component.mjs +3 -3
- package/esm2022/lib/components/plans/calibration/calibration.component.mjs +3 -3
- package/esm2022/lib/components/plans/edit-plan/edit-plan.component.mjs +3 -3
- package/esm2022/lib/components/plans/plans.component.mjs +3 -3
- package/esm2022/lib/components/tab-navigation/tab-navigation.component.mjs +3 -3
- package/esm2022/lib/components/visits/visits.component.mjs +45 -12
- package/esm2022/lib/components/zones/add-audio-zone/add-audio-zone.component.mjs +3 -3
- package/esm2022/lib/components/zones/add-zone/add-zone.component.mjs +3 -3
- package/esm2022/lib/components/zones/add-zone/selection/selection.component.mjs +3 -3
- package/esm2022/lib/components/zones/add-zone/sweep-plan-selection/sweep-plan-selection.component.mjs +3 -3
- package/esm2022/lib/components/zones/zones.component.mjs +3 -3
- package/esm2022/lib/helper.service.mjs +1 -1
- package/esm2022/lib/ngx-smarterplan-location-routing.module.mjs +3 -1
- package/esm2022/lib/ngx-smarterplan-locations.module.mjs +4 -1
- package/esm2022/lib/ngx-smarterplan-locations.service.mjs +1 -1
- package/esm2022/lib/pipes/count-audio-sweeps.pipe.mjs +1 -1
- package/esm2022/lib/radio-button/radio-button.component.mjs +3 -3
- package/esm2022/public-api.mjs +1 -1
- package/fesm2022/smarterplan-ngx-smarterplan-locations.mjs +424 -56
- package/fesm2022/smarterplan-ngx-smarterplan-locations.mjs.map +1 -1
- package/lib/components/detail-location/detail-location.component.d.ts +13 -0
- package/lib/components/locations/locations.component.d.ts +10 -0
- package/lib/components/locations/map/map.component.d.ts +2 -2
- package/lib/components/models3d/models3d.component.d.ts +84 -0
- package/lib/components/visits/visits.component.d.ts +8 -3
- package/lib/components/zones/add-zone/sweep-plan-selection/sweep-plan-selection.component.d.ts +0 -1
- package/lib/ngx-smarterplan-locations.module.d.ts +27 -26
- 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kZWxzM2QuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWxvY2F0aW9ucy9zcmMvbGliL2NvbXBvbmVudHMvbW9kZWxzM2QvbW9kZWxzM2QuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWxvY2F0aW9ucy9zcmMvbGliL2NvbXBvbmVudHMvbW9kZWxzM2QvbW9kZWxzM2QuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBVSxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDN0QsT0FBTyxFQUdILFVBQVUsR0FDYixNQUFNLGdCQUFnQixDQUFDO0FBRXhCLE9BQU8sRUFBWSxtQkFBbUIsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQzNFLE9BQU8sRUFTSCxhQUFhLEVBSWIsMEJBQTBCLEdBQzdCLE1BQU0sbUNBQW1DLENBQUM7QUFFM0MsT0FBTyxFQUFFLE9BQU8sRUFBYSxNQUFNLE1BQU0sQ0FBQzs7Ozs7Ozs7OztBQUUxQzs7Ozs7Ozs7O0dBU0c7QUFLSCxNQUFNLE9BQU8saUJBQWlCO0lBNkJkO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDQTtJQUNEO0lBQ0M7SUF0QzRCLE9BQU8sQ0FBQztJQUVoRCxTQUFTLEdBQWUsRUFBRSxDQUFDO0lBRTNCLFlBQVksQ0FBUTtJQUVwQixPQUFPLENBQVM7SUFFaEIsZ0dBQWdHO0lBQ2hHLE1BQU0sR0FBWSxFQUFFLENBQUM7SUFFckIsU0FBUyxDQUFtQjtJQUU1QixpQkFBaUIsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUV2QixTQUFTLEdBQUcsS0FBSyxDQUFDO0lBRWxCLFlBQVksR0FBRyxLQUFLLENBQUM7SUFFckIsU0FBUyxHQUFHLEtBQUssQ0FBQztJQUVsQixZQUFZLEdBQWtCLElBQUksQ0FBQztJQUVuQyxjQUFjLENBQU07SUFFcEIsUUFBUSxHQUFHLElBQUksT0FBTyxFQUFFLENBQUM7SUFFekIsWUFDWSxFQUFzQixFQUN0QixLQUFxQixFQUNyQixNQUFjLEVBQ2QsWUFBc0IsRUFDdEIsWUFBMEIsRUFDMUIsWUFBMEIsRUFDMUIsY0FBOEIsRUFDOUIsV0FBd0IsRUFDeEIsb0JBQTBDLEVBQzNDLGlCQUFvQyxFQUNuQyxTQUEyQjtRQVYzQixPQUFFLEdBQUYsRUFBRSxDQUFvQjtRQUN0QixVQUFLLEdBQUwsS0FBSyxDQUFnQjtRQUNyQixXQUFNLEdBQU4sTUFBTSxDQUFRO1FBQ2QsaUJBQVksR0FBWixZQUFZLENBQVU7UUFDdEIsaUJBQVksR0FBWixZQUFZLENBQWM7UUFDMUIsaUJBQVksR0FBWixZQUFZLENBQWM7UUFDMUIsbUJBQWMsR0FBZCxjQUFjLENBQWdCO1FBQzlCLGdCQUFXLEdBQVgsV0FBVyxDQUFhO1FBQ3hCLHlCQUFvQixHQUFwQixvQkFBb0IsQ0FBc0I7UUFDM0Msc0JBQWlCLEdBQWpCLGlCQUFpQixDQUFtQjtRQUNuQyxjQUFTLEdBQVQsU0FBUyxDQUFrQjtJQUNwQyxDQUFDO0lBRUosS0FBSyxDQUFDLFFBQVE7UUFDVixJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDdEQsTUFBTSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7SUFDeEIsQ0FBQztJQUVELFdBQVc7UUFDUCxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN6QixJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQzdCLENBQUM7SUFFRCxLQUFLLENBQUMsTUFBTTtRQUNSLElBQUksQ0FBQyxZQUFZLEdBQUcsTUFBTSxJQUFJLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDbkUsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ3RCLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLFlBQVksQ0FBQyx3QkFBd0IsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDOUUsSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDLE1BQU0sSUFBSSxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxNQUFNLEtBQUssYUFBYSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzNGLENBQUM7SUFFRCxjQUFjO1FBQ1YsSUFBSSxDQUFDLFNBQVMsR0FBRztZQUNiLEVBQUUsS0FBSyxFQUFFLFdBQVcsRUFBRSxHQUFHLEVBQUUsZUFBZSxFQUFFO1lBQzVDLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxFQUFFLEdBQUcsRUFBRSxpQkFBaUIsSUFBSSxDQUFDLFlBQVksQ0FBQyxFQUFFLEVBQUUsRUFBRTtZQUMvRSxFQUFFLEtBQUssRUFBRSxXQUFXLEVBQUUsR0FBRyxFQUFFLGlCQUFpQixJQUFJLENBQUMsWUFBWSxDQUFDLEVBQUUsV0FBVyxFQUFFO1NBQ2hGLENBQUM7SUFDTixDQUFDO0lBRUQsUUFBUTtRQUNKLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMseUJBQXlCLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7SUFDcEUsQ0FBQztJQUVELGNBQWMsQ0FBQyxLQUFhO1FBQ3hCLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxLQUFLLEtBQUssSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDO0lBQzNFLENBQUM7SUFFRCxLQUFLO1FBQ0QsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ2hCLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7SUFDMUMsQ0FBQztJQUVELE1BQU0sQ0FBQyxLQUFZO1FBQ2YsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNyQixJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQztRQUN0QixJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssRUFBRSxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUMvQyxDQUFDO0lBRUQsUUFBUTtRQUNKLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDO1FBQ3RCLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztJQUMxQixDQUFDO0lBRUQsUUFBUSxDQUFDLFFBQWUsSUFBSTtRQUN4QixJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQztRQUN2QixJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQztRQUN6QixJQUFJLEtBQUssRUFBRSxDQUFDO1lBQ1IsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQztnQkFDM0IsU0FBUyxFQUFFLEtBQUssQ0FBQyxTQUFTO2dCQUMxQixNQUFNLEVBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFFO2dCQUNyQixJQUFJLEVBQUUsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDO2dCQUN6QyxRQUFRLEVBQUUsQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDO2FBQ25ELENBQUMsQ0FBQztRQUNQLENBQUM7YUFBTSxDQUFDO1lBQ0osSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQztnQkFDM0IsSUFBSSxFQUFFLENBQUMsSUFBSSxFQUFFLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDO2dCQUNuQyxRQUFRLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUM7YUFDMUMsQ0FBQyxDQUFDO1FBQ1AsQ0FBQztJQUNMLENBQUM7SUFFRCwwRUFBMEU7SUFDMUUsYUFBYSxHQUFrQixJQUFJLENBQUM7SUFFcEMsZ0JBQWdCLEdBQWtCLElBQUksQ0FBQztJQUV2Qzs7Ozs7O09BTUc7SUFDSCxLQUFLLENBQUMsY0FBYyxDQUFDLEtBQVk7UUFDN0IsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLE1BQTBCLENBQUM7UUFDL0MsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzlCLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNSLE9BQU87UUFDWCxDQUFDO1FBRUQsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUNyQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUNwRCxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLHFEQUFxRCxDQUFDLENBQUM7WUFDbEcsS0FBSyxDQUFDLEtBQUssR0FBRyxFQUFFLENBQUM7WUFDakIsT0FBTztRQUNYLENBQUM7UUFFRCxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQztRQUN6QixJQUFJLENBQUMsYUFBYSxHQUFHLENBQUMsQ0FBQztRQUN2QixJQUFJLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQztRQUVsQyxJQUFJLENBQUM7WUFDRCxNQUFNLEdBQUcsR0FBRyxNQUFNLDBCQUEwQixDQUN4QyxZQUFZLElBQUksQ0FBQyxPQUFPLEdBQUcsRUFDM0IsSUFBSSxFQUNKLENBQUMsUUFBUSxFQUFFLEVBQUU7Z0JBQ1QsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsR0FBRyxHQUFHLENBQUMsQ0FBQztZQUNwRCxDQUFDLENBQ0osQ0FBQztZQUNGLElBQUksQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLEVBQUUsUUFBUSxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUM7WUFDN0Msd0ZBQXdGO1lBQ3hGLG1CQUFtQjtZQUNuQixJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUM7Z0JBQzdCLElBQUksQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLGdCQUFnQixFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUNqRixDQUFDO1FBQ0wsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDYixJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDOUMsSUFBSSxDQUFDLGdCQUFnQixHQUFHLElBQUksQ0FBQztRQUNqQyxDQUFDO2dCQUFTLENBQUM7WUFDUCxJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQztRQUM5QixDQUFDO0lBQ0wsQ0FBQztJQUVELGtEQUFrRDtJQUNsRCxJQUFJLGFBQWE7UUFDYixPQUFPLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUN0RixDQUFDO0lBRUQsS0FBSyxDQUFDLFFBQVE7UUFDVixJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQztRQUN0QixJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQztRQUV6QixJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLElBQUksSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQzlDLE9BQU87UUFDWCxDQUFDO1FBRUQsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUM7UUFDdkMsTUFBTSxPQUFPLEdBQUc7WUFDWixNQUFNLEVBQUUsYUFBYSxDQUFDLE9BQU87WUFDN0IsT0FBTyxFQUFFLElBQUksQ0FBQyxHQUFHLEVBQUU7WUFDbkIsT0FBTyxFQUFFLElBQUksQ0FBQyxZQUFZLENBQUMsRUFBRTtTQUNyQixDQUFDO1FBRWIsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUM7UUFDekIsSUFBSSxDQUFDO1lBQ0QsSUFBSSxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7Z0JBQ2pCLE9BQU8sQ0FBQyxFQUFFLEdBQUcsU0FBUyxDQUFDLFNBQVMsQ0FBQztnQkFDakMsZ0ZBQWdGO2dCQUNoRix3RUFBd0U7Z0JBQ3hFLE1BQU0sSUFBSSxDQUFDLGNBQWMsQ0FBQyxhQUFhLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQ2pELE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxVQUFVLENBQUM7b0JBQzlCLEVBQUUsRUFBRSxTQUFTLENBQUMsTUFBTTtvQkFDcEIsT0FBTyxFQUFFLFNBQVMsQ0FBQyxRQUFRO29CQUMzQixRQUFRLEVBQUUsU0FBUyxDQUFDLElBQUk7aUJBQ25CLENBQUMsQ0FBQztZQUNmLENBQUM7aUJBQU0sQ0FBQztnQkFDSixNQUFNLElBQUksQ0FBQyxXQUFXLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDdEMsQ0FBQztZQUNELE1BQU0sSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ3BCLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNwQixDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNiLHlGQUF5RjtZQUN6Riw0REFBNEQ7WUFDNUQsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2xELENBQUM7Z0JBQVMsQ0FBQztZQUNQLElBQUksQ0FBQyxZQUFZLEdBQUcsS0FBSyxDQUFDO1FBQzlCLENBQUM7SUFDTCxDQUFDO0lBRUQsb0ZBQW9GO0lBQzVFLEtBQUssQ0FBQyxXQUFXLENBQUMsU0FBYztRQUNwQyxNQUFNLE9BQU8sR0FBRyxNQUFNLElBQUksQ0FBQyxjQUFjLENBQUMsYUFBYSxDQUFDO1lBQ3BELE1BQU0sRUFBRSxhQUFhLENBQUMsT0FBTztZQUM3QixPQUFPLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRTtZQUNuQixPQUFPLEVBQUUsSUFBSSxDQUFDLFlBQVksQ0FBQyxFQUFFO1NBQ3JCLENBQUMsQ0FBQztRQUVkLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNYLE1BQU0sSUFBSSxLQUFLLENBQUMsaURBQWlELENBQUMsQ0FBQztRQUN2RSxDQUFDO1FBRUQsTUFBTSxJQUFJLEdBQUcsTUFBTSxJQUFJLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FBQztZQUMzQyxPQUFPLEVBQUUsU0FBUyxDQUFDLFFBQVE7WUFDM0IsU0FBUyxFQUFFLE9BQU8sQ0FBQyxFQUFFO1lBQ3JCLFFBQVEsRUFBRSxTQUFTLENBQUMsSUFBSTtTQUNuQixDQUFDLENBQUM7UUFFWCxNQUFNLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxVQUFVLENBQ3RDLElBQUksQ0FBQyxPQUFPLEVBQ1osSUFBSSxFQUNKLEtBQUssRUFDTCxJQUFJLEVBQ0osSUFBSSxDQUNQLENBQUM7SUFDTixDQUFDO0lBRUQsS0FBSyxDQUFDLFFBQVEsQ0FBQyxLQUFZO1FBQ3ZCLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzNELElBQUksQ0FBQztZQUNELE1BQU0sSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUM7UUFDckMsQ0FBQztRQUFDLE1BQU0sQ0FBQztZQUNMLE9BQU8sQ0FBQyxZQUFZO1FBQ3hCLENBQUM7UUFFRCxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQztRQUN6QixJQUFJLENBQUM7WUFDRCxNQUFNLElBQUksQ0FBQyxXQUFXLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDakQsTUFBTSxJQUFJLENBQUMsY0FBYyxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDekQsTUFBTSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDeEIsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDYixJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDbEQsQ0FBQztnQkFBUyxDQUFDO1lBQ1AsSUFBSSxDQUFDLFlBQVksR0FBRyxLQUFLLENBQUM7UUFDOUIsQ0FBQztJQUNMLENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDSyxhQUFhLENBQUMsS0FBVTtRQUM1QixJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQzVCLE9BQU8sS0FBSyxDQUFDO1FBQ2pCLENBQUM7UUFDRCxNQUFNLGFBQWEsR0FBRyxLQUFLLEVBQUUsTUFBTSxDQUFDO1FBQ3BDLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsSUFBSSxhQUFhLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQzNELE9BQU8sYUFBYSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQU0sRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLE9BQU8sSUFBSSxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3RGLENBQUM7UUFDRCxJQUFJLEtBQUssRUFBRSxPQUFPLEVBQUUsQ0FBQztZQUNqQixPQUFPLEtBQUssQ0FBQyxPQUFPLENBQUM7UUFDekIsQ0FBQztRQUNELElBQUksQ0FBQztZQUNELE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNqQyxDQUFDO1FBQUMsTUFBTSxDQUFDO1lBQ0wsT0FBTyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDekIsQ0FBQztJQUNMLENBQUM7SUFFRCxnQkFBZ0IsQ0FBQyxNQUFXO1FBQ3hCLElBQUksTUFBTSxLQUFLLG1CQUFtQixDQUFDLEdBQUcsRUFBRSxDQUFDO1lBQ3JDLE9BQU8saUJBQWlCLENBQUM7UUFDN0IsQ0FBQztRQUNELElBQUksTUFBTSxLQUFLLG1CQUFtQixDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQ2hELE9BQU8sMkJBQTJCLENBQUM7UUFDdkMsQ0FBQztRQUNELE9BQU8sU0FBUyxNQUFNLEVBQUUsQ0FBQztJQUM3QixDQUFDO3dHQWxTUSxpQkFBaUI7NEZBQWpCLGlCQUFpQixzS0N4QzlCLHF0T0E0SEE7OzRGRHBGYSxpQkFBaUI7a0JBSjdCLFNBQVM7K0JBQ0ksY0FBYzsrV0FJZ0IsT0FBTztzQkFBOUMsU0FBUzt1QkFBQyxTQUFTLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQsIFZpZXdDaGlsZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgICBVbnR5cGVkRm9ybUdyb3VwLFxuICAgIFVudHlwZWRGb3JtQnVpbGRlcixcbiAgICBWYWxpZGF0b3JzLFxufSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBBY3RpdmF0ZWRSb3V0ZSwgUm91dGVyIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IE5nYk1vZGFsLCBNb2RhbERpc21pc3NSZWFzb25zIH0gZnJvbSAnQG5nLWJvb3RzdHJhcC9uZy1ib290c3RyYXAnO1xuaW1wb3J0IHtcbiAgICBOb2RlLFxuICAgIFZpc2l0LFxuICAgIE1lbnVJdGVtLFxuICAgIFRocmVlSnNJbXBvcnRTZXJ2aWNlLFxuICAgIENhcHR1cmVTZXJ2aWNlLFxuICAgIE5vZGVTZXJ2aWNlLFxuICAgIFNwYWNlU2VydmljZSxcbiAgICBWaXNpdFNlcnZpY2UsXG4gICAgQ2FwdHVyZVZpZXdlcixcbiAgICBDYXB0dXJlLFxuICAgIFNwYWNlLFxuICAgIFZhbGlkYXRvcnNTZXJ2aWNlLFxuICAgIHVwbG9hZEZpbGVUb1MzV2l0aFByb2dyZXNzLFxufSBmcm9tICdAc21hcnRlcnBsYW4vbmd4LXNtYXJ0ZXJwbGFuLWNvcmUnO1xuaW1wb3J0IHsgVHJhbnNsYXRlU2VydmljZSB9IGZyb20gJ0BuZ3gtdHJhbnNsYXRlL2NvcmUnO1xuaW1wb3J0IHsgU3ViamVjdCwgdGFrZVVudGlsIH0gZnJvbSAncnhqcyc7XG5cbi8qKlxuICogQWRtaW4gc2NyZWVuIGZvciB0aGUgM0QgbW9kZWxzIGEgc2l0ZSBjYW4gYmUgdmlzaXRlZCB3aXRoLlxuICpcbiAqIFRoZXNlIGFyZSBzdG9yZWQgdGhlIHNhbWUgd2F5IE1hdHRlcnBvcnQgdmlzaXRzIGFyZSAtIGEgQ2FwdHVyZSBwbHVzIGEgTm9kZSAtIHdpdGggdGhlIHZpZXdlciBzZXRcbiAqIHRvIFRIUkVFSlMgYW5kIHRoZSAuZ2xiJ3MgUzMga2V5IGluIHRoZSBub2RlJ3MgbW9kZWwzRC4gU2hhcmluZyB0aGUgc3RvcmFnZSBpcyB3aGF0IGxldHMgYSBzaXRlXG4gKiBjYXJyeSBzZXZlcmFsIG1vZGVscyBhbmQgd2hhdCBtYWtlcyB0YWdzIGZvbGxvdyB0aGUgc2FtZSBQT0kgcmVjb3JkcyBpbiBlaXRoZXIgdmlld2VyOyB0aGUgc3BsaXRcbiAqIGhlcmUgaXMgb25seSBpbiB0aGUgZm9ybTogYSAzRCBtb2RlbCBpcyBhIG5hbWUgYW5kIGEgZmlsZSwgd2hlcmUgYSBNYXR0ZXJwb3J0IHZpc2l0IGlzIGEgbW9kZWwgSURcbiAqIGFuZCBjYXB0dXJlIGRldGFpbHMuIFBsYWNlbWVudCBhbmQgYWxpZ25tZW50IGFyZSBub3QgYXNrZWQgZm9yIGhlcmUgLSB0aGUgdmlld2VyJ3MgYWxpZ25tZW50IHRvb2xcbiAqIHdyaXRlcyB0aGVtIGludG8gdGhlIGNhcHR1cmUncyBtZXRhZGF0YSBvbmNlIHNvbWVvbmUgY2FsaWJyYXRlcyBhZ2FpbnN0IGEgcmVhbCBzY2VuZS5cbiAqL1xuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6ICdsaWItbW9kZWxzM2QnLFxuICAgIHRlbXBsYXRlVXJsOiAnLi9tb2RlbHMzZC5jb21wb25lbnQuaHRtbCcsXG59KVxuZXhwb3J0IGNsYXNzIE1vZGVsczNkQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcbiAgICBAVmlld0NoaWxkKCdjb250ZW50JywgeyBzdGF0aWM6IHRydWUgfSkgY29udGVudDtcblxuICAgIG1lbnVJdGVtczogTWVudUl0ZW1bXSA9IFtdO1xuXG4gICAgY3VycmVudFNwYWNlOiBTcGFjZTtcblxuICAgIHNwYWNlSWQ6IHN0cmluZztcblxuICAgIC8qKiBPbmx5IHRoZSB2aXNpdHMgY2FwdHVyZWQgYXMgM0QgbW9kZWxzOyBNYXR0ZXJwb3J0IG9uZXMgc3RheSBvbiB0aGUgVmlydHVhbCBWaXNpdHMgc2NyZWVuLiAqL1xuICAgIG1vZGVsczogVmlzaXRbXSA9IFtdO1xuXG4gICAgbW9kZWxGb3JtOiBVbnR5cGVkRm9ybUdyb3VwO1xuXG4gICAgbW9kZWxJbmRleERldGFpbHMgPSAtMTtcblxuICAgIGlzRWRpdGluZyA9IGZhbHNlO1xuXG4gICAgaXNQcm9jZXNzaW5nID0gZmFsc2U7XG5cbiAgICBzdWJtaXR0ZWQgPSBmYWxzZTtcblxuICAgIGVycm9yTWVzc2FnZTogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG5cbiAgICBtb2RhbFJlZmVyZW5jZTogYW55O1xuXG4gICAgZGVzdHJveSQgPSBuZXcgU3ViamVjdCgpO1xuXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIHByaXZhdGUgZmI6IFVudHlwZWRGb3JtQnVpbGRlcixcbiAgICAgICAgcHJpdmF0ZSByb3V0ZTogQWN0aXZhdGVkUm91dGUsXG4gICAgICAgIHByaXZhdGUgcm91dGVyOiBSb3V0ZXIsXG4gICAgICAgIHByaXZhdGUgbW9kYWxTZXJ2aWNlOiBOZ2JNb2RhbCxcbiAgICAgICAgcHJpdmF0ZSBzcGFjZVNlcnZpY2U6IFNwYWNlU2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSB2aXNpdFNlcnZpY2U6IFZpc2l0U2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSBjYXB0dXJlU2VydmljZTogQ2FwdHVyZVNlcnZpY2UsXG4gICAgICAgIHByaXZhdGUgbm9kZVNlcnZpY2U6IE5vZGVTZXJ2aWNlLFxuICAgICAgICBwcml2YXRlIHRocmVlanNJbXBvcnRTZXJ2aWNlOiBUaHJlZUpzSW1wb3J0U2VydmljZSxcbiAgICAgICAgcHVibGljIHZhbGlkYXRvcnNTZXJ2aWNlOiBWYWxpZGF0b3JzU2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSB0cmFuc2xhdGU6IFRyYW5zbGF0ZVNlcnZpY2UsXG4gICAgKSB7fVxuXG4gICAgYXN5bmMgbmdPbkluaXQoKSB7XG4gICAgICAgIHRoaXMuc3BhY2VJZCA9IHRoaXMucm91dGUuc25hcHNob3QucGFyYW1NYXAuZ2V0KCdpZCcpO1xuICAgICAgICBhd2FpdCB0aGlzLnJlbG9hZCgpO1xuICAgIH1cblxuICAgIG5nT25EZXN0cm95KCkge1xuICAgICAgICB0aGlzLmRlc3Ryb3kkLm5leHQodHJ1ZSk7XG4gICAgICAgIHRoaXMuZGVzdHJveSQuY29tcGxldGUoKTtcbiAgICB9XG5cbiAgICBhc3luYyByZWxvYWQoKSB7XG4gICAgICAgIHRoaXMuY3VycmVudFNwYWNlID0gYXdhaXQgdGhpcy5zcGFjZVNlcnZpY2UuZ2V0U3BhY2UodGhpcy5zcGFjZUlkKTtcbiAgICAgICAgdGhpcy5zZXR1cE1lbnVJdGVtcygpO1xuICAgICAgICBjb25zdCB2aXNpdHMgPSBhd2FpdCB0aGlzLnZpc2l0U2VydmljZS5nZXRWaXNpdHNGb3JTcGFjZUZvclVzZXIodGhpcy5zcGFjZUlkKTtcbiAgICAgICAgdGhpcy5tb2RlbHMgPSAodmlzaXRzID8/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\">\
|
|
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\">\
|
|
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,
|
|
48
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGxhbi1sZWdlbmQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWxvY2F0aW9ucy9zcmMvbGliL2NvbXBvbmVudHMvcGxhbi1sZWdlbmQvcGxhbi1sZWdlbmQuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWxvY2F0aW9ucy9zcmMvbGliL2NvbXBvbmVudHMvcGxhbi1sZWdlbmQvcGxhbi1sZWdlbmQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBVSxLQUFLLEVBQWMsTUFBTSxlQUFlLENBQUM7Ozs7QUFRckUsTUFBTSxPQUFPLG1CQUFtQjtJQVFwQjtJQVBELFdBQVcsR0FBWSxLQUFLLENBQUM7SUFFdEMsZUFBZSxHQUFHLEVBQUUsQ0FBQztJQUVyQixXQUFXLEdBQUcsRUFBRSxDQUFDO0lBRWpCLFlBQ1UsU0FBMkI7UUFBM0IsY0FBUyxHQUFULFNBQVMsQ0FBa0I7SUFDbEMsQ0FBQztJQUVKLEtBQUssQ0FBQyxRQUFRO1FBQ1osSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFBO0lBQ2YsQ0FBQztJQUVELEtBQUssQ0FBQyxNQUFNO1FBQ1YsSUFBSSxDQUFDLGVBQWUsR0FBRztZQUNyQjtnQkFDRSxHQUFHLEVBQUUsaUZBQWlGO2dCQUN0RixJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDO2FBQzdDO1lBQ0Q7Z0JBQ0UsR0FBRyxFQUFFLDZGQUE2RjtnQkFDbEcsSUFBSSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQzthQUMzQztTQUNGLENBQUE7UUFDRCxJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUNuQixJQUFJLFdBQVcsR0FBRyxDQUFDO29CQUNqQixHQUFHLEVBQUUsK0ZBQStGO29CQUNwRyxJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDO2lCQUM3QztnQkFDRDtvQkFDRSxHQUFHLEVBQUUsa0ZBQWtGO29CQUN2RixJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFDO2lCQUM5QyxDQUFDLENBQUE7WUFDRixJQUFJLENBQUMsZUFBZSxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFBO1FBQ25FLENBQUM7SUFDSCxDQUFDO3dHQXJDVSxtQkFBbUI7NEZBQW5CLG1CQUFtQiwrRkNSaEMsb1lBU0E7OzRGRERhLG1CQUFtQjtrQkFML0IsU0FBUzsrQkFDRSxpQkFBaUI7cUZBS2xCLFdBQVc7c0JBQW5CLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIE9uSW5pdCwgSW5wdXQsIE9uQ2hhbmdlcyAgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFRyYW5zbGF0ZVNlcnZpY2UgfSBmcm9tIFwiQG5neC10cmFuc2xhdGUvY29yZVwiO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdsaWItcGxhbi1sZWdlbmQnLFxuICB0ZW1wbGF0ZVVybDogJy4vcGxhbi1sZWdlbmQuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9wbGFuLWxlZ2VuZC5jb21wb25lbnQuc2NzcyddXG59KVxuZXhwb3J0IGNsYXNzIFBsYW5MZWdlbmRDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xuICBASW5wdXQoKSBpc0F1ZGlvWm9uZT86Ym9vbGVhbiA9IGZhbHNlO1xuXG4gIGJ1dHRvbnNUb1JlbmRlciA9IFtdO1xuXG4gIGNvbG9yVG9UZXh0ID0ge307XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSB0cmFuc2xhdGU6IFRyYW5zbGF0ZVNlcnZpY2UsXG4gICkge31cblxuICBhc3luYyBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLnJlbmRlcigpXG4gIH1cblxuICBhc3luYyByZW5kZXIoKSB7XG4gICAgdGhpcy5idXR0b25zVG9SZW5kZXIgPSBbXG4gICAgICB7XG4gICAgICAgIHVybDogYHVybChcImh0dHBzOi8vYXBpLmljb25pZnkuZGVzaWduL21kaTphZGp1c3Quc3ZnP2NvbG9yPWdyZWVuJmhlaWdodD0xNyZ3aWR0aD0xN1wiKWAsXG4gICAgICAgIHRleHQ6IHRoaXMudHJhbnNsYXRlLmluc3RhbnQoXCJsZWdlbmQuZ3JlZW5cIilcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIHVybDogYHVybChcImh0dHBzOi8vYXBpLmljb25pZnkuZGVzaWduL21kaTpjbG9zZS1jaXJjbGUtb3V0bGluZS5zdmc/Y29sb3I9cmVkJmhlaWdodD0xNyZ3aWR0aD0xN1wiKWAsXG4gICAgICAgIHRleHQ6IHRoaXMudHJhbnNsYXRlLmluc3RhbnQoXCJsZWdlbmQucmVkXCIpXG4gICAgICB9XG4gICAgXVxuICAgIGlmICh0aGlzLmlzQXVkaW9ab25lKSB7XG4gICAgICAgIGxldCBhdWRpb1BvaW50cyA9IFt7XG4gICAgICAgICAgdXJsOiBgdXJsKFwiaHR0cHM6Ly9hcGkuaWNvbmlmeS5kZXNpZ24vbWRpOmNsb3NlLWNpcmNsZS1vdXRsaW5lLnN2Zz9jb2xvcj1ibGFjayZoZWlnaHQ9MTcmd2lkdGg9MTdcIilgLFxuICAgICAgICAgIHRleHQ6IHRoaXMudHJhbnNsYXRlLmluc3RhbnQoXCJsZWdlbmQuYmxhY2tcIilcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIHVybDogYHVybChcImh0dHBzOi8vYXBpLmljb25pZnkuZGVzaWduL21kaTphZGp1c3Quc3ZnP2NvbG9yPW9yYW5nZSZoZWlnaHQ9MTcmd2lkdGg9MTdcIilgLFxuICAgICAgICAgIHRleHQ6IHRoaXMudHJhbnNsYXRlLmluc3RhbnQoXCJsZWdlbmQub3JhbmdlXCIpXG4gICAgICAgIH1dXG4gICAgICAgIHRoaXMuYnV0dG9uc1RvUmVuZGVyID0gdGhpcy5idXR0b25zVG9SZW5kZXIuY29uY2F0KGF1ZGlvUG9pbnRzKVxuICAgIH1cbiAgfVxuXG4gIC8vc3R5bGVCdXR0b24oZWxlbWVudCwgU3dlZXBTdGF0ZS5ESVNBQkxFRCk7XG5cbn1cbiIsIjxkaXYgY2xhc3M9XCJtdC0zIG1zLTNcIiBjbGFzcz1cImxlZ2VuZENvbnRhaW5lclwiPlxuICAgIDxoNT57e1wibGVnZW5kLnRpdGxlXCIgfCB0cmFuc2xhdGV9fTwvaDU+XG4gICAgPGRpdiBjbGFzcz1cImxlZ2VuZEJveFwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwibGVnZW5kUm93XCIgKm5nRm9yPVwibGV0IGVsZW1udCBvZiBidXR0b25zVG9SZW5kZXJcIj5cbiAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJsZWdlbmRJY29uXCIgW25nU3R5bGVdID0gXCJ7J2JhY2tncm91bmQtaW1hZ2UnOiBlbGVtbnQudXJsfVwiPjwvYnV0dG9uPlxuICAgICAgICAgICAgPHNwYW4+e3tlbGVtbnQudGV4dH19PC9zcGFuPlxuICAgICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbjwvZGl2PlxuIl19
|