@smarterplan/ngx-smarterplan-locations 0.3.4 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/esm2022/lib/components/carousel/carousel.component.mjs +30 -0
  2. package/esm2022/lib/components/chevron/chevron.component.mjs +18 -0
  3. package/esm2022/lib/components/detail-location/detail-location.component.mjs +183 -0
  4. package/{esm2020 → esm2022}/lib/components/form-location/form-location.component.mjs +254 -237
  5. package/esm2022/lib/components/images/images.component.mjs +120 -0
  6. package/esm2022/lib/components/locations/locations.component.mjs +157 -0
  7. package/esm2022/lib/components/locations/map/map-popup/map-popup.component.mjs +72 -0
  8. package/esm2022/lib/components/locations/map/map.component.mjs +92 -0
  9. package/esm2022/lib/components/plan-legend/plan-legend.component.mjs +49 -0
  10. package/esm2022/lib/components/plans/calibration/calibration.component.mjs +494 -0
  11. package/esm2022/lib/components/plans/edit-plan/edit-plan.component.mjs +350 -0
  12. package/{esm2020 → esm2022}/lib/components/plans/plans.component.mjs +243 -225
  13. package/esm2022/lib/components/tab-navigation/tab-navigation.component.mjs +43 -0
  14. package/esm2022/lib/components/visits/visits.component.mjs +294 -0
  15. package/esm2022/lib/components/zones/add-audio-zone/add-audio-zone.component.mjs +250 -0
  16. package/esm2022/lib/components/zones/add-zone/add-zone.component.mjs +333 -0
  17. package/esm2022/lib/components/zones/add-zone/selection/selection.component.mjs +81 -0
  18. package/esm2022/lib/components/zones/add-zone/sweep-plan-selection/sweep-plan-selection.component.mjs +518 -0
  19. package/esm2022/lib/components/zones/zones.component.mjs +291 -0
  20. package/{esm2020 → esm2022}/lib/helper.service.mjs +133 -133
  21. package/esm2022/lib/ngx-smarterplan-location-routing.module.mjs +50 -0
  22. package/esm2022/lib/ngx-smarterplan-locations.module.mjs +124 -0
  23. package/esm2022/lib/ngx-smarterplan-locations.service.mjs +15 -0
  24. package/esm2022/lib/pipes/count-audio-sweeps.pipe.mjs +29 -0
  25. package/esm2022/lib/radio-button/radio-button.component.mjs +28 -0
  26. package/{esm2020 → esm2022}/public-api.mjs +8 -8
  27. package/{esm2020 → esm2022}/smarterplan-ngx-smarterplan-locations.mjs +4 -4
  28. package/{fesm2020 → fesm2022}/smarterplan-ngx-smarterplan-locations.mjs +3959 -3738
  29. package/fesm2022/smarterplan-ngx-smarterplan-locations.mjs.map +1 -0
  30. package/index.d.ts +5 -5
  31. package/lib/components/carousel/carousel.component.d.ts +12 -12
  32. package/lib/components/chevron/chevron.component.d.ts +9 -9
  33. package/lib/components/detail-location/detail-location.component.d.ts +55 -55
  34. package/lib/components/form-location/form-location.component.d.ts +45 -45
  35. package/lib/components/images/images.component.d.ts +33 -33
  36. package/lib/components/locations/locations.component.d.ts +51 -51
  37. package/lib/components/locations/map/map-popup/map-popup.component.d.ts +22 -22
  38. package/lib/components/locations/map/map.component.d.ts +21 -22
  39. package/lib/components/plan-legend/plan-legend.component.d.ts +14 -14
  40. package/lib/components/plans/calibration/calibration.component.d.ts +140 -140
  41. package/lib/components/plans/edit-plan/edit-plan.component.d.ts +55 -55
  42. package/lib/components/plans/plans.component.d.ts +63 -63
  43. package/lib/components/tab-navigation/tab-navigation.component.d.ts +13 -13
  44. package/lib/components/visits/visits.component.d.ts +63 -63
  45. package/lib/components/zones/add-audio-zone/add-audio-zone.component.d.ts +63 -63
  46. package/lib/components/zones/add-zone/add-zone.component.d.ts +69 -69
  47. package/lib/components/zones/add-zone/selection/selection.component.d.ts +44 -44
  48. package/lib/components/zones/add-zone/sweep-plan-selection/sweep-plan-selection.component.d.ts +107 -107
  49. package/lib/components/zones/zones.component.d.ts +73 -73
  50. package/lib/helper.service.d.ts +53 -53
  51. package/lib/ngx-smarterplan-location-routing.module.d.ts +7 -7
  52. package/lib/ngx-smarterplan-locations.module.d.ts +36 -36
  53. package/lib/ngx-smarterplan-locations.service.d.ts +6 -6
  54. package/lib/pipes/count-audio-sweeps.pipe.d.ts +10 -10
  55. package/lib/radio-button/radio-button.component.d.ts +12 -12
  56. package/package.json +13 -19
  57. package/public-api.d.ts +4 -4
  58. package/esm2020/lib/components/carousel/carousel.component.mjs +0 -28
  59. package/esm2020/lib/components/chevron/chevron.component.mjs +0 -18
  60. package/esm2020/lib/components/detail-location/detail-location.component.mjs +0 -168
  61. package/esm2020/lib/components/images/images.component.mjs +0 -107
  62. package/esm2020/lib/components/locations/locations.component.mjs +0 -145
  63. package/esm2020/lib/components/locations/map/map-popup/map-popup.component.mjs +0 -66
  64. package/esm2020/lib/components/locations/map/map.component.mjs +0 -91
  65. package/esm2020/lib/components/plan-legend/plan-legend.component.mjs +0 -47
  66. package/esm2020/lib/components/plans/calibration/calibration.component.mjs +0 -468
  67. package/esm2020/lib/components/plans/edit-plan/edit-plan.component.mjs +0 -324
  68. package/esm2020/lib/components/tab-navigation/tab-navigation.component.mjs +0 -41
  69. package/esm2020/lib/components/visits/visits.component.mjs +0 -275
  70. package/esm2020/lib/components/zones/add-audio-zone/add-audio-zone.component.mjs +0 -230
  71. package/esm2020/lib/components/zones/add-zone/add-zone.component.mjs +0 -315
  72. package/esm2020/lib/components/zones/add-zone/selection/selection.component.mjs +0 -77
  73. package/esm2020/lib/components/zones/add-zone/sweep-plan-selection/sweep-plan-selection.component.mjs +0 -502
  74. package/esm2020/lib/components/zones/zones.component.mjs +0 -268
  75. package/esm2020/lib/ngx-smarterplan-location-routing.module.mjs +0 -49
  76. package/esm2020/lib/ngx-smarterplan-locations.module.mjs +0 -123
  77. package/esm2020/lib/ngx-smarterplan-locations.service.mjs +0 -14
  78. package/esm2020/lib/pipes/count-audio-sweeps.pipe.mjs +0 -27
  79. package/esm2020/lib/radio-button/radio-button.component.mjs +0 -26
  80. package/fesm2015/smarterplan-ngx-smarterplan-locations.mjs +0 -3983
  81. package/fesm2015/smarterplan-ngx-smarterplan-locations.mjs.map +0 -1
  82. package/fesm2020/smarterplan-ngx-smarterplan-locations.mjs.map +0 -1
