tango-app-ui-manage-tickets 3.7.0-beta.5 → 3.7.0-beta.51

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 (46) hide show
  1. package/esm2022/lib/components/audit-mapping-list/audit-mapping-list.component.mjs +486 -0
  2. package/esm2022/lib/components/audit-report-popup/audit-report-popup.component.mjs +387 -0
  3. package/esm2022/lib/components/audit-retag/audit-retag.component.mjs +472 -0
  4. package/esm2022/lib/components/custom-select/custom-select.component.mjs +174 -0
  5. package/esm2022/lib/components/filter-options/filter-options.component.mjs +41 -0
  6. package/esm2022/lib/components/footfall-dic/footfall-dic.component.mjs +373 -202
  7. package/esm2022/lib/components/footfall-dicview/footfall-dicview.component.mjs +1014 -0
  8. package/esm2022/lib/components/footfall-popup/footfall-popup.component.mjs +15 -0
  9. package/esm2022/lib/components/reactive-select/reactive-select.component.mjs +3 -3
  10. package/esm2022/lib/components/remove-audit/remove-audit.component.mjs +80 -0
  11. package/esm2022/lib/components/start-audit/start-audit.component.mjs +751 -0
  12. package/esm2022/lib/components/tango-manage-tickets/tango-manage-tickets.component.mjs +7 -3
  13. package/esm2022/lib/components/ticket-filter-panel/ticket-filter-panel.component.mjs +337 -0
  14. package/esm2022/lib/components/ticket-footfall-new/ticket-footfall-new.component.mjs +2443 -0
  15. package/esm2022/lib/components/ticketclosepopup/ticketclosepopup.component.mjs +43 -0
  16. package/esm2022/lib/components/tickets/tickets.component.mjs +62 -8
  17. package/esm2022/lib/components/viewcategory/viewcategory.component.mjs +89 -0
  18. package/esm2022/lib/services/audit.service.mjs +88 -0
  19. package/esm2022/lib/services/ticket.service.mjs +171 -34
  20. package/esm2022/lib/services/timer.service.mjs +84 -0
  21. package/esm2022/lib/tango-manage-tickets-routing.module.mjs +22 -2
  22. package/esm2022/lib/tango-manage-tickets.module.mjs +60 -5
  23. package/fesm2022/tango-app-ui-manage-tickets.mjs +7135 -332
  24. package/fesm2022/tango-app-ui-manage-tickets.mjs.map +1 -1
  25. package/lib/components/audit-mapping-list/audit-mapping-list.component.d.ts +73 -0
  26. package/lib/components/audit-metrics/audit-metrics.component.d.ts +1 -1
  27. package/lib/components/audit-report-popup/audit-report-popup.component.d.ts +51 -0
  28. package/lib/components/audit-retag/audit-retag.component.d.ts +59 -0
  29. package/lib/components/custom-select/custom-select.component.d.ts +34 -0
  30. package/lib/components/filter-options/filter-options.component.d.ts +15 -0
  31. package/lib/components/footfall-dic/footfall-dic.component.d.ts +22 -9
  32. package/lib/components/footfall-dicview/footfall-dicview.component.d.ts +132 -0
  33. package/lib/components/footfall-popup/footfall-popup.component.d.ts +8 -0
  34. package/lib/components/remove-audit/remove-audit.component.d.ts +16 -0
  35. package/lib/components/start-audit/start-audit.component.d.ts +86 -0
  36. package/lib/components/tango-manage-tickets/tango-manage-tickets.component.d.ts +1 -0
  37. package/lib/components/ticket-filter-panel/ticket-filter-panel.component.d.ts +62 -0
  38. package/lib/components/ticket-footfall-new/ticket-footfall-new.component.d.ts +273 -0
  39. package/lib/components/ticketclosepopup/ticketclosepopup.component.d.ts +15 -0
  40. package/lib/components/tickets/tickets.component.d.ts +4 -0
  41. package/lib/components/viewcategory/viewcategory.component.d.ts +16 -0
  42. package/lib/services/audit.service.d.ts +36 -0
  43. package/lib/services/ticket.service.d.ts +35 -8
  44. package/lib/services/timer.service.d.ts +22 -0
  45. package/lib/tango-manage-tickets.module.d.ts +22 -5
  46. package/package.json +1 -1
