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.
- package/esm2022/lib/components/documents/brand-documents/brand-documents.component.mjs +352 -0
- package/esm2022/lib/components/documents/documents.component.mjs +4 -3
- package/esm2022/lib/services/client-api.service.mjs +20 -1
- package/esm2022/lib/tango-manage-settings.module.mjs +4 -1
- package/fesm2022/tango-app-ui-manage-settings.mjs +367 -4
- package/fesm2022/tango-app-ui-manage-settings.mjs.map +1 -1
- package/lib/components/activity-logs/activity-logs.component.d.ts +1 -1
- package/lib/components/contact-directory/contact-directory.component.d.ts +1 -1
- package/lib/components/documents/brand-documents/brand-documents.component.d.ts +95 -0
- package/lib/components/payments-subscription/billing/billing-group-form/billing-group-form.component.d.ts +1 -1
- package/lib/components/payments-subscription/billing/billing.component.d.ts +1 -1
- package/lib/components/payments-subscription/invoice-credits/invoice-credits.component.d.ts +2 -2
- package/lib/components/tango-manage-settings/tango-manage-settings.component.d.ts +1 -1
- package/lib/services/client-api.service.d.ts +7 -0
- package/lib/tango-manage-settings.module.d.ts +54 -53
- package/package.json +1 -1
|
@@ -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=
|