tango-app-ui-manage-settings 3.7.43 → 3.7.45

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.
@@ -0,0 +1,352 @@
1
+ import { Component } from '@angular/core';
2
+ import { of, Subject, timer } from 'rxjs';
3
+ import { catchError, distinctUntilChanged, map, switchMap, take, takeUntil } from 'rxjs/operators';
4
+ import * as i0 from "@angular/core";
5
+ import * as i1 from "../../../services/client-api.service";
6
+ import * as i2 from "tango-app-ui-global";
7
+ import * as i3 from "tango-app-ui-shared";
8
+ import * as i4 from "@angular/router";
9
+ import * as i5 from "@angular/common";
10
+ import * as i6 from "@ng-bootstrap/ng-bootstrap";
11
+ const PAGE_SIZES = [10, 20, 30];
12
+ const EXPIRY_SOON_DAYS = 30;
13
+ const POLL_MS = 15000;
14
+ const MAX_POLLS = 20;
15
+ /**
16
+ * Read-only list of the brand-level documents of the selected brand, shown under the KYC card on
17
+ * Settings > Documents. Same list endpoint and status rule as the Documents page; uploading and
18
+ * editing stay on that page. Shown only with the Global > Documents View permission.
19
+ */
20
+ export class BrandDocumentsComponent {
21
+ apiService;
22
+ gs;
23
+ toast;
24
+ router;
25
+ cd;
26
+ canView = false;
27
+ clientId = '';
28
+ documents = [];
29
+ loading = false;
30
+ noData = false;
31
+ configured = true;
32
+ pagination = { offset: 1, limit: 10, totalCount: 0 };
33
+ paginationSizes = PAGE_SIZES;
34
+ /** Row whose signed link is being prepared; its actions are disabled meanwhile. */
35
+ busyId = null;
36
+ statusLabels = {
37
+ processing: 'Processing',
38
+ valid: 'Valid',
39
+ expiring_soon: 'Expiring soon',
40
+ expired: 'Expired',
41
+ no_expiry: 'No expiry',
42
+ };
43
+ statusBadge = {
44
+ processing: 'blue-badge',
45
+ valid: 'green-badge',
46
+ expiring_soon: 'yellow-badge',
47
+ expired: 'red-badge',
48
+ no_expiry: 'gray-badge',
49
+ };
50
+ pollSub;
51
+ clientSub;
52
+ reload$ = new Subject();
53
+ destroy$ = new Subject();
54
+ constructor(apiService, gs, toast, router, cd) {
55
+ this.apiService = apiService;
56
+ this.gs = gs;
57
+ this.toast = toast;
58
+ this.router = router;
59
+ this.cd = cd;
60
+ // One pipeline, so brand, paging and poll triggers never race each other.
61
+ this.reload$.pipe(switchMap((silent) => {
62
+ if (!silent) {
63
+ this.loading = true;
64
+ this.noData = false;
65
+ this.cd.detectChanges();
66
+ }
67
+ return this.apiService.listDocuments(this.buildQuery()).pipe(map((res) => ({ res, failed: false })), catchError((err) => {
68
+ this.toast.getErrorToast(err?.error?.error || err?.error?.message || 'Could not load documents');
69
+ return of({ res: null, failed: true });
70
+ }));
71
+ }), takeUntil(this.destroy$)).subscribe(({ res, failed }) => {
72
+ this.loading = false;
73
+ if (failed || !res || res.code !== 200) {
74
+ this.documents = [];
75
+ this.noData = true;
76
+ this.cd.detectChanges();
77
+ return;
78
+ }
79
+ this.documents = res.data?.result || [];
80
+ const count = res.data?.count || 0;
81
+ this.pagination = { ...this.pagination, totalCount: count };
82
+ this.paginationSizes = count < 10 ? [count] : PAGE_SIZES;
83
+ this.noData = this.documents.length === 0;
84
+ this.cd.detectChanges();
85
+ this.managePolling();
86
+ });
87
+ }
88
+ ngOnInit() {
89
+ this.configured = this.apiService.isDocumentsConfigured;
90
+ // Access is the Global > Documents View permission; it arrives with the profile call.
91
+ this.gs.userAccess.pipe(takeUntil(this.destroy$)).subscribe((access) => {
92
+ const canView = access?.Global_Documents_isAdd === true;
93
+ if (canView === this.canView) {
94
+ return;
95
+ }
96
+ this.canView = canView;
97
+ if (canView) {
98
+ this.watchClient();
99
+ }
100
+ else {
101
+ this.stopPolling();
102
+ this.clientSub?.unsubscribe();
103
+ this.clientSub = undefined;
104
+ }
105
+ this.cd.detectChanges();
106
+ });
107
+ }
108
+ ngOnDestroy() {
109
+ this.stopPolling();
110
+ this.destroy$.next();
111
+ this.destroy$.complete();
112
+ }
113
+ /** The selected brand: header dropdown for tango users, own client for client users. */
114
+ watchClient() {
115
+ this.clientSub?.unsubscribe();
116
+ this.clientSub = this.apiService.clientId
117
+ .pipe(map((id) => this.resolveClientId(id)), distinctUntilChanged(), takeUntil(this.destroy$))
118
+ .subscribe((clientId) => {
119
+ this.clientId = clientId;
120
+ this.stopPolling();
121
+ if (!this.configured || !clientId) {
122
+ this.documents = [];
123
+ this.noData = true;
124
+ this.cd.detectChanges();
125
+ return;
126
+ }
127
+ this.pagination.offset = 1;
128
+ this.load();
129
+ });
130
+ }
131
+ /** Client users always query their own client, whatever the header holds. */
132
+ resolveClientId(headerClient) {
133
+ let user = {};
134
+ try {
135
+ user = JSON.parse(localStorage.getItem('user-info') || '{}');
136
+ }
137
+ catch {
138
+ user = {};
139
+ }
140
+ if (user?.userType === 'client' && user?.clientId) {
141
+ return String(user.clientId);
142
+ }
143
+ return headerClient ? String(headerClient) : '';
144
+ }
145
+ buildQuery() {
146
+ return {
147
+ clientId: this.clientId,
148
+ scope: 'brand',
149
+ sortColumn: 'createdAt',
150
+ sortBy: -1,
151
+ offset: this.pagination.offset,
152
+ limit: this.pagination.limit,
153
+ };
154
+ }
155
+ load(silent = false) {
156
+ this.reload$.next(silent);
157
+ }
158
+ // ---------- processing refresh ----------
159
+ /** While any row is still being processed, silently refresh every 15 s, capped at 20 polls. */
160
+ managePolling() {
161
+ const processing = this.documents.some((d) => d.ocrStatus === 'processing');
162
+ if (!processing) {
163
+ this.stopPolling();
164
+ return;
165
+ }
166
+ if (this.pollSub) {
167
+ return;
168
+ }
169
+ this.pollSub = timer(POLL_MS, POLL_MS)
170
+ .pipe(take(MAX_POLLS), takeUntil(this.destroy$))
171
+ .subscribe(() => this.load(true));
172
+ }
173
+ stopPolling() {
174
+ this.pollSub?.unsubscribe();
175
+ this.pollSub = undefined;
176
+ }
177
+ // ---------- paging ----------
178
+ onPageChange(page) {
179
+ this.pagination.offset = Number(page);
180
+ this.stopPolling();
181
+ this.load();
182
+ }
183
+ onPageSizeChange(size) {
184
+ this.pagination.limit = Number(size);
185
+ this.pagination.offset = 1;
186
+ this.stopPolling();
187
+ this.load();
188
+ }
189
+ paginationSize() {
190
+ return this.pagination.totalCount < 10 ? this.pagination.totalCount : this.pagination.limit;
191
+ }
192
+ // ---------- actions ----------
193
+ goToDocuments() {
194
+ this.router.navigate(['/manage/documents'], { queryParams: { tab: 'brand' } });
195
+ }
196
+ /** Opens the file in a new tab. The tab is opened on the click itself so popup blockers allow it. */
197
+ openDocument(doc) {
198
+ if (this.busyId) {
199
+ return;
200
+ }
201
+ const tab = window.open('', '_blank');
202
+ if (tab) {
203
+ tab.opener = null;
204
+ }
205
+ this.busyId = doc._id;
206
+ this.apiService.getDocumentUrl(this.clientId, doc._id, false)
207
+ .pipe(takeUntil(this.destroy$))
208
+ .subscribe({
209
+ next: (res) => {
210
+ this.busyId = null;
211
+ const url = res?.data?.url;
212
+ if (url && tab) {
213
+ tab.location.href = url;
214
+ }
215
+ else {
216
+ tab?.close();
217
+ this.toast.getErrorToast('Could not open the file');
218
+ }
219
+ this.cd.detectChanges();
220
+ },
221
+ error: (err) => {
222
+ this.busyId = null;
223
+ tab?.close();
224
+ this.toast.getErrorToast(err?.error?.error || err?.error?.message || 'Could not open the file');
225
+ this.cd.detectChanges();
226
+ },
227
+ });
228
+ }
229
+ /** Asks for an attachment link so the browser saves the file instead of opening it. */
230
+ downloadDocument(doc) {
231
+ if (this.busyId) {
232
+ return;
233
+ }
234
+ this.busyId = doc._id;
235
+ this.apiService.getDocumentUrl(this.clientId, doc._id, true)
236
+ .pipe(takeUntil(this.destroy$))
237
+ .subscribe({
238
+ next: (res) => {
239
+ this.busyId = null;
240
+ const url = res?.data?.url;
241
+ if (url) {
242
+ const link = document.createElement('a');
243
+ link.href = url;
244
+ link.rel = 'noopener';
245
+ document.body.appendChild(link);
246
+ link.click();
247
+ link.remove();
248
+ }
249
+ else {
250
+ this.toast.getErrorToast('Could not download the file');
251
+ }
252
+ this.cd.detectChanges();
253
+ },
254
+ error: (err) => {
255
+ this.busyId = null;
256
+ this.toast.getErrorToast(err?.error?.error || err?.error?.message || 'Could not download the file');
257
+ this.cd.detectChanges();
258
+ },
259
+ });
260
+ }
261
+ // ---------- cell helpers ----------
262
+ trackById(_, doc) {
263
+ return doc._id;
264
+ }
265
+ fileKind(ext) {
266
+ switch ((ext || '').toLowerCase()) {
267
+ case 'pdf': return 'pdf';
268
+ case 'jpg':
269
+ case 'jpeg':
270
+ case 'png': return 'image';
271
+ default: return 'other';
272
+ }
273
+ }
274
+ formatFileSize(bytes) {
275
+ if (!bytes || bytes <= 0) {
276
+ return '-';
277
+ }
278
+ if (bytes < 1024) {
279
+ return `${bytes} B`;
280
+ }
281
+ if (bytes < 1024 * 1024) {
282
+ return `${Math.round(bytes / 1024)} KB`;
283
+ }
284
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
285
+ }
286
+ /** Whole days from today (local) to a 'YYYY-MM-DD' date; negative when in the past. */
287
+ daysUntil(date) {
288
+ if (!date) {
289
+ return null;
290
+ }
291
+ const target = new Date(`${date.slice(0, 10)}T00:00:00`);
292
+ if (isNaN(target.getTime())) {
293
+ return null;
294
+ }
295
+ const today = new Date();
296
+ today.setHours(0, 0, 0, 0);
297
+ return Math.round((target.getTime() - today.getTime()) / 86400000);
298
+ }
299
+ /** Same rule as the Documents page badge and the mobile list. */
300
+ statusOf(doc) {
301
+ if (doc.ocrStatus === 'processing') {
302
+ return 'processing';
303
+ }
304
+ const days = this.daysUntil(doc.expiryDate);
305
+ if (days === null) {
306
+ return 'no_expiry';
307
+ }
308
+ if (days < 0) {
309
+ return 'expired';
310
+ }
311
+ if (days <= EXPIRY_SOON_DAYS) {
312
+ return 'expiring_soon';
313
+ }
314
+ return 'valid';
315
+ }
316
+ expiryText(doc) {
317
+ const days = this.daysUntil(doc.expiryDate);
318
+ if (days === null) {
319
+ return 'No validity date';
320
+ }
321
+ if (days === 0) {
322
+ return 'Expires today';
323
+ }
324
+ if (days < 0) {
325
+ return `Expired ${Math.abs(days)} day${Math.abs(days) === 1 ? '' : 's'} ago`;
326
+ }
327
+ return `${days} day${days === 1 ? '' : 's'} left`;
328
+ }
329
+ isExpired(doc) {
330
+ const days = this.daysUntil(doc.expiryDate);
331
+ return days !== null && days < 0;
332
+ }
333
+ /** Which stores see the file: all of them, or the chosen few. */
334
+ sharedText(doc) {
335
+ const n = doc.storeIds?.length || 0;
336
+ return n ? `${n} store${n === 1 ? '' : 's'}` : 'All stores';
337
+ }
338
+ sharedTooltip(doc) {
339
+ if (!doc.storeIds?.length) {
340
+ return '';
341
+ }
342
+ const names = doc.storeNames?.length ? doc.storeNames : doc.storeIds;
343
+ return names.slice(0, 15).join(', ') + (names.length > 15 ? ` +${names.length - 15} more` : '');
344
+ }
345
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: BrandDocumentsComponent, deps: [{ token: i1.ClientApiService }, { token: i2.GlobalStateService }, { token: i3.ToastService }, { token: i4.Router }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
346
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: BrandDocumentsComponent, selector: "lib-brand-documents", ngImport: i0, template: "<div *ngIf=\"canView\" class=\"documents-card\">\r\n <div class=\"d-flex justify-content-between align-items-start flex-wrap gap-3 mb-6\">\r\n <div>\r\n <div class=\"header\">Brand documents <span *ngIf=\"configured && !loading\" class=\"blue-badge ms-2\">{{ pagination.totalCount }}</span></div>\r\n <div class=\"sub-text\">Files uploaded at brand level and shared with stores. Upload and edit them on the Documents page.</div>\r\n </div>\r\n <div class=\"d-flex align-items-center flex-shrink-0\">\r\n <button type=\"button\" (click)=\"load()\" [disabled]=\"loading || !configured\"\r\n class=\"btn btn-default btn-outline btn-outline-default rounded-3 toolbar-control me-3\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\">\r\n <path d=\"M21 12a9 9 0 1 1-2.64-6.36M21 3v6h-6\" stroke=\"#344054\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </svg>\r\n <span>Refresh</span>\r\n </button>\r\n <button type=\"button\" (click)=\"goToDocuments()\" class=\"btn btn-outline rounded-3 toolbar-control toolbar-control--primary\">\r\n <span>Open Documents</span>\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\">\r\n <path d=\"M7 17 17 7M8 7h9v9\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"!configured\" class=\"empty-state\">\r\n <div class=\"text-sub\">Documents API URL is not configured.</div>\r\n </div>\r\n\r\n <ng-container *ngIf=\"configured\">\r\n <div *ngIf=\"!loading && !noData\" class=\"table-responsive\">\r\n <table class=\"table bottom-border text-nowrap\">\r\n <thead>\r\n <tr>\r\n <th>Document</th>\r\n <th>Document ID</th>\r\n <th>Type</th>\r\n <th>Available to</th>\r\n <th>Valid till</th>\r\n <th>Status</th>\r\n <th>Uploaded</th>\r\n <th>Actions</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr *ngFor=\"let doc of documents; trackBy: trackById\">\r\n <td>\r\n <div class=\"d-flex align-items-center\">\r\n <span class=\"file-badge file-badge--{{ fileKind(doc.extension) }}\">{{ doc.extension || 'file' }}</span>\r\n <div class=\"ms-3 file-cell\">\r\n <div class=\"table-title text-truncate\" [ngbTooltip]=\"doc.fileName\" container=\"body\">{{ doc.fileName }}</div>\r\n <div class=\"table-sub\">{{ formatFileSize(doc.fileSize) }}</div>\r\n </div>\r\n </div>\r\n </td>\r\n <td><span class=\"doc-code\">{{ doc.documentCode || '-' }}</span></td>\r\n <td>\r\n <ng-container *ngIf=\"doc.ocrStatus === 'processing'\">\r\n <span class=\"text-sub\"><span class=\"spinner-border spinner-border-sm me-2\" role=\"status\"></span>Detecting...</span>\r\n </ng-container>\r\n <ng-container *ngIf=\"doc.ocrStatus === 'failed'\">\r\n <span class=\"text-sub\">{{ doc.type || 'Not detected' }}</span>\r\n </ng-container>\r\n <ng-container *ngIf=\"doc.ocrStatus === 'done'\">{{ doc.type || '-' }}</ng-container>\r\n </td>\r\n <td>\r\n <span [ngClass]=\"doc.storeIds?.length ? 'gray-badge' : 'blue-badge'\" [ngbTooltip]=\"sharedTooltip(doc)\" container=\"body\">{{ sharedText(doc) }}</span>\r\n </td>\r\n <td>\r\n <ng-container *ngIf=\"doc.ocrStatus === 'processing'; else expiryCell\">\r\n <span class=\"text-sub\">Detecting...</span>\r\n </ng-container>\r\n <ng-template #expiryCell>\r\n <ng-container *ngIf=\"doc.expiryDate; else noExpiry\">\r\n <div class=\"table-title\">{{ doc.expiryDate | customDateFormat }}</div>\r\n <div class=\"table-sub\" [class.text-danger]=\"isExpired(doc)\">{{ expiryText(doc) }}</div>\r\n </ng-container>\r\n <ng-template #noExpiry>\r\n <div class=\"table-title\">No expiry</div>\r\n <div class=\"table-sub\">No validity date</div>\r\n </ng-template>\r\n </ng-template>\r\n </td>\r\n <td><span [ngClass]=\"statusBadge[statusOf(doc)]\">{{ statusLabels[statusOf(doc)] }}</span></td>\r\n <td>\r\n <div class=\"table-title\">{{ doc.createdAt | customDateFormat }}</div>\r\n <div class=\"table-sub\">{{ doc.uploadedBy?.name || 'NA' }}</div>\r\n </td>\r\n <td class=\"text-nowrap\">\r\n <div class=\"d-flex align-items-center gap-1\">\r\n <a class=\"action-icon\" [class.action-icon--busy]=\"busyId === doc._id\" ngbTooltip=\"View\" container=\"body\" (click)=\"openDocument(doc)\">\r\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z\" stroke-width=\"1.7\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z\" stroke-width=\"1.7\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\r\n </a>\r\n <a class=\"action-icon\" [class.action-icon--busy]=\"busyId === doc._id\" ngbTooltip=\"Download\" container=\"body\" (click)=\"downloadDocument(doc)\">\r\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5M16.5 12 12 16.5m0 0L7.5 12m4.5 4.5V3\" stroke-width=\"1.7\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\r\n </a>\r\n </div>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n <div *ngIf=\"!loading && !noData\" class=\"mt-6\">\r\n <lib-pagination [itemsPerPage]=\"pagination.limit\" [currentPage]=\"pagination.offset\" [totalItems]=\"pagination.totalCount\"\r\n [paginationSizes]=\"paginationSizes\" [pageSize]=\"paginationSize()\"\r\n (pageChange)=\"onPageChange($event)\" (pageSizeChange)=\"onPageSizeChange($event)\"></lib-pagination>\r\n </div>\r\n\r\n <div *ngIf=\"loading\" class=\"row loader d-flex justify-content-center align-items-center\">\r\n <div class=\"shimmer\">\r\n <div class=\"wrapper\">\r\n <div class=\"stroke animate title\"></div>\r\n <div class=\"stroke animate link\"></div>\r\n <div class=\"stroke animate description\"></div>\r\n </div>\r\n </div>\r\n <div class=\"shimmer\">\r\n <div class=\"wrapper\">\r\n <div class=\"stroke animate title\"></div>\r\n <div class=\"stroke animate link\"></div>\r\n <div class=\"stroke animate description\"></div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"!loading && noData\" class=\"empty-state\">\r\n <img class=\"img-src\" src=\"./assets/tango/Icons/Nodata.svg\" alt=\"\">\r\n <div class=\"text-sub mt-3\">No brand documents uploaded yet</div>\r\n </div>\r\n </ng-container>\r\n</div>\r\n", styles: [".documents-card{border-radius:10px;background:#fff;padding:16px}.header{color:var(--Gray-700, #344054);font-family:Inter;font-size:18px;font-weight:600;line-height:28px}.header .blue-badge{vertical-align:middle}.sub-text{color:var(--Gray-500, #667085);font-size:14px;line-height:20px;margin-top:2px}.toolbar-control{height:40px!important;display:inline-flex!important;align-items:center;gap:8px;padding:0 16px!important;font-size:14px!important;font-weight:600!important;line-height:20px!important;white-space:nowrap;color:var(--Gray-700, #344054)!important;transition:background-color .15s ease,border-color .15s ease}.toolbar-control svg{flex-shrink:0}.toolbar-control--primary{color:var(--Primary-700, #009BF3)!important;border-color:#a6e0ff!important}.toolbar-control--primary:hover{background:var(--Primary-50, #EAF8FF)!important}td{vertical-align:middle}.text-sub{color:var(--Gray-500, #667085)!important;font-size:14px!important;font-weight:400!important;line-height:20px}.table-title{color:var(--Gray-700, #344054);font-size:14px;font-weight:500;line-height:20px}.table-sub{line-height:20px!important;color:var(--Gray-500, #667085)!important;font-size:13px}.file-cell{max-width:260px}.doc-code{font-size:13px;font-weight:500;color:var(--Gray-700, #344054);letter-spacing:.2px}.gray-badge,.red-badge,.blue-badge,.yellow-badge,.green-badge{font-size:12px;font-weight:500;line-height:18px;border-radius:16px;padding:2px 8px;white-space:nowrap}.green-badge{color:#027a48;background:#ecfdf3}.yellow-badge{color:#b54708;background:#fffaeb}.blue-badge{color:#009bf3;background:#eaf8ff}.red-badge{color:#b42318;background:#fef3f2}.gray-badge{color:#344054;background:#f2f4f7}.file-badge{display:inline-block;min-width:40px;text-align:center;padding:3px 6px;border-radius:4px;font-size:11px;font-weight:700;text-transform:uppercase;color:#667085;background:#eaecf0}.file-badge--pdf{color:#b42318;background:#fef3f2}.file-badge--image{color:#6941c6;background:#f4f3ff}.action-icon{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;border-radius:6px;cursor:pointer;color:var(--Gray-500, #667085);transition:background-color .15s ease,color .15s ease}.action-icon svg{width:18px;height:18px;stroke:currentColor}.action-icon:hover{background:#f2f4f7;color:var(--Primary-700, #009BF3)}.action-icon--busy{opacity:.5;pointer-events:none}.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:40px 0}.empty-state .img-src{width:25%;height:50%}@media (prefers-reduced-motion: reduce){.toolbar-control,.action-icon{transition:none}}\n"], dependencies: [{ kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i6.NgbTooltip, selector: "[ngbTooltip]", inputs: ["animation", "autoClose", "placement", "popperOptions", "triggers", "positionTarget", "container", "disableTooltip", "tooltipClass", "tooltipContext", "openDelay", "closeDelay", "ngbTooltip"], outputs: ["shown", "hidden"], exportAs: ["ngbTooltip"] }, { kind: "component", type: i3.PaginationComponent, selector: "lib-pagination", inputs: ["collection", "itemsPerPage", "currentPage", "totalItems", "directionLinks", "pageSize", "paginationSizes"], outputs: ["pageChange", "pageSizeChange"] }, { kind: "pipe", type: i3.CustomDateFormatPipe, name: "customDateFormat" }] });
347
+ }
348
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: BrandDocumentsComponent, decorators: [{
349
+ type: Component,
350
+ args: [{ selector: 'lib-brand-documents', template: "<div *ngIf=\"canView\" class=\"documents-card\">\r\n <div class=\"d-flex justify-content-between align-items-start flex-wrap gap-3 mb-6\">\r\n <div>\r\n <div class=\"header\">Brand documents <span *ngIf=\"configured && !loading\" class=\"blue-badge ms-2\">{{ pagination.totalCount }}</span></div>\r\n <div class=\"sub-text\">Files uploaded at brand level and shared with stores. Upload and edit them on the Documents page.</div>\r\n </div>\r\n <div class=\"d-flex align-items-center flex-shrink-0\">\r\n <button type=\"button\" (click)=\"load()\" [disabled]=\"loading || !configured\"\r\n class=\"btn btn-default btn-outline btn-outline-default rounded-3 toolbar-control me-3\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\">\r\n <path d=\"M21 12a9 9 0 1 1-2.64-6.36M21 3v6h-6\" stroke=\"#344054\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </svg>\r\n <span>Refresh</span>\r\n </button>\r\n <button type=\"button\" (click)=\"goToDocuments()\" class=\"btn btn-outline rounded-3 toolbar-control toolbar-control--primary\">\r\n <span>Open Documents</span>\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\">\r\n <path d=\"M7 17 17 7M8 7h9v9\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"!configured\" class=\"empty-state\">\r\n <div class=\"text-sub\">Documents API URL is not configured.</div>\r\n </div>\r\n\r\n <ng-container *ngIf=\"configured\">\r\n <div *ngIf=\"!loading && !noData\" class=\"table-responsive\">\r\n <table class=\"table bottom-border text-nowrap\">\r\n <thead>\r\n <tr>\r\n <th>Document</th>\r\n <th>Document ID</th>\r\n <th>Type</th>\r\n <th>Available to</th>\r\n <th>Valid till</th>\r\n <th>Status</th>\r\n <th>Uploaded</th>\r\n <th>Actions</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr *ngFor=\"let doc of documents; trackBy: trackById\">\r\n <td>\r\n <div class=\"d-flex align-items-center\">\r\n <span class=\"file-badge file-badge--{{ fileKind(doc.extension) }}\">{{ doc.extension || 'file' }}</span>\r\n <div class=\"ms-3 file-cell\">\r\n <div class=\"table-title text-truncate\" [ngbTooltip]=\"doc.fileName\" container=\"body\">{{ doc.fileName }}</div>\r\n <div class=\"table-sub\">{{ formatFileSize(doc.fileSize) }}</div>\r\n </div>\r\n </div>\r\n </td>\r\n <td><span class=\"doc-code\">{{ doc.documentCode || '-' }}</span></td>\r\n <td>\r\n <ng-container *ngIf=\"doc.ocrStatus === 'processing'\">\r\n <span class=\"text-sub\"><span class=\"spinner-border spinner-border-sm me-2\" role=\"status\"></span>Detecting...</span>\r\n </ng-container>\r\n <ng-container *ngIf=\"doc.ocrStatus === 'failed'\">\r\n <span class=\"text-sub\">{{ doc.type || 'Not detected' }}</span>\r\n </ng-container>\r\n <ng-container *ngIf=\"doc.ocrStatus === 'done'\">{{ doc.type || '-' }}</ng-container>\r\n </td>\r\n <td>\r\n <span [ngClass]=\"doc.storeIds?.length ? 'gray-badge' : 'blue-badge'\" [ngbTooltip]=\"sharedTooltip(doc)\" container=\"body\">{{ sharedText(doc) }}</span>\r\n </td>\r\n <td>\r\n <ng-container *ngIf=\"doc.ocrStatus === 'processing'; else expiryCell\">\r\n <span class=\"text-sub\">Detecting...</span>\r\n </ng-container>\r\n <ng-template #expiryCell>\r\n <ng-container *ngIf=\"doc.expiryDate; else noExpiry\">\r\n <div class=\"table-title\">{{ doc.expiryDate | customDateFormat }}</div>\r\n <div class=\"table-sub\" [class.text-danger]=\"isExpired(doc)\">{{ expiryText(doc) }}</div>\r\n </ng-container>\r\n <ng-template #noExpiry>\r\n <div class=\"table-title\">No expiry</div>\r\n <div class=\"table-sub\">No validity date</div>\r\n </ng-template>\r\n </ng-template>\r\n </td>\r\n <td><span [ngClass]=\"statusBadge[statusOf(doc)]\">{{ statusLabels[statusOf(doc)] }}</span></td>\r\n <td>\r\n <div class=\"table-title\">{{ doc.createdAt | customDateFormat }}</div>\r\n <div class=\"table-sub\">{{ doc.uploadedBy?.name || 'NA' }}</div>\r\n </td>\r\n <td class=\"text-nowrap\">\r\n <div class=\"d-flex align-items-center gap-1\">\r\n <a class=\"action-icon\" [class.action-icon--busy]=\"busyId === doc._id\" ngbTooltip=\"View\" container=\"body\" (click)=\"openDocument(doc)\">\r\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z\" stroke-width=\"1.7\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z\" stroke-width=\"1.7\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\r\n </a>\r\n <a class=\"action-icon\" [class.action-icon--busy]=\"busyId === doc._id\" ngbTooltip=\"Download\" container=\"body\" (click)=\"downloadDocument(doc)\">\r\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5M16.5 12 12 16.5m0 0L7.5 12m4.5 4.5V3\" stroke-width=\"1.7\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\r\n </a>\r\n </div>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n <div *ngIf=\"!loading && !noData\" class=\"mt-6\">\r\n <lib-pagination [itemsPerPage]=\"pagination.limit\" [currentPage]=\"pagination.offset\" [totalItems]=\"pagination.totalCount\"\r\n [paginationSizes]=\"paginationSizes\" [pageSize]=\"paginationSize()\"\r\n (pageChange)=\"onPageChange($event)\" (pageSizeChange)=\"onPageSizeChange($event)\"></lib-pagination>\r\n </div>\r\n\r\n <div *ngIf=\"loading\" class=\"row loader d-flex justify-content-center align-items-center\">\r\n <div class=\"shimmer\">\r\n <div class=\"wrapper\">\r\n <div class=\"stroke animate title\"></div>\r\n <div class=\"stroke animate link\"></div>\r\n <div class=\"stroke animate description\"></div>\r\n </div>\r\n </div>\r\n <div class=\"shimmer\">\r\n <div class=\"wrapper\">\r\n <div class=\"stroke animate title\"></div>\r\n <div class=\"stroke animate link\"></div>\r\n <div class=\"stroke animate description\"></div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"!loading && noData\" class=\"empty-state\">\r\n <img class=\"img-src\" src=\"./assets/tango/Icons/Nodata.svg\" alt=\"\">\r\n <div class=\"text-sub mt-3\">No brand documents uploaded yet</div>\r\n </div>\r\n </ng-container>\r\n</div>\r\n", styles: [".documents-card{border-radius:10px;background:#fff;padding:16px}.header{color:var(--Gray-700, #344054);font-family:Inter;font-size:18px;font-weight:600;line-height:28px}.header .blue-badge{vertical-align:middle}.sub-text{color:var(--Gray-500, #667085);font-size:14px;line-height:20px;margin-top:2px}.toolbar-control{height:40px!important;display:inline-flex!important;align-items:center;gap:8px;padding:0 16px!important;font-size:14px!important;font-weight:600!important;line-height:20px!important;white-space:nowrap;color:var(--Gray-700, #344054)!important;transition:background-color .15s ease,border-color .15s ease}.toolbar-control svg{flex-shrink:0}.toolbar-control--primary{color:var(--Primary-700, #009BF3)!important;border-color:#a6e0ff!important}.toolbar-control--primary:hover{background:var(--Primary-50, #EAF8FF)!important}td{vertical-align:middle}.text-sub{color:var(--Gray-500, #667085)!important;font-size:14px!important;font-weight:400!important;line-height:20px}.table-title{color:var(--Gray-700, #344054);font-size:14px;font-weight:500;line-height:20px}.table-sub{line-height:20px!important;color:var(--Gray-500, #667085)!important;font-size:13px}.file-cell{max-width:260px}.doc-code{font-size:13px;font-weight:500;color:var(--Gray-700, #344054);letter-spacing:.2px}.gray-badge,.red-badge,.blue-badge,.yellow-badge,.green-badge{font-size:12px;font-weight:500;line-height:18px;border-radius:16px;padding:2px 8px;white-space:nowrap}.green-badge{color:#027a48;background:#ecfdf3}.yellow-badge{color:#b54708;background:#fffaeb}.blue-badge{color:#009bf3;background:#eaf8ff}.red-badge{color:#b42318;background:#fef3f2}.gray-badge{color:#344054;background:#f2f4f7}.file-badge{display:inline-block;min-width:40px;text-align:center;padding:3px 6px;border-radius:4px;font-size:11px;font-weight:700;text-transform:uppercase;color:#667085;background:#eaecf0}.file-badge--pdf{color:#b42318;background:#fef3f2}.file-badge--image{color:#6941c6;background:#f4f3ff}.action-icon{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;border-radius:6px;cursor:pointer;color:var(--Gray-500, #667085);transition:background-color .15s ease,color .15s ease}.action-icon svg{width:18px;height:18px;stroke:currentColor}.action-icon:hover{background:#f2f4f7;color:var(--Primary-700, #009BF3)}.action-icon--busy{opacity:.5;pointer-events:none}.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:40px 0}.empty-state .img-src{width:25%;height:50%}@media (prefers-reduced-motion: reduce){.toolbar-control,.action-icon{transition:none}}\n"] }]
351
+ }], ctorParameters: () => [{ type: i1.ClientApiService }, { type: i2.GlobalStateService }, { type: i3.ToastService }, { type: i4.Router }, { type: i0.ChangeDetectorRef }] });
352
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnJhbmQtZG9jdW1lbnRzLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3RhbmdvLW1hbmFnZS1zZXR0aW5ncy9zcmMvbGliL2NvbXBvbmVudHMvZG9jdW1lbnRzL2JyYW5kLWRvY3VtZW50cy9icmFuZC1kb2N1bWVudHMuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvdGFuZ28tbWFuYWdlLXNldHRpbmdzL3NyYy9saWIvY29tcG9uZW50cy9kb2N1bWVudHMvYnJhbmQtZG9jdW1lbnRzL2JyYW5kLWRvY3VtZW50cy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQXFCLFNBQVMsRUFBcUIsTUFBTSxlQUFlLENBQUM7QUFFaEYsT0FBTyxFQUFFLEVBQUUsRUFBRSxPQUFPLEVBQWdCLEtBQUssRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUN4RCxPQUFPLEVBQUUsVUFBVSxFQUFFLG9CQUFvQixFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDOzs7Ozs7OztBQTBCbkcsTUFBTSxVQUFVLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0FBQ2hDLE1BQU0sZ0JBQWdCLEdBQUcsRUFBRSxDQUFDO0FBQzVCLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQztBQUN0QixNQUFNLFNBQVMsR0FBRyxFQUFFLENBQUM7QUFFckI7Ozs7R0FJRztBQU1ILE1BQU0sT0FBTyx1QkFBdUI7SUFpQ3hCO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFwQ1YsT0FBTyxHQUFHLEtBQUssQ0FBQztJQUNoQixRQUFRLEdBQUcsRUFBRSxDQUFDO0lBQ2QsU0FBUyxHQUF1QixFQUFFLENBQUM7SUFDbkMsT0FBTyxHQUFHLEtBQUssQ0FBQztJQUNoQixNQUFN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O1FBQzlCLE1BQU0sQ0FBQyxHQUFHLEdBQUcsQ0FBQyxRQUFRLEVBQUUsTUFBTSxJQUFJLENBQUMsQ0FBQztRQUNwQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDO0lBQzlELENBQUM7SUFFRCxhQUFhLENBQUMsR0FBcUI7UUFDakMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsTUFBTSxFQUFFO1lBQUUsT0FBTyxFQUFFLENBQUM7U0FBRTtRQUN6QyxNQUFNLEtBQUssR0FBRyxHQUFHLENBQUMsVUFBVSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQztRQUNyRSxPQUFPLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLEtBQUssQ0FBQyxNQUFNLEdBQUcsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ2xHLENBQUM7d0dBeFRVLHVCQUF1Qjs0RkFBdkIsdUJBQXVCLDJEQzVDcEMsaXNSQWtJQTs7NEZEdEZhLHVCQUF1QjtrQkFMbkMsU0FBUzsrQkFDRSxxQkFBcUIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDaGFuZ2VEZXRlY3RvclJlZiwgQ29tcG9uZW50LCBPbkRlc3Ryb3ksIE9uSW5pdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBSb3V0ZXIgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xyXG5pbXBvcnQgeyBvZiwgU3ViamVjdCwgU3Vic2NyaXB0aW9uLCB0aW1lciB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyBjYXRjaEVycm9yLCBkaXN0aW5jdFVudGlsQ2hhbmdlZCwgbWFwLCBzd2l0Y2hNYXAsIHRha2UsIHRha2VVbnRpbCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcclxuaW1wb3J0IHsgVG9hc3RTZXJ2aWNlIH0gZnJvbSAndGFuZ28tYXBwLXVpLXNoYXJlZCc7XHJcbmltcG9ydCB7IEdsb2JhbFN0YXRlU2VydmljZSB9IGZyb20gJ3RhbmdvLWFwcC11aS1nbG9iYWwnO1xyXG5pbXBvcnQgeyBDbGllbnRBcGlTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vLi4vc2VydmljZXMvY2xpZW50LWFwaS5zZXJ2aWNlJztcclxuXHJcbnR5cGUgRG9jdW1lbnRTdGF0dXMgPSAncHJvY2Vzc2luZycgfCAndmFsaWQnIHwgJ2V4cGlyaW5nX3Nvb24nIHwgJ2V4cGlyZWQnIHwgJ25vX2V4cGlyeSc7XHJcbnR5cGUgRmlsZUtpbmQgPSAncGRmJyB8ICdpbWFnZScgfCAnb3RoZXInO1xyXG5cclxuLyoqIFJvdyBzaGFwZSBvZiBQT1NUIC9kb2N1bWVudC9saXN0LCBsaW1pdGVkIHRvIHdoYXQgdGhpcyB0YWJsZSBzaG93cy4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBCcmFuZERvY3VtZW50Um93IHtcclxuICBfaWQ6IHN0cmluZztcclxuICBkb2N1bWVudENvZGU/OiBzdHJpbmcgfCBudWxsO1xyXG4gIHNjb3BlOiAnYnJhbmQnIHwgJ3N0b3JlJztcclxuICBzdG9yZUlkczogc3RyaW5nW107ICAgICAgICAgIC8vIFtdID0gZXZlcnkgc3RvcmUgb2YgdGhlIGJyYW5kLCBpbmNsdWRpbmcgc3RvcmVzIGFkZGVkIGxhdGVyXHJcbiAgc3RvcmVOYW1lcz86IHN0cmluZ1tdO1xyXG4gIGZpbGVOYW1lOiBzdHJpbmc7XHJcbiAgZmlsZVNpemU6IG51bWJlcjtcclxuICBleHRlbnNpb246IHN0cmluZyB8IG51bGw7XHJcbiAgdHlwZTogc3RyaW5nIHwgbnVsbDtcclxuICBleHBpcnlEYXRlOiBzdHJpbmcgfCBudWxsOyAgIC8vICdZWVlZLU1NLUREJ1xyXG4gIG9jclN0YXR1czogJ3Byb2Nlc3NpbmcnIHwgJ2RvbmUnIHwgJ2ZhaWxlZCc7XHJcbiAgaXNBY3RpdmU6IGJvb2xlYW47XHJcbiAgdXBsb2FkZWRCeT86IHsgdXNlcklkPzogc3RyaW5nOyBuYW1lPzogc3RyaW5nIH07XHJcbiAgY3JlYXRlZEF0OiBzdHJpbmc7XHJcbn1cclxuXHJcbmNvbnN0IFBBR0VfU0laRVMgPSBbMTAsIDIwLCAzMF07XHJcbmNvbnN0IEVYUElSWV9TT09OX0RBWVMgPSAzMDtcclxuY29uc3QgUE9MTF9NUyA9IDE1MDAwO1xyXG5jb25zdCBNQVhfUE9MTFMgPSAyMDtcclxuXHJcbi8qKlxyXG4gKiBSZWFkLW9ubHkgbGlzdCBvZiB0aGUgYnJhbmQtbGV2ZWwgZG9jdW1lbnRzIG9mIHRoZSBzZWxlY3RlZCBicmFuZCwgc2hvd24gdW5kZXIgdGhlIEtZQyBjYXJkIG9uXHJcbiAqIFNldHRpbmdzID4gRG9jdW1lbnRzLiBTYW1lIGxpc3QgZW5kcG9pbnQgYW5kIHN0YXR1cyBydWxlIGFzIHRoZSBEb2N1bWVudHMgcGFnZTsgdXBsb2FkaW5nIGFuZFxyXG4gKiBlZGl0aW5nIHN0YXkgb24gdGhhdCBwYWdlLiBTaG93biBvbmx5IHdpdGggdGhlIEdsb2JhbCA+IERvY3VtZW50cyBWaWV3IHBlcm1pc3Npb24uXHJcbiAqL1xyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogJ2xpYi1icmFuZC1kb2N1bWVudHMnLFxyXG4gIHRlbXBsYXRlVXJsOiAnLi9icmFuZC1kb2N1bWVudHMuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsOiAnLi9icmFuZC1kb2N1bWVudHMuY29tcG9uZW50LnNjc3MnLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgQnJhbmREb2N1bWVudHNDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSB7XHJcbiAgY2FuVmlldyA9IGZhbHNlO1xyXG4gIGNsaWVudElkID0gJyc7XHJcbiAgZG9jdW1lbnRzOiBCcmFuZERvY3VtZW50Um93W10gPSBbXTtcclxuICBsb2FkaW5nID0gZmFsc2U7XHJcbiAgbm9EYXRhID0gZmFsc2U7XHJcbiAgY29uZmlndXJlZCA9IHRydWU7XHJcbiAgcGFnaW5hdGlvbiA9IHsgb2Zmc2V0OiAxLCBsaW1pdDogMTAsIHRvdGFsQ291bnQ6IDAgfTtcclxuICBwYWdpbmF0aW9uU2l6ZXM6IG51bWJlcltdID0gUEFHRV9TSVpFUztcclxuICAvKiogUm93IHdob3NlIHNpZ25lZCBsaW5rIGlzIGJlaW5nIHByZXBhcmVkOyBpdHMgYWN0aW9ucyBhcmUgZGlzYWJsZWQgbWVhbndoaWxlLiAqL1xyXG4gIGJ1c3lJZDogc3RyaW5nIHwgbnVsbCA9IG51bGw7XHJcblxyXG4gIHJlYWRvbmx5IHN0YXR1c0xhYmVsczogUmVjb3JkPERvY3VtZW50U3RhdHVzLCBzdHJpbmc+ID0ge1xyXG4gICAgcHJvY2Vzc2luZzogJ1Byb2Nlc3NpbmcnLFxyXG4gICAgdmFsaWQ6ICdWYWxpZCcsXHJcbiAgICBleHBpcmluZ19zb29uOiAnRXhwaXJpbmcgc29vbicsXHJcbiAgICBleHBpcmVkOiAnRXhwaXJlZCcsXHJcbiAgICBub19leHBpcnk6ICdObyBleHBpcnknLFxyXG4gIH07XHJcbiAgcmVhZG9ubHkgc3RhdHVzQmFkZ2U6IFJlY29yZDxEb2N1bWVudFN0YXR1cywgc3RyaW5nPiA9IHtcclxuICAgIHByb2Nlc3Npbmc6ICdibHVlLWJhZGdlJyxcclxuICAgIHZhbGlkOiAnZ3JlZW4tYmFkZ2UnLFxyXG4gICAgZXhwaXJpbmdfc29vbjogJ3llbGxvdy1iYWRnZScsXHJcbiAgICBleHBpcmVkOiAncmVkLWJhZGdlJyxcclxuICAgIG5vX2V4cGlyeTogJ2dyYXktYmFkZ2UnLFxyXG4gIH07XHJcblxyXG4gIHByaXZhdGUgcG9sbFN1Yj86IFN1YnNjcmlwdGlvbjtcclxuICBwcml2YXRlIGNsaWVudFN1Yj86IFN1YnNjcmlwdGlvbjtcclxuICBwcml2YXRlIHJlYWRvbmx5IHJlbG9hZCQgPSBuZXcgU3ViamVjdDxib29sZWFuPigpO1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgZGVzdHJveSQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xyXG5cclxuICBjb25zdHJ1Y3RvcihcclxuICAgIHByaXZhdGUgYXBpU2VydmljZTogQ2xpZW50QXBpU2VydmljZSxcclxuICAgIHByaXZhdGUgZ3M6IEdsb2JhbFN0YXRlU2VydmljZSxcclxuICAgIHByaXZhdGUgdG9hc3Q6IFRvYXN0U2VydmljZSxcclxuICAgIHByaXZhdGUgcm91dGVyOiBSb3V0ZXIsXHJcbiAgICBwcml2YXRlIGNkOiBDaGFuZ2VEZXRlY3RvclJlZixcclxuICApIHtcclxuICAgIC8vIE9uZSBwaXBlbGluZSwgc28gYnJhbmQsIHBhZ2luZyBhbmQgcG9sbCB0cmlnZ2VycyBuZXZlciByYWNlIGVhY2ggb3RoZXIuXHJcbiAgICB0aGlzLnJlbG9hZCQucGlwZShcclxuICAgICAgc3dpdGNoTWFwKChzaWxlbnQpID0+IHtcclxuICAgICAgICBpZiAoIXNpbGVudCkge1xyXG4gICAgICAgICAgdGhpcy5sb2FkaW5nID0gdHJ1ZTtcclxuICAgICAgICAgIHRoaXMubm9EYXRhID0gZmFsc2U7XHJcbiAgICAgICAgICB0aGlzLmNkLmRldGVjdENoYW5nZXMoKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuYXBpU2VydmljZS5saXN0RG9jdW1lbnRzKHRoaXMuYnVpbGRRdWVyeSgpKS5waXBlKFxyXG4gICAgICAgICAgbWFwKChyZXM6IGFueSkgPT4gKHsgcmVzLCBmYWlsZWQ6IGZhbHNlIH0pKSxcclxuICAgICAgICAgIGNhdGNoRXJyb3IoKGVycikgPT4ge1xyXG4gICAgICAgICAgICB0aGlzLnRvYXN0LmdldEVycm9yVG9hc3QoZXJyPy5lcnJvcj8uZXJyb3IgfHwgZXJyPy5lcnJvcj8ubWVzc2FnZSB8fCAnQ291bGQgbm90IGxvYWQgZG9jdW1lbnRzJyk7XHJcbiAgICAgICAgICAgIHJldHVybiBvZih7IHJlczogbnVsbCwgZmFpbGVkOiB0cnVlIH0pO1xyXG4gICAgICAgICAgfSksXHJcbiAgICAgICAgKTtcclxuICAgICAgfSksXHJcbiAgICAgIHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSxcclxuICAgICkuc3Vic2NyaWJlKCh7IHJlcywgZmFpbGVkIH0pID0+IHtcclxuICAgICAgdGhpcy5sb2FkaW5nID0gZmFsc2U7XHJcbiAgICAgIGlmIChmYWlsZWQgfHwgIXJlcyB8fCByZXMuY29kZSAhPT0gMjAwKSB7XHJcbiAgICAgICAgdGhpcy5kb2N1bWVudHMgPSBbXTtcclxuICAgICAgICB0aGlzLm5vRGF0YSA9IHRydWU7XHJcbiAgICAgICAgdGhpcy5jZC5kZXRlY3RDaGFuZ2VzKCk7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcbiAgICAgIHRoaXMuZG9jdW1lbnRzID0gcmVzLmRhdGE/LnJlc3VsdCB8fCBbXTtcclxuICAgICAgY29uc3QgY291bnQgPSByZXMuZGF0YT8uY291bnQgfHwgMDtcclxuICAgICAgdGhpcy5wYWdpbmF0aW9uID0geyAuLi50aGlzLnBhZ2luYXRpb24sIHRvdGFsQ291bnQ6IGNvdW50IH07XHJcbiAgICAgIHRoaXMucGFnaW5hdGlvblNpemVzID0gY291bnQgPCAxMCA/IFtjb3VudF0gOiBQQUdFX1NJWkVTO1xyXG4gICAgICB0aGlzLm5vRGF0YSA9IHRoaXMuZG9jdW1lbnRzLmxlbmd0aCA9PT0gMDtcclxuICAgICAgdGhpcy5jZC5kZXRlY3RDaGFuZ2VzKCk7XHJcbiAgICAgIHRoaXMubWFuYWdlUG9sbGluZygpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBuZ09uSW5pdCgpOiB2b2lkIHtcclxuICAgIHRoaXMuY29uZmlndXJlZCA9IHRoaXMuYXBpU2VydmljZS5pc0RvY3VtZW50c0NvbmZpZ3VyZWQ7XHJcbiAgICAvLyBBY2Nlc3MgaXMgdGhlIEdsb2JhbCA+IERvY3VtZW50cyBWaWV3IHBlcm1pc3Npb247IGl0IGFycml2ZXMgd2l0aCB0aGUgcHJvZmlsZSBjYWxsLlxyXG4gICAgdGhpcy5ncy51c2VyQWNjZXNzLnBpcGUodGFrZVVudGlsKHRoaXMuZGVzdHJveSQpKS5zdWJzY3JpYmUoKGFjY2VzczogYW55KSA9PiB7XHJcbiAgICAgIGNvbnN0IGNhblZpZXcgPSBhY2Nlc3M/Lkdsb2JhbF9Eb2N1bWVudHNfaXNBZGQgPT09IHRydWU7XHJcbiAgICAgIGlmIChjYW5WaWV3ID09PSB0aGlzLmNhblZpZXcpIHsgcmV0dXJuOyB9XHJcbiAgICAgIHRoaXMuY2FuVmlldyA9IGNhblZpZXc7XHJcbiAgICAgIGlmIChjYW5WaWV3KSB7XHJcbiAgICAgICAgdGhpcy53YXRjaENsaWVudCgpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMuc3RvcFBvbGxpbmcoKTtcclxuICAgICAgICB0aGlzLmNsaWVudFN1Yj8udW5zdWJzY3JpYmUoKTtcclxuICAgICAgICB0aGlzLmNsaWVudFN1YiA9IHVuZGVmaW5lZDtcclxuICAgICAgfVxyXG4gICAgICB0aGlzLmNkLmRldGVjdENoYW5nZXMoKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XHJcbiAgICB0aGlzLnN0b3BQb2xsaW5nKCk7XHJcbiAgICB0aGlzLmRlc3Ryb3kkLm5leHQoKTtcclxuICAgIHRoaXMuZGVzdHJveSQuY29tcGxldGUoKTtcclxuICB9XHJcblxyXG4gIC8qKiBUaGUgc2VsZWN0ZWQgYnJhbmQ6IGhlYWRlciBkcm9wZG93biBmb3IgdGFuZ28gdXNlcnMsIG93biBjbGllbnQgZm9yIGNsaWVudCB1c2Vycy4gKi9cclxuICBwcml2YXRlIHdhdGNoQ2xpZW50KCk6IHZvaWQge1xyXG4gICAgdGhpcy5jbGllbnRTdWI/LnVuc3Vic2NyaWJlKCk7XHJcbiAgICB0aGlzLmNsaWVudFN1YiA9IHRoaXMuYXBpU2VydmljZS5jbGllbnRJZFxyXG4gICAgICAucGlwZShcclxuICAgICAgICBtYXAoKGlkKSA9PiB0aGlzLnJlc29sdmVDbGllbnRJZChpZCkpLFxyXG4gICAgICAgIGRpc3RpbmN0VW50aWxDaGFuZ2VkKCksXHJcbiAgICAgICAgdGFrZVVudGlsKHRoaXMuZGVzdHJveSQpLFxyXG4gICAgICApXHJcbiAgICAgIC5zdWJzY3JpYmUoKGNsaWVudElkKSA9PiB7XHJcbiAgICAgICAgdGhpcy5jbGllbnRJZCA9IGNsaWVudElkO1xyXG4gICAgICAgIHRoaXMuc3RvcFBvbGxpbmcoKTtcclxuICAgICAgICBpZiAoIXRoaXMuY29uZmlndXJlZCB8fCAhY2xpZW50SWQpIHtcclxuICAgICAgICAgIHRoaXMuZG9jdW1lbnRzID0gW107XHJcbiAgICAgICAgICB0aGlzLm5vRGF0YSA9IHRydWU7XHJcbiAgICAgICAgICB0aGlzLmNkLmRldGVjdENoYW5nZXMoKTtcclxuICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5wYWdpbmF0aW9uLm9mZnNldCA9IDE7XHJcbiAgICAgICAgdGhpcy5sb2FkKCk7XHJcbiAgICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqIENsaWVudCB1c2VycyBhbHdheXMgcXVlcnkgdGhlaXIgb3duIGNsaWVudCwgd2hhdGV2ZXIgdGhlIGhlYWRlciBob2xkcy4gKi9cclxuICBwcml2YXRlIHJlc29sdmVDbGllbnRJZChoZWFkZXJDbGllbnQ6IHN0cmluZyB8IG51bGwgfCB1bmRlZmluZWQpOiBzdHJpbmcge1xyXG4gICAgbGV0IHVzZXI6IGFueSA9IHt9O1xyXG4gICAgdHJ5IHsgdXNlciA9IEpTT04ucGFyc2UobG9jYWxTdG9yYWdlLmdldEl0ZW0oJ3VzZXItaW5mbycpIHx8ICd7fScpOyB9IGNhdGNoIHsgdXNlciA9IHt9OyB9XHJcbiAgICBpZiAodXNlcj8udXNlclR5cGUgPT09ICdjbGllbnQnICYmIHVzZXI/LmNsaWVudElkKSB7IHJldHVybiBTdHJpbmcodXNlci5jbGllbnRJZCk7IH1cclxuICAgIHJldHVybiBoZWFkZXJDbGllbnQgPyBTdHJpbmcoaGVhZGVyQ2xpZW50KSA6ICcnO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBidWlsZFF1ZXJ5KCk6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHtcclxuICAgIHJldHVybiB7XHJcbiAgICAgIGNsaWVudElkOiB0aGlzLmNsaWVudElkLFxyXG4gICAgICBzY29wZTogJ2JyYW5kJyxcclxuICAgICAgc29ydENvbHVtbjogJ2NyZWF0ZWRBdCcsXHJcbiAgICAgIHNvcnRCeTogLTEsXHJcbiAgICAgIG9mZnNldDogdGhpcy5wYWdpbmF0aW9uLm9mZnNldCxcclxuICAgICAgbGltaXQ6IHRoaXMucGFnaW5hdGlvbi5saW1pdCxcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICBsb2FkKHNpbGVudCA9IGZhbHNlKTogdm9pZCB7XHJcbiAgICB0aGlzLnJlbG9hZCQubmV4dChzaWxlbnQpO1xyXG4gIH1cclxuXHJcbiAgLy8gLS0tLS0tLS0tLSBwcm9jZXNzaW5nIHJlZnJlc2ggLS0tLS0tLS0tLVxyXG5cclxuICAvKiogV2hpbGUgYW55IHJvdyBpcyBzdGlsbCBiZWluZyBwcm9jZXNzZWQsIHNpbGVudGx5IHJlZnJlc2ggZXZlcnkgMTUgcywgY2FwcGVkIGF0IDIwIHBvbGxzLiAqL1xyXG4gIHByaXZhdGUgbWFuYWdlUG9sbGluZygpOiB2b2lkIHtcclxuICAgIGNvbnN0IHByb2Nlc3NpbmcgPSB0aGlzLmRvY3VtZW50cy5zb21lKChkKSA9PiBkLm9jclN0YXR1cyA9PT0gJ3Byb2Nlc3NpbmcnKTtcclxuICAgIGlmICghcHJvY2Vzc2luZykge1xyXG4gICAgICB0aGlzLnN0b3BQb2xsaW5nKCk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIGlmICh0aGlzLnBvbGxTdWIpIHsgcmV0dXJuOyB9XHJcbiAgICB0aGlzLnBvbGxTdWIgPSB0aW1lcihQT0xMX01TLCBQT0xMX01TKVxyXG4gICAgICAucGlwZSh0YWtlKE1BWF9QT0xMUyksIHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSlcclxuICAgICAgLnN1YnNjcmliZSgoKSA9PiB0aGlzLmxvYWQodHJ1ZSkpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBzdG9wUG9sbGluZygpOiB2b2lkIHtcclxuICAgIHRoaXMucG9sbFN1Yj8udW5zdWJzY3JpYmUoKTtcclxuICAgIHRoaXMucG9sbFN1YiA9IHVuZGVmaW5lZDtcclxuICB9XHJcblxyXG4gIC8vIC0tLS0tLS0tLS0gcGFnaW5nIC0tLS0tLS0tLS1cclxuXHJcbiAgb25QYWdlQ2hhbmdlKHBhZ2U6IG51bWJlcik6IHZvaWQge1xyXG4gICAgdGhpcy5wYWdpbmF0aW9uLm9mZnNldCA9IE51bWJlcihwYWdlKTtcclxuICAgIHRoaXMuc3RvcFBvbGxpbmcoKTtcclxuICAgIHRoaXMubG9hZCgpO1xyXG4gIH1cclxuXHJcbiAgb25QYWdlU2l6ZUNoYW5nZShzaXplOiBudW1iZXIpOiB2b2lkIHtcclxuICAgIHRoaXMucGFnaW5hdGlvbi5saW1pdCA9IE51bWJlcihzaXplKTtcclxuICAgIHRoaXMucGFnaW5hdGlvbi5vZmZzZXQgPSAxO1xyXG4gICAgdGhpcy5zdG9wUG9sbGluZygpO1xyXG4gICAgdGhpcy5sb2FkKCk7XHJcbiAgfVxyXG5cclxuICBwYWdpbmF0aW9uU2l6ZSgpOiBudW1iZXIge1xyXG4gICAgcmV0dXJuIHRoaXMucGFnaW5hdGlvbi50b3RhbENvdW50IDwgMTAgPyB0aGlzLnBhZ2luYXRpb24udG90YWxDb3VudCA6IHRoaXMucGFnaW5hdGlvbi5saW1pdDtcclxuICB9XHJcblxyXG4gIC8vIC0tLS0tLS0tLS0gYWN0aW9ucyAtLS0tLS0tLS0tXHJcblxyXG4gIGdvVG9Eb2N1bWVudHMoKTogdm9pZCB7XHJcbiAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbJy9tYW5hZ2UvZG9jdW1lbnRzJ10sIHsgcXVlcnlQYXJhbXM6IHsgdGFiOiAnYnJhbmQnIH0gfSk7XHJcbiAgfVxyXG5cclxuICAvKiogT3BlbnMgdGhlIGZpbGUgaW4gYSBuZXcgdGFiLiBUaGUgdGFiIGlzIG9wZW5lZCBvbiB0aGUgY2xpY2sgaXRzZWxmIHNvIHBvcHVwIGJsb2NrZXJzIGFsbG93IGl0LiAqL1xyXG4gIG9wZW5Eb2N1bWVudChkb2M6IEJyYW5kRG9jdW1lbnRSb3cpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLmJ1c3lJZCkgeyByZXR1cm47IH1cclxuICAgIGNvbnN0IHRhYiA9IHdpbmRvdy5vcGVuKCcnLCAnX2JsYW5rJyk7XHJcbiAgICBpZiAodGFiKSB7IHRhYi5vcGVuZXIgPSBudWxsOyB9XHJcbiAgICB0aGlzLmJ1c3lJZCA9IGRvYy5faWQ7XHJcbiAgICB0aGlzLmFwaVNlcnZpY2UuZ2V0RG9jdW1lbnRVcmwodGhpcy5jbGllbnRJZCwgZG9jLl9pZCwgZmFsc2UpXHJcbiAgICAgIC5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSlcclxuICAgICAgLnN1YnNjcmliZSh7XHJcbiAgICAgICAgbmV4dDogKHJlczogYW55KSA9PiB7XHJcbiAgICAgICAgICB0aGlzLmJ1c3lJZCA9IG51bGw7XHJcbiAgICAgICAgICBjb25zdCB1cmwgPSByZXM/LmRhdGE/LnVybDtcclxuICAgICAgICAgIGlmICh1cmwgJiYgdGFiKSB7XHJcbiAgICAgICAgICAgIHRhYi5sb2NhdGlvbi5ocmVmID0gdXJsO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgdGFiPy5jbG9zZSgpO1xyXG4gICAgICAgICAgICB0aGlzLnRvYXN0LmdldEVycm9yVG9hc3QoJ0NvdWxkIG5vdCBvcGVuIHRoZSBmaWxlJyk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICB0aGlzLmNkLmRldGVjdENoYW5nZXMoKTtcclxuICAgICAgICB9LFxyXG4gICAgICAgIGVycm9yOiAoZXJyKSA9PiB7XHJcbiAgICAgICAgICB0aGlzLmJ1c3lJZCA9IG51bGw7XHJcbiAgICAgICAgICB0YWI/LmNsb3NlKCk7XHJcbiAgICAgICAgICB0aGlzLnRvYXN0LmdldEVycm9yVG9hc3QoZXJyPy5lcnJvcj8uZXJyb3IgfHwgZXJyPy5lcnJvcj8ubWVzc2FnZSB8fCAnQ291bGQgbm90IG9wZW4gdGhlIGZpbGUnKTtcclxuICAgICAgICAgIHRoaXMuY2QuZGV0ZWN0Q2hhbmdlcygpO1xyXG4gICAgICAgIH0sXHJcbiAgICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqIEFza3MgZm9yIGFuIGF0dGFjaG1lbnQgbGluayBzbyB0aGUgYnJvd3NlciBzYXZlcyB0aGUgZmlsZSBpbnN0ZWFkIG9mIG9wZW5pbmcgaXQuICovXHJcbiAgZG93bmxvYWREb2N1bWVudChkb2M6IEJyYW5kRG9jdW1lbnRSb3cpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLmJ1c3lJZCkgeyByZXR1cm47IH1cclxuICAgIHRoaXMuYnVzeUlkID0gZG9jLl9pZDtcclxuICAgIHRoaXMuYXBpU2VydmljZS5nZXREb2N1bWVudFVybCh0aGlzLmNsaWVudElkLCBkb2MuX2lkLCB0cnVlKVxyXG4gICAgICAucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpXHJcbiAgICAgIC5zdWJzY3JpYmUoe1xyXG4gICAgICAgIG5leHQ6IChyZXM6IGFueSkgPT4ge1xyXG4gICAgICAgICAgdGhpcy5idXN5SWQgPSBudWxsO1xyXG4gICAgICAgICAgY29uc3QgdXJsID0gcmVzPy5kYXRhPy51cmw7XHJcbiAgICAgICAgICBpZiAodXJsKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGxpbmsgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdhJyk7XHJcbiAgICAgICAgICAgIGxpbmsuaHJlZiA9IHVybDtcclxuICAgICAgICAgICAgbGluay5yZWwgPSAnbm9vcGVuZXInO1xyXG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGxpbmspO1xyXG4gICAgICAgICAgICBsaW5rLmNsaWNrKCk7XHJcbiAgICAgICAgICAgIGxpbmsucmVtb3ZlKCk7XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB0aGlzLnRvYXN0LmdldEVycm9yVG9hc3QoJ0NvdWxkIG5vdCBkb3dubG9hZCB0aGUgZmlsZScpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgdGhpcy5jZC5kZXRlY3RDaGFuZ2VzKCk7XHJcbiAgICAgICAgfSxcclxuICAgICAgICBlcnJvcjogKGVycikgPT4ge1xyXG4gICAgICAgICAgdGhpcy5idXN5SWQgPSBudWxsO1xyXG4gICAgICAgICAgdGhpcy50b2FzdC5nZXRFcnJvclRvYXN0KGVycj8uZXJyb3I/LmVycm9yIHx8IGVycj8uZXJyb3I/Lm1lc3NhZ2UgfHwgJ0NvdWxkIG5vdCBkb3dubG9hZCB0aGUgZmlsZScpO1xyXG4gICAgICAgICAgdGhpcy5jZC5kZXRlY3RDaGFuZ2VzKCk7XHJcbiAgICAgICAgfSxcclxuICAgICAgfSk7XHJcbiAgfVxyXG5cclxuICAvLyAtLS0tLS0tLS0tIGNlbGwgaGVscGVycyAtLS0tLS0tLS0tXHJcblxyXG4gIHRyYWNrQnlJZChfOiBudW1iZXIsIGRvYzogQnJhbmREb2N1bWVudFJvdyk6IHN0cmluZyB7XHJcbiAgICByZXR1cm4gZG9jLl9pZDtcclxuICB9XHJcblxyXG4gIGZpbGVLaW5kKGV4dDogc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCk6IEZpbGVLaW5kIHtcclxuICAgIHN3aXRjaCAoKGV4dCB8fCAnJykudG9Mb3dlckNhc2UoKSkge1xyXG4gICAgICBjYXNlICdwZGYnOiByZXR1cm4gJ3BkZic7XHJcbiAgICAgIGNhc2UgJ2pwZyc6IGNhc2UgJ2pwZWcnOiBjYXNlICdwbmcnOiByZXR1cm4gJ2ltYWdlJztcclxuICAgICAgZGVmYXVsdDogcmV0dXJuICdvdGhlcic7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBmb3JtYXRGaWxlU2l6ZShieXRlczogbnVtYmVyIHwgbnVsbCB8IHVuZGVmaW5lZCk6IHN0cmluZyB7XHJcbiAgICBpZiAoIWJ5dGVzIHx8IGJ5dGVzIDw9IDApIHsgcmV0dXJuICctJzsgfVxyXG4gICAgaWYgKGJ5dGVzIDwgMTAyNCkgeyByZXR1cm4gYCR7Ynl0ZXN9IEJgOyB9XHJcbiAgICBpZiAoYnl0ZXMgPCAxMDI0ICogMTAyNCkgeyByZXR1cm4gYCR7TWF0aC5yb3VuZChieXRlcyAvIDEwMjQpfSBLQmA7IH1cclxuICAgIHJldHVybiBgJHsoYnl0ZXMgLyAoMTAyNCAqIDEwMjQpKS50b0ZpeGVkKDEpfSBNQmA7XHJcbiAgfVxyXG5cclxuICAvKiogV2hvbGUgZGF5cyBmcm9tIHRvZGF5IChsb2NhbCkgdG8gYSAnWVlZWS1NTS1ERCcgZGF0ZTsgbmVnYXRpdmUgd2hlbiBpbiB0aGUgcGFzdC4gKi9cclxuICBwcml2YXRlIGRheXNVbnRpbChkYXRlOiBzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkKTogbnVtYmVyIHwgbnVsbCB7XHJcbiAgICBpZiAoIWRhdGUpIHsgcmV0dXJuIG51bGw7IH1cclxuICAgIGNvbnN0IHRhcmdldCA9IG5ldyBEYXRlKGAke2RhdGUuc2xpY2UoMCwgMTApfVQwMDowMDowMGApO1xyXG4gICAgaWYgKGlzTmFOKHRhcmdldC5nZXRUaW1lKCkpKSB7IHJldHVybiBudWxsOyB9XHJcbiAgICBjb25zdCB0b2RheSA9IG5ldyBEYXRlKCk7XHJcbiAgICB0b2RheS5zZXRIb3VycygwLCAwLCAwLCAwKTtcclxuICAgIHJldHVybiBNYXRoLnJvdW5kKCh0YXJnZXQuZ2V0VGltZSgpIC0gdG9kYXkuZ2V0VGltZSgpKSAvIDg2NDAwMDAwKTtcclxuICB9XHJcblxyXG4gIC8qKiBTYW1lIHJ1bGUgYXMgdGhlIERvY3VtZW50cyBwYWdlIGJhZGdlIGFuZCB0aGUgbW9iaWxlIGxpc3QuICovXHJcbiAgc3RhdHVzT2YoZG9jOiBCcmFuZERvY3VtZW50Um93KTogRG9jdW1lbnRTdGF0dXMge1xyXG4gICAgaWYgKGRvYy5vY3JTdGF0dXMgPT09ICdwcm9jZXNzaW5nJykgeyByZXR1cm4gJ3Byb2Nlc3NpbmcnOyB9XHJcbiAgICBjb25zdCBkYXlzID0gdGhpcy5kYXlzVW50aWwoZG9jLmV4cGlyeURhdGUpO1xyXG4gICAgaWYgKGRheXMgPT09IG51bGwpIHsgcmV0dXJuICdub19leHBpcnknOyB9XHJcbiAgICBpZiAoZGF5cyA8IDApIHsgcmV0dXJuICdleHBpcmVkJzsgfVxyXG4gICAgaWYgKGRheXMgPD0gRVhQSVJZX1NPT05fREFZUykgeyByZXR1cm4gJ2V4cGlyaW5nX3Nvb24nOyB9XHJcbiAgICByZXR1cm4gJ3ZhbGlkJztcclxuICB9XHJcblxyXG4gIGV4cGlyeVRleHQoZG9jOiBCcmFuZERvY3VtZW50Um93KTogc3RyaW5nIHtcclxuICAgIGNvbnN0IGRheXMgPSB0aGlzLmRheXNVbnRpbChkb2MuZXhwaXJ5RGF0ZSk7XHJcbiAgICBpZiAoZGF5cyA9PT0gbnVsbCkgeyByZXR1cm4gJ05vIHZhbGlkaXR5IGRhdGUnOyB9XHJcbiAgICBpZiAoZGF5cyA9PT0gMCkgeyByZXR1cm4gJ0V4cGlyZXMgdG9kYXknOyB9XHJcbiAgICBpZiAoZGF5cyA8IDApIHsgcmV0dXJuIGBFeHBpcmVkICR7TWF0aC5hYnMoZGF5cyl9IGRheSR7TWF0aC5hYnMoZGF5cykgPT09IDEgPyAnJyA6ICdzJ30gYWdvYDsgfVxyXG4gICAgcmV0dXJuIGAke2RheXN9IGRheSR7ZGF5cyA9PT0gMSA/ICcnIDogJ3MnfSBsZWZ0YDtcclxuICB9XHJcblxyXG4gIGlzRXhwaXJlZChkb2M6IEJyYW5kRG9jdW1lbnRSb3cpOiBib29sZWFuIHtcclxuICAgIGNvbnN0IGRheXMgPSB0aGlzLmRheXNVbnRpbChkb2MuZXhwaXJ5RGF0ZSk7XHJcbiAgICByZXR1cm4gZGF5cyAhPT0gbnVsbCAmJiBkYXlzIDwgMDtcclxuICB9XHJcblxyXG4gIC8qKiBXaGljaCBzdG9yZXMgc2VlIHRoZSBmaWxlOiBhbGwgb2YgdGhlbSwgb3IgdGhlIGNob3NlbiBmZXcuICovXHJcbiAgc2hhcmVkVGV4dChkb2M6IEJyYW5kRG9jdW1lbnRSb3cpOiBzdHJpbmcge1xyXG4gICAgY29uc3QgbiA9IGRvYy5zdG9yZUlkcz8ubGVuZ3RoIHx8IDA7XHJcbiAgICByZXR1cm4gbiA/IGAke259IHN0b3JlJHtuID09PSAxID8gJycgOiAncyd9YCA6ICdBbGwgc3RvcmVzJztcclxuICB9XHJcblxyXG4gIHNoYXJlZFRvb2x0aXAoZG9jOiBCcmFuZERvY3VtZW50Um93KTogc3RyaW5nIHtcclxuICAgIGlmICghZG9jLnN0b3JlSWRzPy5sZW5ndGgpIHsgcmV0dXJuICcnOyB9XHJcbiAgICBjb25zdCBuYW1lcyA9IGRvYy5zdG9yZU5hbWVzPy5sZW5ndGggPyBkb2Muc3RvcmVOYW1lcyA6IGRvYy5zdG9yZUlkcztcclxuICAgIHJldHVybiBuYW1lcy5zbGljZSgwLCAxNSkuam9pbignLCAnKSArIChuYW1lcy5sZW5ndGggPiAxNSA/IGAgKyR7bmFtZXMubGVuZ3RoIC0gMTV9IG1vcmVgIDogJycpO1xyXG4gIH1cclxufVxyXG4iLCI8ZGl2ICpuZ0lmPVwiY2FuVmlld1wiIGNsYXNzPVwiZG9jdW1lbnRzLWNhcmRcIj5cclxuICAgIDxkaXYgY2xhc3M9XCJkLWZsZXgganVzdGlmeS1jb250ZW50LWJldHdlZW4gYWxpZ24taXRlbXMtc3RhcnQgZmxleC13cmFwIGdhcC0zIG1iLTZcIj5cclxuICAgICAgICA8ZGl2PlxyXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiaGVhZGVyXCI+QnJhbmQgZG9jdW1lbnRzIDxzcGFuICpuZ0lmPVwiY29uZmlndXJlZCAmJiAhbG9hZGluZ1wiIGNsYXNzPVwiYmx1ZS1iYWRnZSBtcy0yXCI+e3sgcGFnaW5hdGlvbi50b3RhbENvdW50IH19PC9zcGFuPjwvZGl2PlxyXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3ViLXRleHRcIj5GaWxlcyB1cGxvYWRlZCBhdCBicmFuZCBsZXZlbCBhbmQgc2hhcmVkIHdpdGggc3RvcmVzLiBVcGxvYWQgYW5kIGVkaXQgdGhlbSBvbiB0aGUgRG9jdW1lbnRzIHBhZ2UuPC9kaXY+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBhbGlnbi1pdGVtcy1jZW50ZXIgZmxleC1zaHJpbmstMFwiPlxyXG4gICAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiAoY2xpY2spPVwibG9hZCgpXCIgW2Rpc2FibGVkXT1cImxvYWRpbmcgfHwgIWNvbmZpZ3VyZWRcIlxyXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJidG4gYnRuLWRlZmF1bHQgYnRuLW91dGxpbmUgYnRuLW91dGxpbmUtZGVmYXVsdCByb3VuZGVkLTMgdG9vbGJhci1jb250cm9sIG1lLTNcIj5cclxuICAgICAgICAgICAgICAgIDxzdmcgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiIHdpZHRoPVwiMThcIiBoZWlnaHQ9XCIxOFwiIHZpZXdCb3g9XCIwIDAgMjQgMjRcIiBmaWxsPVwibm9uZVwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9XCJNMjEgMTJhOSA5IDAgMSAxLTIuNjQtNi4zNk0yMSAzdjZoLTZcIiBzdHJva2U9XCIjMzQ0MDU0XCIgc3Ryb2tlLXdpZHRoPVwiMlwiIHN0cm9rZS1saW5lY2FwPVwicm91bmRcIiBzdHJva2UtbGluZWpvaW49XCJyb3VuZFwiIC8+XHJcbiAgICAgICAgICAgICAgICA8L3N2Zz5cclxuICAgICAgICAgICAgICAgIDxzcGFuPlJlZnJlc2g8L3NwYW4+XHJcbiAgICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiAoY2xpY2spPVwiZ29Ub0RvY3VtZW50cygpXCIgY2xhc3M9XCJidG4gYnRuLW91dGxpbmUgcm91bmRlZC0zIHRvb2xiYXItY29udHJvbCB0b29sYmFyLWNvbnRyb2wtLXByaW1hcnlcIj5cclxuICAgICAgICAgICAgICAgIDxzcGFuPk9wZW4gRG9jdW1lbnRzPC9zcGFuPlxyXG4gICAgICAgICAgICAgICAgPHN2ZyB4bWxucz1cImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIgd2lkdGg9XCIxNlwiIGhlaWdodD1cIjE2XCIgdmlld0JveD1cIjAgMCAyNCAyNFwiIGZpbGw9XCJub25lXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD1cIk03IDE3IDE3IDdNOCA3aDl2OVwiIHN0cm9rZT1cImN1cnJlbnRDb2xvclwiIHN0cm9rZS13aWR0aD1cIjJcIiBzdHJva2UtbGluZWNhcD1cInJvdW5kXCIgc3Ryb2tlLWxpbmVqb2luPVwicm91bmRcIiAvPlxyXG4gICAgICAgICAgICAgICAgPC9zdmc+XHJcbiAgICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgPC9kaXY+XHJcblxyXG4gICAgPGRpdiAqbmdJZj1cIiFjb25maWd1cmVkXCIgY2xhc3M9XCJlbXB0eS1zdGF0ZVwiPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJ0ZXh0LXN1YlwiPkRvY3VtZW50cyBBUEkgVVJMIGlzIG5vdCBjb25maWd1cmVkLjwvZGl2PlxyXG4gICAgPC9kaXY+XHJcblxyXG4gICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImNvbmZpZ3VyZWRcIj5cclxuICAgICAgICA8ZGl2ICpuZ0lmPVwiIWxvYWRpbmcgJiYgIW5vRGF0YVwiIGNsYXNzPVwidGFibGUtcmVzcG9uc2l2ZVwiPlxyXG4gICAgICAgICAgICA8dGFibGUgY2xhc3M9XCJ0YWJsZSBib3R0b20tYm9yZGVyIHRleHQtbm93cmFwXCI+XHJcbiAgICAgICAgICAgICAgICA8dGhlYWQ+XHJcbiAgICAgICAgICAgICAgICAgICAgPHRyPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8dGg+RG9jdW1lbnQ8L3RoPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8dGg+RG9jdW1lbnQgSUQ8L3RoPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8dGg+VHlwZTwvdGg+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDx0aD5BdmFpbGFibGUgdG88L3RoPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8dGg+VmFsaWQgdGlsbDwvdGg+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDx0aD5TdGF0dXM8L3RoPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8dGg+VXBsb2FkZWQ8L3RoPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8dGg+QWN0aW9uczwvdGg+XHJcbiAgICAgICAgICAgICAgICAgICAgPC90cj5cclxuICAgICAgICAgICAgICAgIDwvdGhlYWQ+XHJcbiAgICAgICAgICAgICAgICA8dGJvZHk+XHJcbiAgICAgICAgICAgICAgICAgICAgPHRyICpuZ0Zvcj1cImxldCBkb2Mgb2YgZG9jdW1lbnRzOyB0cmFja0J5OiB0cmFja0J5SWRcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPHRkPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBhbGlnbi1pdGVtcy1jZW50ZXJcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImZpbGUtYmFkZ2UgZmlsZS1iYWRnZS0te3sgZmlsZUtpbmQoZG9jLmV4dGVuc2lvbikgfX1cIj57eyBkb2MuZXh0ZW5zaW9uIHx8ICdmaWxlJyB9fTwvc3Bhbj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibXMtMyBmaWxlLWNlbGxcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInRhYmxlLXRpdGxlIHRleHQtdHJ1bmNhdGVcIiBbbmdiVG9vbHRpcF09XCJkb2MuZmlsZU5hbWVcIiBjb250YWluZXI9XCJib2R5XCI+e3sgZG9jLmZpbGVOYW1lIH19PC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0YWJsZS1zdWJcIj57eyBmb3JtYXRGaWxlU2l6ZShkb2MuZmlsZVNpemUpIH19PC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPC90ZD5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPHRkPjxzcGFuIGNsYXNzPVwiZG9jLWNvZGVcIj57eyBkb2MuZG9jdW1lbnRDb2RlIHx8ICctJyB9fTwvc3Bhbj48L3RkPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8dGQ+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiZG9jLm9jclN0YXR1cyA9PT0gJ3Byb2Nlc3NpbmcnXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJ0ZXh0LXN1YlwiPjxzcGFuIGNsYXNzPVwic3Bpbm5lci1ib3JkZXIgc3Bpbm5lci1ib3JkZXItc20gbWUtMlwiIHJvbGU9XCJzdGF0dXNcIj48L3NwYW4+RGV0ZWN0aW5nLi4uPC9zcGFuPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiZG9jLm9jclN0YXR1cyA9PT0gJ2ZhaWxlZCdcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInRleHQtc3ViXCI+e3sgZG9jLnR5cGUgfHwgJ05vdCBkZXRlY3RlZCcgfX08L3NwYW4+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJkb2Mub2NyU3RhdHVzID09PSAnZG9uZSdcIj57eyBkb2MudHlwZSB8fCAnLScgfX08L25nLWNvbnRhaW5lcj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPC90ZD5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPHRkPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gW25nQ2xhc3NdPVwiZG9jLnN0b3JlSWRzPy5sZW5ndGggPyAnZ3JheS1iYWRnZScgOiAnYmx1ZS1iYWRnZSdcIiBbbmdiVG9vbHRpcF09XCJzaGFyZWRUb29sdGlwKGRvYylcIiBjb250YWluZXI9XCJib2R5XCI+e3sgc2hhcmVkVGV4dChkb2MpIH19PC9zcGFuPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8L3RkPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8dGQ+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiZG9jLm9jclN0YXR1cyA9PT0gJ3Byb2Nlc3NpbmcnOyBlbHNlIGV4cGlyeUNlbGxcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInRleHQtc3ViXCI+RGV0ZWN0aW5nLi4uPC9zcGFuPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgI2V4cGlyeUNlbGw+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImRvYy5leHBpcnlEYXRlOyBlbHNlIG5vRXhwaXJ5XCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0YWJsZS10aXRsZVwiPnt7IGRvYy5leHBpcnlEYXRlIHwgY3VzdG9tRGF0ZUZvcm1hdCB9fTwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwidGFibGUtc3ViXCIgW2NsYXNzLnRleHQtZGFuZ2VyXT1cImlzRXhwaXJlZChkb2MpXCI+e3sgZXhwaXJ5VGV4dChkb2MpIH19PC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG5nLXRlbXBsYXRlICNub0V4cGlyeT5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInRhYmxlLXRpdGxlXCI+Tm8gZXhwaXJ5PC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0YWJsZS1zdWJcIj5ObyB2YWxpZGl0eSBkYXRlPC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvdGQ+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDx0ZD48c3BhbiBbbmdDbGFzc109XCJzdGF0dXNCYWRnZVtzdGF0dXNPZihkb2MpXVwiPnt7IHN0YXR1c0xhYmVsc1tzdGF0dXNPZihkb2MpXSB9fTwvc3Bhbj48L3RkPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8dGQ+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwidGFibGUtdGl0bGVcIj57eyBkb2MuY3JlYXRlZEF0IHwgY3VzdG9tRGF0ZUZvcm1hdCB9fTwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInRhYmxlLXN1YlwiPnt7IGRvYy51cGxvYWRlZEJ5Py5uYW1lIHx8ICdOQScgfX08L2Rpdj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPC90ZD5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPHRkIGNsYXNzPVwidGV4dC1ub3dyYXBcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkLWZsZXggYWxpZ24taXRlbXMtY2VudGVyIGdhcC0xXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGEgY2xhc3M9XCJhY3Rpb24taWNvblwiIFtjbGFzcy5hY3Rpb24taWNvbi0tYnVzeV09XCJidXN5SWQgPT09IGRvYy5faWRcIiBuZ2JUb29sdGlwPVwiVmlld1wiIGNvbnRhaW5lcj1cImJvZHlcIiAoY2xpY2spPVwib3BlbkRvY3VtZW50KGRvYylcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHN2ZyB2aWV3Qm94PVwiMCAwIDI0IDI0XCIgZmlsbD1cIm5vbmVcIiB4bWxucz1cImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCI+PHBhdGggZD1cIk0yLjAzNiAxMi4zMjJhMS4wMTIgMS4wMTIgMCAwIDEgMC0uNjM5QzMuNDIzIDcuNTEgNy4zNiA0LjUgMTIgNC41YzQuNjM4IDAgOC41NzMgMy4wMDcgOS45NjMgNy4xNzguMDcuMjA3LjA3LjQzMSAwIC42MzlDMjAuNTc3IDE2LjQ5IDE2LjY0IDE5LjUgMTIgMTkuNWMtNC42MzggMC04LjU3My0zLjAwNy05Ljk2My03LjE3OFpcIiBzdHJva2Utd2lkdGg9XCIxLjdcIiBzdHJva2UtbGluZWNhcD1cInJvdW5kXCIgc3Ryb2tlLWxpbmVqb2luPVwicm91bmRcIi8+PHBhdGggZD1cIk0xNSAxMmEzIDMgMCAxIDEtNiAwIDMgMyAwIDAgMSA2IDBaXCIgc3Ryb2tlLXdpZHRoPVwiMS43XCIgc3Ryb2tlLWxpbmVjYXA9XCJyb3VuZFwiIHN0cm9rZS1saW5lam9pbj1cInJvdW5kXCIvPjwvc3ZnPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvYT5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YSBjbGFzcz1cImFjdGlvbi1pY29uXCIgW2NsYXNzLmFjdGlvbi1pY29uLS1idXN5XT1cImJ1c3lJZCA9PT0gZG9jLl9pZFwiIG5nYlRvb2x0aXA9XCJEb3dubG9hZFwiIGNvbnRhaW5lcj1cImJvZHlcIiAoY2xpY2spPVwiZG93bmxvYWREb2N1bWVudChkb2MpXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzdmcgdmlld0JveD1cIjAgMCAyNCAyNFwiIGZpbGw9XCJub25lXCIgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiPjxwYXRoIGQ9XCJNMyAxNi41djIuMjVBMi4yNSAyLjI1IDAgMCAwIDUuMjUgMjFoMTMuNUEyLjI1IDIuMjUgMCAwIDAgMjEgMTguNzVWMTYuNU0xNi41IDEyIDEyIDE2LjVtMCAwTDcuNSAxMm00LjUgNC41VjNcIiBzdHJva2Utd2lkdGg9XCIxLjdcIiBzdHJva2UtbGluZWNhcD1cInJvdW5kXCIgc3Ryb2tlLWxpbmVqb2luPVwicm91bmRcIi8+PC9zdmc+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9hPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvdGQ+XHJcbiAgICAgICAgICAgICAgICAgICAgPC90cj5cclxuICAgICAgICAgICAgICAgIDwvdGJvZHk+XHJcbiAgICAgICAgICAgIDwvdGFibGU+XHJcbiAgICAgICAgPC9kaXY+XHJcblxyXG4gICAgICAgIDxkaXYgKm5nSWY9XCIhbG9hZGluZyAmJiAhbm9EYXRhXCIgY2xhc3M9XCJtdC02XCI+XHJcbiAgICAgICAgICAgIDxsaWItcGFnaW5hdGlvbiBbaXRlbXNQZXJQYWdlXT1cInBhZ2luYXRpb24ubGltaXRcIiBbY3VycmVudFBhZ2VdPVwicGFnaW5hdGlvbi5vZmZzZXRcIiBbdG90YWxJdGVtc109XCJwYWdpbmF0aW9uLnRvdGFsQ291bnRcIlxyXG4gICAgICAgICAgICAgICAgW3BhZ2luYXRpb25TaXplc109XCJwYWdpbmF0aW9uU2l6ZXNcIiBbcGFnZVNpemVdPVwicGFnaW5hdGlvblNpemUoKVwiXHJcbiAgICAgICAgICAgICAgICAocGFnZUNoYW5nZSk9XCJvblBhZ2VDaGFuZ2UoJGV2ZW50KVwiIChwYWdlU2l6ZUNoYW5nZSk9XCJvblBhZ2VTaXplQ2hhbmdlKCRldmVudClcIj48L2xpYi1wYWdpbmF0aW9uPlxyXG4gICAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgICA8ZGl2ICpuZ0lmPVwibG9hZGluZ1wiIGNsYXNzPVwicm93IGxvYWRlciBkLWZsZXgganVzdGlmeS1jb250ZW50LWNlbnRlciBhbGlnbi1pdGVtcy1jZW50ZXJcIj5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInNoaW1tZXJcIj5cclxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ3cmFwcGVyXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInN0cm9rZSBhbmltYXRlIHRpdGxlXCI+PC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInN0cm9rZSBhbmltYXRlIGxpbmtcIj48L2Rpdj5cclxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3Ryb2tlIGFuaW1hdGUgZGVzY3JpcHRpb25cIj48L2Rpdj5cclxuICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInNoaW1tZXJcIj5cclxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ3cmFwcGVyXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInN0cm9rZSBhbmltYXRlIHRpdGxlXCI+PC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInN0cm9rZSBhbmltYXRlIGxpbmtcIj48L2Rpdj5cclxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3Ryb2tlIGFuaW1hdGUgZGVzY3JpcHRpb25cIj48L2Rpdj5cclxuICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgPGRpdiAqbmdJZj1cIiFsb2FkaW5nICYmIG5vRGF0YVwiIGNsYXNzPVwiZW1wdHktc3RhdGVcIj5cclxuICAgICAgICAgICAgPGltZyBjbGFzcz1cImltZy1zcmNcIiBzcmM9XCIuL2Fzc2V0cy90YW5nby9JY29ucy9Ob2RhdGEuc3ZnXCIgYWx0PVwiXCI+XHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0ZXh0LXN1YiBtdC0zXCI+Tm8gYnJhbmQgZG9jdW1lbnRzIHVwbG9hZGVkIHlldDwvZGl2PlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgPC9uZy1jb250YWluZXI+XHJcbjwvZGl2PlxyXG4iXX0=