@@ -0,0 +1,337 @@
1
+ import { Component, EventEmitter, HostListener, Input, Output } from '@angular/core';
2
+ import * as i0 from "@angular/core";
3
+ import * as i1 from "@angular/forms";
4
+ import * as i2 from "../../services/ticket.service";
5
+ import * as i3 from "@angular/common";
6
+ export class TicketFilterPanelComponent {
7
+ fb;
8
+ eRef;
9
+ service;
10
+ apply = new EventEmitter();
11
+ panelClosed = new EventEmitter(); // ✅ not `close`
12
+ permissionType = null;
13
+ userType = null; // e.g. 'tango' or others
14
+ client;
15
+ onDocumentClick(event) {
16
+ if (!this.isOpen)
17
+ return;
18
+ const clickedInside = this.eRef.nativeElement.contains(event.target);
19
+ if (!clickedInside) {
20
+ this.close();
21
+ }
22
+ }
23
+ isOpen = false; // controls visibility
24
+ // called from parent via #filterPanel.open()
25
+ open() {
26
+ this.isOpen = true;
27
+ }
28
+ // called from close button inside the panel
29
+ close() {
30
+ this.isOpen = false;
31
+ this.panelClosed.emit();
32
+ }
33
+ showPanel = false; // you can also control this from parent
34
+ statusOptions = [
35
+ 'Open',
36
+ 'In-Progress',
37
+ 'Close',
38
+ 'Under tango review',
39
+ 'Tango review done',
40
+ 'Expired',
41
+ 'Tango Expired',
42
+ ];
43
+ conditionOptions = [
44
+ { value: 'gt', label: '> Greater than' },
45
+ { value: 'lt', label: '< Lesser than' },
46
+ { value: 'gte', label: '>= Greater than or equal to' },
47
+ { value: 'lte', label: '<= Lesser than or equal to' },
48
+ { value: 'between', label: 'Between' },
49
+ ];
50
+ filterForm;
51
+ constructor(fb, eRef, service) {
52
+ this.fb = fb;
53
+ this.eRef = eRef;
54
+ this.service = service;
55
+ this.filterForm = this.fb.group({
56
+ status: [[]],
57
+ reviewerCondition: [null],
58
+ reviewerFrom: [null],
59
+ reviewerTo: [null],
60
+ approverCondition: [null],
61
+ approverFrom: [null],
62
+ approverTo: [null],
63
+ tangoCondition: [null],
64
+ tangoFrom: [null],
65
+ tangoTo: [null],
66
+ reviewedBy: [[]],
67
+ approvedBy: [[]],
68
+ });
69
+ }
70
+ get isTango() {
71
+ return this.userType === 'tango';
72
+ }
73
+ // SHOW / HIDE RULES
74
+ // Reviewer accuracy and "Reviewed by" visible for tango + reviewer
75
+ get showReviewerAccuracy() {
76
+ return this.permissionType === 'review';
77
+ }
78
+ get showReviewedBy() {
79
+ return this.isTango || this.permissionType === 'review';
80
+ }
81
+ // Approver accuracy and "Approved by" visible for tango + approver
82
+ get showApproverAccuracy() {
83
+ return this.permissionType === 'approve';
84
+ }
85
+ get showApprovedBy() {
86
+ return this.isTango || this.permissionType === 'approve';
87
+ }
88
+ // Tango accuracy only for tango users
89
+ get showTangoAccuracy() {
90
+ return this.isTango;
91
+ }
92
+ statusDropdownOpen = false;
93
+ isStatusSelected(status) {
94
+ const selected = this.filterForm.value.status || [];
95
+ return selected.includes(status);
96
+ }
97
+ onStatusChange(event, status) {
98
+ const checkbox = event.target;
99
+ const selected = this.filterForm.value.status || [];
100
+ let next;
101
+ if (checkbox.checked) {
102
+ next = selected.includes(status) ? selected : [...selected, status];
103
+ }
104
+ else {
105
+ next = selected.filter(s => s !== status);
106
+ }
107
+ this.filterForm.patchValue({ status: next });
108
+ }
109
+ toggleStatusDropdown(event) {
110
+ if (event) {
111
+ event.stopPropagation(); // avoid document click closing it
112
+ }
113
+ this.statusDropdownOpen = !this.statusDropdownOpen;
114
+ }
115
+ // Are all statuses currently selected?
116
+ areAllStatusesSelected() {
117
+ const selected = this.filterForm.value.status || [];
118
+ return selected.length > 0 && selected.length === this.statusOptions.length;
119
+ }
120
+ // Handle "Select All" checkbox change
121
+ onStatusSelectAllChange(event) {
122
+ const checkbox = event.target;
123
+ if (checkbox.checked) {
124
+ // Select every status
125
+ this.filterForm.patchValue({ status: [...this.statusOptions] });
126
+ }
127
+ else {
128
+ // Clear all
129
+ this.filterForm.patchValue({ status: [] });
130
+ }
131
+ }
132
+ get selectedStatuses() {
133
+ return this.filterForm.value.status || [];
134
+ }
135
+ isBetween(controlName) {
136
+ return this.filterForm.get(controlName)?.value === 'between';
137
+ }
138
+ ngOnChanges(changes) {
139
+ if (changes['client'] || changes['permissionType'] || changes['userType']) {
140
+ this.loadReviewerList();
141
+ }
142
+ }
143
+ userList;
144
+ loadReviewerList() {
145
+ if (!this.client) {
146
+ this.userList = [];
147
+ return;
148
+ }
149
+ let type;
150
+ if (this.userType === 'tango') {
151
+ type = 'tango'; // or 'all'
152
+ }
153
+ else if (this.permissionType === 'review') {
154
+ type = 'review';
155
+ }
156
+ else if (this.permissionType === 'approve') {
157
+ type = 'approve';
158
+ }
159
+ else {
160
+ this.userList = [];
161
+ return;
162
+ }
163
+ this.service.getReviewerApi(this.client, type).subscribe({
164
+ next: (res) => {
165
+ if (res && res.code === 200) {
166
+ this.userList = res.data;
167
+ }
168
+ else {
169
+ this.userList = [];
170
+ }
171
+ },
172
+ error: () => {
173
+ this.userList = [];
174
+ }
175
+ });
176
+ }
177
+ // open flags
178
+ reviewerDropdownOpen = false;
179
+ approverDropdownOpen = false;
180
+ // convenience getters
181
+ get selectedReviewedBy() {
182
+ return this.filterForm.value.reviewedBy || [];
183
+ }
184
+ get selectedApprovedBy() {
185
+ return this.filterForm.value.approvedBy || [];
186
+ }
187
+ // --- Reviewed By helpers ---
188
+ toggleReviewerDropdown(event) {
189
+ if (event)
190
+ event.stopPropagation();
191
+ this.reviewerDropdownOpen = !this.reviewerDropdownOpen;
192
+ }
193
+ isReviewerSelected(email) {
194
+ return this.selectedReviewedBy.includes(email);
195
+ }
196
+ onReviewerChange(event, email) {
197
+ const checkbox = event.target;
198
+ const selected = [...this.selectedReviewedBy];
199
+ if (checkbox.checked) {
200
+ if (!selected.includes(email))
201
+ selected.push(email);
202
+ }
203
+ else {
204
+ const i = selected.indexOf(email);
205
+ if (i >= 0)
206
+ selected.splice(i, 1);
207
+ }
208
+ this.filterForm.patchValue({ reviewedBy: selected });
209
+ }
210
+ areAllReviewersSelected() {
211
+ return (this.userList.length > 0 &&
212
+ this.selectedReviewedBy.length === this.userList.length);
213
+ }
214
+ onReviewerSelectAll(event) {
215
+ const checkbox = event.target;
216
+ if (checkbox.checked) {
217
+ this.filterForm.patchValue({
218
+ reviewedBy: this.userList.map((u) => u.email),
219
+ });
220
+ }
221
+ else {
222
+ this.filterForm.patchValue({ reviewedBy: [] });
223
+ }
224
+ }
225
+ // --- Approved By helpers ---
226
+ toggleApproverDropdown(event) {
227
+ if (event)
228
+ event.stopPropagation();
229
+ this.approverDropdownOpen = !this.approverDropdownOpen;
230
+ }
231
+ isApproverSelected(email) {
232
+ return this.selectedApprovedBy.includes(email);
233
+ }
234
+ onApproverChange(event, email) {
235
+ const checkbox = event.target;
236
+ const selected = [...this.selectedApprovedBy];
237
+ if (checkbox.checked) {
238
+ if (!selected.includes(email))
239
+ selected.push(email);
240
+ }
241
+ else {
242
+ const i = selected.indexOf(email);
243
+ if (i >= 0)
244
+ selected.splice(i, 1);
245
+ }
246
+ this.filterForm.patchValue({ approvedBy: selected });
247
+ }
248
+ areAllApproversSelected() {
249
+ return (this.userList.length > 0 &&
250
+ this.selectedApprovedBy.length === this.userList.length);
251
+ }
252
+ onApproverSelectAll(event) {
253
+ const checkbox = event.target;
254
+ if (checkbox.checked) {
255
+ this.filterForm.patchValue({
256
+ approvedBy: this.userList.map((u) => u.email),
257
+ });
258
+ }
259
+ else {
260
+ this.filterForm.patchValue({ approvedBy: [] });
261
+ }
262
+ }
263
+ onReset() {
264
+ this.filterForm.reset({
265
+ status: [],
266
+ reviewerCondition: null,
267
+ reviewerFrom: null,
268
+ reviewerTo: null,
269
+ approverCondition: null,
270
+ approverFrom: null,
271
+ approverTo: null,
272
+ tangoCondition: null,
273
+ tangoFrom: null,
274
+ tangoTo: null,
275
+ reviewedBy: [],
276
+ approvedBy: [],
277
+ });
278
+ this.close();
279
+ }
280
+ mapAccuracy(condition, from, to) {
281
+ // nothing selected
282
+ if (!condition || from == null)
283
+ return null;
284
+ // "between" → "90 to 100"
285
+ if (condition === 'between') {
286
+ if (to == null)
287
+ return null;
288
+ return `${from} to ${to}`;
289
+ }
290
+ // other conditions (gt, lt, gte, lte)
291
+ const opMap = {
292
+ gt: '>',
293
+ lt: '<',
294
+ gte: '>=',
295
+ lte: '<=',
296
+ between: '', // already handled above
297
+ };
298
+ return `${opMap[condition]} ${from}`; // e.g. ">= 90"
299
+ }
300
+ onApply() {
301
+ const raw = this.filterForm.value;
302
+ const reviewerStr = this.mapAccuracy(raw.reviewerCondition, raw.reviewerFrom, raw.reviewerTo);
303
+ const approverStr = this.mapAccuracy(raw.approverCondition, raw.approverFrom, raw.approverTo);
304
+ const tangoStr = this.mapAccuracy(raw.tangoCondition, raw.tangoFrom, raw.tangoTo);
305
+ const payload = {
306
+ filterByStatus: raw.status || [],
307
+ filterByReviewer: reviewerStr,
308
+ filterByApprover: approverStr,
309
+ filterByTango: tangoStr,
310
+ filterByReviewedBy: raw.reviewedBy || [],
311
+ fileterByApprovedBy: raw.approvedBy || [],
312
+ };
313
+ this.apply.emit(payload);
314
+ this.close();
315
+ this.showPanel = false;
316
+ }
317
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TicketFilterPanelComponent, deps: [{ token: i1.FormBuilder }, { token: i0.ElementRef }, { token: i2.TicketService }], target: i0.ɵɵFactoryTarget.Component });
318
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: TicketFilterPanelComponent, selector: "lib-ticket-filter-panel", inputs: { permissionType: "permissionType", userType: "userType", client: "client" }, outputs: { apply: "apply", panelClosed: "panelClosed" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, usesOnChanges: true, ngImport: i0, template: "<!-- ticket-filter-panel.component.html -->\r\n<div class=\"filter-wrapper\" *ngIf=\"isOpen\">\r\n <div class=\"filter-card\">\r\n <div class=\"filter-header d-flex justify-content-between align-items-center mb-3\">\r\n <div class=\"title\">Filter Options</div>\r\n <!-- <button type=\"button\" class=\"btn-close\" (click)=\"close()\">\u2715</button> -->\r\n </div>\r\n\r\n <form [formGroup]=\"filterForm\">\r\n <!-- Status -->\r\n<div class=\"mb-3 position-relative\" (click)=\"$event.stopPropagation()\">\r\n <label class=\"form-label\">Status</label>\r\n\r\n <!-- Header / trigger -->\r\n <div\r\n class=\"status-select border rounded px-3 py-2 d-flex justify-content-between align-items-center\"\r\n (click)=\"toggleStatusDropdown($event)\"\r\n >\r\n <span *ngIf=\"!selectedStatuses.length\">Select</span>\r\n\r\n <span *ngIf=\"selectedStatuses.length === 1\">\r\n {{ selectedStatuses[0] }}\r\n </span>\r\n\r\n <span *ngIf=\"selectedStatuses.length > 1\" class=\"d-flex align-items-center\">\r\n <span>{{ selectedStatuses[0] }}</span>\r\n <span class=\"badge ms-2\">\r\n +{{ selectedStatuses.length - 1 }}\r\n </span>\r\n </span>\r\n\r\n </div>\r\n\r\n <!-- DROPDOWN PANEL (OVERLAY) -->\r\n <div\r\n class=\"status-dropdown position-absolute w-100 mt-1 border rounded p-1 bg-white\"\r\n style=\"z-index: 1000; max-height: 220px; overflow-y: auto;\"\r\n *ngIf=\"statusDropdownOpen\"\r\n (click)=\"$event.stopPropagation()\"\r\n >\r\n <!-- Select All -->\r\n <div class=\"form-check px-0 d-flex align-items-center mb-2\">\r\n <input\r\n type=\"checkbox\"\r\n class=\"form-check-input text-dark\"\r\n id=\"status-select-all\"\r\n [checked]=\"areAllStatusesSelected()\"\r\n (change)=\"onStatusSelectAllChange($event)\"\r\n />\r\n <label class=\"form-check-label ms-2\" for=\"status-select-all\">\r\n Select All\r\n </label>\r\n </div>\r\n\r\n\r\n <!-- Options -->\r\n <div\r\n class=\"form-check px-0 d-flex align-items-center mb-1\"\r\n *ngFor=\"let s of statusOptions\"\r\n >\r\n <input\r\n type=\"checkbox\"\r\n class=\"form-check-input text-dark\"\r\n [id]=\"'status-' + s\"\r\n [checked]=\"isStatusSelected(s)\"\r\n (change)=\"onStatusChange($event, s)\"\r\n />\r\n <label class=\"form-check-label ms-2\" [for]=\"'status-' + s\">\r\n {{ s }}\r\n </label>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n\r\n\r\n <!-- Reviewer accuracy -->\r\n <div class=\"mb-3\" *ngIf=\"showReviewerAccuracy\">\r\n <label class=\"form-label\">Reviewer accuracy (%) by condition</label>\r\n <div class=\"d-flex gap-2\">\r\n <select class=\"form-select w-100\" formControlName=\"reviewerCondition\">\r\n <option [ngValue]=\"null\">Select</option>\r\n <option *ngFor=\"let c of conditionOptions\" [ngValue]=\"c.value\">\r\n {{ c.label }}\r\n </option>\r\n </select>\r\n\r\n <!-- one or two inputs -->\r\n <ng-container *ngIf=\"isBetween('reviewerCondition'); else singleReviewer\">\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"reviewerFrom\"\r\n placeholder=\"From\" />\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"reviewerTo\"\r\n placeholder=\"To\" />\r\n </ng-container>\r\n <ng-template #singleReviewer>\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"reviewerFrom\"\r\n placeholder=\"1 to 100%\" />\r\n </ng-template>\r\n </div>\r\n </div>\r\n\r\n <!-- Approver accuracy -->\r\n <div class=\"mb-3\" *ngIf=\"showApproverAccuracy\">\r\n <label class=\"form-label\">Approver accuracy (%) by condition</label>\r\n <div class=\"d-flex gap-2\">\r\n <select class=\"form-select w-100\" formControlName=\"approverCondition\">\r\n <option [ngValue]=\"null\">Select</option>\r\n <option *ngFor=\"let c of conditionOptions\" [ngValue]=\"c.value\">\r\n {{ c.label }}\r\n </option>\r\n </select>\r\n\r\n <ng-container *ngIf=\"isBetween('approverCondition'); else singleApprover\">\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"approverFrom\"\r\n placeholder=\"From\" />\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"approverTo\"\r\n placeholder=\"To\" />\r\n </ng-container>\r\n <ng-template #singleApprover>\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"approverFrom\"\r\n placeholder=\"1 to 100%\" />\r\n </ng-template>\r\n </div>\r\n </div>\r\n\r\n <!-- Tango accuracy -->\r\n <div class=\"mb-3\" *ngIf=\"showTangoAccuracy\">\r\n <label class=\"form-label\">Tango accuracy (%) by condition</label>\r\n <div class=\"d-flex gap-2\">\r\n <select class=\"form-select w-50\" formControlName=\"tangoCondition\">\r\n <option [ngValue]=\"null\">Select</option>\r\n <option *ngFor=\"let c of conditionOptions\" [ngValue]=\"c.value\">\r\n {{ c.label }}\r\n </option>\r\n </select>\r\n\r\n <ng-container *ngIf=\"isBetween('tangoCondition'); else singleTango\">\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"tangoFrom\"\r\n placeholder=\"From\" />\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"tangoTo\"\r\n placeholder=\"To\" />\r\n </ng-container>\r\n <ng-template #singleTango>\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"tangoFrom\"\r\n placeholder=\"1 to 100%\" />\r\n </ng-template>\r\n </div>\r\n </div>\r\n<div\r\n class=\"mb-3 position-relative\"\r\n *ngIf=\"showReviewedBy\"\r\n (click)=\"$event.stopPropagation()\"\r\n>\r\n <label class=\"form-label\">Reviewed by</label>\r\n\r\n <!-- Trigger / display -->\r\n <div\r\n class=\"border rounded px-3 py-2 d-flex justify-content-between align-items-center\"\r\n (click)=\"toggleReviewerDropdown($event)\"\r\n >\r\n <!-- 0 selected -->\r\n <span *ngIf=\"!selectedReviewedBy.length\">\r\n Select\r\n </span>\r\n\r\n <!-- 1 selected -->\r\n <span *ngIf=\"selectedReviewedBy.length === 1\">\r\n {{ selectedReviewedBy[0] }}\r\n </span>\r\n\r\n <!-- >1 selected -->\r\n <span\r\n *ngIf=\"selectedReviewedBy.length > 1\"\r\n class=\"d-flex align-items-center\"\r\n >\r\n <span>{{ selectedReviewedBy[0] }}</span>\r\n <span class=\"badge ms-2\">\r\n +{{ selectedReviewedBy.length - 1 }}\r\n </span>\r\n </span>\r\n </div>\r\n\r\n <!-- Dropdown panel -->\r\n <div\r\n *ngIf=\"reviewerDropdownOpen\"\r\n class=\"position-absolute w-100 border rounded bg-white p-1 mt-1\"\r\n style=\"z-index: 1000; max-height: 220px; overflow-y: auto;\"\r\n (click)=\"$event.stopPropagation()\"\r\n >\r\n <!-- Select All -->\r\n <div class=\"form-check px-0 mb-2 d-flex align-items-center\">\r\n <input\r\n type=\"checkbox\"\r\n class=\"form-check-input\"\r\n id=\"reviewer-all\"\r\n [checked]=\"areAllReviewersSelected()\"\r\n (change)=\"onReviewerSelectAll($event)\"\r\n />\r\n <label for=\"reviewer-all\" class=\"form-check-label ms-2\">\r\n Select All\r\n </label>\r\n </div>\r\n\r\n <!-- Options -->\r\n <div\r\n class=\"form-check mb-1 px-0 d-flex align-items-center\"\r\n *ngFor=\"let u of userList\"\r\n >\r\n <input\r\n class=\"form-check-input\"\r\n type=\"checkbox\"\r\n [id]=\"'rev-' + u.email\"\r\n [checked]=\"isReviewerSelected(u.email)\"\r\n (change)=\"onReviewerChange($event, u.email)\"\r\n />\r\n <label class=\"form-check-label ms-2\" [for]=\"'rev-' + u.email\">\r\n {{ u.email }}\r\n </label>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n\r\n <!-- Approved By -->\r\n<div\r\n class=\"mb-3 position-relative\"\r\n *ngIf=\"showApprovedBy\"\r\n (click)=\"$event.stopPropagation()\"\r\n>\r\n <label class=\"form-label\">Approved by</label>\r\n\r\n <!-- Trigger / display -->\r\n <div\r\n class=\"border rounded px-3 py-2 d-flex justify-content-between align-items-center\"\r\n (click)=\"toggleApproverDropdown($event)\"\r\n >\r\n <!-- 0 selected -->\r\n <span *ngIf=\"!selectedApprovedBy.length\">\r\n Select\r\n </span>\r\n\r\n <!-- 1 selected -->\r\n <span *ngIf=\"selectedApprovedBy.length === 1\">\r\n {{ selectedApprovedBy[0] }}\r\n </span>\r\n\r\n <!-- >1 selected -->\r\n <span\r\n *ngIf=\"selectedApprovedBy.length > 1\"\r\n class=\"d-flex align-items-center\"\r\n >\r\n <span>{{ selectedApprovedBy[0] }}</span>\r\n <span class=\"badge ms-2\">\r\n +{{ selectedApprovedBy.length - 1 }}\r\n </span>\r\n </span>\r\n\r\n </div>\r\n\r\n <!-- Dropdown panel -->\r\n <div\r\n *ngIf=\"approverDropdownOpen\"\r\n class=\"position-absolute w-100 border rounded bg-white p-2 mt-1\"\r\n style=\"z-index: 1000; max-height: 220px; overflow-y: auto;\"\r\n (click)=\"$event.stopPropagation()\"\r\n >\r\n <!-- Select All -->\r\n <div class=\"form-check px-0 mb-2 d-flex align-items-center\">\r\n <input\r\n type=\"checkbox\"\r\n class=\"form-check-input\"\r\n id=\"approver-all\"\r\n [checked]=\"areAllApproversSelected()\"\r\n (change)=\"onApproverSelectAll($event)\"\r\n />\r\n <label for=\"approver-all\" class=\"form-check-label ms-2\">\r\n Select All\r\n </label>\r\n </div>\r\n\r\n <!-- Options -->\r\n <div\r\n class=\"form-check mb-1 px-0 d-flex align-items-center\"\r\n *ngFor=\"let u of userList\"\r\n >\r\n <input\r\n class=\"form-check-input\"\r\n type=\"checkbox\"\r\n [id]=\"'app-' + u.email\"\r\n [checked]=\"isApproverSelected(u.email)\"\r\n (change)=\"onApproverChange($event, u.email)\"\r\n />\r\n <label class=\"form-check-label ms-2\" [for]=\"'app-' + u.email\">\r\n {{ u.email }}\r\n </label>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n\r\n <!-- Footer buttons -->\r\n <div class=\"d-flex justify-content-between w-100 mt-4\">\r\n <button type=\"button\" class=\"btn btn-outline w-50 me-1\" (click)=\"onReset()\">\r\n Reset\r\n </button>\r\n <button type=\"button\" class=\"btn btn-primary w-50 ms-1\" (click)=\"onApply()\">\r\n Apply\r\n </button>\r\n </div>\r\n </form>\r\n </div>\r\n</div>\r\n", styles: [".filter-wrapper{position:absolute;top:0;right:0;padding:16px;z-index:1050}.filter-card{width:350px;background:#fff;border-radius:12px;padding:16px 18px;box-shadow:0 8px 30px #00000014;font-size:13px}.filter-header .title{font-weight:600;font-size:14px}.btn-close{border:none;background:transparent;font-size:16px;cursor:pointer}.form-label{font-size:12px;margin-bottom:4px}.form-select,.form-control{font-size:13px}.gap-2{gap:4px}.badge{padding:0 6px;border-radius:999px;font-size:11px;background:#e5f3ff;color:#007bff}input[type=checkbox]{width:16px!important;height:16px!important;margin:-2px 5px;border-radius:4px!important;-webkit-appearance:none;-moz-appearance:none;-o-appearance:none;appearance:none;outline:1px solid var(--gray-600, #D0D5DD)!important;box-shadow:none;font-size:.5em;text-align:center;line-height:1em;background:#fff}input[type=checkbox]{outline:1px solid var(--primary-600, #00A3FF)!important;background-color:var(--primary-50, #EAF8FF)}input[type=checkbox]:checked:after{content:\"\";transform:rotate(45deg);border-bottom:2px solid #00A3FF;border-right:2px solid #00A3FF;display:inline-block;width:.5em;padding-left:3px;padding-top:10px;padding-right:0}\n"], dependencies: [{ kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { 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"] }] });
319
+ }
320
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TicketFilterPanelComponent, decorators: [{
321
+ type: Component,
322
+ args: [{ selector: 'lib-ticket-filter-panel', template: "<!-- ticket-filter-panel.component.html -->\r\n<div class=\"filter-wrapper\" *ngIf=\"isOpen\">\r\n <div class=\"filter-card\">\r\n <div class=\"filter-header d-flex justify-content-between align-items-center mb-3\">\r\n <div class=\"title\">Filter Options</div>\r\n <!-- <button type=\"button\" class=\"btn-close\" (click)=\"close()\">\u2715</button> -->\r\n </div>\r\n\r\n <form [formGroup]=\"filterForm\">\r\n <!-- Status -->\r\n<div class=\"mb-3 position-relative\" (click)=\"$event.stopPropagation()\">\r\n <label class=\"form-label\">Status</label>\r\n\r\n <!-- Header / trigger -->\r\n <div\r\n class=\"status-select border rounded px-3 py-2 d-flex justify-content-between align-items-center\"\r\n (click)=\"toggleStatusDropdown($event)\"\r\n >\r\n <span *ngIf=\"!selectedStatuses.length\">Select</span>\r\n\r\n <span *ngIf=\"selectedStatuses.length === 1\">\r\n {{ selectedStatuses[0] }}\r\n </span>\r\n\r\n <span *ngIf=\"selectedStatuses.length > 1\" class=\"d-flex align-items-center\">\r\n <span>{{ selectedStatuses[0] }}</span>\r\n <span class=\"badge ms-2\">\r\n +{{ selectedStatuses.length - 1 }}\r\n </span>\r\n </span>\r\n\r\n </div>\r\n\r\n <!-- DROPDOWN PANEL (OVERLAY) -->\r\n <div\r\n class=\"status-dropdown position-absolute w-100 mt-1 border rounded p-1 bg-white\"\r\n style=\"z-index: 1000; max-height: 220px; overflow-y: auto;\"\r\n *ngIf=\"statusDropdownOpen\"\r\n (click)=\"$event.stopPropagation()\"\r\n >\r\n <!-- Select All -->\r\n <div class=\"form-check px-0 d-flex align-items-center mb-2\">\r\n <input\r\n type=\"checkbox\"\r\n class=\"form-check-input text-dark\"\r\n id=\"status-select-all\"\r\n [checked]=\"areAllStatusesSelected()\"\r\n (change)=\"onStatusSelectAllChange($event)\"\r\n />\r\n <label class=\"form-check-label ms-2\" for=\"status-select-all\">\r\n Select All\r\n </label>\r\n </div>\r\n\r\n\r\n <!-- Options -->\r\n <div\r\n class=\"form-check px-0 d-flex align-items-center mb-1\"\r\n *ngFor=\"let s of statusOptions\"\r\n >\r\n <input\r\n type=\"checkbox\"\r\n class=\"form-check-input text-dark\"\r\n [id]=\"'status-' + s\"\r\n [checked]=\"isStatusSelected(s)\"\r\n (change)=\"onStatusChange($event, s)\"\r\n />\r\n <label class=\"form-check-label ms-2\" [for]=\"'status-' + s\">\r\n {{ s }}\r\n </label>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n\r\n\r\n <!-- Reviewer accuracy -->\r\n <div class=\"mb-3\" *ngIf=\"showReviewerAccuracy\">\r\n <label class=\"form-label\">Reviewer accuracy (%) by condition</label>\r\n <div class=\"d-flex gap-2\">\r\n <select class=\"form-select w-100\" formControlName=\"reviewerCondition\">\r\n <option [ngValue]=\"null\">Select</option>\r\n <option *ngFor=\"let c of conditionOptions\" [ngValue]=\"c.value\">\r\n {{ c.label }}\r\n </option>\r\n </select>\r\n\r\n <!-- one or two inputs -->\r\n <ng-container *ngIf=\"isBetween('reviewerCondition'); else singleReviewer\">\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"reviewerFrom\"\r\n placeholder=\"From\" />\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"reviewerTo\"\r\n placeholder=\"To\" />\r\n </ng-container>\r\n <ng-template #singleReviewer>\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"reviewerFrom\"\r\n placeholder=\"1 to 100%\" />\r\n </ng-template>\r\n </div>\r\n </div>\r\n\r\n <!-- Approver accuracy -->\r\n <div class=\"mb-3\" *ngIf=\"showApproverAccuracy\">\r\n <label class=\"form-label\">Approver accuracy (%) by condition</label>\r\n <div class=\"d-flex gap-2\">\r\n <select class=\"form-select w-100\" formControlName=\"approverCondition\">\r\n <option [ngValue]=\"null\">Select</option>\r\n <option *ngFor=\"let c of conditionOptions\" [ngValue]=\"c.value\">\r\n {{ c.label }}\r\n </option>\r\n </select>\r\n\r\n <ng-container *ngIf=\"isBetween('approverCondition'); else singleApprover\">\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"approverFrom\"\r\n placeholder=\"From\" />\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"approverTo\"\r\n placeholder=\"To\" />\r\n </ng-container>\r\n <ng-template #singleApprover>\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"approverFrom\"\r\n placeholder=\"1 to 100%\" />\r\n </ng-template>\r\n </div>\r\n </div>\r\n\r\n <!-- Tango accuracy -->\r\n <div class=\"mb-3\" *ngIf=\"showTangoAccuracy\">\r\n <label class=\"form-label\">Tango accuracy (%) by condition</label>\r\n <div class=\"d-flex gap-2\">\r\n <select class=\"form-select w-50\" formControlName=\"tangoCondition\">\r\n <option [ngValue]=\"null\">Select</option>\r\n <option *ngFor=\"let c of conditionOptions\" [ngValue]=\"c.value\">\r\n {{ c.label }}\r\n </option>\r\n </select>\r\n\r\n <ng-container *ngIf=\"isBetween('tangoCondition'); else singleTango\">\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"tangoFrom\"\r\n placeholder=\"From\" />\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"tangoTo\"\r\n placeholder=\"To\" />\r\n </ng-container>\r\n <ng-template #singleTango>\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"tangoFrom\"\r\n placeholder=\"1 to 100%\" />\r\n </ng-template>\r\n </div>\r\n </div>\r\n<div\r\n class=\"mb-3 position-relative\"\r\n *ngIf=\"showReviewedBy\"\r\n (click)=\"$event.stopPropagation()\"\r\n>\r\n <label class=\"form-label\">Reviewed by</label>\r\n\r\n <!-- Trigger / display -->\r\n <div\r\n class=\"border rounded px-3 py-2 d-flex justify-content-between align-items-center\"\r\n (click)=\"toggleReviewerDropdown($event)\"\r\n >\r\n <!-- 0 selected -->\r\n <span *ngIf=\"!selectedReviewedBy.length\">\r\n Select\r\n </span>\r\n\r\n <!-- 1 selected -->\r\n <span *ngIf=\"selectedReviewedBy.length === 1\">\r\n {{ selectedReviewedBy[0] }}\r\n </span>\r\n\r\n <!-- >1 selected -->\r\n <span\r\n *ngIf=\"selectedReviewedBy.length > 1\"\r\n class=\"d-flex align-items-center\"\r\n >\r\n <span>{{ selectedReviewedBy[0] }}</span>\r\n <span class=\"badge ms-2\">\r\n +{{ selectedReviewedBy.length - 1 }}\r\n </span>\r\n </span>\r\n </div>\r\n\r\n <!-- Dropdown panel -->\r\n <div\r\n *ngIf=\"reviewerDropdownOpen\"\r\n class=\"position-absolute w-100 border rounded bg-white p-1 mt-1\"\r\n style=\"z-index: 1000; max-height: 220px; overflow-y: auto;\"\r\n (click)=\"$event.stopPropagation()\"\r\n >\r\n <!-- Select All -->\r\n <div class=\"form-check px-0 mb-2 d-flex align-items-center\">\r\n <input\r\n type=\"checkbox\"\r\n class=\"form-check-input\"\r\n id=\"reviewer-all\"\r\n [checked]=\"areAllReviewersSelected()\"\r\n (change)=\"onReviewerSelectAll($event)\"\r\n />\r\n <label for=\"reviewer-all\" class=\"form-check-label ms-2\">\r\n Select All\r\n </label>\r\n </div>\r\n\r\n <!-- Options -->\r\n <div\r\n class=\"form-check mb-1 px-0 d-flex align-items-center\"\r\n *ngFor=\"let u of userList\"\r\n >\r\n <input\r\n class=\"form-check-input\"\r\n type=\"checkbox\"\r\n [id]=\"'rev-' + u.email\"\r\n [checked]=\"isReviewerSelected(u.email)\"\r\n (change)=\"onReviewerChange($event, u.email)\"\r\n />\r\n <label class=\"form-check-label ms-2\" [for]=\"'rev-' + u.email\">\r\n {{ u.email }}\r\n </label>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n\r\n <!-- Approved By -->\r\n<div\r\n class=\"mb-3 position-relative\"\r\n *ngIf=\"showApprovedBy\"\r\n (click)=\"$event.stopPropagation()\"\r\n>\r\n <label class=\"form-label\">Approved by</label>\r\n\r\n <!-- Trigger / display -->\r\n <div\r\n class=\"border rounded px-3 py-2 d-flex justify-content-between align-items-center\"\r\n (click)=\"toggleApproverDropdown($event)\"\r\n >\r\n <!-- 0 selected -->\r\n <span *ngIf=\"!selectedApprovedBy.length\">\r\n Select\r\n </span>\r\n\r\n <!-- 1 selected -->\r\n <span *ngIf=\"selectedApprovedBy.length === 1\">\r\n {{ selectedApprovedBy[0] }}\r\n </span>\r\n\r\n <!-- >1 selected -->\r\n <span\r\n *ngIf=\"selectedApprovedBy.length > 1\"\r\n class=\"d-flex align-items-center\"\r\n >\r\n <span>{{ selectedApprovedBy[0] }}</span>\r\n <span class=\"badge ms-2\">\r\n +{{ selectedApprovedBy.length - 1 }}\r\n </span>\r\n </span>\r\n\r\n </div>\r\n\r\n <!-- Dropdown panel -->\r\n <div\r\n *ngIf=\"approverDropdownOpen\"\r\n class=\"position-absolute w-100 border rounded bg-white p-2 mt-1\"\r\n style=\"z-index: 1000; max-height: 220px; overflow-y: auto;\"\r\n (click)=\"$event.stopPropagation()\"\r\n >\r\n <!-- Select All -->\r\n <div class=\"form-check px-0 mb-2 d-flex align-items-center\">\r\n <input\r\n type=\"checkbox\"\r\n class=\"form-check-input\"\r\n id=\"approver-all\"\r\n [checked]=\"areAllApproversSelected()\"\r\n (change)=\"onApproverSelectAll($event)\"\r\n />\r\n <label for=\"approver-all\" class=\"form-check-label ms-2\">\r\n Select All\r\n </label>\r\n </div>\r\n\r\n <!-- Options -->\r\n <div\r\n class=\"form-check mb-1 px-0 d-flex align-items-center\"\r\n *ngFor=\"let u of userList\"\r\n >\r\n <input\r\n class=\"form-check-input\"\r\n type=\"checkbox\"\r\n [id]=\"'app-' + u.email\"\r\n [checked]=\"isApproverSelected(u.email)\"\r\n (change)=\"onApproverChange($event, u.email)\"\r\n />\r\n <label class=\"form-check-label ms-2\" [for]=\"'app-' + u.email\">\r\n {{ u.email }}\r\n </label>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n\r\n <!-- Footer buttons -->\r\n <div class=\"d-flex justify-content-between w-100 mt-4\">\r\n <button type=\"button\" class=\"btn btn-outline w-50 me-1\" (click)=\"onReset()\">\r\n Reset\r\n </button>\r\n <button type=\"button\" class=\"btn btn-primary w-50 ms-1\" (click)=\"onApply()\">\r\n Apply\r\n </button>\r\n </div>\r\n </form>\r\n </div>\r\n</div>\r\n", styles: [".filter-wrapper{position:absolute;top:0;right:0;padding:16px;z-index:1050}.filter-card{width:350px;background:#fff;border-radius:12px;padding:16px 18px;box-shadow:0 8px 30px #00000014;font-size:13px}.filter-header .title{font-weight:600;font-size:14px}.btn-close{border:none;background:transparent;font-size:16px;cursor:pointer}.form-label{font-size:12px;margin-bottom:4px}.form-select,.form-control{font-size:13px}.gap-2{gap:4px}.badge{padding:0 6px;border-radius:999px;font-size:11px;background:#e5f3ff;color:#007bff}input[type=checkbox]{width:16px!important;height:16px!important;margin:-2px 5px;border-radius:4px!important;-webkit-appearance:none;-moz-appearance:none;-o-appearance:none;appearance:none;outline:1px solid var(--gray-600, #D0D5DD)!important;box-shadow:none;font-size:.5em;text-align:center;line-height:1em;background:#fff}input[type=checkbox]{outline:1px solid var(--primary-600, #00A3FF)!important;background-color:var(--primary-50, #EAF8FF)}input[type=checkbox]:checked:after{content:\"\";transform:rotate(45deg);border-bottom:2px solid #00A3FF;border-right:2px solid #00A3FF;display:inline-block;width:.5em;padding-left:3px;padding-top:10px;padding-right:0}\n"] }]
323
+ }], ctorParameters: () => [{ type: i1.FormBuilder }, { type: i0.ElementRef }, { type: i2.TicketService }], propDecorators: { apply: [{
324
+ type: Output
325
+ }], panelClosed: [{
326
+ type: Output
327
+ }], permissionType: [{
328
+ type: Input
329
+ }], userType: [{
330
+ type: Input
331
+ }], client: [{
332
+ type: Input
333
+ }], onDocumentClick: [{
334
+ type: HostListener,
335
+ args: ['document:click', ['$event']]
336
+ }] } });
337
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGlja2V0LWZpbHRlci1wYW5lbC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy90YW5nby1tYW5hZ2UtdGlja2V0cy9zcmMvbGliL2NvbXBvbmVudHMvdGlja2V0LWZpbHRlci1wYW5lbC90aWNrZXQtZmlsdGVyLXBhbmVsLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3RhbmdvLW1hbmFnZS10aWNrZXRzL3NyYy9saWIvY29tcG9uZW50cy90aWNrZXQtZmlsdGVyLXBhbmVsL3RpY2tldC1maWx0ZXItcGFuZWwuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBYyxZQUFZLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBYSxNQUFNLEVBQWlCLE1BQU0sZUFBZSxDQUFDOzs7OztBQVczSCxNQUFNLE9BQU8sMEJBQTBCO0lBbURqQjtJQUF3QjtJQUF5QjtJQWxEMUQsS0FBSyxHQUFHLElBQUksWUFBWSxFQUFPLENBQUM7SUFDakMsV0FBVyxHQUFHLElBQUksWUFBWSxFQUFRLENBQUMsQ0FBRyxnQkFBZ0I7SUFDM0QsY0FBYyxHQUFrQixJQUFJLENBQUM7SUFDdkMsUUFBUSxHQUFrQixJQUFJLENBQUMsQ0FBQyx5QkFBeUI7SUFDekQsTUFBTSxDQUFNO0lBRW5CLGVBQWUsQ0FBQyxLQUFpQjtRQUMvQixJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU07WUFBRSxPQUFPO1FBRXpCLE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDckUsSUFBSSxDQUFDLGFBQWEsRUFBRTtZQUNsQixJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7U0FDZDtJQUNILENBQUM7SUFDRCxNQUFNLEdBQUcsS0FBSyxDQUFDLENBQXFDLHNC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LGNBQWMsRUFBRSxHQUFHLENBQUMsTUFBTSxJQUFJLEVBQUU7WUFFaEMsZ0JBQWdCLEVBQUUsV0FBVztZQUM3QixnQkFBZ0IsRUFBRSxXQUFXO1lBQzdCLGFBQWEsRUFBRSxRQUFRO1lBRXZCLGtCQUFrQixFQUFFLEdBQUcsQ0FBQyxVQUFVLElBQUksRUFBRTtZQUN4QyxtQkFBbUIsRUFBRSxHQUFHLENBQUMsVUFBVSxJQUFJLEVBQUU7U0FDMUMsQ0FBQztRQUVGLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3pCLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNYLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDO0lBQ3pCLENBQUM7d0dBdldVLDBCQUEwQjs0RkFBMUIsMEJBQTBCLHlTQ1h2Qyw0cFhBcVdBOzs0RkQxVmEsMEJBQTBCO2tCQUx0QyxTQUFTOytCQUNFLHlCQUF5QjtxSUFLeEIsS0FBSztzQkFBZCxNQUFNO2dCQUNFLFdBQVc7c0JBQXBCLE1BQU07Z0JBQ0UsY0FBYztzQkFBdEIsS0FBSztnQkFDQyxRQUFRO3NCQUFoQixLQUFLO2dCQUNHLE1BQU07c0JBQWQsS0FBSztnQkFFSixlQUFlO3NCQURkLFlBQVk7dUJBQUMsZ0JBQWdCLEVBQUUsQ0FBQyxRQUFRLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIEVsZW1lbnRSZWYsIEV2ZW50RW1pdHRlciwgSG9zdExpc3RlbmVyLCBJbnB1dCwgT25DaGFuZ2VzLCBPdXRwdXQsIFNpbXBsZUNoYW5nZXMgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgRm9ybUJ1aWxkZXIsIEZvcm1Hcm91cCB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcclxuaW1wb3J0IHsgVGlja2V0U2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL3RpY2tldC5zZXJ2aWNlJztcclxuXHJcbnR5cGUgQ29uZGl0aW9uID0gJ2d0JyB8ICdsdCcgfCAnZ3RlJyB8ICdsdGUnIHwgJ2JldHdlZW4nO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdsaWItdGlja2V0LWZpbHRlci1wYW5lbCcsXHJcbiAgdGVtcGxhdGVVcmw6ICcuL3RpY2tldC1maWx0ZXItcGFuZWwuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsOiAnLi90aWNrZXQtZmlsdGVyLXBhbmVsLmNvbXBvbmVudC5zY3NzJ1xyXG59KVxyXG5leHBvcnQgY2xhc3MgVGlja2V0RmlsdGVyUGFuZWxDb21wb25lbnQgaW1wbGVtZW50cyBPbkNoYW5nZXMge1xyXG4gICBAT3V0cHV0KCkgYXBwbHkgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcclxuICBAT3V0cHV0KCkgcGFuZWxDbG9zZWQgPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7ICAgLy8g4pyFIG5vdCBgY2xvc2VgXHJcbiAgQElucHV0KCkgcGVybWlzc2lvblR5cGU6IHN0cmluZyB8IG51bGwgPSBudWxsO1xyXG5ASW5wdXQoKSB1c2VyVHlwZTogc3RyaW5nIHwgbnVsbCA9IG51bGw7IC8vIGUuZy4gJ3RhbmdvJyBvciBvdGhlcnNcclxuQElucHV0KCkgY2xpZW50IDphbnk7XHJcbiAgQEhvc3RMaXN0ZW5lcignZG9jdW1lbnQ6Y2xpY2snLCBbJyRldmVudCddKVxyXG4gIG9uRG9jdW1lbnRDbGljayhldmVudDogTW91c2VFdmVudCk6IHZvaWQge1xyXG4gICAgaWYgKCF0aGlzLmlzT3BlbikgcmV0dXJuO1xyXG5cclxuICAgIGNvbnN0IGNsaWNrZWRJbnNpZGUgPSB0aGlzLmVSZWYubmF0aXZlRWxlbWVudC5jb250YWlucyhldmVudC50YXJnZXQpO1xyXG4gICAgaWYgKCFjbGlja2VkSW5zaWRlKSB7XHJcbiAgICAgIHRoaXMuY2xvc2UoKTtcclxuICAgIH1cclxuICB9XHJcbiAgaXNPcGVuID0gZmFsc2U7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNvbnRyb2xzIHZpc2liaWxpdHlcclxuXHJcbiAgLy8gY2FsbGVkIGZyb20gcGFyZW50IHZpYSAjZmlsdGVyUGFuZWwub3BlbigpXHJcbiAgb3BlbigpIHtcclxuICAgIHRoaXMuaXNPcGVuID0gdHJ1ZTtcclxuICB9XHJcblxyXG4gIC8vIGNhbGxlZCBmcm9tIGNsb3NlIGJ1dHRvbiBpbnNpZGUgdGhlIHBhbmVsXHJcbiAgY2xvc2UoKSB7XHJcbiAgICB0aGlzLmlzT3BlbiA9IGZhbHNlO1xyXG4gICAgdGhpcy5wYW5lbENsb3NlZC5lbWl0KCk7XHJcbiAgfVxyXG5cclxuICBzaG93UGFuZWwgPSBmYWxzZTsgICAgICAgICAgIC8vIHlvdSBjYW4gYWxzbyBjb250cm9sIHRoaXMgZnJvbSBwYXJlbnRcclxuXHJcbnN0YXR1c09wdGlvbnM6IGFueVtdID0gW1xyXG4gICdPcGVuJyxcclxuICAnSW4tUHJvZ3Jlc3MnLFxyXG4gICdDbG9zZScsXHJcbiAgJ1VuZGVyIHRhbmdvIHJldmlldycsXHJcbiAgJ1RhbmdvIHJldmlldyBkb25lJyxcclxuICAnRXhwaXJlZCcsXHJcbiAgJ1RhbmdvIEV4cGlyZWQnLFxyXG5dO1xyXG5cclxuXHJcbiAgY29uZGl0aW9uT3B0aW9ucyA9IFtcclxuICAgIHsgdmFsdWU6ICdndCcsIGxhYmVsOiAnPiBHcmVhdGVyIHRoYW4nIH0sXHJcbiAgICB7IHZhbHVlOiAnbHQnLCBsYWJlbDogJzwgTGVzc2VyIHRoYW4nIH0sXHJcbiAgICB7IHZhbHVlOiAnZ3RlJywgbGFiZWw6ICc+PSBHcmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8nIH0sXHJcbiAgICB7IHZhbHVlOiAnbHRlJywgbGFiZWw6ICc8PSBMZXNzZXIgdGhhbiBvciBlcXVhbCB0bycgfSxcclxuICAgIHsgdmFsdWU6ICdiZXR3ZWVuJywgbGFiZWw6ICdCZXR3ZWVuJyB9LFxyXG4gIF07XHJcblxyXG4gIGZpbHRlckZvcm06IEZvcm1Hcm91cDtcclxuXHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBmYjogRm9ybUJ1aWxkZXIscHJpdmF0ZSBlUmVmOiBFbGVtZW50UmVmLHByaXZhdGUgc2VydmljZTpUaWNrZXRTZXJ2aWNlKSB7XHJcbiAgICB0aGlzLmZpbHRlckZvcm0gPSB0aGlzLmZiLmdyb3VwKHtcclxuICAgICAgc3RhdHVzOiBbW11dLFxyXG5cclxuICAgICAgcmV2aWV3ZXJDb25kaXRpb246IFtudWxsIGFzIENvbmRpdGlvbiB8IG51bGxdLFxyXG4gICAgICByZXZpZXdlckZyb206IFtudWxsXSxcclxuICAgICAgcmV2aWV3ZXJUbzogW251bGxdLFxyXG5cclxuICAgICAgYXBwcm92ZXJDb25kaXRpb246IFtudWxsIGFzIENvbmRpdGlvbiB8IG51bGxdLFxyXG4gICAgICBhcHByb3ZlckZyb206IFtudWxsXSxcclxuICAgICAgYXBwcm92ZXJUbzogW251bGxdLFxyXG5cclxuICAgICAgdGFuZ29Db25kaXRpb246IFtudWxsIGFzIENvbmRpdGlvbiB8IG51bGxdLFxyXG4gICAgICB0YW5nb0Zyb206IFtudWxsXSxcclxuICAgICAgdGFuZ29UbzogW251bGxdLFxyXG5cclxuICAgICAgcmV2aWV3ZWRCeTogW1tdXSxcclxuICBhcHByb3ZlZEJ5OiBbW11dLCAgXHJcbiAgICB9KTtcclxuICB9XHJcblxyXG5nZXQgaXNUYW5nbygpOiBib29sZWFuIHtcclxuICByZXR1cm4gdGhpcy51c2VyVHlwZSA9PT0gJ3RhbmdvJztcclxufVxyXG5cclxuLy8gU0hPVyAvIEhJREUgUlVMRVNcclxuXHJcbi8vIFJldmlld2VyIGFjY3VyYWN5IGFuZCBcIlJldmlld2VkIGJ5XCIgdmlzaWJsZSBmb3IgdGFuZ28gKyByZXZpZXdlclxyXG5nZXQgc2hvd1Jldmlld2VyQWNjdXJhY3koKTogYm9vbGVhbiB7XHJcbiAgcmV0dXJuIHRoaXMucGVybWlzc2lvblR5cGUgPT09ICdyZXZpZXcnO1xyXG59XHJcblxyXG5nZXQgc2hvd1Jldmlld2VkQnkoKTogYm9vbGVhbiB7XHJcbiAgcmV0dXJuIHRoaXMuaXNUYW5nbyB8fCB0aGlzLnBlcm1pc3Npb25UeXBlID09PSAncmV2aWV3JztcclxufVxyXG5cclxuLy8gQXBwcm92ZXIgYWNjdXJhY3kgYW5kIFwiQXBwcm92ZWQgYnlcIiB2aXNpYmxlIGZvciB0YW5nbyArIGFwcHJvdmVyXHJcbmdldCBzaG93QXBwcm92ZXJBY2N1cmFjeSgpOiBib29sZWFuIHtcclxuICByZXR1cm4gdGhpcy5wZXJtaXNzaW9uVHlwZSA9PT0gJ2FwcHJvdmUnO1xyXG59XHJcblxyXG5nZXQgc2hvd0FwcHJvdmVkQnkoKTogYm9vbGVhbiB7XHJcbiAgcmV0dXJuIHRoaXMuaXNUYW5nbyB8fCB0aGlzLnBlcm1pc3Npb25UeXBlID09PSAnYXBwcm92ZSc7XHJcbn1cclxuXHJcbi8vIFRhbmdvIGFjY3VyYWN5IG9ubHkgZm9yIHRhbmdvIHVzZXJzXHJcbmdldCBzaG93VGFuZ29BY2N1cmFjeSgpOiBib29sZWFuIHtcclxuICByZXR1cm4gdGhpcy5pc1RhbmdvO1xyXG59XHJcbnN0YXR1c0Ryb3Bkb3duT3BlbiA9IGZhbHNlO1xyXG5pc1N0YXR1c1NlbGVjdGVkKHN0YXR1czogc3RyaW5nKTogYm9vbGVhbiB7XHJcbiAgY29uc3Qgc2VsZWN0ZWQ6IHN0cmluZ1tdID0gdGhpcy5maWx0ZXJGb3JtLnZhbHVlLnN0YXR1cyB8fCBbXTtcclxuICByZXR1cm4gc2VsZWN0ZWQuaW5jbHVkZXMoc3RhdHVzKTtcclxufVxyXG5cclxub25TdGF0dXNDaGFuZ2UoZXZlbnQ6IEV2ZW50LCBzdGF0dXM6IHN0cmluZykge1xyXG4gIGNvbnN0IGNoZWNrYm94ID0gZXZlbnQudGFyZ2V0IGFzIEhUTUxJbnB1dEVsZW1lbnQ7XHJcbiAgY29uc3Qgc2VsZWN0ZWQ6IHN0cmluZ1tdID0gdGhpcy5maWx0ZXJGb3JtLnZhbHVlLnN0YXR1cyB8fCBbXTtcclxuICBsZXQgbmV4dDogc3RyaW5nW107XHJcblxyXG4gIGlmIChjaGVja2JveC5jaGVja2VkKSB7XHJcbiAgICBuZXh0ID0gc2VsZWN0ZWQuaW5jbHVkZXMoc3RhdHVzKSA/IHNlbGVjdGVkIDogWy4uLnNlbGVjdGVkLCBzdGF0dXNdO1xyXG4gIH0gZWxzZSB7XHJcbiAgICBuZXh0ID0gc2VsZWN0ZWQuZmlsdGVyKHMgPT4gcyAhPT0gc3RhdHVzKTtcclxuICB9XHJcblxyXG4gIHRoaXMuZmlsdGVyRm9ybS5wYXRjaFZhbHVlKHsgc3RhdHVzOiBuZXh0IH0pO1xyXG59XHJcblxyXG50b2dnbGVTdGF0dXNEcm9wZG93bihldmVudD86IE1vdXNlRXZlbnQpIHtcclxuICBpZiAoZXZlbnQpIHtcclxuICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpOyAvLyBhdm9pZCBkb2N1bWVudCBjbGljayBjbG9zaW5nIGl0XHJcbiAgfVxyXG4gIHRoaXMuc3RhdHVzRHJvcGRvd25PcGVuID0gIXRoaXMuc3RhdHVzRHJvcGRvd25PcGVuO1xyXG59XHJcblxyXG4vLyBBcmUgYWxsIHN0YXR1c2VzIGN1cnJlbnRseSBzZWxlY3RlZD9cclxuYXJlQWxsU3RhdHVzZXNTZWxlY3RlZCgpOiBib29sZWFuIHtcclxuICBjb25zdCBzZWxlY3RlZDogc3RyaW5nW10gPSB0aGlzLmZpbHRlckZvcm0udmFsdWUuc3RhdHVzIHx8IFtdO1xyXG4gIHJldHVybiBzZWxlY3RlZC5sZW5ndGggPiAwICYmIHNlbGVjdGVkLmxlbmd0aCA9PT0gdGhpcy5zdGF0dXNPcHRpb25zLmxlbmd0aDtcclxufVxyXG5cclxuLy8gSGFuZGxlIFwiU2VsZWN0IEFsbFwiIGNoZWNrYm94IGNoYW5nZVxyXG5vblN0YXR1c1NlbGVjdEFsbENoYW5nZShldmVudDogRXZlbnQpIHtcclxuICBjb25zdCBjaGVja2JveCA9IGV2ZW50LnRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50O1xyXG5cclxuICBpZiAoY2hlY2tib3guY2hlY2tlZCkge1xyXG4gICAgLy8gU2VsZWN0IGV2ZXJ5IHN0YXR1c1xyXG4gICAgdGhpcy5maWx0ZXJGb3JtLnBhdGNoVmFsdWUoeyBzdGF0dXM6IFsuLi50aGlzLnN0YXR1c09wdGlvbnNdIH0pO1xyXG4gIH0gZWxzZSB7XHJcbiAgICAvLyBDbGVhciBhbGxcclxuICAgIHRoaXMuZmlsdGVyRm9ybS5wYXRjaFZhbHVlKHsgc3RhdHVzOiBbXSB9KTtcclxuICB9XHJcbn1cclxuZ2V0IHNlbGVjdGVkU3RhdHVzZXMoKTogc3RyaW5nW10ge1xyXG4gIHJldHVybiB0aGlzLmZpbHRlckZvcm0udmFsdWUuc3RhdHVzIHx8IFtdO1xyXG59XHJcblxyXG4gIGlzQmV0d2Vlbihjb250cm9sTmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gdGhpcy5maWx0ZXJGb3JtLmdldChjb250cm9sTmFtZSk/LnZhbHVlID09PSAnYmV0d2Vlbic7XHJcbiAgfVxyXG5uZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XHJcbiAgaWYgKGNoYW5nZXNbJ2NsaWVudCddIHx8IGNoYW5nZXNbJ3Blcm1pc3Npb25UeXBlJ10gfHwgY2hhbmdlc1sndXNlclR5cGUnXSkge1xyXG4gICAgdGhpcy5sb2FkUmV2aWV3ZXJMaXN0KCk7XHJcbiAgfVxyXG59XHJcbnVzZXJMaXN0OmFueVxyXG5wcml2YXRlIGxvYWRSZXZpZXdlckxpc3QoKTogdm9pZCB7XHJcbiAgaWYgKCF0aGlzLmNsaWVudCkge1xyXG4gICAgdGhpcy51c2VyTGlzdCA9IFtdO1xyXG4gICAgcmV0dXJuO1xyXG4gIH1cclxuXHJcbiAgbGV0IHR5cGU6IHN0cmluZztcclxuXHJcbiAgaWYgKHRoaXMudXNlclR5cGUgPT09ICd0YW5nbycpIHtcclxuICAgIHR5cGUgPSAndGFuZ28nOyAgICAvLyBvciAnYWxsJ1xyXG4gIH0gZWxzZSBpZiAodGhpcy5wZXJtaXNzaW9uVHlwZSA9PT0gJ3JldmlldycpIHtcclxuICAgIHR5cGUgPSAncmV2aWV3JztcclxuICB9IGVsc2UgaWYgKHRoaXMucGVybWlzc2lvblR5cGUgPT09ICdhcHByb3ZlJykge1xyXG4gICAgdHlwZSA9ICdhcHByb3ZlJztcclxuICB9IGVsc2Uge1xyXG4gICAgdGhpcy51c2VyTGlzdCA9IFtdO1xyXG4gICAgcmV0dXJuO1xyXG4gIH1cclxuXHJcbiAgdGhpcy5zZXJ2aWNlLmdldFJldmlld2VyQXBpKHRoaXMuY2xpZW50LCB0eXBlKS5zdWJzY3JpYmUoe1xyXG4gICAgbmV4dDogKHJlczogYW55KSA9PiB7XHJcbiAgICAgIGlmIChyZXMgJiYgcmVzLmNvZGUgPT09IDIwMCkge1xyXG4gICAgICAgIHRoaXMudXNlckxpc3QgPSByZXMuZGF0YTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICB0aGlzLnVzZXJMaXN0ID0gW107XHJcbiAgICAgIH1cclxuICAgIH0sXHJcbiAgICBlcnJvcjogKCkgPT4ge1xyXG4gICAgICB0aGlzLnVzZXJMaXN0ID0gW107XHJcbiAgICB9XHJcbiAgfSk7XHJcbn1cclxuXHJcbi8vIG9wZW4gZmxhZ3NcclxucmV2aWV3ZXJEcm9wZG93bk9wZW4gPSBmYWxzZTtcclxuYXBwcm92ZXJEcm9wZG93bk9wZW4gPSBmYWxzZTtcclxuXHJcbi8vIGNvbnZlbmllbmNlIGdldHRlcnNcclxuZ2V0IHNlbGVjdGVkUmV2aWV3ZWRCeSgpOiBzdHJpbmdbXSB7XHJcbiAgcmV0dXJuIHRoaXMuZmlsdGVyRm9ybS52YWx1ZS5yZXZpZXdlZEJ5IHx8IFtdO1xyXG59XHJcblxyXG5nZXQgc2VsZWN0ZWRBcHByb3ZlZEJ5KCk6IHN0cmluZ1tdIHtcclxuICByZXR1cm4gdGhpcy5maWx0ZXJGb3JtLnZhbHVlLmFwcHJvdmVkQnkgfHwgW107XHJcbn1cclxuXHJcbi8vIC0tLSBSZXZpZXdlZCBCeSBoZWxwZXJzIC0tLVxyXG5cclxudG9nZ2xlUmV2aWV3ZXJEcm9wZG93bihldmVudD86IE1vdXNlRXZlbnQpIHtcclxuICBpZiAoZXZlbnQpIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gIHRoaXMucmV2aWV3ZXJEcm9wZG93bk9wZW4gPSAhdGhpcy5yZXZpZXdlckRyb3Bkb3duT3BlbjtcclxufVxyXG5cclxuaXNSZXZpZXdlclNlbGVjdGVkKGVtYWlsOiBzdHJpbmcpOiBib29sZWFuIHtcclxuICByZXR1cm4gdGhpcy5zZWxlY3RlZFJldmlld2VkQnkuaW5jbHVkZXMoZW1haWwpO1xyXG59XHJcblxyXG5vblJldmlld2VyQ2hhbmdlKGV2ZW50OiBFdmVudCwgZW1haWw6IHN0cmluZykge1xyXG4gIGNvbnN0IGNoZWNrYm94ID0gZXZlbnQudGFyZ2V0IGFzIEhUTUxJbnB1dEVsZW1lbnQ7XHJcbiAgY29uc3Qgc2VsZWN0ZWQgPSBbLi4udGhpcy5zZWxlY3RlZFJldmlld2VkQnldO1xyXG5cclxuICBpZiAoY2hlY2tib3guY2hlY2tlZCkge1xyXG4gICAgaWYgKCFzZWxlY3RlZC5pbmNsdWRlcyhlbWFpbCkpIHNlbGVjdGVkLnB1c2goZW1haWwpO1xyXG4gIH0gZWxzZSB7XHJcbiAgICBjb25zdCBpID0gc2VsZWN0ZWQuaW5kZXhPZihlbWFpbCk7XHJcbiAgICBpZiAoaSA+PSAwKSBzZWxlY3RlZC5zcGxpY2UoaSwgMSk7XHJcbiAgfVxyXG5cclxuICB0aGlzLmZpbHRlckZvcm0ucGF0Y2hWYWx1ZSh7IHJldmlld2VkQnk6IHNlbGVjdGVkIH0pO1xyXG59XHJcblxyXG5hcmVBbGxSZXZpZXdlcnNTZWxlY3RlZCgpOiBib29sZWFuIHtcclxuICByZXR1cm4gKFxyXG4gICAgdGhpcy51c2VyTGlzdC5sZW5ndGggPiAwICYmXHJcbiAgICB0aGlzLnNlbGVjdGVkUmV2aWV3ZWRCeS5sZW5ndGggPT09IHRoaXMudXNlckxpc3QubGVuZ3RoXHJcbiAgKTtcclxufVxyXG5cclxub25SZXZpZXdlclNlbGVjdEFsbChldmVudDogRXZlbnQpIHtcclxuICBjb25zdCBjaGVja2JveCA9IGV2ZW50LnRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50O1xyXG5cclxuICBpZiAoY2hlY2tib3guY2hlY2tlZCkge1xyXG4gICAgdGhpcy5maWx0ZXJGb3JtLnBhdGNoVmFsdWUoe1xyXG4gICAgICByZXZpZXdlZEJ5OiB0aGlzLnVzZXJMaXN0Lm1hcCgodTphbnkpID0+IHUuZW1haWwpLFxyXG4gICAgfSk7XHJcbiAgfSBlbHNlIHtcclxuICAgIHRoaXMuZmlsdGVyRm9ybS5wYXRjaFZhbHVlKHsgcmV2aWV3ZWRCeTogW10gfSk7XHJcbiAgfVxyXG59XHJcblxyXG4vLyAtLS0gQXBwcm92ZWQgQnkgaGVscGVycyAtLS1cclxuXHJcbnRvZ2dsZUFwcHJvdmVyRHJvcGRvd24oZXZlbnQ/OiBNb3VzZUV2ZW50KSB7XHJcbiAgaWYgKGV2ZW50KSBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcclxuICB0aGlzLmFwcHJvdmVyRHJvcGRvd25PcGVuID0gIXRoaXMuYXBwcm92ZXJEcm9wZG93bk9wZW47XHJcbn1cclxuXHJcbmlzQXBwcm92ZXJTZWxlY3RlZChlbWFpbDogc3RyaW5nKTogYm9vbGVhbiB7XHJcbiAgcmV0dXJuIHRoaXMuc2VsZWN0ZWRBcHByb3ZlZEJ5LmluY2x1ZGVzKGVtYWlsKTtcclxufVxyXG5cclxub25BcHByb3ZlckNoYW5nZShldmVudDogRXZlbnQsIGVtYWlsOiBzdHJpbmcpIHtcclxuICBjb25zdCBjaGVja2JveCA9IGV2ZW50LnRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50O1xyXG4gIGNvbnN0IHNlbGVjdGVkID0gWy4uLnRoaXMuc2VsZWN0ZWRBcHByb3ZlZEJ5XTtcclxuXHJcbiAgaWYgKGNoZWNrYm94LmNoZWNrZWQpIHtcclxuICAgIGlmICghc2VsZWN0ZWQuaW5jbHVkZXMoZW1haWwpKSBzZWxlY3RlZC5wdXNoKGVtYWlsKTtcclxuICB9IGVsc2Uge1xyXG4gICAgY29uc3QgaSA9IHNlbGVjdGVkLmluZGV4T2YoZW1haWwpO1xyXG4gICAgaWYgKGkgPj0gMCkgc2VsZWN0ZWQuc3BsaWNlKGksIDEpO1xyXG4gIH1cclxuXHJcbiAgdGhpcy5maWx0ZXJGb3JtLnBhdGNoVmFsdWUoeyBhcHByb3ZlZEJ5OiBzZWxlY3RlZCB9KTtcclxufVxyXG5cclxuYXJlQWxsQXBwcm92ZXJzU2VsZWN0ZWQoKTogYm9vbGVhbiB7XHJcbiAgcmV0dXJuIChcclxuICAgIHRoaXMudXNlckxpc3QubGVuZ3RoID4gMCAmJlxyXG4gICAgdGhpcy5zZWxlY3RlZEFwcHJvdmVkQnkubGVuZ3RoID09PSB0aGlzLnVzZXJMaXN0Lmxlbmd0aFxyXG4gICk7XHJcbn1cclxuXHJcbm9uQXBwcm92ZXJTZWxlY3RBbGwoZXZlbnQ6IEV2ZW50KSB7XHJcbiAgY29uc3QgY2hlY2tib3ggPSBldmVudC50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudDtcclxuXHJcbiAgaWYgKGNoZWNrYm94LmNoZWNrZWQpIHtcclxuICAgIHRoaXMuZmlsdGVyRm9ybS5wYXRjaFZhbHVlKHtcclxuICAgICAgYXBwcm92ZWRCeTogdGhpcy51c2VyTGlzdC5tYXAoKHU6YW55KSA9PiB1LmVtYWlsKSxcclxuICAgIH0pO1xyXG4gIH0gZWxzZSB7XHJcbiAgICB0aGlzLmZpbHRlckZvcm0ucGF0Y2hWYWx1ZSh7IGFwcHJvdmVkQnk6IFtdIH0pO1xyXG4gIH1cclxufVxyXG5cclxuXHJcbiAgb25SZXNldCgpOiB2b2lkIHtcclxuICAgIHRoaXMuZmlsdGVyRm9ybS5yZXNldCh7XHJcbiAgICAgIHN0YXR1czogW10sXHJcbiAgcmV2aWV3ZXJDb25kaXRpb246IG51bGwsXHJcbiAgcmV2aWV3ZXJGcm9tOiBudWxsLFxyXG4gIHJldmlld2VyVG86IG51bGwsXHJcbiAgYXBwcm92ZXJDb25kaXRpb246IG51bGwsXHJcbiAgYXBwcm92ZXJGcm9tOiBudWxsLFxyXG4gIGFwcHJvdmVyVG86IG51bGwsXHJcbiAgdGFuZ29Db25kaXRpb246IG51bGwsXHJcbiAgdGFuZ29Gcm9tOiBudWxsLFxyXG4gIHRhbmdvVG86IG51bGwsXHJcbiAgcmV2aWV3ZWRCeTogW10sXHJcbiAgYXBwcm92ZWRCeTogW10sXHJcbiAgICB9KTtcclxuICAgICAgdGhpcy5jbG9zZSgpO1xyXG4gIH1cclxucHJpdmF0ZSBtYXBBY2N1cmFjeShcclxuICBjb25kaXRpb246IENvbmRpdGlvbiB8IG51bGwsXHJcbiAgZnJvbTogbnVtYmVyIHwgbnVsbCxcclxuICB0bzogbnVtYmVyIHwgbnVsbFxyXG4pOiBzdHJpbmcgfCBudWxsIHtcclxuXHJcbiAgLy8gbm90aGluZyBzZWxlY3RlZFxyXG4gIGlmICghY29uZGl0aW9uIHx8IGZyb20gPT0gbnVsbCkgcmV0dXJuIG51bGw7XHJcblxyXG4gIC8vIFwiYmV0d2VlblwiIOKGkiBcIjkwIHRvIDEwMFwiXHJcbiAgaWYgKGNvbmRpdGlvbiA9PT0gJ2JldHdlZW4nKSB7XHJcbiAgICBpZiAodG8gPT0gbnVsbCkgcmV0dXJuIG51bGw7XHJcbiAgICByZXR1cm4gYCR7ZnJvbX0gdG8gJHt0b31gO1xyXG4gIH1cclxuXHJcbiAgLy8gb3RoZXIgY29uZGl0aW9ucyAoZ3QsIGx0LCBndGUsIGx0ZSlcclxuICBjb25zdCBvcE1hcDogUmVjb3JkPENvbmRpdGlvbiwgc3RyaW5nPiA9IHtcclxuICAgIGd0OiAnPicsXHJcbiAgICBsdDogJzwnLFxyXG4gICAgZ3RlOiAnPj0nLFxyXG4gICAgbHRlOiAnPD0nLFxyXG4gICAgYmV0d2VlbjogJycsIC8vIGFscmVhZHkgaGFuZGxlZCBhYm92ZVxyXG4gIH07XHJcblxyXG4gIHJldHVybiBgJHtvcE1hcFtjb25kaXRpb25dfSAke2Zyb219YDsgIC8vIGUuZy4gXCI+PSA5MFwiXHJcbn1cclxuXHJcbiAgb25BcHBseSgpOiB2b2lkIHtcclxuXHJcbiAgIGNvbnN0IHJhdyA9IHRoaXMuZmlsdGVyRm9ybS52YWx1ZTtcclxuXHJcbiAgY29uc3QgcmV2aWV3ZXJTdHIgPSB0aGlzLm1hcEFjY3VyYWN5KHJhdy5yZXZpZXdlckNvbmRpdGlvbiwgcmF3LnJldmlld2VyRnJvbSwgcmF3LnJldmlld2VyVG8pO1xyXG4gIGNvbnN0IGFwcHJvdmVyU3RyID0gdGhpcy5tYXBBY2N1cmFjeShyYXcuYXBwcm92ZXJDb25kaXRpb24sIHJhdy5hcHByb3ZlckZyb20sIHJhdy5hcHByb3ZlclRvKTtcclxuICBjb25zdCB0YW5nb1N0ciAgICA9IHRoaXMubWFwQWNjdXJhY3kocmF3LnRhbmdvQ29uZGl0aW9uLCByYXcudGFuZ29Gcm9tLCByYXcudGFuZ29Ubyk7XHJcblxyXG4gIGNvbnN0IHBheWxvYWQgPSB7XHJcbiAgICBmaWx0ZXJCeVN0YXR1czogcmF3LnN0YXR1cyB8fCBbXSxcclxuXHJcbiAgICBmaWx0ZXJCeVJldmlld2VyOiByZXZpZXdlclN0cixcclxuICAgIGZpbHRlckJ5QXBwcm92ZXI6IGFwcHJvdmVyU3RyLFxyXG4gICAgZmlsdGVyQnlUYW5nbzogdGFuZ29TdHIsXHJcblxyXG4gICAgZmlsdGVyQnlSZXZpZXdlZEJ5OiByYXcucmV2aWV3ZWRCeSB8fCBbXSwgICAgICAgIFxyXG4gICAgZmlsZXRlckJ5QXBwcm92ZWRCeTogcmF3LmFwcHJvdmVkQnkgfHwgW10sICAgICAgICBcclxuICB9O1xyXG5cclxuICB0aGlzLmFwcGx5LmVtaXQocGF5bG9hZCk7XHJcbiAgdGhpcy5jbG9zZSgpO1xyXG4gICAgdGhpcy5zaG93UGFuZWwgPSBmYWxzZTtcclxuICB9XHJcblxyXG5cclxufVxyXG4iLCI8IS0tIHRpY2tldC1maWx0ZXItcGFuZWwuY29tcG9uZW50Lmh0bWwgLS0+XHJcbjxkaXYgY2xhc3M9XCJmaWx0ZXItd3JhcHBlclwiICpuZ0lmPVwiaXNPcGVuXCI+XHJcbiAgPGRpdiBjbGFzcz1cImZpbHRlci1jYXJkXCI+XHJcbiAgICA8ZGl2IGNsYXNzPVwiZmlsdGVyLWhlYWRlciBkLWZsZXgganVzdGlmeS1jb250ZW50LWJldHdlZW4gYWxpZ24taXRlbXMtY2VudGVyIG1iLTNcIj5cclxuICA8ZGl2IGNsYXNzPVwidGl0bGVcIj5GaWx0ZXIgT3B0aW9uczwvZGl2PlxyXG4gICAgICA8IS0tIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYnRuLWNsb3NlXCIgKGNsaWNrKT1cImNsb3NlKClcIj7inJU8L2J1dHRvbj4gLS0+XHJcbiAgICA8L2Rpdj5cclxuXHJcbiAgICA8Zm9ybSBbZm9ybUdyb3VwXT1cImZpbHRlckZvcm1cIj5cclxuICAgICAgPCEtLSBTdGF0dXMgLS0+XHJcbjxkaXYgY2xhc3M9XCJtYi0zIHBvc2l0aW9uLXJlbGF0aXZlXCIgKGNsaWNrKT1cIiRldmVudC5zdG9wUHJvcGFnYXRpb24oKVwiPlxyXG4gIDxsYWJlbCBjbGFzcz1cImZvcm0tbGFiZWxcIj5TdGF0dXM8L2xhYmVsPlxyXG5cclxuICA8IS0tIEhlYWRlciAvIHRyaWdnZXIgLS0+XHJcbiAgPGRpdlxyXG4gICAgY2xhc3M9XCJzdGF0dXMtc2VsZWN0IGJvcmRlciByb3VuZGVkIHB4LTMgcHktMiBkLWZsZXgganVzdGlmeS1jb250ZW50LWJldHdlZW4gYWxpZ24taXRlbXMtY2VudGVyXCJcclxuICAgIChjbGljayk9XCJ0b2dnbGVTdGF0dXNEcm9wZG93bigkZXZlbnQpXCJcclxuICA+XHJcbiAgICA8c3BhbiAqbmdJZj1cIiFzZWxlY3RlZFN0YXR1c2VzLmxlbmd0aFwiPlNlbGVjdDwvc3Bhbj5cclxuXHJcbiAgICA8c3BhbiAqbmdJZj1cInNlbGVjdGVkU3RhdHVzZXMubGVuZ3RoID09PSAxXCI+XHJcbiAgICAgIHt7IHNlbGVjdGVkU3RhdHVzZXNbMF0gfX1cclxuICAgIDwvc3Bhbj5cclxuXHJcbiAgICA8c3BhbiAqbmdJZj1cInNlbGVjdGVkU3RhdHVzZXMubGVuZ3RoID4gMVwiIGNsYXNzPVwiZC1mbGV4IGFsaWduLWl0ZW1zLWNlbnRlclwiPlxyXG4gICAgICA8c3Bhbj57eyBzZWxlY3RlZFN0YXR1c2VzWzBdIH19PC9zcGFuPlxyXG4gICAgICA8c3BhbiBjbGFzcz1cImJhZGdlIG1zLTJcIj5cclxuICAgICAgICAre3sgc2VsZWN0ZWRTdGF0dXNlcy5sZW5ndGggLSAxIH19XHJcbiAgICAgIDwvc3Bhbj5cclxuICAgIDwvc3Bhbj5cclxuXHJcbiAgPC9kaXY+XHJcblxyXG4gIDwhLS0gRFJPUERPV04gUEFORUwgKE9WRVJMQVkpIC0tPlxyXG4gIDxkaXZcclxuICAgIGNsYXNzPVwic3RhdHVzLWRyb3Bkb3duIHBvc2l0aW9uLWFic29sdXRlIHctMTAwIG10LTEgYm9yZGVyIHJvdW5kZWQgcC0xIGJnLXdoaXRlXCJcclxuICAgIHN0eWxlPVwiei1pbmRleDogMTAwMDsgbWF4LWhlaWdodDogMjIwcHg7IG92ZXJmbG93LXk6IGF1dG87XCJcclxuICAgICpuZ0lmPVwic3RhdHVzRHJvcGRvd25PcGVuXCJcclxuICAgIChjbGljayk9XCIkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcIlxyXG4gID5cclxuICAgIDwhLS0gU2VsZWN0IEFsbCAtLT5cclxuICAgIDxkaXYgY2xhc3M9XCJmb3JtLWNoZWNrIHB4LTAgZC1mbGV4IGFsaWduLWl0ZW1zLWNlbnRlciBtYi0yXCI+XHJcbiAgICAgIDxpbnB1dFxyXG4gICAgICAgIHR5cGU9XCJjaGVja2JveFwiXHJcbiAgICAgICAgY2xhc3M9XCJmb3JtLWNoZWNrLWlucHV0IHRleHQtZGFya1wiXHJcbiAgICAgICAgaWQ9XCJzdGF0dXMtc2VsZWN0LWFsbFwiXHJcbiAgICAgICAgW2NoZWNrZWRdPVwiYXJlQWxsU3RhdHVzZXNTZWxlY3RlZCgpXCJcclxuICAgICAgICAoY2hhbmdlKT1cIm9uU3RhdHVzU2VsZWN0QWxsQ2hhbmdlKCRldmVudClcIlxyXG4gICAgICAvPlxyXG4gICAgICA8bGFiZWwgY2xhc3M9XCJmb3JtLWNoZWNrLWxhYmVsIG1zLTJcIiBmb3I9XCJzdGF0dXMtc2VsZWN0LWFsbFwiPlxyXG4gICAgICAgIFNlbGVjdCBBbGxcclxuICAgICAgPC9sYWJlbD5cclxuICAgIDwvZGl2PlxyXG5cclxuXHJcbiAgICA8IS0tIE9wdGlvbnMgLS0+XHJcbiAgICA8ZGl2XHJcbiAgICAgIGNsYXNzPVwiZm9ybS1jaGVjayBweC0wIGQtZmxleCBhbGlnbi1pdGVtcy1jZW50ZXIgbWItMVwiXHJcbiAgICAgICpuZ0Zvcj1cImxldCBzIG9mIHN0YXR1c09wdGlvbnNcIlxyXG4gICAgPlxyXG4gICAgICA8aW5wdXRcclxuICAgICAgICB0eXBlPVwiY2hlY2tib3hcIlxyXG4gICAgICAgIGNsYXNzPVwiZm9ybS1jaGVjay1pbnB1dCB0ZXh0LWRhcmtcIlxyXG4gICAgICAgIFtpZF09XCInc3RhdHVzLScgKyBzXCJcclxuICAgICAgICBbY2hlY2tlZF09XCJpc1N0YXR1c1NlbGVjdGVkKHMpXCJcclxuICAgICAgICAoY2hhbmdlKT1cIm9uU3RhdHVzQ2hhbmdlKCRldmVudCwgcylcIlxyXG4gICAgICAvPlxyXG4gICAgICA8bGFiZWwgY2xhc3M9XCJmb3JtLWNoZWNrLWxhYmVsIG1zLTJcIiBbZm9yXT1cIidzdGF0dXMtJyArIHNcIj5cclxuICAgICAgICB7eyBzIH19XHJcbiAgICAgIDwvbGFiZWw+XHJcbiAgICA8L2Rpdj5cclxuICA8L2Rpdj5cclxuPC9kaXY+XHJcblxyXG5cclxuXHJcbiAgICAgIDwhLS0gUmV2aWV3ZXIgYWNjdXJhY3kgLS0+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJtYi0zXCIgKm5nSWY9XCJzaG93UmV2aWV3ZXJBY2N1cmFjeVwiPlxyXG4gICAgICAgIDxsYWJlbCBjbGFzcz1cImZvcm0tbGFiZWxcIj5SZXZpZXdlciBhY2N1cmFjeSAoJSkgYnkgY29uZGl0aW9uPC9sYWJlbD5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwiZC1mbGV4IGdhcC0yXCI+XHJcbiAgICAgICAgICA8c2VsZWN0IGNsYXNzPVwiZm9ybS1zZWxlY3Qgdy0xMDBcIiBmb3JtQ29udHJvbE5hbWU9XCJyZXZpZXdlckNvbmRpdGlvblwiPlxyXG4gICAgICAgICAgICA8b3B0aW9uIFtuZ1ZhbHVlXT1cIm51bGxcIj5TZWxlY3Q8L29wdGlvbj5cclxuICAgICAgICAgICAgPG9wdGlvbiAqbmdGb3I9XCJsZXQgYyBvZiBjb25kaXRpb25PcHRpb25zXCIgW25nVmFsdWVdPVwiYy52YWx1ZVwiPlxyXG4gICAgICAgICAgICAgIHt7IGMubGFiZWwgfX1cclxuICAgICAgICAgICAgPC9vcHRpb24+XHJcbiAgICAgICAgICA8L3NlbGVjdD5cclxuXHJcbiAgICAgICAgICA8IS0tIG9uZSBvciB0d28gaW5wdXRzIC0tPlxyXG4gICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImlzQmV0d2VlbigncmV2aWV3ZXJDb25kaXRpb24nKTsgZWxzZSBzaW5nbGVSZXZpZXdlclwiPlxyXG4gICAgICAgICAgICA8aW5wdXRcclxuICAgICAgICAgICAgICB0eXBlPVwibnVtYmVyXCJcclxuICAgICAgICAgICAgICBtaW49XCIxXCJcclxuICAgICAgICAgICAgICBtYXg9XCIxMDBcIlxyXG4gICAgICAgICAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sXCJcclxuICAgICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJyZXZpZXdlckZyb21cIlxyXG4gICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwiRnJvbVwiIC8+XHJcbiAgICAgICAgICAgIDxpbnB1dFxyXG4gICAgICAgICAgICAgIHR5cGU9XCJudW1iZXJcIlxyXG4gICAgICAgICAgICAgIG1pbj1cIjFcIlxyXG4gICAgICAgICAgICAgIG1heD1cIjEwMFwiXHJcbiAgICAgICAgICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxyXG4gICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cInJldmlld2VyVG9cIlxyXG4gICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwiVG9cIiAvPlxyXG4gICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICA8bmctdGVtcGxhdGUgI3NpbmdsZVJldmlld2VyPlxyXG4gICAgICAgICAgICA8aW5wdXRcclxuICAgICAgICAgICAgICB0eXBlPVwibnVtYmVyXCJcclxuICAgICAgICAgICAgICBtaW49XCIxXCJcclxuICAgICAgICAgICAgICBtYXg9XCIxMDBcIlxyXG4gICAgICAgICAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sXCJcclxuICAgICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJyZXZpZXdlckZyb21cIlxyXG4gICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwiMSB0byAxMDAlXCIgLz5cclxuICAgICAgICAgIDwvbmctdGVtcGxhdGU+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgPCEtLSBBcHByb3ZlciBhY2N1cmFjeSAtLT5cclxuICAgICAgPGRpdiBjbGFzcz1cIm1iLTNcIiAqbmdJZj1cInNob3dBcHByb3ZlckFjY3VyYWN5XCI+XHJcbiAgICAgICAgPGxhYmVsIGNsYXNzPVwiZm9ybS1sYWJlbFwiPkFwcHJvdmVyIGFjY3VyYWN5ICglKSBieSBjb25kaXRpb248L2xhYmVsPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJkLWZsZXggZ2FwLTJcIj5cclxuICAgICAgICAgIDxzZWxlY3QgY2xhc3M9XCJmb3JtLXNlbGVjdCB3LTEwMFwiIGZvcm1Db250cm9sTmFtZT1cImFwcHJvdmVyQ29uZGl0aW9uXCI+XHJcbiAgICAgICAgICAgIDxvcHRpb24gW25nVmFsdWVdPVwibnVsbFwiPlNlbGVjdDwvb3B0aW9uPlxyXG4gICAgICAgICAgICA8b3B0aW9uICpuZ0Zvcj1cImxldCBjIG9mIGNvbmRpdGlvbk9wdGlvbnNcIiBbbmdWYWx1ZV09XCJjLnZhbHVlXCI+XHJcbiAgICAgICAgICAgICAge3sgYy5sYWJlbCB9fVxyXG4gICAgICAgICAgICA8L29wdGlvbj5cclxuICAgICAgICAgIDwvc2VsZWN0PlxyXG5cclxuICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJpc0JldHdlZW4oJ2FwcHJvdmVyQ29uZGl0aW9uJyk7IGVsc2Ugc2luZ2xlQXBwcm92ZXJcIj5cclxuICAgICAgICAgICAgPGlucHV0XHJcbiAgICAgICAgICAgICAgdHlwZT1cIm51bWJlclwiXHJcbiAgICAgICAgICAgICAgbWluPVwiMVwiXHJcbiAgICAgICAgICAgICAgbWF4PVwiMTAwXCJcclxuICAgICAgICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXHJcbiAgICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwiYXBwcm92ZXJGcm9tXCJcclxuICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cIkZyb21cIiAvPlxyXG4gICAgICAgICAgICA8aW5wdXRcclxuICAgICAgICAgICAgICB0eXBlPVwibnVtYmVyXCJcclxuICAgICAgICAgICAgICBtaW49XCIxXCJcclxuICAgICAgICAgICAgICBtYXg9XCIxMDBcIlxyXG4gICAgICAgICAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sXCJcclxuICAgICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJhcHByb3ZlclRvXCJcclxuICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cIlRvXCIgLz5cclxuICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgPG5nLXRlbXBsYXRlICNzaW5nbGVBcHByb3Zlcj5cclxuICAgICAgICAgICAgPGlucHV0XHJcbiAgICAgICAgICAgICAgdHlwZT1cIm51bWJlclwiXHJcbiAgICAgICAgICAgICAgbWluPVwiMVwiXHJcbiAgICAgICAgICAgICAgbWF4PVwiMTAwXCJcclxuICAgICAgICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXHJcbiAgICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwiYXBwcm92ZXJGcm9tXCJcclxuICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cIjEgdG8gMTAwJVwiIC8+XHJcbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICA8L2Rpdj5cclxuXHJcbiAgICAgIDwhLS0gVGFuZ28gYWNjdXJhY3kgLS0+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJtYi0zXCIgKm5nSWY9XCJzaG93VGFuZ29BY2N1cmFjeVwiPlxyXG4gICAgICAgIDxsYWJlbCBjbGFzcz1cImZvcm0tbGFiZWxcIj5UYW5nbyBhY2N1cmFjeSAoJSkgYnkgY29uZGl0aW9uPC9sYWJlbD5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwiZC1mbGV4IGdhcC0yXCI+XHJcbiAgICAgICAgICA8c2VsZWN0IGNsYXNzPVwiZm9ybS1zZWxlY3Qgdy01MFwiIGZvcm1Db250cm9sTmFtZT1cInRhbmdvQ29uZGl0aW9uXCI+XHJcbiAgICAgICAgICAgIDxvcHRpb24gW25nVmFsdWVdPVwibnVsbFwiPlNlbGVjdDwvb3B0aW9uPlxyXG4gICAgICAgICAgICA8b3B0aW9uICpuZ0Zvcj1cImxldCBjIG9mIGNvbmRpdGlvbk9wdGlvbnNcIiBbbmdWYWx1ZV09XCJjLnZhbHVlXCI+XHJcbiAgICAgICAgICAgICAge3sgYy5sYWJlbCB9fVxyXG4gICAgICAgICAgICA8L29wdGlvbj5cclxuICAgICAgICAgIDwvc2VsZWN0PlxyXG5cclxuICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJpc0JldHdlZW4oJ3RhbmdvQ29uZGl0aW9uJyk7IGVsc2Ugc2luZ2xlVGFuZ29cIj5cclxuICAgICAgICAgICAgPGlucHV0XHJcbiAgICAgICAgICAgICAgdHlwZT1cIm51bWJlclwiXHJcbiAgICAgICAgICAgICAgbWluPVwiMVwiXHJcbiAgICAgICAgICAgICAgbWF4PVwiMTAwXCJcclxuICAgICAgICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXHJcbiAgICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwidGFuZ29Gcm9tXCJcclxuICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cIkZyb21cIiAvPlxyXG4gICAgICAgICAgICA8aW5wdXRcclxuICAgICAgICAgICAgICB0eXBlPVwibnVtYmVyXCJcclxuICAgICAgICAgICAgICBtaW49XCIxXCJcclxuICAgICAgICAgICAgICBtYXg9XCIxMDBcIlxyXG4gICAgICAgICAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sXCJcclxuICAgICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJ0YW5nb1RvXCJcclxuICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cIlRvXCIgLz5cclxuICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgPG5nLXRlbXBsYXRlICNzaW5nbGVUYW5nbz5cclxuICAgICAgICAgICAgPGlucHV0XHJcbiAgICAgICAgICAgICAgdHlwZT1cIm51bWJlclwiXHJcbiAgICAgICAgICAgICAgbWluPVwiMVwiXHJcbiAgICAgICAgICAgICAgbWF4PVwiMTAwXCJcclxuICAgICAgICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXHJcbiAgICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwidGFuZ29Gcm9tXCJcclxuICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cIjEgdG8gMTAwJVwiIC8+XHJcbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICA8L2Rpdj5cclxuPGRpdlxyXG4gIGNsYXNzPVwibWItMyBwb3NpdGlvbi1yZWxhdGl2ZVwiXHJcbiAgKm5nSWY9XCJzaG93UmV2aWV3ZWRCeVwiXHJcbiAgKGNsaWNrKT1cIiRldmVudC5zdG9wUHJvcGFnYXRpb24oKVwiXHJcbj5cclxuICA8bGFiZWwgY2xhc3M9XCJmb3JtLWxhYmVsXCI+UmV2aWV3ZWQgYnk8L2xhYmVsPlxyXG5cclxuICA8IS0tIFRyaWdnZXIgLyBkaXNwbGF5IC0tPlxyXG4gIDxkaXZcclxuICAgIGNsYXNzPVwiYm9yZGVyIHJvdW5kZWQgcHgtMyBweS0yIGQtZmxleCBqdXN0aWZ5LWNvbnRlbnQtYmV0d2VlbiBhbGlnbi1pdGVtcy1jZW50ZXJcIlxyXG4gICAgKGNsaWNrKT1cInRvZ2dsZVJldmlld2VyRHJvcGRvd24oJGV2ZW50KVwiXHJcbiAgPlxyXG4gICAgPCEtLSAwIHNlbGVjdGVkIC0tPlxyXG4gICAgPHNwYW4gKm5nSWY9XCIhc2VsZWN0ZWRSZXZpZXdlZEJ5Lmxlbmd0aFwiPlxyXG4gICAgICBTZWxlY3RcclxuICAgIDwvc3Bhbj5cclxuXHJcbiAgICA8IS0tIDEgc2VsZWN0ZWQgLS0+XHJcbiAgICA8c3BhbiAqbmdJZj1cInNlbGVjdGVkUmV2aWV3ZWRCeS5sZW5ndGggPT09IDFcIj5cclxuICAgICAge3sgc2VsZWN0ZWRSZXZpZXdlZEJ5WzBdIH19XHJcbiAgICA8L3NwYW4+XHJcblxyXG4gICAgPCEtLSA+MSBzZWxlY3RlZCAtLT5cclxuICAgIDxzcGFuXHJcbiAgICAgICpuZ0lmPVwic2VsZWN0ZWRSZXZpZXdlZEJ5Lmxlbmd0aCA+IDFcIlxyXG4gICAgICBjbGFzcz1cImQtZmxleCBhbGlnbi1pdGVtcy1jZW50ZXJcIlxyXG4gICAgPlxyXG4gICAgICA8c3Bhbj57eyBzZWxlY3RlZFJldmlld2VkQnlbMF0gfX08L3NwYW4+XHJcbiAgICAgIDxzcGFuIGNsYXNzPVwiYmFkZ2UgbXMtMlwiPlxyXG4gICAgICAgICt7eyBzZWxlY3RlZFJldmlld2VkQnkubGVuZ3RoIC0gMSB9fVxyXG4gICAgICA8L3NwYW4+XHJcbiAgICA8L3NwYW4+XHJcbiAgPC9kaXY+XHJcblxyXG4gIDwhLS0gRHJvcGRvd24gcGFuZWwgLS0+XHJcbiAgPGRpdlxyXG4gICAgKm5nSWY9XCJyZXZpZXdlckRyb3Bkb3duT3BlblwiXHJcbiAgICBjbGFzcz1cInBvc2l0aW9uLWFic29sdXRlIHctMTAwIGJvcmRlciByb3VuZGVkIGJnLXdoaXRlIHAtMSBtdC0xXCJcclxuICAgIHN0eWxlPVwiei1pbmRleDogMTAwMDsgbWF4LWhlaWdodDogMjIwcHg7IG92ZXJmbG93LXk6IGF1dG87XCJcclxuICAgIChjbGljayk9XCIkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcIlxyXG4gID5cclxuICAgIDwhLS0gU2VsZWN0IEFsbCAtLT5cclxuICAgIDxkaXYgY2xhc3M9XCJmb3JtLWNoZWNrIHB4LTAgbWItMiBkLWZsZXggYWxpZ24taXRlbXMtY2VudGVyXCI+XHJcbiAgICAgIDxpbnB1dFxyXG4gICAgICAgIHR5cGU9XCJjaGVja2JveFwiXHJcbiAgICAgICAgY2xhc3M9XCJmb3JtLWNoZWNrLWlucHV0XCJcclxuICAgICAgICBpZD1cInJldmlld2VyLWFsbFwiXHJcbiAgICAgICAgW2NoZWNrZWRdPVwiYXJlQWxsUmV2aWV3ZXJzU2VsZWN0ZWQoKVwiXHJcbiAgICAgICAgKGNoYW5nZSk9XCJvblJldmlld2VyU2VsZWN0QWxsKCRldmVudClcIlxyXG4gICAgICAvPlxyXG4gICAgICA8bGFiZWwgZm9yPVwicmV2aWV3ZXItYWxsXCIgY2xhc3M9XCJmb3JtLWNoZWNrLWxhYmVsIG1zLTJcIj5cclxuICAgICAgICBTZWxlY3QgQWxsXHJcbiAgICAgIDwvbGFiZWw+XHJcbiAgICA8L2Rpdj5cclxuXHJcbiAgICA8IS0tIE9wdGlvbnMgLS0+XHJcbiAgICA8ZGl2XHJcbiAgICAgIGNsYXNzPVwiZm9ybS1jaGVjayBtYi0xIHB4LTAgZC1mbGV4IGFsaWduLWl0ZW1zLWNlbnRlclwiXHJcbiAgICAgICpuZ0Zvcj1cImxldCB1IG9mIHVzZXJMaXN0XCJcclxuICAgID5cclxuICAgICAgPGlucHV0XHJcbiAgICAgICAgY2xhc3M9XCJmb3JtLWNoZWNrLWlucHV0XCJcclxuICAgICAgICB0eXBlPVwiY2hlY2tib3hcIlxyXG4gICAgICAgIFtpZF09XCIncmV2LScgKyB1LmVtYWlsXCJcclxuICAgICAgICBbY2hlY2tlZF09XCJpc1Jldmlld2VyU2VsZWN0ZWQodS5lbWFpbClcIlxyXG4gICAgICAgIChjaGFuZ2UpPVwib25SZXZpZXdlckNoYW5nZSgkZXZlbnQsIHUuZW1haWwpXCJcclxuICAgICAgLz5cclxuICAgICAgPGxhYmVsIGNsYXNzPVwiZm9ybS1jaGVjay1sYWJlbCBtcy0yXCIgW2Zvcl09XCIncmV2LScgKyB1LmVtYWlsXCI+XHJcbiAgICAgICAge3sgdS5lbWFpbCB9fVxyXG4gICAgICA8L2xhYmVsPlxyXG4gICAgPC9kaXY+XHJcbiAgPC9kaXY+XHJcbjwvZGl2PlxyXG5cclxuXHJcbiAgICAgIDwhLS0gQXBwcm92ZWQgQnkgLS0+XHJcbjxkaXZcclxuICBjbGFzcz1cIm1iLTMgcG9zaXRpb24tcmVsYXRpdmVcIlxyXG4gICpuZ0lmPVwic2hvd0FwcHJvdmVkQnlcIlxyXG4gIChjbGljayk9XCIkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcIlxyXG4+XHJcbiAgPGxhYmVsIGNsYXNzPVwiZm9ybS1sYWJlbFwiPkFwcHJvdmVkIGJ5PC9sYWJlbD5cclxuXHJcbiAgPCEtLSBUcmlnZ2VyIC8gZGlzcGxheSAtLT5cclxuICA8ZGl2XHJcbiAgICBjbGFzcz1cImJvcmRlciByb3VuZGVkIHB4LTMgcHktMiBkLWZsZXgganVzdGlmeS1jb250ZW50LWJldHdlZW4gYWxpZ24taXRlbXMtY2VudGVyXCJcclxuICAgIChjbGljayk9XCJ0b2dnbGVBcHByb3ZlckRyb3Bkb3duKCRldmVudClcIlxyXG4gID5cclxuICAgIDwhLS0gMCBzZWxlY3RlZCAtLT5cclxuICAgIDxzcGFuICpuZ0lmPVwiIXNlbGVjdGVkQXBwcm92ZWRCeS5sZW5ndGhcIj5cclxuICAgICAgU2VsZWN0XHJcbiAgICA8L3NwYW4+XHJcblxyXG4gICAgPCEtLSAxIHNlbGVjdGVkIC0tPlxyXG4gICAgPHNwYW4gKm5nSWY9XCJzZWxlY3RlZEFwcHJvdmVkQnkubGVuZ3RoID09PSAxXCI+XHJcbiAgICAgIHt7IHNlbGVjdGVkQXBwcm92ZWRCeVswXSB9fVxyXG4gICAgPC9zcGFuPlxyXG5cclxuICAgIDwhLS0gPjEgc2VsZWN0ZWQgLS0+XHJcbiAgICA8c3BhblxyXG4gICAgICAqbmdJZj1cInNlbGVjdGVkQXBwcm92ZWRCeS5sZW5ndGggPiAxXCJcclxuICAgICAgY2xhc3M9XCJkLWZsZXggYWxpZ24taXRlbXMtY2VudGVyXCJcclxuICAgID5cclxuICAgICAgPHNwYW4+e3sgc2VsZWN0ZWRBcHByb3ZlZEJ5WzBdIH19PC9zcGFuPlxyXG4gICAgICA8c3BhbiBjbGFzcz1cImJhZGdlIG1zLTJcIj5cclxuICAgICAgICAre3sgc2VsZWN0ZWRBcHByb3ZlZEJ5Lmxlbmd0aCAtIDEgfX1cclxuICAgICAgPC9zcGFuPlxyXG4gICAgPC9zcGFuPlxyXG5cclxuICA8L2Rpdj5cclxuXHJcbiAgPCEtLSBEcm9wZG93biBwYW5lbCAtLT5cclxuICA8ZGl2XHJcbiAgICAqbmdJZj1cImFwcHJvdmVyRHJvcGRvd25PcGVuXCJcclxuICAgIGNsYXNzPVwicG9zaXRpb24tYWJzb2x1dGUgdy0xMDAgYm9yZGVyIHJvdW5kZWQgYmctd2hpdGUgcC0yIG10LTFcIlxyXG4gICAgc3R5bGU9XCJ6LWluZGV4OiAxMDAwOyBtYXgtaGVpZ2h0OiAyMjBweDsgb3ZlcmZsb3cteTogYXV0bztcIlxyXG4gICAgKGNsaWNrKT1cIiRldmVudC5zdG9wUHJvcGFnYXRpb24oKVwiXHJcbiAgPlxyXG4gICAgPCEtLSBTZWxlY3QgQWxsIC0tPlxyXG4gICAgPGRpdiBjbGFzcz1cImZvcm0tY2hlY2sgcHgtMCBtYi0yIGQtZmxleCBhbGlnbi1pdGVtcy1jZW50ZXJcIj5cclxuICAgICAgPGlucHV0XHJcbiAgICAgICAgdHlwZT1cImNoZWNrYm94XCJcclxuICAgICAgICBjbGFzcz1cImZvcm0tY2hlY2staW5wdXRcIlxyXG4gICAgICAgIGlkPVwiYXBwcm92ZXItYWxsXCJcclxuICAgICAgICBbY2hlY2tlZF09XCJhcmVBbGxBcHByb3ZlcnNTZWxlY3RlZCgpXCJcclxuICAgICAgICAoY2hhbmdlKT1cIm9uQXBwcm92ZXJTZWxlY3RBbGwoJGV2ZW50KVwiXHJcbiAgICAgIC8+XHJcbiAgICAgIDxsYWJlbCBmb3I9XCJhcHByb3Zlci1hbGxcIiBjbGFzcz1cImZvcm0tY2hlY2stbGFiZWwgbXMtMlwiPlxyXG4gICAgICAgIFNlbGVjdCBBbGxcclxuICAgICAgPC9sYWJlbD5cclxuICAgIDwvZGl2PlxyXG5cclxuICAgIDwhLS0gT3B0aW9ucyAtLT5cclxuICAgIDxkaXZcclxuICAgICAgY2xhc3M9XCJmb3JtLWNoZWNrIG1iLTEgcHgtMCBkLWZsZXggYWxpZ24taXRlbXMtY2VudGVyXCJcclxuICAgICAgKm5nRm9yPVwibGV0IHUgb2YgdXNlckxpc3RcIlxyXG4gICAgPlxyXG4gICAgICA8aW5wdXRcclxuICAgICAgICBjbGFzcz1cImZvcm0tY2hlY2staW5wdXRcIlxyXG4gICAgICAgIHR5cGU9XCJjaGVja2JveFwiXHJcbiAgICAgICAgW2lkXT1cIidhcHAtJyArIHUuZW1haWxcIlxyXG4gICAgICAgIFtjaGVja2VkXT1cImlzQXBwcm92ZXJTZWxlY3RlZCh1LmVtYWlsKVwiXHJcbiAgICAgICAgKGNoYW5nZSk9XCJvbkFwcHJvdmVyQ2hhbmdlKCRldmVudCwgdS5lbWFpbClcIlxyXG4gICAgICAvPlxyXG4gICAgICA8bGFiZWwgY2xhc3M9XCJmb3JtLWNoZWNrLWxhYmVsIG1zLTJcIiBbZm9yXT1cIidhcHAtJyArIHUuZW1haWxcIj5cclxuICAgICAgICB7eyB1LmVtYWlsIH19XHJcbiAgICAgIDwvbGFiZWw+XHJcbiAgICA8L2Rpdj5cclxuICA8L2Rpdj5cclxuPC9kaXY+XHJcblxyXG5cclxuICAgICAgPCEtLSBGb290ZXIgYnV0dG9ucyAtLT5cclxuICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBqdXN0aWZ5LWNvbnRlbnQtYmV0d2VlbiB3LTEwMCBtdC00XCI+XHJcbiAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidG4gYnRuLW91dGxpbmUgdy01MCBtZS0xXCIgKGNsaWNrKT1cIm9uUmVzZXQoKVwiPlxyXG4gICAgICAgICAgUmVzZXRcclxuICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJ0biBidG4tcHJpbWFyeSB3LTUwIG1zLTFcIiAoY2xpY2spPVwib25BcHBseSgpXCI+XHJcbiAgICAgICAgICBBcHBseVxyXG4gICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICA8L2Rpdj5cclxuICAgIDwvZm9ybT5cclxuICA8L2Rpdj5cclxuPC9kaXY+XHJcbiJdfQ==