@@ -1,275 +0,0 @@
1
- import { Component, ViewChild } from '@angular/core';
2
- import { Validators, } from '@angular/forms';
3
- import { ModalDismissReasons } from '@ng-bootstrap/ng-bootstrap';
4
- import { CaptureViewer, } from '@smarterplan/ngx-smarterplan-core';
5
- import { Subject, takeUntil } from 'rxjs';
6
- import * as i0 from "@angular/core";
7
- import * as i1 from "@angular/forms";
8
- import * as i2 from "@smarterplan/ngx-smarterplan-core";
9
- import * as i3 from "@angular/router";
10
- import * as i4 from "@ng-bootstrap/ng-bootstrap";
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
- export class VisitsComponent {
16
- constructor(fb, matterportImportService, captureService, nodeService, spaceService, route, modalService, visitService, validatorsService, translate, navigatorService, router) {
17
- this.fb = fb;
18
- this.matterportImportService = matterportImportService;
19
- this.captureService = captureService;
20
- this.nodeService = nodeService;
21
- this.spaceService = spaceService;
22
- this.route = route;
23
- this.modalService = modalService;
24
- this.visitService = visitService;
25
- this.validatorsService = validatorsService;
26
- this.translate = translate;
27
- this.navigatorService = navigatorService;
28
- this.router = router;
29
- this.visitIndexDetails = -1;
30
- this.isEditing = false;
31
- this.visitSubmitted = false;
32
- this.currentSpace = { zones: [] };
33
- this.visits = [];
34
- this.canCancelImport = false;
35
- this.imagesProcessed = 0;
36
- this.totalImages = 0;
37
- this.imagesUploaded = 0;
38
- this.menuItems = [];
39
- this.errorForm = false;
40
- this.isProcessing = false;
41
- this.destroy$ = new Subject();
42
- this.matterportImportService.importingImages.pipe(takeUntil(this.destroy$)).subscribe(() => {
43
- this.canCancelImport = true;
44
- });
45
- this.matterportImportService.sweepProcessedCount.pipe(takeUntil(this.destroy$)).subscribe((count) => {
46
- this.imagesProcessed = count + 1;
47
- });
48
- this.matterportImportService.totalSweepsCount.pipe(takeUntil(this.destroy$)).subscribe((count) => {
49
- this.totalImages = count;
50
- });
51
- this.navigatorService.locationIDChange
52
- .pipe(takeUntil(this.destroy$))
53
- .subscribe((spaceID) => {
54
- this.router.navigate(["dashboard/localisation", spaceID, "visits"]);
55
- });
56
- this.route.params.subscribe((params) => {
57
- this.spaceId = params.id;
58
- this.resetVisits();
59
- });
60
- }
61
- async ngOnInit() {
62
- this.spaceId = this.route.snapshot.paramMap.get('id');
63
- await this.resetVisits();
64
- }
65
- ngOnDestroy() {
66
- this.destroy$.next(true);
67
- this.destroy$.complete();
68
- }
69
- /*
70
- Visit = {
71
- captureID: string,
72
- model3d: string,
73
- takenAt: number,
74
- spaceID: string,
75
- viewer: CaptureViewer,
76
- surface: number,
77
- node: Node,
78
- name?: string | null
79
- }
80
- */
81
- setupMenuItems() {
82
- this.menuItems = [
83
- { label: 'Locations', url: '/localisation' },
84
- {
85
- label: this.currentSpace.name,
86
- url: `/localisation/${this.currentSpace.id}`,
87
- },
88
- {
89
- label: 'Virtual visits',
90
- url: `/localisation/${this.currentSpace.id}/visits`,
91
- },
92
- ];
93
- }
94
- onGoBack() {
95
- this.onCancel();
96
- }
97
- async resetVisits() {
98
- this.visits = [];
99
- this.currentSpace = await this.spaceService.getSpace(this.spaceId);
100
- this.setupMenuItems();
101
- await this.visitService
102
- .getVisitsForSpaceForUser(this.spaceId)
103
- .then((visits) => {
104
- if (visits) {
105
- this.visits = visits;
106
- }
107
- });
108
- }
109
- initVisitForm(input = null) {
110
- if (input) {
111
- this.visitForm = this.fb.group({
112
- captureID: input.captureID,
113
- nodeID: input.node.id,
114
- name: [input.name, [Validators.required]],
115
- model3D: [input.model3d, [Validators.required]],
116
- viewer: input.viewer ? input.viewer : CaptureViewer.MATTERPORT,
117
- surface: input.surface ? input.surface : null,
118
- });
119
- this.captureDate = input.takenAt;
120
- }
121
- else {
122
- this.visitForm = this.fb.group({
123
- model3D: [null, [Validators.required]],
124
- viewer: CaptureViewer.MATTERPORT,
125
- surface: null,
126
- name: [null, [Validators.required]],
127
- });
128
- }
129
- }
130
- async onToggleDetail(index) {
131
- this.visitIndexDetails = index === this.visitIndexDetails ? -1 : index;
132
- this.imagesUploaded = await this.matterportImportService.getUploadedImageCount(this.visits[index].model3d);
133
- }
134
- onAddVisit() {
135
- this.initVisitForm();
136
- this.menuItems.push({ label: 'New' });
137
- }
138
- onEdit(visit) {
139
- this.initVisitForm(visit);
140
- this.isEditing = true;
141
- this.menuItems.push({ label: visit.name });
142
- }
143
- async onSubmitVisit() {
144
- this.visitSubmitted = true;
145
- if (!this.visitForm.valid) {
146
- this.errorForm = true;
147
- return;
148
- }
149
- this.errorForm = false;
150
- const formValue = this.visitForm.value;
151
- const capture = {
152
- viewer: formValue.viewer,
153
- takenAt: this.captureDate,
154
- surface: formValue.surface,
155
- spaceID: this.currentSpace.id,
156
- };
157
- if (this.isEditing) {
158
- capture.id = formValue.captureID;
159
- await this.captureService.updateCapture(capture);
160
- const node = {
161
- id: formValue.nodeID,
162
- model3D: formValue.model3D,
163
- metadata: formValue.name,
164
- };
165
- await this.nodeService.updateNode(node);
166
- }
167
- else {
168
- let createdNode;
169
- await this.captureService.createCapture(capture).then(async (res) => {
170
- if (res) {
171
- const node = {
172
- model3D: formValue.model3D,
173
- captureID: res.id,
174
- metadata: formValue.name,
175
- };
176
- createdNode = await this.nodeService.createNode(node);
177
- }
178
- });
179
- this.launchImport(formValue.model3D, formValue.surface, createdNode, false)
180
- .then((success) => {
181
- this.modalReference.close('import ended with success');
182
- })
183
- .catch((e) => {
184
- this.modalReference.close(`Error while import: ${e}`);
185
- alert(`Error while import: ${e} ${JSON.stringify(e)}`);
186
- this.onDelete({
187
- node: createdNode,
188
- captureID: createdNode.captureID,
189
- }, false);
190
- });
191
- }
192
- await this.resetVisits();
193
- this.onCancel();
194
- }
195
- get model3D() {
196
- return this.visitForm.get('model3D');
197
- }
198
- get name() {
199
- return this.visitForm.get('name');
200
- }
201
- onCancel() {
202
- this.visitSubmitted = false;
203
- this.visitForm = null;
204
- this.isEditing = false;
205
- this.canCancelImport = false;
206
- this.totalImages = 0;
207
- this.imagesProcessed = 0;
208
- this.errorForm = false;
209
- this.setupMenuItems();
210
- }
211
- async onDelete(visit, needPermission = true) {
212
- const message = this.translate.instant('confirm.deleteVisit');
213
- // eslint-disable-next-line no-alert
214
- if (window.confirm(message) || !needPermission) {
215
- console.log(this.visitIndexDetails);
216
- this.isProcessing = true;
217
- await this.visitService.deleteVisit(visit, this.spaceId);
218
- await this.resetVisits();
219
- this.isProcessing = false;
220
- }
221
- }
222
- getDismissReason(reason) {
223
- if (reason === ModalDismissReasons.ESC) {
224
- return 'by pressing ESC';
225
- }
226
- if (reason === ModalDismissReasons.BACKDROP_CLICK) {
227
- return 'by clicking on a backdrop';
228
- }
229
- return `with: ${reason}`;
230
- }
231
- async launchImport(model3D, surface, node, imagesOnly = false, overrideExisting = false) {
232
- this.modalReference = this.modalService.open(this.content, {
233
- ariaLabelledBy: "modal-basic-title",
234
- });
235
- this.modalReference.result.then((result) => {
236
- this.closeResult = `Closed with: ${result}`;
237
- console.log(this.closeResult);
238
- this.cancelImport();
239
- }, (error) => {
240
- this.closeResult = `Dismissed ${this.getDismissReason(error)}`;
241
- console.log(this.closeResult);
242
- this.cancelImport();
243
- });
244
- try {
245
- await this.matterportImportService.initSdkForModel(model3D);
246
- await this.matterportImportService.importData(this.spaceId, surface, imagesOnly, node, overrideExisting);
247
- this.modalReference.close();
248
- }
249
- catch (error) {
250
- console.log(error);
251
- Promise.reject(error);
252
- }
253
- }
254
- cancelImport() {
255
- this.matterportImportService.abandon();
256
- this.onCancel();
257
- this.resetVisits();
258
- }
259
- onImportImages(visit, overrideExisting) {
260
- this.launchImport(visit.model3d, null, visit.node.id, true, overrideExisting);
261
- }
262
- isFormError(control) {
263
- return control && control.invalid && this.errorForm;
264
- }
265
- }
266
- VisitsComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: VisitsComponent, deps: [{ token: i1.UntypedFormBuilder }, { token: i2.MatterportImportService }, { token: i2.CaptureService }, { token: i2.NodeService }, { token: i2.SpaceService }, { token: i3.ActivatedRoute }, { token: i4.NgbModal }, { token: i2.VisitService }, { token: i2.ValidatorsService }, { token: i5.TranslateService }, { token: i2.NavigatorService }, { token: i3.Router }], target: i0.ɵɵFactoryTarget.Component });
267
- VisitsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: VisitsComponent, selector: "lib-visits", viewQueries: [{ propertyName: "content", first: true, predicate: ["content"], descendants: true }], ngImport: i0, template: "<div class=\"container-fluid\" class=\"dashboard-tab\">\r\n <div class=\"m-3\">\r\n <lib-tab-navigation [menuItems]='menuItems' (onGoBack)=\"onGoBack()\"></lib-tab-navigation>\r\n </div>\r\n\r\n <div class=\"row main-form-container\">\r\n <div class=\"col-md-6 form-container\">\r\n <ul class=\"list-group list-group-flush\" *ngIf=\"!visitForm\">\r\n <li class=\"list-group-item list-group-item-action\" *ngFor=\"let visit of visits; index as index\">\r\n <div class=\"d-flex justify-content-between align-items-center\" (click)=\"onToggleDetail(index)\">\r\n {{visit.name ? visit.name : visit.model3d }}\r\n <lib-chevron [conditionShowing]=\"index==visitIndexDetails\"></lib-chevron>\r\n </div>\r\n <div *ngIf=\"index==visitIndexDetails\">\r\n <ul class=\"list-group list-group-flush\">\r\n <li class=\"list-group-item bg-transparent\">{{'Name' | translate}} : {{ visit.name ?\r\n visit.name : \"Not provided\" | translate}}</li>\r\n <li class=\"list-group-item bg-transparent\">{{'3D Model' | translate}} : {{ visit.model3d }}\r\n </li>\r\n <li class=\"list-group-item bg-transparent\">{{'Surface' | translate}}, m<sup>2</sup>: {{\r\n visit.surface ?\r\n visit.surface : 'Not provided' | translate}}</li>\r\n <li class=\"list-group-item bg-transparent\">{{'Viewer' | translate}} : {{ visit.viewer }}\r\n </li>\r\n <li class=\"list-group-item bg-transparent\">{{'Date of capture' | translate}} : {{\r\n visit.takenAt | timeDateString | async}}\r\n <li class=\"list-group-item bg-transparent\">{{'Images are imported' | translate}} : {{\r\n imagesUploaded }}\r\n </li>\r\n </ul>\r\n \r\n <lib-loader *ngIf=\"isProcessing\"></lib-loader>\r\n\r\n <div class=\"action-button-container mt-3\">\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"onImportImages(visit, true)\" [disabled]=\"isProcessing\">{{'Import all images' |\r\n translate}}</button>\r\n <button type=\"button\" *ngIf=\"imagesUploaded > 0\" class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"onImportImages(visit, false)\" [disabled]=\"isProcessing\">{{'Import from image' |\r\n translate}} {{imagesUploaded}}</button>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2\" [disabled]=\"isProcessing\"\r\n (click)=\"onEdit(visit)\">{{'Edit' | translate}}</button>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\" [disabled]=\"isProcessing\"\r\n (click)=\"onDelete(visit)\">{{'Delete' | translate}}</button>\r\n </div>\r\n </div>\r\n </li>\r\n </ul>\r\n <div *ngIf=\"visitForm\">\r\n <form (ngSubmit)=\"onSubmitVisit()\" [formGroup]=\"visitForm\">\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Name' | translate}}</label>\r\n <div class=\"col-sm-10\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"name\">\r\n </div>\r\n </div>\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Reference 3D model' | translate}} *</label>\r\n <div class=\"col-sm-10\">\r\n <input type=\"text\" class=\"form-control\" [readonly]=\"isEditing\"\r\n [class.is-invalid]=\"model3D.invalid && visitSubmitted\" required\r\n formControlName=\"model3D\">\r\n <div class=\"invalid-feedback\">\r\n <ngb-alert data-testid=\"new-location-name-invalid\" [dismissible]=\"false\" type=\"danger\" \r\n *ngIf=\"validatorsService.isControlError(visitForm.controls['name']) \r\n || isFormError(visitForm.controls['name'])\">\r\n {{validatorsService.getError(visitForm.controls['name']) | translate}}\r\n </ngb-alert>\r\n </div>\r\n <div *ngIf=\"isEditing\" class=\"text-danger\">\r\n {{'Cannot change 3D model reference. Please add new model.' | translate}}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Viewer' | translate}}</label>\r\n <div class=\"col-sm-10\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"viewer\">\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Surface' | translate}}</label>\r\n <div class=\"col-sm-10\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"surface\">\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Capture Date' | translate}}</label>\r\n <div class=\"input-group\">\r\n <input class=\"form-control\" placeholder=\"dd/mm/yyyy\" [(ngModel)]=\"captureDate\" ngbDatepicker\r\n #d1=\"ngbDatepicker\" [ngModelOptions]=\"{standalone: true}\">\r\n <div class=\"input-group-append\">\r\n <button class=\"btn btn-outline-secondary calendar\" (click)=\"d1.toggle()\"\r\n type=\"button\"></button>\r\n </div>\r\n </div>\r\n </div>\r\n <button type=\"submit\" class=\"btn btn-outline-primary rounded-pill me-2\">{{'Save' |\r\n translate}}</button>\r\n <button type=\"button\" (click)=\"onCancel()\" class=\"btn btn-outline-primary rounded-pill\">{{'Cancel' |\r\n translate}}</button>\r\n <div class=\"invalid-feedback\" *ngIf=\"errorForm\">\r\n <ngb-alert data-testid=\"new-location-form-invalid\" [dismissible]=\"false\" type=\"danger\">\r\n {{'errorForm.infoBtn' |translate}}\r\n \r\n </ngb-alert>\r\n </div>\r\n </form>\r\n </div>\r\n <div *ngIf=\"!visitForm\">\r\n <button class=\"btn btn-outline-primary rounded-pill\" (click)=\"onAddVisit()\">{{'Add 3D visit' |\r\n translate}}</button>\r\n </div>\r\n </div>\r\n <div id=\"viewer-frame\" style=\"width: 100%; aspect-ratio: 2/1;\"></div>\r\n </div>\r\n <ng-template #content let-modal>\r\n <div class=\"modal-header\">\r\n <h4 class=\"modal-title\" id=\"modal-basic-title\">{{'Importing Data' | translate}}</h4>\r\n <button type=\"button\" class=\"close\" aria-label=\"Close\" (click)=\"modal.dismiss('Cross click')\">\r\n <span aria-hidden=\"true\">\u00D7</span>\r\n </button>\r\n </div>\r\n <div class=\"modal-body\">\r\n {{'Please do not leave or refresh this page...' | translate}}\r\n <div *ngIf=\"totalImages != 0\">Imported {{imagesProcessed}} out of {{totalImages}} images.</div>\r\n <div class=\"d-flex justify-content-center\">\r\n <div class=\"spinner-border\" role=\"status\">\r\n <span class=\"visually-hidden\">{{'Loading' | translate}}...</span>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"modal-footer\">\r\n <button type=\"button\" class=\"btn btn-outline-dark\" [disabled]=\"!canCancelImport\"\r\n (click)=\"modal.close('Cancel click')\">{{'Cancel import of images' | translate}}</button>\r\n </div>\r\n </ng-template>\r\n</div>", styles: [".col-form-label{width:180px;margin-bottom:1rem}.btn-outline-primary{width:200px;margin-right:1rem}.input-group{width:83%;height:-moz-fit-content;height:fit-content}.main-form-container{width:60vw;display:flex;flex-direction:column}@media screen and (max-width: 765px){.main-form-container{width:90vw}}.main-form-container .form-container{width:100%}\n"], dependencies: [{ kind: "component", type: i4.NgbAlert, selector: "ngb-alert", inputs: ["animation", "dismissible", "type"], outputs: ["closed"], exportAs: ["ngbAlert"] }, { kind: "directive", type: i4.NgbInputDatepicker, selector: "input[ngbDatepicker]", inputs: ["autoClose", "contentTemplate", "datepickerClass", "dayTemplate", "dayTemplateData", "displayMonths", "firstDayOfWeek", "footerTemplate", "markDisabled", "minDate", "maxDate", "navigation", "outsideDays", "placement", "popperOptions", "restoreFocus", "showWeekNumbers", "startDate", "container", "positionTarget", "weekdays", "disabled"], outputs: ["dateSelect", "navigate", "closed"], exportAs: ["ngbDatepicker"] }, { 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.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i2.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: i6.AsyncPipe, name: "async" }, { kind: "pipe", type: i5.TranslatePipe, name: "translate" }, { kind: "pipe", type: i2.TimeDateToLocalStringPipe, name: "timeDateString" }] });
268
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: VisitsComponent, decorators: [{
269
- type: Component,
270
- args: [{ selector: 'lib-visits', template: "<div class=\"container-fluid\" class=\"dashboard-tab\">\r\n <div class=\"m-3\">\r\n <lib-tab-navigation [menuItems]='menuItems' (onGoBack)=\"onGoBack()\"></lib-tab-navigation>\r\n </div>\r\n\r\n <div class=\"row main-form-container\">\r\n <div class=\"col-md-6 form-container\">\r\n <ul class=\"list-group list-group-flush\" *ngIf=\"!visitForm\">\r\n <li class=\"list-group-item list-group-item-action\" *ngFor=\"let visit of visits; index as index\">\r\n <div class=\"d-flex justify-content-between align-items-center\" (click)=\"onToggleDetail(index)\">\r\n {{visit.name ? visit.name : visit.model3d }}\r\n <lib-chevron [conditionShowing]=\"index==visitIndexDetails\"></lib-chevron>\r\n </div>\r\n <div *ngIf=\"index==visitIndexDetails\">\r\n <ul class=\"list-group list-group-flush\">\r\n <li class=\"list-group-item bg-transparent\">{{'Name' | translate}} : {{ visit.name ?\r\n visit.name : \"Not provided\" | translate}}</li>\r\n <li class=\"list-group-item bg-transparent\">{{'3D Model' | translate}} : {{ visit.model3d }}\r\n </li>\r\n <li class=\"list-group-item bg-transparent\">{{'Surface' | translate}}, m<sup>2</sup>: {{\r\n visit.surface ?\r\n visit.surface : 'Not provided' | translate}}</li>\r\n <li class=\"list-group-item bg-transparent\">{{'Viewer' | translate}} : {{ visit.viewer }}\r\n </li>\r\n <li class=\"list-group-item bg-transparent\">{{'Date of capture' | translate}} : {{\r\n visit.takenAt | timeDateString | async}}\r\n <li class=\"list-group-item bg-transparent\">{{'Images are imported' | translate}} : {{\r\n imagesUploaded }}\r\n </li>\r\n </ul>\r\n \r\n <lib-loader *ngIf=\"isProcessing\"></lib-loader>\r\n\r\n <div class=\"action-button-container mt-3\">\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"onImportImages(visit, true)\" [disabled]=\"isProcessing\">{{'Import all images' |\r\n translate}}</button>\r\n <button type=\"button\" *ngIf=\"imagesUploaded > 0\" class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"onImportImages(visit, false)\" [disabled]=\"isProcessing\">{{'Import from image' |\r\n translate}} {{imagesUploaded}}</button>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2\" [disabled]=\"isProcessing\"\r\n (click)=\"onEdit(visit)\">{{'Edit' | translate}}</button>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\" [disabled]=\"isProcessing\"\r\n (click)=\"onDelete(visit)\">{{'Delete' | translate}}</button>\r\n </div>\r\n </div>\r\n </li>\r\n </ul>\r\n <div *ngIf=\"visitForm\">\r\n <form (ngSubmit)=\"onSubmitVisit()\" [formGroup]=\"visitForm\">\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Name' | translate}}</label>\r\n <div class=\"col-sm-10\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"name\">\r\n </div>\r\n </div>\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Reference 3D model' | translate}} *</label>\r\n <div class=\"col-sm-10\">\r\n <input type=\"text\" class=\"form-control\" [readonly]=\"isEditing\"\r\n [class.is-invalid]=\"model3D.invalid && visitSubmitted\" required\r\n formControlName=\"model3D\">\r\n <div class=\"invalid-feedback\">\r\n <ngb-alert data-testid=\"new-location-name-invalid\" [dismissible]=\"false\" type=\"danger\" \r\n *ngIf=\"validatorsService.isControlError(visitForm.controls['name']) \r\n || isFormError(visitForm.controls['name'])\">\r\n {{validatorsService.getError(visitForm.controls['name']) | translate}}\r\n </ngb-alert>\r\n </div>\r\n <div *ngIf=\"isEditing\" class=\"text-danger\">\r\n {{'Cannot change 3D model reference. Please add new model.' | translate}}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Viewer' | translate}}</label>\r\n <div class=\"col-sm-10\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"viewer\">\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Surface' | translate}}</label>\r\n <div class=\"col-sm-10\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"surface\">\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Capture Date' | translate}}</label>\r\n <div class=\"input-group\">\r\n <input class=\"form-control\" placeholder=\"dd/mm/yyyy\" [(ngModel)]=\"captureDate\" ngbDatepicker\r\n #d1=\"ngbDatepicker\" [ngModelOptions]=\"{standalone: true}\">\r\n <div class=\"input-group-append\">\r\n <button class=\"btn btn-outline-secondary calendar\" (click)=\"d1.toggle()\"\r\n type=\"button\"></button>\r\n </div>\r\n </div>\r\n </div>\r\n <button type=\"submit\" class=\"btn btn-outline-primary rounded-pill me-2\">{{'Save' |\r\n translate}}</button>\r\n <button type=\"button\" (click)=\"onCancel()\" class=\"btn btn-outline-primary rounded-pill\">{{'Cancel' |\r\n translate}}</button>\r\n <div class=\"invalid-feedback\" *ngIf=\"errorForm\">\r\n <ngb-alert data-testid=\"new-location-form-invalid\" [dismissible]=\"false\" type=\"danger\">\r\n {{'errorForm.infoBtn' |translate}}\r\n \r\n </ngb-alert>\r\n </div>\r\n </form>\r\n </div>\r\n <div *ngIf=\"!visitForm\">\r\n <button class=\"btn btn-outline-primary rounded-pill\" (click)=\"onAddVisit()\">{{'Add 3D visit' |\r\n translate}}</button>\r\n </div>\r\n </div>\r\n <div id=\"viewer-frame\" style=\"width: 100%; aspect-ratio: 2/1;\"></div>\r\n </div>\r\n <ng-template #content let-modal>\r\n <div class=\"modal-header\">\r\n <h4 class=\"modal-title\" id=\"modal-basic-title\">{{'Importing Data' | translate}}</h4>\r\n <button type=\"button\" class=\"close\" aria-label=\"Close\" (click)=\"modal.dismiss('Cross click')\">\r\n <span aria-hidden=\"true\">\u00D7</span>\r\n </button>\r\n </div>\r\n <div class=\"modal-body\">\r\n {{'Please do not leave or refresh this page...' | translate}}\r\n <div *ngIf=\"totalImages != 0\">Imported {{imagesProcessed}} out of {{totalImages}} images.</div>\r\n <div class=\"d-flex justify-content-center\">\r\n <div class=\"spinner-border\" role=\"status\">\r\n <span class=\"visually-hidden\">{{'Loading' | translate}}...</span>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"modal-footer\">\r\n <button type=\"button\" class=\"btn btn-outline-dark\" [disabled]=\"!canCancelImport\"\r\n (click)=\"modal.close('Cancel click')\">{{'Cancel import of images' | translate}}</button>\r\n </div>\r\n </ng-template>\r\n</div>", styles: [".col-form-label{width:180px;margin-bottom:1rem}.btn-outline-primary{width:200px;margin-right:1rem}.input-group{width:83%;height:-moz-fit-content;height:fit-content}.main-form-container{width:60vw;display:flex;flex-direction:column}@media screen and (max-width: 765px){.main-form-container{width:90vw}}.main-form-container .form-container{width:100%}\n"] }]
271
- }], ctorParameters: function () { return [{ type: i1.UntypedFormBuilder }, { type: i2.MatterportImportService }, { type: i2.CaptureService }, { type: i2.NodeService }, { type: i2.SpaceService }, { type: i3.ActivatedRoute }, { type: i4.NgbModal }, { type: i2.VisitService }, { type: i2.ValidatorsService }, { type: i5.TranslateService }, { type: i2.NavigatorService }, { type: i3.Router }]; }, propDecorators: { content: [{
272
- type: ViewChild,
273
- args: ['content', { static: false }]
274
- }] } });
275
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmlzaXRzLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1zbWFydGVycGxhbi1sb2NhdGlvbnMvc3JjL2xpYi9jb21wb25lbnRzL3Zpc2l0cy92aXNpdHMuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWxvY2F0aW9ucy9zcmMvbGliL2NvbXBvbmVudHMvdmlzaXRzL3Zpc2l0cy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFVLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUM3RCxPQUFPLEVBR0gsVUFBVSxHQUViLE1BQU0sZ0JBQWdCLENBQUM7QUFFeEIsT0FBTyxFQUFZLG1CQUFtQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDM0UsT0FBTyxFQVNILGFBQWEsR0FJaEIsTUFBTSxtQ0FBbUMsQ0FBQztBQUUzQyxPQUFPLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLE1BQU0sQ0FBQzs7Ozs7Ozs7OztBQU8xQyxNQUFNLE9BQU8sZUFBZTtJQXVDeEIsWUFDWSxFQUFzQixFQUN0Qix1QkFBZ0QsRUFDaEQsY0FBOEIsRUFDOUIsV0FBd0IsRUFDeEIsWUFBMEIsRUFDMUIsS0FBcUIsRUFDckIsWUFBc0IsRUFDdEIsWUFBMEIsRUFDM0IsaUJBQW9DLEVBQ25DLFNBQTJCLEVBQzNCLGdCQUFrQyxFQUNsQyxNQUFjO1FBWGQsT0FBRSxHQUFGLEVBQUUsQ0FBb0I7UUFDdEIsNEJBQXVCLEdBQXZCLHVCQUF1QixDQUF5QjtRQUNoRCxtQkFBYyxHQUFkLGNBQWMsQ0FBZ0I7UUFDOUIsZ0JBQVcsR0FBWCxXQUFXLENBQWE7UUFDeEIsaUJBQVksR0FBWixZQUFZLENBQWM7UUFDMUIsVUFBSyxHQUFMLEtBQUssQ0FBZ0I7UUFDckIsaUJBQVksR0FBWixZQUFZ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LEtBQUssRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBWaWV3Q2hpbGQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHtcclxuICAgIFVudHlwZWRGb3JtR3JvdXAsXHJcbiAgICBVbnR5cGVkRm9ybUJ1aWxkZXIsXHJcbiAgICBWYWxpZGF0b3JzLFxyXG4gICAgQWJzdHJhY3RDb250cm9sLFxyXG59IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcclxuaW1wb3J0IHsgQWN0aXZhdGVkUm91dGUsIFJvdXRlciB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XHJcbmltcG9ydCB7IE5nYk1vZGFsLCBNb2RhbERpc21pc3NSZWFzb25zIH0gZnJvbSAnQG5nLWJvb3RzdHJhcC9uZy1ib290c3RyYXAnO1xyXG5pbXBvcnQge1xyXG4gICAgTm9kZSxcclxuICAgIFZpc2l0LFxyXG4gICAgTWVudUl0ZW0sXHJcbiAgICBNYXR0ZXJwb3J0SW1wb3J0U2VydmljZSxcclxuICAgIENhcHR1cmVTZXJ2aWNlLFxyXG4gICAgTm9kZVNlcnZpY2UsXHJcbiAgICBTcGFjZVNlcnZpY2UsXHJcbiAgICBWaXNpdFNlcnZpY2UsXHJcbiAgICBDYXB0dXJlVmlld2VyLFxyXG4gICAgQ2FwdHVyZSxcclxuICAgIFZhbGlkYXRvcnNTZXJ2aWNlLFxyXG4gICAgTmF2aWdhdG9yU2VydmljZSxcclxufSBmcm9tICdAc21hcnRlcnBsYW4vbmd4LXNtYXJ0ZXJwbGFuLWNvcmUnO1xyXG5pbXBvcnQgeyBUcmFuc2xhdGVTZXJ2aWNlIH0gZnJvbSAnQG5neC10cmFuc2xhdGUvY29yZSc7XHJcbmltcG9ydCB7IFN1YmplY3QsIHRha2VVbnRpbCB9IGZyb20gJ3J4anMnO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgICBzZWxlY3RvcjogJ2xpYi12aXNpdHMnLFxyXG4gICAgdGVtcGxhdGVVcmw6ICcuL3Zpc2l0cy5jb21wb25lbnQuaHRtbCcsXHJcbiAgICBzdHlsZVVybHM6IFsnLi92aXNpdHMuY29tcG9uZW50LnNjc3MnXSxcclxufSlcclxuZXhwb3J0IGNsYXNzIFZpc2l0c0NvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XHJcbiAgICBzcGFjZUlkOiBzdHJpbmc7XHJcblxyXG4gICAgdmlzaXRJbmRleERldGFpbHMgPSAtMTtcclxuXHJcbiAgICB2aXNpdEZvcm06IFVudHlwZWRGb3JtR3JvdXA7XHJcblxyXG4gICAgaXNFZGl0aW5nOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gICAgdmlzaXRTdWJtaXR0ZWQ6IGJvb2xlYW4gPSBmYWxzZTtcclxuXHJcbiAgICBjYXB0dXJlRGF0ZTogbnVtYmVyO1xyXG5cclxuICAgIGN1cnJlbnRTcGFjZSA9IHsgem9uZXM6IFtdIH0gYXMgYW55O1xyXG5cclxuICAgIHZpc2l0czogVmlzaXRbXSA9IFtdO1xyXG5cclxuICAgIGNsb3NlUmVzdWx0OiBzdHJpbmc7XHJcblxyXG4gICAgQFZpZXdDaGlsZCgnY29udGVudCcsIHsgc3RhdGljOiBmYWxzZSB9KSBwcml2YXRlIGNvbnRlbnQ7XHJcblxyXG4gICAgbW9kYWxSZWZlcmVuY2U6IGFueTtcclxuXHJcbiAgICBjYW5DYW5jZWxJbXBvcnQgPSBmYWxzZTtcclxuXHJcbiAgICBpbWFnZXNQcm9jZXNzZWQ6IG51bWJlciA9IDA7XHJcblxyXG4gICAgdG90YWxJbWFnZXM6IG51bWJlciA9IDA7XHJcblxyXG4gICAgaW1hZ2VzVXBsb2FkZWQ6IG51bWJlciA9IDA7XHJcblxyXG4gICAgbWVudUl0ZW1zOiBNZW51SXRlbVtdID0gW107XHJcblxyXG4gICAgZXJyb3JGb3JtOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gICAgaXNQcm9jZXNzaW5nID0gZmFsc2U7XHJcblxyXG4gICAgZGVzdHJveSQgPSBuZXcgU3ViamVjdCgpO1xyXG5cclxuICAgIGNvbnN0cnVjdG9yKFxyXG4gICAgICAgIHByaXZhdGUgZmI6IFVudHlwZWRGb3JtQnVpbGRlcixcclxuICAgICAgICBwcml2YXRlIG1hdHRlcnBvcnRJbXBvcnRTZXJ2aWNlOiBNYXR0ZXJwb3J0SW1wb3J0U2VydmljZSxcclxuICAgICAgICBwcml2YXRlIGNhcHR1cmVTZXJ2aWNlOiBDYXB0dXJlU2VydmljZSxcclxuICAgICAgICBwcml2YXRlIG5vZGVTZXJ2aWNlOiBOb2RlU2VydmljZSxcclxuICAgICAgICBwcml2YXRlIHNwYWNlU2VydmljZTogU3BhY2VTZXJ2aWNlLFxyXG4gICAgICAgIHByaXZhdGUgcm91dGU6IEFjdGl2YXRlZFJvdXRlLFxyXG4gICAgICAgIHByaXZhdGUgbW9kYWxTZXJ2aWNlOiBOZ2JNb2RhbCxcclxuICAgICAgICBwcml2YXRlIHZpc2l0U2VydmljZTogVmlzaXRTZXJ2aWNlLFxyXG4gICAgICAgIHB1YmxpYyB2YWxpZGF0b3JzU2VydmljZTogVmFsaWRhdG9yc1NlcnZpY2UsXHJcbiAgICAgICAgcHJpdmF0ZSB0cmFuc2xhdGU6IFRyYW5zbGF0ZVNlcnZpY2UsXHJcbiAgICAgICAgcHJpdmF0ZSBuYXZpZ2F0b3JTZXJ2aWNlOiBOYXZpZ2F0b3JTZXJ2aWNlLFxyXG4gICAgICAgIHByaXZhdGUgcm91dGVyOiBSb3V0ZXIsXHJcbiAgICApIHtcclxuICAgICAgICB0aGlzLm1hdHRlcnBvcnRJbXBvcnRTZXJ2aWNlLmltcG9ydGluZ0ltYWdlcy5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSkuc3Vic2NyaWJlKCgpID0+IHtcclxuICAgICAgICAgICAgdGhpcy5jYW5DYW5jZWxJbXBvcnQgPSB0cnVlO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIHRoaXMubWF0dGVycG9ydEltcG9ydFNlcnZpY2Uuc3dlZXBQcm9jZXNzZWRDb3VudC5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSkuc3Vic2NyaWJlKChjb3VudCkgPT4ge1xyXG4gICAgICAgICAgICB0aGlzLmltYWdlc1Byb2Nlc3NlZCA9IGNvdW50ICsgMTtcclxuICAgICAgICB9KTtcclxuICAgICAgICB0aGlzLm1hdHRlcnBvcnRJbXBvcnRTZXJ2aWNlLnRvdGFsU3dlZXBzQ291bnQucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpLnN1YnNjcmliZSgoY291bnQpID0+IHtcclxuICAgICAgICAgICAgdGhpcy50b3RhbEltYWdlcyA9IGNvdW50O1xyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICB0aGlzLm5hdmlnYXRvclNlcnZpY2UubG9jYXRpb25JRENoYW5nZVxyXG4gICAgICAgICAgICAucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpXHJcbiAgICAgICAgICAgIC5zdWJzY3JpYmUoKHNwYWNlSUQpID0+IHtcclxuICAgICAgICAgICAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFtcImRhc2hib2FyZC9sb2NhbGlzYXRpb25cIiwgc3BhY2VJRCwgXCJ2aXNpdHNcIl0pO1xyXG4gICAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgdGhpcy5yb3V0ZS5wYXJhbXMuc3Vic2NyaWJlKChwYXJhbXMpID0+IHtcclxuICAgICAgICAgICAgdGhpcy5zcGFjZUlkID0gcGFyYW1zLmlkO1xyXG4gICAgICAgICAgICB0aGlzLnJlc2V0VmlzaXRzKCk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgYXN5bmMgbmdPbkluaXQoKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICAgICAgdGhpcy5zcGFjZUlkID0gdGhpcy5yb3V0ZS5zbmFwc2hvdC5wYXJhbU1hcC5nZXQoJ2lkJyk7XHJcbiAgICAgICAgYXdhaXQgdGhpcy5yZXNldFZpc2l0cygpO1xyXG4gICAgfVxyXG5cclxuICAgIG5nT25EZXN0cm95KCkge1xyXG4gICAgICAgIHRoaXMuZGVzdHJveSQubmV4dCh0cnVlKTtcclxuICAgICAgICB0aGlzLmRlc3Ryb3kkLmNvbXBsZXRlKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLypcclxuICAgIFZpc2l0ID0ge1xyXG4gICAgICBjYXB0dXJlSUQ6IHN0cmluZyxcclxuICAgICAgbW9kZWwzZDogc3RyaW5nLFxyXG4gICAgICB0YWtlbkF0OiBudW1iZXIsXHJcbiAgICAgIHNwYWNlSUQ6IHN0cmluZyxcclxuICAgICAgdmlld2VyOiBDYXB0dXJlVmlld2VyLFxyXG4gICAgICBzdXJmYWNlOiBudW1iZXIsXHJcbiAgICAgIG5vZGU6IE5vZGUsXHJcbiAgICAgIG5hbWU/OiBzdHJpbmcgfCBudWxsXHJcbiAgICB9XHJcbiAgICAqL1xyXG4gICAgc2V0dXBNZW51SXRlbXMoKSB7XHJcbiAgICAgICAgdGhpcy5tZW51SXRlbXMgPSBbXHJcbiAgICAgICAgICAgIHsgbGFiZWw6ICdMb2NhdGlvbnMnLCB1cmw6ICcvbG9jYWxpc2F0aW9uJyB9LFxyXG4gICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICBsYWJlbDogdGhpcy5jdXJyZW50U3BhY2UubmFtZSxcclxuICAgICAgICAgICAgICAgIHVybDogYC9sb2NhbGlzYXRpb24vJHt0aGlzLmN1cnJlbnRTcGFjZS5pZH1gLFxyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICBsYWJlbDogJ1ZpcnR1YWwgdmlzaXRzJyxcclxuICAgICAgICAgICAgICAgIHVybDogYC9sb2NhbGlzYXRpb24vJHt0aGlzLmN1cnJlbnRTcGFjZS5pZH0vdmlzaXRzYCxcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICBdO1xyXG4gICAgfVxyXG5cclxuICAgIG9uR29CYWNrKCkge1xyXG4gICAgICAgIHRoaXMub25DYW5jZWwoKTtcclxuICAgIH1cclxuXHJcbiAgICBhc3luYyByZXNldFZpc2l0cygpIHtcclxuICAgICAgICB0aGlzLnZpc2l0cyA9IFtdO1xyXG4gICAgICAgIHRoaXMuY3VycmVudFNwYWNlID0gYXdhaXQgdGhpcy5zcGFjZVNlcnZpY2UuZ2V0U3BhY2UodGhpcy5zcGFjZUlkKTtcclxuICAgICAgICB0aGlzLnNldHVwTWVudUl0ZW1zKCk7XHJcbiAgICAgICAgYXdhaXQgdGhpcy52aXNpdFNlcnZpY2VcclxuICAgICAgICAgICAgLmdldFZpc2l0c0ZvclNwYWNlRm9yVXNlcih0aGlzLnNwYWNlSWQpXHJcbiAgICAgICAgICAgIC50aGVuKCh2aXNpdHMpID0+IHtcclxuICAgICAgICAgICAgICAgIGlmICh2aXNpdHMpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLnZpc2l0cyA9IHZpc2l0cztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgaW5pdFZpc2l0Rm9ybShpbnB1dDogVmlzaXQgPSBudWxsKSB7XHJcbiAgICAgICAgaWYgKGlucHV0KSB7XHJcbiAgICAgICAgICAgIHRoaXMudmlzaXRGb3JtID0gdGhpcy5mYi5ncm91cCh7XHJcbiAgICAgICAgICAgICAgICBjYXB0dXJlSUQ6IGlucHV0LmNhcHR1cmVJRCxcclxuICAgICAgICAgICAgICAgIG5vZGVJRDogaW5wdXQubm9kZS5pZCxcclxuICAgICAgICAgICAgICAgIG5hbWU6IFtpbnB1dC5uYW1lLCBbVmFsaWRhdG9ycy5yZXF1aXJlZF1dLFxyXG4gICAgICAgICAgICAgICAgbW9kZWwzRDogW2lucHV0Lm1vZGVsM2QsIFtWYWxpZGF0b3JzLnJlcXVpcmVkXV0sXHJcbiAgICAgICAgICAgICAgICB2aWV3ZXI6IGlucHV0LnZpZXdlciA/IGlucHV0LnZpZXdlciA6IENhcHR1cmVWaWV3ZXIuTUFUVEVSUE9SVCxcclxuICAgICAgICAgICAgICAgIHN1cmZhY2U6IGlucHV0LnN1cmZhY2UgPyBpbnB1dC5zdXJmYWNlIDogbnVsbCxcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIHRoaXMuY2FwdHVyZURhdGUgPSBpbnB1dC50YWtlbkF0O1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHRoaXMudmlzaXRGb3JtID0gdGhpcy5mYi5ncm91cCh7XHJcbiAgICAgICAgICAgICAgICBtb2RlbDNEOiBbbnVsbCwgW1ZhbGlkYXRvcnMucmVxdWlyZWRdXSxcclxuICAgICAgICAgICAgICAgIHZpZXdlcjogQ2FwdHVyZVZpZXdlci5NQVRURVJQT1JULFxyXG4gICAgICAgICAgICAgICAgc3VyZmFjZTogbnVsbCxcclxuICAgICAgICAgICAgICAgIG5hbWU6IFtudWxsLCBbVmFsaWRhdG9ycy5yZXF1aXJlZF1dLFxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgYXN5bmMgb25Ub2dnbGVEZXRhaWwoaW5kZXgpIHtcclxuICAgICAgICB0aGlzLnZpc2l0SW5kZXhEZXRhaWxzID0gaW5kZXggPT09IHRoaXMudmlzaXRJbmRleERldGFpbHMgPyAtMSA6IGluZGV4O1xyXG4gICAgICAgIHRoaXMuaW1hZ2VzVXBsb2FkZWQgPSBhd2FpdCB0aGlzLm1hdHRlcnBvcnRJbXBvcnRTZXJ2aWNlLmdldFVwbG9hZGVkSW1hZ2VDb3VudCh0aGlzLnZpc2l0c1tpbmRleF0ubW9kZWwzZCk7XHJcbiAgICB9XHJcblxyXG4gICAgb25BZGRWaXNpdCgpIHtcclxuICAgICAgICB0aGlzLmluaXRWaXNpdEZvcm0oKTtcclxuICAgICAgICB0aGlzLm1lbnVJdGVtcy5wdXNoKHsgbGFiZWw6ICdOZXcnIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIG9uRWRpdCh2aXNpdCkge1xyXG4gICAgICAgIHRoaXMuaW5pdFZpc2l0Rm9ybSh2aXNpdCk7XHJcbiAgICAgICAgdGhpcy5pc0VkaXRpbmcgPSB0cnVlO1xyXG4gICAgICAgIHRoaXMubWVudUl0ZW1zLnB1c2goeyBsYWJlbDogdmlzaXQubmFtZSB9KTtcclxuICAgIH1cclxuXHJcbiAgICBhc3luYyBvblN1Ym1pdFZpc2l0KCkge1xyXG4gICAgICAgIHRoaXMudmlzaXRTdWJtaXR0ZWQgPSB0cnVlO1xyXG4gICAgICAgIGlmICghdGhpcy52aXNpdEZvcm0udmFsaWQpIHtcclxuICAgICAgICAgICAgdGhpcy5lcnJvckZvcm0gPSB0cnVlO1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMuZXJyb3JGb3JtID0gZmFsc2U7XHJcbiAgICAgICAgY29uc3QgZm9ybVZhbHVlID0gdGhpcy52aXNpdEZvcm0udmFsdWU7XHJcbiAgICAgICAgY29uc3QgY2FwdHVyZSA9IHtcclxuICAgICAgICAgICAgdmlld2VyOiBmb3JtVmFsdWUudmlld2VyLFxyXG4gICAgICAgICAgICB0YWtlbkF0OiB0aGlzLmNhcHR1cmVEYXRlLFxyXG4gICAgICAgICAgICBzdXJmYWNlOiBmb3JtVmFsdWUuc3VyZmFjZSxcclxuICAgICAgICAgICAgc3BhY2VJRDogdGhpcy5jdXJyZW50U3BhY2UuaWQsXHJcbiAgICAgICAgfSBhcyBDYXB0dXJlO1xyXG5cclxuICAgICAgICBpZiAodGhpcy5pc0VkaXRpbmcpIHtcclxuICAgICAgICAgICAgY2FwdHVyZS5pZCA9IGZvcm1WYWx1ZS5jYXB0dXJlSUQ7XHJcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuY2FwdHVyZVNlcnZpY2UudXBkYXRlQ2FwdHVyZShjYXB0dXJlKTtcclxuICAgICAgICAgICAgY29uc3Qgbm9kZSA9IHtcclxuICAgICAgICAgICAgICAgIGlkOiBmb3JtVmFsdWUubm9kZUlELFxyXG4gICAgICAgICAgICAgICAgbW9kZWwzRDogZm9ybVZhbHVlLm1vZGVsM0QsXHJcbiAgICAgICAgICAgICAgICBtZXRhZGF0YTogZm9ybVZhbHVlLm5hbWUsXHJcbiAgICAgICAgICAgIH0gYXMgTm9kZTtcclxuICAgICAgICAgICAgYXdhaXQgdGhpcy5ub2RlU2VydmljZS51cGRhdGVOb2RlKG5vZGUpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGxldCBjcmVhdGVkTm9kZTtcclxuICAgICAgICAgICAgYXdhaXQgdGhpcy5jYXB0dXJlU2VydmljZS5jcmVhdGVDYXB0dXJlKGNhcHR1cmUpLnRoZW4oYXN5bmMgKHJlcykgPT4ge1xyXG4gICAgICAgICAgICAgICAgaWYgKHJlcykge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG5vZGUgPSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vZGVsM0Q6IGZvcm1WYWx1ZS5tb2RlbDNELFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXB0dXJlSUQ6IHJlcy5pZCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGE6IGZvcm1WYWx1ZS5uYW1lLFxyXG4gICAgICAgICAgICAgICAgICAgIH0gYXMgTm9kZTtcclxuICAgICAgICAgICAgICAgICAgICBjcmVhdGVkTm9kZSA9IGF3YWl0IHRoaXMubm9kZVNlcnZpY2UuY3JlYXRlTm9kZShub2RlKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIHRoaXMubGF1bmNoSW1wb3J0KFxyXG4gICAgICAgICAgICAgICAgZm9ybVZhbHVlLm1vZGVsM0QsXHJcbiAgICAgICAgICAgICAgICBmb3JtVmFsdWUuc3VyZmFjZSxcclxuICAgICAgICAgICAgICAgIGNyZWF0ZWROb2RlLFxyXG4gICAgICAgICAgICAgICAgZmFsc2VcclxuICAgICAgICAgICAgKVxyXG4gICAgICAgICAgICAgICAgLnRoZW4oKHN1Y2Nlc3MpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLm1vZGFsUmVmZXJlbmNlLmNsb3NlKCdpbXBvcnQgZW5kZWQgd2l0aCBzdWNjZXNzJyk7XHJcbiAgICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICAgICAgLmNhdGNoKChlKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tb2RhbFJlZmVyZW5jZS5jbG9zZShgRXJyb3Igd2hpbGUgaW1wb3J0OiAke2V9YCk7XHJcbiAgICAgICAgICAgICAgICAgICAgYWxlcnQoYEVycm9yIHdoaWxlIGltcG9ydDogJHtlfSAke0pTT04uc3RyaW5naWZ5KGUpfWApO1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMub25EZWxldGUoe1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlOiBjcmVhdGVkTm9kZSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgY2FwdHVyZUlEOiBjcmVhdGVkTm9kZS5jYXB0dXJlSUQsXHJcbiAgICAgICAgICAgICAgICAgICAgfSBhcyBWaXNpdCwgZmFsc2UpO1xyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGF3YWl0IHRoaXMucmVzZXRWaXNpdHMoKTtcclxuICAgICAgICB0aGlzLm9uQ2FuY2VsKCk7XHJcbiAgICB9XHJcblxyXG4gICAgZ2V0IG1vZGVsM0QoKTogQWJzdHJhY3RDb250cm9sIHtcclxuICAgICAgICByZXR1cm4gdGhpcy52aXNpdEZvcm0uZ2V0KCdtb2RlbDNEJyk7XHJcbiAgICB9XHJcblxyXG4gICAgZ2V0IG5hbWUoKTogQWJzdHJhY3RDb250cm9sIHtcclxuICAgICAgICByZXR1cm4gdGhpcy52aXNpdEZvcm0uZ2V0KCduYW1lJyk7XHJcbiAgICB9XHJcblxyXG4gICAgb25DYW5jZWwoKSB7XHJcbiAgICAgICAgdGhpcy52aXNpdFN1Ym1pdHRlZCA9IGZhbHNlO1xyXG4gICAgICAgIHRoaXMudmlzaXRGb3JtID0gbnVsbDtcclxuICAgICAgICB0aGlzLmlzRWRpdGluZyA9IGZhbHNlO1xyXG4gICAgICAgIHRoaXMuY2FuQ2FuY2VsSW1wb3J0ID0gZmFsc2U7XHJcbiAgICAgICAgdGhpcy50b3RhbEltYWdlcyA9IDA7XHJcbiAgICAgICAgdGhpcy5pbWFnZXNQcm9jZXNzZWQgPSAwO1xyXG4gICAgICAgIHRoaXMuZXJyb3JGb3JtID0gZmFsc2U7XHJcbiAgICAgICAgdGhpcy5zZXR1cE1lbnVJdGVtcygpO1xyXG4gICAgfVxyXG5cclxuICAgIGFzeW5jIG9uRGVsZXRlKHZpc2l0OiBWaXNpdCwgbmVlZFBlcm1pc3Npb24gPSB0cnVlKSB7XHJcbiAgICAgICAgY29uc3QgbWVzc2FnZSA9IHRoaXMudHJhbnNsYXRlLmluc3RhbnQoJ2NvbmZpcm0uZGVsZXRlVmlzaXQnKTtcclxuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tYWxlcnRcclxuICAgICAgICBpZiAod2luZG93LmNvbmZpcm0obWVzc2FnZSkgfHwgIW5lZWRQZXJtaXNzaW9uKSB7XHJcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKHRoaXMudmlzaXRJbmRleERldGFpbHMpO1xyXG4gICAgICAgICAgICB0aGlzLmlzUHJvY2Vzc2luZyA9IHRydWU7XHJcbiAgICAgICAgICAgIGF3YWl0IHRoaXMudmlzaXRTZXJ2aWNlLmRlbGV0ZVZpc2l0KHZpc2l0LCB0aGlzLnNwYWNlSWQpO1xyXG4gICAgICAgICAgICBhd2FpdCB0aGlzLnJlc2V0VmlzaXRzKCk7XHJcbiAgICAgICAgICAgIHRoaXMuaXNQcm9jZXNzaW5nID0gZmFsc2U7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgZ2V0RGlzbWlzc1JlYXNvbihyZWFzb246IGFueSk6IHN0cmluZyB7XHJcbiAgICAgICAgaWYgKHJlYXNvbiA9PT0gTW9kYWxEaXNtaXNzUmVhc29ucy5FU0MpIHtcclxuICAgICAgICAgICAgcmV0dXJuICdieSBwcmVzc2luZyBFU0MnO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAocmVhc29uID09PSBNb2RhbERpc21pc3NSZWFzb25zLkJBQ0tEUk9QX0NMSUNLKSB7XHJcbiAgICAgICAgICAgIHJldHVybiAnYnkgY2xpY2tpbmcgb24gYSBiYWNrZHJvcCc7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBgd2l0aDogJHtyZWFzb259YDtcclxuICAgIH1cclxuXHJcbiAgICBhc3luYyBsYXVuY2hJbXBvcnQoXHJcbiAgICAgICAgbW9kZWwzRCxcclxuICAgICAgICBzdXJmYWNlLFxyXG4gICAgICAgIG5vZGUsXHJcbiAgICAgICAgaW1hZ2VzT25seSA9IGZhbHNlLFxyXG4gICAgICAgIG92ZXJyaWRlRXhpc3RpbmcgPSBmYWxzZSxcclxuICAgICkge1xyXG4gICAgICAgIHRoaXMubW9kYWxSZWZlcmVuY2UgPSB0aGlzLm1vZGFsU2VydmljZS5vcGVuKHRoaXMuY29udGVudCwge1xyXG4gICAgICAgICAgICBhcmlhTGFiZWxsZWRCeTogXCJtb2RhbC1iYXNpYy10aXRsZVwiLFxyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIHRoaXMubW9kYWxSZWZlcmVuY2UucmVzdWx0LnRoZW4oXHJcbiAgICAgICAgICAgIChyZXN1bHQpID0+IHtcclxuICAgICAgICAgICAgICAgIHRoaXMuY2xvc2VSZXN1bHQgPSBgQ2xvc2VkIHdpdGg6ICR7cmVzdWx0fWA7XHJcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyh0aGlzLmNsb3NlUmVzdWx0KTtcclxuICAgICAgICAgICAgICAgIHRoaXMuY2FuY2VsSW1wb3J0KCk7XHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIChlcnJvcikgPT4ge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5jbG9zZVJlc3VsdCA9IGBEaXNtaXNzZWQgJHt0aGlzLmdldERpc21pc3NSZWFzb24oZXJyb3IpfWA7XHJcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyh0aGlzLmNsb3NlUmVzdWx0KTtcclxuICAgICAgICAgICAgICAgIHRoaXMuY2FuY2VsSW1wb3J0KCk7XHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgKTtcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBhd2FpdCB0aGlzLm1hdHRlcnBvcnRJbXBvcnRTZXJ2aWNlLmluaXRTZGtGb3JNb2RlbChtb2RlbDNEKTtcclxuXHJcbiAgICAgICAgICAgIGF3YWl0IHRoaXMubWF0dGVycG9ydEltcG9ydFNlcnZpY2UuaW1wb3J0RGF0YShcclxuICAgICAgICAgICAgICAgIHRoaXMuc3BhY2VJZCxcclxuICAgICAgICAgICAgICAgIHN1cmZhY2UsXHJcbiAgICAgICAgICAgICAgICBpbWFnZXNPbmx5LFxyXG4gICAgICAgICAgICAgICAgbm9kZSxcclxuICAgICAgICAgICAgICAgIG92ZXJyaWRlRXhpc3RpbmdcclxuICAgICAgICAgICAgKTtcclxuXHJcbiAgICAgICAgICAgIHRoaXMubW9kYWxSZWZlcmVuY2UuY2xvc2UoKTtcclxuXHJcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgICAgICAgY29uc29sZS5sb2coZXJyb3IpO1xyXG4gICAgICAgICAgICBQcm9taXNlLnJlamVjdChlcnJvcik7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgY2FuY2VsSW1wb3J0KCkge1xyXG4gICAgICAgIHRoaXMubWF0dGVycG9ydEltcG9ydFNlcnZpY2UuYWJhbmRvbigpO1xyXG4gICAgICAgIHRoaXMub25DYW5jZWwoKTtcclxuICAgICAgICB0aGlzLnJlc2V0VmlzaXRzKCk7XHJcbiAgICB9XHJcblxyXG4gICAgb25JbXBvcnRJbWFnZXModmlzaXQ6IFZpc2l0LCBvdmVycmlkZUV4aXN0aW5nKSB7XHJcbiAgICAgICAgdGhpcy5sYXVuY2hJbXBvcnQodmlzaXQubW9kZWwzZCwgbnVsbCwgdmlzaXQubm9kZS5pZCwgdHJ1ZSwgb3ZlcnJpZGVFeGlzdGluZyk7XHJcbiAgICB9XHJcblxyXG4gICAgaXNGb3JtRXJyb3IoY29udHJvbCkge1xyXG4gICAgICAgIHJldHVybiBjb250cm9sICYmIGNvbnRyb2wuaW52YWxpZCAmJiB0aGlzLmVycm9yRm9ybTtcclxuICAgIH1cclxufVxyXG4iLCI8ZGl2IGNsYXNzPVwiY29udGFpbmVyLWZsdWlkXCIgY2xhc3M9XCJkYXNoYm9hcmQtdGFiXCI+XHJcbiAgICA8ZGl2IGNsYXNzPVwibS0zXCI+XHJcbiAgICAgICAgPGxpYi10YWItbmF2aWdhdGlvbiBbbWVudUl0ZW1zXT0nbWVudUl0ZW1zJyAob25Hb0JhY2spPVwib25Hb0JhY2soKVwiPjwvbGliLXRhYi1uYXZpZ2F0aW9uPlxyXG4gICAgPC9kaXY+XHJcblxyXG4gICAgPGRpdiBjbGFzcz1cInJvdyBtYWluLWZvcm0tY29udGFpbmVyXCI+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cImNvbC1tZC02IGZvcm0tY29udGFpbmVyXCI+XHJcbiAgICAgICAgICAgIDx1bCBjbGFzcz1cImxpc3QtZ3JvdXAgbGlzdC1ncm91cC1mbHVzaFwiICpuZ0lmPVwiIXZpc2l0Rm9ybVwiPlxyXG4gICAgICAgICAgICAgICAgPGxpIGNsYXNzPVwibGlzdC1ncm91cC1pdGVtIGxpc3QtZ3JvdXAtaXRlbS1hY3Rpb25cIiAqbmdGb3I9XCJsZXQgdmlzaXQgb2YgdmlzaXRzOyBpbmRleCBhcyBpbmRleFwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkLWZsZXgganVzdGlmeS1jb250ZW50LWJldHdlZW4gYWxpZ24taXRlbXMtY2VudGVyXCIgKGNsaWNrKT1cIm9uVG9nZ2xlRGV0YWlsKGluZGV4KVwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICB7e3Zpc2l0Lm5hbWUgPyB2aXNpdC5uYW1lIDogdmlzaXQubW9kZWwzZCB9fVxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8bGliLWNoZXZyb24gW2NvbmRpdGlvblNob3dpbmddPVwiaW5kZXg9PXZpc2l0SW5kZXhEZXRhaWxzXCI+PC9saWItY2hldnJvbj5cclxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgICAgICA8ZGl2ICpuZ0lmPVwiaW5kZXg9PXZpc2l0SW5kZXhEZXRhaWxzXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDx1bCBjbGFzcz1cImxpc3QtZ3JvdXAgbGlzdC1ncm91cC1mbHVzaFwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGxpIGNsYXNzPVwibGlzdC1ncm91cC1pdGVtIGJnLXRyYW5zcGFyZW50XCI+e3snTmFtZScgfCB0cmFuc2xhdGV9fSA6IHt7IHZpc2l0Lm5hbWUgP1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpc2l0Lm5hbWUgOiBcIk5vdCBwcm92aWRlZFwiIHwgdHJhbnNsYXRlfX08L2xpPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGxpIGNsYXNzPVwibGlzdC1ncm91cC1pdGVtIGJnLXRyYW5zcGFyZW50XCI+e3snM0QgTW9kZWwnIHwgdHJhbnNsYXRlfX0gOiB7eyB2aXNpdC5tb2RlbDNkIH19XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2xpPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGxpIGNsYXNzPVwibGlzdC1ncm91cC1pdGVtIGJnLXRyYW5zcGFyZW50XCI+e3snU3VyZmFjZScgfCB0cmFuc2xhdGV9fSwgbTxzdXA+Mjwvc3VwPjoge3tcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2aXNpdC5zdXJmYWNlID9cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2aXNpdC5zdXJmYWNlIDogJ05vdCBwcm92aWRlZCcgfCB0cmFuc2xhdGV9fTwvbGk+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGkgY2xhc3M9XCJsaXN0LWdyb3VwLWl0ZW0gYmctdHJhbnNwYXJlbnRcIj57eydWaWV3ZXInIHwgdHJhbnNsYXRlfX0gOiB7eyB2aXNpdC52aWV3ZXIgfX1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbGk+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGkgY2xhc3M9XCJsaXN0LWdyb3VwLWl0ZW0gYmctdHJhbnNwYXJlbnRcIj57eydEYXRlIG9mIGNhcHR1cmUnIHwgdHJhbnNsYXRlfX0gOiB7e1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpc2l0LnRha2VuQXQgfCB0aW1lRGF0ZVN0cmluZyB8IGFzeW5jfX1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGkgY2xhc3M9XCJsaXN0LWdyb3VwLWl0ZW0gYmctdHJhbnNwYXJlbnRcIj57eydJbWFnZXMgYXJlIGltcG9ydGVkJyB8IHRyYW5zbGF0ZX19IDoge3tcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW1hZ2VzVXBsb2FkZWQgfX1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2xpPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8L3VsPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgICAgICAgICAgICAgPGxpYi1sb2FkZXIgKm5nSWY9XCJpc1Byb2Nlc3NpbmdcIj48L2xpYi1sb2FkZXI+XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYWN0aW9uLWJ1dHRvbi1jb250YWluZXIgbXQtM1wiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJ0biBidG4tb3V0bGluZS1wcmltYXJ5IHJvdW5kZWQtcGlsbCBtZS0yXCIgKGNsaWNrKT1cIm9uSW1wb3J0SW1hZ2VzKHZpc2l0LCB0cnVlKVwiIFtkaXNhYmxlZF09XCJpc1Byb2Nlc3NpbmdcIj57eydJbXBvcnQgYWxsIGltYWdlcycgfFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNsYXRlfX08L2J1dHRvbj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiICpuZ0lmPVwiaW1hZ2VzVXBsb2FkZWQgPiAwXCIgY2xhc3M9XCJidG4gYnRuLW91dGxpbmUtcHJpbWFyeSByb3VuZGVkLXBpbGwgbWUtMlwiIChjbGljayk9XCJvbkltcG9ydEltYWdlcyh2aXNpdCwgZmFsc2UpXCIgW2Rpc2FibGVkXT1cImlzUHJvY2Vzc2luZ1wiPnt7J0ltcG9ydCBmcm9tIGltYWdlJyB8XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNsYXRlfX0ge3tpbWFnZXNVcGxvYWRlZH19PC9idXR0b24+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYnRuIGJ0bi1vdXRsaW5lLXByaW1hcnkgcm91bmRlZC1waWxsIG1lLTJcIiBbZGlzYWJsZWRdPVwiaXNQcm9jZXNzaW5nXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJvbkVkaXQodmlzaXQpXCI+e3snRWRpdCcgfCB0cmFuc2xhdGV9fTwvYnV0dG9uPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJ0biBidG4tb3V0bGluZS1wcmltYXJ5IHJvdW5kZWQtcGlsbFwiIFtkaXNhYmxlZF09XCJpc1Byb2Nlc3NpbmdcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cIm9uRGVsZXRlKHZpc2l0KVwiPnt7J0RlbGV0ZScgfCB0cmFuc2xhdGV9fTwvYnV0dG9uPlxyXG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgPC9saT5cclxuICAgICAgICAgICAgPC91bD5cclxuICAgICAgICAgICAgPGRpdiAqbmdJZj1cInZpc2l0Rm9ybVwiPlxyXG4gICAgICAgICAgICAgICAgPGZvcm0gKG5nU3VibWl0KT1cIm9uU3VibWl0VmlzaXQoKVwiIFtmb3JtR3JvdXBdPVwidmlzaXRGb3JtXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1iLTMgcm93XCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImNvbC1zbS0yIGNvbC1mb3JtLWxhYmVsXCI+e3snTmFtZScgfCB0cmFuc2xhdGV9fTwvbGFiZWw+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtc20tMTBcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCB0eXBlPVwidGV4dFwiIGNsYXNzPVwiZm9ybS1jb250cm9sXCIgZm9ybUNvbnRyb2xOYW1lPVwibmFtZVwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWItMyByb3dcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwiY29sLXNtLTIgY29sLWZvcm0tbGFiZWxcIj57eydSZWZlcmVuY2UgM0QgbW9kZWwnIHwgdHJhbnNsYXRlfX0gKjwvbGFiZWw+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtc20tMTBcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCB0eXBlPVwidGV4dFwiIGNsYXNzPVwiZm9ybS1jb250cm9sXCIgW3JlYWRvbmx5XT1cImlzRWRpdGluZ1wiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2NsYXNzLmlzLWludmFsaWRdPVwibW9kZWwzRC5pbnZhbGlkICYmIHZpc2l0U3VibWl0dGVkXCIgcmVxdWlyZWRcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJtb2RlbDNEXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxuZ2ItYWxlcnQgZGF0YS10ZXN0aWQ9XCJuZXctbG9jYXRpb24tbmFtZS1pbnZhbGlkXCIgW2Rpc21pc3NpYmxlXT1cImZhbHNlXCIgdHlwZT1cImRhbmdlclwiIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpuZ0lmPVwidmFsaWRhdG9yc1NlcnZpY2UuaXNDb250cm9sRXJyb3IodmlzaXRGb3JtLmNvbnRyb2xzWyduYW1lJ10pIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8fCAgaXNGb3JtRXJyb3IodmlzaXRGb3JtLmNvbnRyb2xzWyduYW1lJ10pXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge3t2YWxpZGF0b3JzU2VydmljZS5nZXRFcnJvcih2aXNpdEZvcm0uY29udHJvbHNbJ25hbWUnXSkgfCB0cmFuc2xhdGV9fVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbmdiLWFsZXJ0PlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2ICpuZ0lmPVwiaXNFZGl0aW5nXCIgY2xhc3M9XCJ0ZXh0LWRhbmdlclwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7J0Nhbm5vdCBjaGFuZ2UgM0QgbW9kZWwgcmVmZXJlbmNlLiBQbGVhc2UgYWRkIG5ldyBtb2RlbC4nIHwgdHJhbnNsYXRlfX1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1iLTMgcm93XCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImNvbC1zbS0yIGNvbC1mb3JtLWxhYmVsXCI+e3snVmlld2VyJyB8IHRyYW5zbGF0ZX19PC9sYWJlbD5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNvbC1zbS0xMFwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJ0ZXh0XCIgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIiBmb3JtQ29udHJvbE5hbWU9XCJ2aWV3ZXJcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtYi0zIHJvd1wiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJjb2wtc20tMiBjb2wtZm9ybS1sYWJlbFwiPnt7J1N1cmZhY2UnIHwgdHJhbnNsYXRlfX08L2xhYmVsPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLXNtLTEwXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgdHlwZT1cInRleHRcIiBjbGFzcz1cImZvcm0tY29udHJvbFwiIGZvcm1Db250cm9sTmFtZT1cInN1cmZhY2VcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtYi0zIHJvd1wiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJjb2wtc20tMiBjb2wtZm9ybS1sYWJlbFwiPnt7J0NhcHR1cmUgRGF0ZScgfCB0cmFuc2xhdGV9fTwvbGFiZWw+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1ncm91cFwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IGNsYXNzPVwiZm9ybS1jb250cm9sXCIgcGxhY2Vob2xkZXI9XCJkZC9tbS95eXl5XCIgWyhuZ01vZGVsKV09XCJjYXB0dXJlRGF0ZVwiIG5nYkRhdGVwaWNrZXJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjZDE9XCJuZ2JEYXRlcGlja2VyXCIgW25nTW9kZWxPcHRpb25zXT1cIntzdGFuZGFsb25lOiB0cnVlfVwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImlucHV0LWdyb3VwLWFwcGVuZFwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJidG4gYnRuLW91dGxpbmUtc2Vjb25kYXJ5IGNhbGVuZGFyXCIgKGNsaWNrKT1cImQxLnRvZ2dsZSgpXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiPjwvYnV0dG9uPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT1cInN1Ym1pdFwiIGNsYXNzPVwiYnRuIGJ0bi1vdXRsaW5lLXByaW1hcnkgcm91bmRlZC1waWxsIG1lLTJcIj57eydTYXZlJyB8XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zbGF0ZX19PC9idXR0b24+XHJcbiAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgKGNsaWNrKT1cIm9uQ2FuY2VsKClcIiBjbGFzcz1cImJ0biBidG4tb3V0bGluZS1wcmltYXJ5IHJvdW5kZWQtcGlsbFwiPnt7J0NhbmNlbCcgfFxyXG4gICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2xhdGV9fTwvYnV0dG9uPlxyXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgKm5nSWY9XCJlcnJvckZvcm1cIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxuZ2ItYWxlcnQgZGF0YS10ZXN0aWQ9XCJuZXctbG9jYXRpb24tZm9ybS1pbnZhbGlkXCIgW2Rpc21pc3NpYmxlXT1cImZhbHNlXCIgdHlwZT1cImRhbmdlclwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7eydlcnJvckZvcm0uaW5mb0J0bicgfHRyYW5zbGF0ZX19XHJcbiAgICAgICAgICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbmdiLWFsZXJ0PlxyXG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgPC9mb3JtPlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgPGRpdiAqbmdJZj1cIiF2aXNpdEZvcm1cIj5cclxuICAgICAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJidG4gYnRuLW91dGxpbmUtcHJpbWFyeSByb3VuZGVkLXBpbGxcIiAoY2xpY2spPVwib25BZGRWaXNpdCgpXCI+e3snQWRkIDNEIHZpc2l0JyB8XHJcbiAgICAgICAgICAgICAgICAgICAgdHJhbnNsYXRlfX08L2J1dHRvbj5cclxuICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgPGRpdiBpZD1cInZpZXdlci1mcmFtZVwiIHN0eWxlPVwid2lkdGg6IDEwMCU7IGFzcGVjdC1yYXRpbzogMi8xO1wiPjwvZGl2PlxyXG4gICAgPC9kaXY+XHJcbiAgICA8bmctdGVtcGxhdGUgI2NvbnRlbnQgbGV0LW1vZGFsPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJtb2RhbC1oZWFkZXJcIj5cclxuICAgICAgICAgICAgPGg0IGNsYXNzPVwibW9kYWwtdGl0bGVcIiBpZD1cIm1vZGFsLWJhc2ljLXRpdGxlXCI+e3snSW1wb3J0aW5nIERhdGEnIHwgdHJhbnNsYXRlfX08L2g0PlxyXG4gICAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImNsb3NlXCIgYXJpYS1sYWJlbD1cIkNsb3NlXCIgKGNsaWNrKT1cIm1vZGFsLmRpc21pc3MoJ0Nyb3NzIGNsaWNrJylcIj5cclxuICAgICAgICAgICAgICAgIDxzcGFuIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPsOXPC9zcGFuPlxyXG4gICAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwibW9kYWwtYm9keVwiPlxyXG4gICAgICAgICAgICB7eydQbGVhc2UgZG8gbm90IGxlYXZlIG9yIHJlZnJlc2ggdGhpcyBwYWdlLi4uJyB8IHRyYW5zbGF0ZX19XHJcbiAgICAgICAgICAgIDxkaXYgKm5nSWY9XCJ0b3RhbEltYWdlcyAhPSAwXCI+SW1wb3J0ZWQge3tpbWFnZXNQcm9jZXNzZWR9fSBvdXQgb2Yge3t0b3RhbEltYWdlc319IGltYWdlcy48L2Rpdj5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBqdXN0aWZ5LWNvbnRlbnQtY2VudGVyXCI+XHJcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3Bpbm5lci1ib3JkZXJcIiByb2xlPVwic3RhdHVzXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJ2aXN1YWxseS1oaWRkZW5cIj57eydMb2FkaW5nJyB8IHRyYW5zbGF0ZX19Li4uPC9zcGFuPlxyXG4gICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJtb2RhbC1mb290ZXJcIj5cclxuICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidG4gYnRuLW91dGxpbmUtZGFya1wiIFtkaXNhYmxlZF09XCIhY2FuQ2FuY2VsSW1wb3J0XCJcclxuICAgICAgICAgICAgICAgIChjbGljayk9XCJtb2RhbC5jbG9zZSgnQ2FuY2VsIGNsaWNrJylcIj57eydDYW5jZWwgaW1wb3J0IG9mIGltYWdlcycgfCB0cmFuc2xhdGV9fTwvYnV0dG9uPlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgPC9uZy10ZW1wbGF0ZT5cclxuPC9kaXY+Il19