tango-app-ui-manage-billing 3.3.9 → 3.3.10
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/bank-transactions/bank-transactions.component.mjs +273 -0
- package/esm2022/lib/components/bank-transactions/resolve-transaction/resolve-transaction.component.mjs +156 -0
- package/esm2022/lib/components/billing-summary/billing-summary.component.mjs +182 -0
- package/esm2022/lib/components/billing-tabs/billing-tabs.component.mjs +15 -3
- package/esm2022/lib/components/brand-invoices/brand-invoices.component.mjs +12 -7
- package/esm2022/lib/components/brands-billing/brands-billing.component.mjs +83 -40
- package/esm2022/lib/components/daily-pricing/daily-pricing.component.mjs +45 -3
- package/esm2022/lib/components/estimates/estimate-preview/estimate-preview.component.mjs +102 -0
- package/esm2022/lib/components/estimates/estimates.component.mjs +236 -0
- package/esm2022/lib/components/invoice-preview/invoice-preview.component.mjs +18 -3
- package/esm2022/lib/components/plans-subscription/billing/billing-group-form/billing-group-form.component.mjs +460 -0
- package/esm2022/lib/components/plans-subscription/billing/billing-group-view/billing-group-view.component.mjs +20 -0
- package/esm2022/lib/components/plans-subscription/billing/billing.component.mjs +203 -0
- package/esm2022/lib/components/plans-subscription/billing/request-confirmation/request-confirmation.component.mjs +22 -0
- package/esm2022/lib/components/plans-subscription/invoice-credits/invoice-credits.component.mjs +343 -0
- package/esm2022/lib/components/plans-subscription/invoice-credits/paynow/paynow.component.mjs +131 -0
- package/esm2022/lib/components/plans-subscription/payments-subscription.component.mjs +1328 -0
- package/esm2022/lib/components/plans-subscription/request-popups/footfallview-confirmation/footfallview-confirmation.component.mjs +26 -0
- package/esm2022/lib/components/plans-subscription/request-popups/skiptrail/skiptrail.component.mjs +29 -0
- package/esm2022/lib/components/plans-subscription/request-popups/starttrailrequest/starttrailrequest.component.mjs +25 -0
- package/esm2022/lib/components/plans-subscription/request-popups/subscribe-request/subscribe-request.component.mjs +29 -0
- package/esm2022/lib/components/plans-subscription/subscription-popups/add-stepprice/add-stepprice.component.mjs +52 -0
- package/esm2022/lib/components/plans-subscription/subscription-popups/credit-note/credit-note.component.mjs +166 -0
- package/esm2022/lib/components/plans-subscription/subscription-popups/model-content/model-content.component.mjs +47 -0
- package/esm2022/lib/components/plans-subscription/subscription-popups/multidropdown/multidropdown.component.mjs +322 -0
- package/esm2022/lib/components/plans-subscription/subscription-popups/need-help/need-help.component.mjs +114 -0
- package/esm2022/lib/components/plans-subscription/subscription-popups/needhelp/needhelp.component.mjs +24 -0
- package/esm2022/lib/components/plans-subscription/subscription-popups/pricing-revised/pricing-revised.component.mjs +50 -0
- package/esm2022/lib/components/plans-subscription/subscription-popups/product-confirmation/product-confirmation.component.mjs +117 -0
- package/esm2022/lib/components/plans-subscription/subscription-popups/skip-trail/skip-trail.component.mjs +24 -0
- package/esm2022/lib/components/plans-subscription/subscription-popups/subscribe-product/subscribe-product.component.mjs +99 -0
- package/esm2022/lib/components/plans-subscription/subscription-popups/subscription-approval/subscription-approval.component.mjs +128 -0
- package/esm2022/lib/components/plans-subscription/subscription-popups/successfull-subscription/successfull-subscription.component.mjs +20 -0
- package/esm2022/lib/components/plans-subscription/subscription-popups/suspended/suspended.component.mjs +11 -0
- package/esm2022/lib/components/plans-subscription/subscription-popups/trail-expired/trail-expired.component.mjs +11 -0
- package/esm2022/lib/components/plans-subscription/subscription-popups/trail-settings/trail-settings.component.mjs +52 -0
- package/esm2022/lib/components/plans-subscription/subscription-popups/unsubscribe-request/unsubscribe-request.component.mjs +30 -0
- package/esm2022/lib/components/plans-subscription/subscription-popups/unsubscribeproduct/unsubscribeproduct.component.mjs +22 -0
- package/esm2022/lib/components/plans-subscription/subscription-popups/update/update.component.mjs +93 -0
- package/esm2022/lib/components/plans-subscription/subscription-popups/upgrade-plan/upgrade-plan.component.mjs +607 -0
- package/esm2022/lib/components/plans-subscription/subscription-popups/viewstores/viewstores.component.mjs +315 -0
- package/esm2022/lib/components/services/billing.service.mjs +65 -1
- package/esm2022/lib/components/setup-billing/setup-billing.component.mjs +3 -3
- package/esm2022/lib/components/tango-manage-billing/edit-invoice/edit-invoice.component.mjs +28 -4
- package/esm2022/lib/components/tango-manage-billing/tango-manage-billing.component.mjs +98 -7
- package/esm2022/lib/services/client-api.service.mjs +307 -0
- package/esm2022/lib/services/payment-subscription.service.mjs +249 -0
- package/esm2022/lib/services/util.mjs +46 -0
- package/esm2022/lib/tango-manage-billing-routing.module.mjs +11 -1
- package/esm2022/lib/tango-manage-billing.module.mjs +122 -4
- package/fesm2022/tango-app-ui-manage-billing.mjs +7407 -831
- package/fesm2022/tango-app-ui-manage-billing.mjs.map +1 -1
- package/lib/components/bank-transactions/bank-transactions.component.d.ts +75 -0
- package/lib/components/bank-transactions/resolve-transaction/resolve-transaction.component.d.ts +37 -0
- package/lib/components/billing-summary/billing-summary.component.d.ts +45 -0
- package/lib/components/brands-billing/brands-billing.component.d.ts +14 -1
- package/lib/components/daily-pricing/daily-pricing.component.d.ts +4 -0
- package/lib/components/estimates/estimate-preview/estimate-preview.component.d.ts +26 -0
- package/lib/components/estimates/estimates.component.d.ts +61 -0
- package/lib/components/invoice-preview/invoice-preview.component.d.ts +1 -0
- package/lib/components/plans-subscription/billing/billing-group-form/billing-group-form.component.d.ts +66 -0
- package/lib/components/plans-subscription/billing/billing-group-view/billing-group-view.component.d.ts +9 -0
- package/lib/components/plans-subscription/billing/billing.component.d.ts +44 -0
- package/lib/components/plans-subscription/billing/request-confirmation/request-confirmation.component.d.ts +10 -0
- package/lib/components/plans-subscription/invoice-credits/invoice-credits.component.d.ts +82 -0
- package/lib/components/plans-subscription/invoice-credits/paynow/paynow.component.d.ts +30 -0
- package/lib/components/plans-subscription/payments-subscription.component.d.ts +197 -0
- package/lib/components/plans-subscription/request-popups/footfallview-confirmation/footfallview-confirmation.component.d.ts +11 -0
- package/lib/components/plans-subscription/request-popups/skiptrail/skiptrail.component.d.ts +12 -0
- package/lib/components/plans-subscription/request-popups/starttrailrequest/starttrailrequest.component.d.ts +11 -0
- package/lib/components/plans-subscription/request-popups/subscribe-request/subscribe-request.component.d.ts +12 -0
- package/lib/components/plans-subscription/subscription-popups/add-stepprice/add-stepprice.component.d.ts +21 -0
- package/lib/components/plans-subscription/subscription-popups/credit-note/credit-note.component.d.ts +42 -0
- package/lib/components/plans-subscription/subscription-popups/model-content/model-content.component.d.ts +16 -0
- package/lib/components/plans-subscription/subscription-popups/multidropdown/multidropdown.component.d.ts +55 -0
- package/lib/components/plans-subscription/subscription-popups/need-help/need-help.component.d.ts +41 -0
- package/lib/components/plans-subscription/subscription-popups/needhelp/needhelp.component.d.ts +10 -0
- package/lib/components/plans-subscription/subscription-popups/pricing-revised/pricing-revised.component.d.ts +15 -0
- package/lib/components/plans-subscription/subscription-popups/product-confirmation/product-confirmation.component.d.ts +28 -0
- package/lib/components/plans-subscription/subscription-popups/skip-trail/skip-trail.component.d.ts +12 -0
- package/lib/components/plans-subscription/subscription-popups/subscribe-product/subscribe-product.component.d.ts +29 -0
- package/lib/components/plans-subscription/subscription-popups/subscription-approval/subscription-approval.component.d.ts +27 -0
- package/lib/components/plans-subscription/subscription-popups/successfull-subscription/successfull-subscription.component.d.ts +9 -0
- package/lib/components/plans-subscription/subscription-popups/suspended/suspended.component.d.ts +5 -0
- package/lib/components/plans-subscription/subscription-popups/trail-expired/trail-expired.component.d.ts +5 -0
- package/lib/components/plans-subscription/subscription-popups/trail-settings/trail-settings.component.d.ts +22 -0
- package/lib/components/plans-subscription/subscription-popups/unsubscribe-request/unsubscribe-request.component.d.ts +14 -0
- package/lib/components/plans-subscription/subscription-popups/unsubscribeproduct/unsubscribeproduct.component.d.ts +10 -0
- package/lib/components/plans-subscription/subscription-popups/update/update.component.d.ts +33 -0
- package/lib/components/plans-subscription/subscription-popups/upgrade-plan/upgrade-plan.component.d.ts +102 -0
- package/lib/components/plans-subscription/subscription-popups/viewstores/viewstores.component.d.ts +46 -0
- package/lib/components/services/billing.service.d.ts +21 -0
- package/lib/components/tango-manage-billing/edit-invoice/edit-invoice.component.d.ts +1 -1
- package/lib/components/tango-manage-billing/tango-manage-billing.component.d.ts +15 -0
- package/lib/services/client-api.service.d.ts +98 -0
- package/lib/services/payment-subscription.service.d.ts +73 -0
- package/lib/services/util.d.ts +14 -0
- package/lib/tango-manage-billing.module.d.ts +62 -26
- package/package.json +1 -1
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import { Component } from '@angular/core';
|
|
2
|
+
import { Subject, takeUntil } from 'rxjs';
|
|
3
|
+
import { InvoicePreviewComponent } from '../invoice-preview/invoice-preview.component';
|
|
4
|
+
import { ResolveTransactionComponent } from './resolve-transaction/resolve-transaction.component';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
import * as i1 from "../services/billing.service";
|
|
7
|
+
import * as i2 from "tango-app-ui-shared";
|
|
8
|
+
import * as i3 from "@ng-bootstrap/ng-bootstrap";
|
|
9
|
+
import * as i4 from "@angular/common";
|
|
10
|
+
import * as i5 from "@angular/forms";
|
|
11
|
+
// Bank-statement reconciliation tab. Upload a statement export (CSV/XLSX),
|
|
12
|
+
// rows land in the `banktransaction` collection and are bucketed by status:
|
|
13
|
+
// reconciled / needs_review / unmatched / excluded. Classification rules are
|
|
14
|
+
// not wired yet — new rows arrive as 'unmatched' until that pass exists.
|
|
15
|
+
export class BankTransactionsComponent {
|
|
16
|
+
billingService;
|
|
17
|
+
toast;
|
|
18
|
+
changeDetector;
|
|
19
|
+
modalService;
|
|
20
|
+
// 'upload' shows the dropzone (empty collection); 'results' the table view.
|
|
21
|
+
stage = 'upload';
|
|
22
|
+
loading = true;
|
|
23
|
+
uploading = false;
|
|
24
|
+
noData = false;
|
|
25
|
+
rows = [];
|
|
26
|
+
totalItems = 0;
|
|
27
|
+
cards = {
|
|
28
|
+
reconciled: { count: 0, amount: 0 },
|
|
29
|
+
needs_review: { count: 0, amount: 0 },
|
|
30
|
+
unmatched: { count: 0, amount: 0 },
|
|
31
|
+
excluded: { count: 0, amount: 0 },
|
|
32
|
+
total: 0,
|
|
33
|
+
};
|
|
34
|
+
// Status segment tabs — ids match the backend enum.
|
|
35
|
+
statusTabs = [
|
|
36
|
+
{ id: 'all', label: 'All' },
|
|
37
|
+
{ id: 'reconciled', label: 'Reconciled' },
|
|
38
|
+
{ id: 'needs_review', label: 'Needs review' },
|
|
39
|
+
{ id: 'unmatched', label: 'Unmatched' },
|
|
40
|
+
{ id: 'excluded', label: 'Excluded' },
|
|
41
|
+
];
|
|
42
|
+
activeStatus = 'all';
|
|
43
|
+
// Filter popover state.
|
|
44
|
+
filterOpen = false;
|
|
45
|
+
fromDate = '';
|
|
46
|
+
toDate = '';
|
|
47
|
+
source = 'all';
|
|
48
|
+
searchValue = '';
|
|
49
|
+
// Pagination — mirrors the All Invoices table.
|
|
50
|
+
currentPage = 1;
|
|
51
|
+
pageSize = 10;
|
|
52
|
+
itemsPerPage = 10;
|
|
53
|
+
paginationSizes = [10, 20, 30];
|
|
54
|
+
destroy$ = new Subject();
|
|
55
|
+
constructor(billingService, toast, changeDetector, modalService) {
|
|
56
|
+
this.billingService = billingService;
|
|
57
|
+
this.toast = toast;
|
|
58
|
+
this.changeDetector = changeDetector;
|
|
59
|
+
this.modalService = modalService;
|
|
60
|
+
}
|
|
61
|
+
ngOnInit() {
|
|
62
|
+
this.loadList(true);
|
|
63
|
+
}
|
|
64
|
+
ngOnDestroy() {
|
|
65
|
+
this.destroy$.next();
|
|
66
|
+
this.destroy$.complete();
|
|
67
|
+
}
|
|
68
|
+
// firstLoad decides the stage: an empty, unfiltered collection means the
|
|
69
|
+
// user has never uploaded — show the dropzone instead of an empty table.
|
|
70
|
+
loadList(firstLoad = false) {
|
|
71
|
+
this.loading = true;
|
|
72
|
+
const filters = {
|
|
73
|
+
status: this.activeStatus,
|
|
74
|
+
from: this.fromDate,
|
|
75
|
+
to: this.toDate,
|
|
76
|
+
source: this.source,
|
|
77
|
+
searchValue: this.searchValue,
|
|
78
|
+
limit: this.pageSize,
|
|
79
|
+
offset: this.currentPage,
|
|
80
|
+
};
|
|
81
|
+
this.billingService.bankTransactionList(filters).pipe(takeUntil(this.destroy$)).subscribe({
|
|
82
|
+
next: (res) => {
|
|
83
|
+
this.loading = false;
|
|
84
|
+
this.rows = res?.data?.data || [];
|
|
85
|
+
this.totalItems = res?.data?.count || 0;
|
|
86
|
+
if (res?.data?.cards) {
|
|
87
|
+
this.cards = res.data.cards;
|
|
88
|
+
}
|
|
89
|
+
this.noData = this.rows.length === 0;
|
|
90
|
+
if (firstLoad) {
|
|
91
|
+
this.stage = this.cards.total > 0 ? 'results' : 'upload';
|
|
92
|
+
}
|
|
93
|
+
this.changeDetector.detectChanges();
|
|
94
|
+
},
|
|
95
|
+
error: () => {
|
|
96
|
+
this.loading = false;
|
|
97
|
+
this.rows = [];
|
|
98
|
+
this.totalItems = 0;
|
|
99
|
+
this.noData = true;
|
|
100
|
+
if (firstLoad) {
|
|
101
|
+
this.stage = 'upload';
|
|
102
|
+
}
|
|
103
|
+
this.changeDetector.detectChanges();
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
onFileSelected(event) {
|
|
108
|
+
const file = event?.target?.files?.[0];
|
|
109
|
+
if (!file)
|
|
110
|
+
return;
|
|
111
|
+
const ok = /\.(xlsx|xls|csv)$/i.test(file.name);
|
|
112
|
+
if (!ok) {
|
|
113
|
+
this.toast.getErrorToast('Upload the bank statement as Excel (.xlsx, .xls) or CSV');
|
|
114
|
+
event.target.value = '';
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
this.uploading = true;
|
|
118
|
+
this.billingService.uploadBankStatement(file).pipe(takeUntil(this.destroy$)).subscribe({
|
|
119
|
+
next: (res) => {
|
|
120
|
+
this.uploading = false;
|
|
121
|
+
const d = res?.data || {};
|
|
122
|
+
const s = d.summary || {};
|
|
123
|
+
let msg = `"${file.name}" — ${d.inserted || 0} transactions added`;
|
|
124
|
+
if (d.inserted) {
|
|
125
|
+
msg += `: ${s.reconciled || 0} reconciled, ${s.needs_review || 0} need review, ` +
|
|
126
|
+
`${s.unmatched || 0} unmatched, ${s.excluded || 0} excluded`;
|
|
127
|
+
}
|
|
128
|
+
if (d.duplicates)
|
|
129
|
+
msg += ` (${d.duplicates} duplicates skipped)`;
|
|
130
|
+
if (d.closedInvoices?.length)
|
|
131
|
+
msg += ` · ${d.closedInvoices.length} invoice(s) closed as paid`;
|
|
132
|
+
this.toast.getPrimaryToast(msg);
|
|
133
|
+
// Auto-reconciliation may have closed invoices — refetch options next time.
|
|
134
|
+
this.resolveOptionsCache = null;
|
|
135
|
+
this.stage = 'results';
|
|
136
|
+
this.activeStatus = 'all';
|
|
137
|
+
this.currentPage = 1;
|
|
138
|
+
this.loadList();
|
|
139
|
+
},
|
|
140
|
+
error: (err) => {
|
|
141
|
+
this.uploading = false;
|
|
142
|
+
this.toast.getErrorToast(err?.error?.message || 'Failed to parse the statement file');
|
|
143
|
+
this.changeDetector.detectChanges();
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
event.target.value = '';
|
|
147
|
+
}
|
|
148
|
+
setStatus(id) {
|
|
149
|
+
this.activeStatus = id;
|
|
150
|
+
this.currentPage = 1;
|
|
151
|
+
this.loadList();
|
|
152
|
+
}
|
|
153
|
+
// Stat cards double as filters: clicking selects that status, clicking the
|
|
154
|
+
// already-selected card clears back to All.
|
|
155
|
+
toggleCardFilter(id) {
|
|
156
|
+
this.setStatus(this.activeStatus === id ? 'all' : id);
|
|
157
|
+
}
|
|
158
|
+
toggleFilter() {
|
|
159
|
+
this.filterOpen = !this.filterOpen;
|
|
160
|
+
}
|
|
161
|
+
applyFilters() {
|
|
162
|
+
this.currentPage = 1;
|
|
163
|
+
this.loadList();
|
|
164
|
+
}
|
|
165
|
+
clearFilters() {
|
|
166
|
+
this.fromDate = '';
|
|
167
|
+
this.toDate = '';
|
|
168
|
+
this.source = 'all';
|
|
169
|
+
this.currentPage = 1;
|
|
170
|
+
this.loadList();
|
|
171
|
+
}
|
|
172
|
+
get activeFilterCount() {
|
|
173
|
+
return (this.fromDate ? 1 : 0) + (this.toDate ? 1 : 0) + (this.source !== 'all' ? 1 : 0);
|
|
174
|
+
}
|
|
175
|
+
searchField() {
|
|
176
|
+
this.currentPage = 1;
|
|
177
|
+
this.loadList();
|
|
178
|
+
}
|
|
179
|
+
onPageChange(page) {
|
|
180
|
+
this.currentPage = page;
|
|
181
|
+
this.loadList();
|
|
182
|
+
}
|
|
183
|
+
onPageSizeChange(size) {
|
|
184
|
+
this.pageSize = size;
|
|
185
|
+
this.itemsPerPage = size;
|
|
186
|
+
this.currentPage = 1;
|
|
187
|
+
this.loadList();
|
|
188
|
+
}
|
|
189
|
+
// Reconciled rows carry the matched invoice's _id — open the same preview
|
|
190
|
+
// popup the All Invoices table uses.
|
|
191
|
+
openInvoicePreview(t) {
|
|
192
|
+
if (!t?.invoiceId)
|
|
193
|
+
return;
|
|
194
|
+
this.billingService.getInvoiceById(t.invoiceId).pipe(takeUntil(this.destroy$)).subscribe({
|
|
195
|
+
next: (res) => {
|
|
196
|
+
const invoiceData = res?.data;
|
|
197
|
+
if (!invoiceData) {
|
|
198
|
+
this.toast.getErrorToast('Failed to load invoice');
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
const modalRef = this.modalService.open(InvoicePreviewComponent, {
|
|
202
|
+
centered: true, size: 'xl', scrollable: true,
|
|
203
|
+
});
|
|
204
|
+
modalRef.componentInstance.invoiceData = invoiceData;
|
|
205
|
+
},
|
|
206
|
+
error: () => this.toast.getErrorToast('Failed to load invoice'),
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
// "Resolve & reconcile" popup for needs-review / unmatched rows. The
|
|
210
|
+
// customer/invoice options are cached for the page session — fetched once,
|
|
211
|
+
// invalidated only when an action changes invoice state (reconcile) or a
|
|
212
|
+
// new statement is uploaded.
|
|
213
|
+
resolveOptionsCache = null;
|
|
214
|
+
openResolve(t) {
|
|
215
|
+
if (this.resolveOptionsCache) {
|
|
216
|
+
this.showResolveModal(t, this.resolveOptionsCache);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
this.billingService.bankResolveOptions().pipe(takeUntil(this.destroy$)).subscribe({
|
|
220
|
+
next: (res) => {
|
|
221
|
+
this.resolveOptionsCache = res?.data || [];
|
|
222
|
+
this.showResolveModal(t, this.resolveOptionsCache);
|
|
223
|
+
},
|
|
224
|
+
error: () => this.toast.getErrorToast('Failed to load customers and invoices'),
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
showResolveModal(t, options) {
|
|
228
|
+
const modalRef = this.modalService.open(ResolveTransactionComponent, {
|
|
229
|
+
centered: true, size: 'md', scrollable: true,
|
|
230
|
+
});
|
|
231
|
+
modalRef.componentInstance.txn = t;
|
|
232
|
+
modalRef.componentInstance.options = options;
|
|
233
|
+
modalRef.result.then((msg) => {
|
|
234
|
+
if (msg) {
|
|
235
|
+
this.toast.getPrimaryToast(String(msg));
|
|
236
|
+
// A resolve may have closed/partially-paid an invoice — refetch next time.
|
|
237
|
+
this.resolveOptionsCache = null;
|
|
238
|
+
this.loadList();
|
|
239
|
+
}
|
|
240
|
+
}).catch(() => { });
|
|
241
|
+
}
|
|
242
|
+
// ===== Display helpers =====
|
|
243
|
+
statusLabel(s) {
|
|
244
|
+
const map = {
|
|
245
|
+
reconciled: 'Reconciled', needs_review: 'Needs review',
|
|
246
|
+
unmatched: 'Unmatched', excluded: 'Excluded',
|
|
247
|
+
};
|
|
248
|
+
return map[s] || s;
|
|
249
|
+
}
|
|
250
|
+
statusPillClass(s) {
|
|
251
|
+
const map = {
|
|
252
|
+
reconciled: 'pill pill-green', needs_review: 'pill pill-amber',
|
|
253
|
+
unmatched: 'pill pill-red', excluded: 'pill pill-gray',
|
|
254
|
+
};
|
|
255
|
+
return map[s] || 'pill pill-gray';
|
|
256
|
+
}
|
|
257
|
+
sourceLabel(s) {
|
|
258
|
+
const map = { bank: 'Bank Statement', va: 'Virtual Account', gateway: 'Gateway' };
|
|
259
|
+
return map[s] || s;
|
|
260
|
+
}
|
|
261
|
+
countOf(id) {
|
|
262
|
+
if (id === 'all')
|
|
263
|
+
return this.cards.total;
|
|
264
|
+
return this.cards[id]?.count || 0;
|
|
265
|
+
}
|
|
266
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: BankTransactionsComponent, deps: [{ token: i1.BillingService }, { token: i2.ToastService }, { token: i0.ChangeDetectorRef }, { token: i3.NgbModal }], target: i0.ɵɵFactoryTarget.Component });
|
|
267
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: BankTransactionsComponent, selector: "lib-bank-transactions", ngImport: i0, template: "<div>\n <!-- ============ Upload stage (no statements yet) ============ -->\n <div *ngIf=\"stage === 'upload' && !loading\" class=\"px-4 pb-4\">\n <div class=\"billingheader ms-1 mt-6\">Bank Statement Reconciliation</div>\n <div class=\"text-muted small ms-1 mt-1\">Upload a bank statement \u2014 transactions are stored and split into\n Reconciled, Needs review, Unmatched and Excluded.</div>\n <label class=\"dropzone mt-4\" for=\"stmt-file\">\n <div class=\"dz-ic\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\"\n stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M12 21V9M8 13l4-4 4 4M5 5h14\" />\n </svg>\n </div>\n <div class=\"dz-title mt-3\">Upload bank statement</div>\n <div class=\"text-muted small mt-1\">Drag & drop or click to browse \u00B7 <strong>Excel (.xlsx, .xls) or CSV</strong></div>\n <button type=\"button\" class=\"btn btn-primary btn-sm mt-3\" [disabled]=\"uploading\"\n onclick=\"document.getElementById('stmt-file').click(); event.preventDefault();\">\n {{ uploading ? 'Parsing\u2026' : 'Upload & parse' }}\n </button>\n </label>\n <input id=\"stmt-file\" type=\"file\" accept=\".xlsx,.xls,.csv\" class=\"d-none\" (change)=\"onFileSelected($event)\">\n </div>\n\n <!-- ============ Results stage ============ -->\n <div *ngIf=\"stage === 'results'\">\n <!-- Upload-another action -->\n <div class=\"d-flex justify-content-end align-items-center mt-4 me-4\">\n <input id=\"stmt-file-again\" type=\"file\" accept=\".xlsx,.xls,.csv\" class=\"d-none\"\n (change)=\"onFileSelected($event)\">\n <button type=\"button\" class=\"btn-outline btn align-items-end text-nowrap invheader\" [disabled]=\"uploading\"\n onclick=\"document.getElementById('stmt-file-again').click()\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\">\n <path d=\"M17.5 12.5V15.8333C17.5 16.2754 17.3244 16.6993 17.0118 17.0118C16.6993 17.3244 16.2754 17.5 15.8333 17.5H4.16667C3.72464 17.5 3.30072 17.3244 2.98816 17.0118C2.67559 16.6993 2.5 16.2754 2.5 15.8333V12.5M14.1667 6.66667L10 2.5M10 2.5L5.83333 6.66667M10 2.5V12.5\"\n stroke=\"#344054\" stroke-width=\"1.67\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n <span class=\"ms-2\">{{ uploading ? 'Parsing\u2026' : 'Upload another statement' }}</span>\n </button>\n </div>\n\n <!-- Status cards \u2014 clicking a card filters the table (click again to clear) -->\n <div class=\"row g-3 mt-1 mb-2 mx-2\">\n <div class=\"col\">\n <div class=\"invoice-card card-clickable\" [class.card-active]=\"activeStatus === 'reconciled'\"\n (click)=\"toggleCardFilter('reconciled')\">\n <div class=\"invoice-card-label\">Reconciled</div>\n <div class=\"invoice-card-value text-success\">{{ cards.reconciled.count }}</div>\n <div class=\"invoice-card-sub\">\u20B9{{ cards.reconciled.amount | number:'1.2-2':'en-IN' }}</div>\n </div>\n </div>\n <div class=\"col\">\n <div class=\"invoice-card card-clickable\" [class.card-active]=\"activeStatus === 'needs_review'\"\n (click)=\"toggleCardFilter('needs_review')\">\n <div class=\"invoice-card-label\">Needs review</div>\n <div class=\"invoice-card-value text-warning\">{{ cards.needs_review.count }}</div>\n <div class=\"invoice-card-sub\">\u20B9{{ cards.needs_review.amount | number:'1.2-2':'en-IN' }}</div>\n </div>\n </div>\n <div class=\"col\">\n <div class=\"invoice-card card-clickable\" [class.card-active]=\"activeStatus === 'unmatched'\"\n (click)=\"toggleCardFilter('unmatched')\">\n <div class=\"invoice-card-label\">Unmatched</div>\n <div class=\"invoice-card-value text-danger\">{{ cards.unmatched.count }}</div>\n <div class=\"invoice-card-sub\">\u20B9{{ cards.unmatched.amount | number:'1.2-2':'en-IN' }}</div>\n </div>\n </div>\n <div class=\"col\">\n <div class=\"invoice-card card-clickable\" [class.card-active]=\"activeStatus === 'excluded'\"\n (click)=\"toggleCardFilter('excluded')\">\n <div class=\"invoice-card-label\">Excluded</div>\n <div class=\"invoice-card-value\">{{ cards.excluded.count }}</div>\n <div class=\"invoice-card-sub\">\u20B9{{ cards.excluded.amount | number:'1.2-2':'en-IN' }}</div>\n </div>\n </div>\n </div>\n\n <!-- Status tabs + search/filter -->\n <div class=\"card-header paymenthistory border-0\">\n <div class=\"d-flex align-items-center gap-2 flex-wrap\">\n <button *ngFor=\"let tab of statusTabs\" class=\"btn btn-sm status-tab\"\n [class.active]=\"activeStatus === tab.id\"\n (click)=\"setStatus(tab.id)\">\n {{ tab.label }}\n <span *ngIf=\"countOf(tab.id)\" class=\"countchip ms-1\">{{ countOf(tab.id) }}</span>\n </button>\n </div>\n <div class=\"card-toolbar ms-auto\">\n <div class=\"d-flex align-items-center position-relative my-1\">\n <span class=\"svg-icon invoicesearch svg-icon-1 position-absolute mt-6 ms-3\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\">\n <rect opacity=\"0.5\" x=\"17.0365\" y=\"15.1223\" width=\"8.15546\" height=\"2\" rx=\"1\"\n transform=\"rotate(45 17.0365 15.1223)\" fill=\"currentColor\"></rect>\n <path d=\"M11 19C6.55556 19 3 15.4444 3 11C3 6.55556 6.55556 3 11 3C15.4444 3 19 6.55556 19 11C19 15.4444 15.4444 19 11 19ZM11 5C7.53333 5 5 7.53333 5 11C5 14.4667 7.53333 17 11 17C14.4667 17 17 14.4667 17 11C17 7.53333 14.4667 5 11 5Z\"\n fill=\"currentColor\"></path>\n </svg>\n </span>\n <input [(ngModel)]=\"searchValue\" type=\"text\" class=\"form-control ps-14 invoicesearch\"\n placeholder=\"Search payer, narration, UTR...\" autocomplete=\"off\" (change)=\"searchField()\" />\n <button type=\"button\" class=\"btn-outline btn align-items-end text-nowrap invheader\"\n (click)=\"toggleFilter()\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\"\n stroke=\"#344054\" stroke-width=\"2\">\n <path d=\"M3 5h18M6 12h12M10 19h4\" />\n </svg>\n <span class=\"ms-2\">Filter</span>\n <span *ngIf=\"activeFilterCount\" class=\"countchip ms-1\">{{ activeFilterCount }}</span>\n </button>\n </div>\n </div>\n </div>\n\n <!-- Filter panel -->\n <div *ngIf=\"filterOpen\" class=\"filter-panel mx-4 mb-3\">\n <div class=\"row g-3\">\n <div class=\"col-md-4\">\n <label class=\"form-label small fw-semibold\">Date \u2014 from</label>\n <input type=\"date\" class=\"form-control\" [(ngModel)]=\"fromDate\" (change)=\"applyFilters()\">\n </div>\n <div class=\"col-md-4\">\n <label class=\"form-label small fw-semibold\">Date \u2014 to</label>\n <input type=\"date\" class=\"form-control\" [(ngModel)]=\"toDate\" (change)=\"applyFilters()\">\n </div>\n <div class=\"col-md-4\">\n <label class=\"form-label small fw-semibold\">Source</label>\n <select class=\"form-select\" [(ngModel)]=\"source\" (change)=\"applyFilters()\">\n <option value=\"all\">All sources</option>\n <option value=\"bank\">Bank Statement</option>\n <option value=\"va\">Virtual Account</option>\n <option value=\"gateway\">Gateway</option>\n </select>\n </div>\n </div>\n <div class=\"d-flex justify-content-between align-items-center mt-3\" *ngIf=\"activeFilterCount\">\n <span class=\"text-muted small\">{{ totalItems }} transactions match</span>\n <button class=\"btn btn-link btn-sm p-0\" (click)=\"clearFilters()\">Clear all filters</button>\n </div>\n </div>\n\n <!-- Loading shimmer -->\n <ng-container *ngIf=\"loading\">\n <div class=\"row loader d-flex justify-content-center align-items-center\">\n <div class=\"shimmer\">\n <div class=\"wrapper\">\n <div class=\"stroke animate title\"></div>\n <div class=\"stroke animate link\"></div>\n <div class=\"stroke animate description\"></div>\n </div>\n </div>\n </div>\n </ng-container>\n\n <!-- Empty -->\n <ng-container *ngIf=\"!loading && noData\">\n <div class=\"row\">\n <div class=\"col-lg-12 mb-3\">\n <div class=\"card-body d-flex justify-content-center align-items-center flex-column\">\n <img class=\"img-src w-25\" src=\"./assets/tango/Icons/Nodata.svg\" alt=\"\">\n </div>\n </div>\n </div>\n </ng-container>\n\n <!-- Transactions table -->\n <div *ngIf=\"!loading && !noData\" class=\"table-responsive\">\n <table class=\"table accordion table bottom-border invoivetable text-nowrap\">\n <thead>\n <tr>\n <th>Date</th>\n <th>Source</th>\n <th>Payer (from narration)</th>\n <th>Reference / UTR</th>\n <th>Amount</th>\n <th>Brand Name</th>\n <th>Invoice</th>\n <th>Result</th>\n <th>Status</th>\n <th>Action</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let t of rows\">\n <td>\n <div class=\"table-title\">{{ t.valueDate | date: 'dd MMM, yyyy' }}</div>\n </td>\n <td>\n <span class=\"srcchip\" [class.srcchip-va]=\"t.source === 'va'\">{{ sourceLabel(t.source) }}</span>\n </td>\n <td>\n <div class=\"table-title payer-cell\">{{ t.payer || '\u2014' }}</div>\n <div class=\"narration-sub\" [title]=\"t.narration\">{{ t.narration }}</div>\n </td>\n <td>\n <span class=\"mono\">{{ t.refNo || '\u2014' }}</span>\n </td>\n <td>\n <div class=\"table-title\"><strong>\u20B9{{ t.amount | number:'1.2-2':'en-IN' }}</strong></div>\n </td>\n <td>\n <div class=\"table-title\">{{ t.identifiedClientName || '\u2014' }}</div>\n </td>\n <td>\n <div class=\"table-title\">\n <a *ngIf=\"t.invoice && t.invoiceId\" class=\"invoice-link\"\n (click)=\"openInvoicePreview(t); $event.stopPropagation()\">{{ t.invoice }}</a>\n <span *ngIf=\"t.invoice && !t.invoiceId\">{{ t.invoice }}</span>\n <span *ngIf=\"!t.invoice\">\u2014</span>\n </div>\n </td>\n <td>\n <div class=\"result-note\" [title]=\"t.resultNote\">{{ t.resultNote || '\u2014' }}</div>\n </td>\n <td>\n <span *ngIf=\"t.contacted\" class=\"pill pill-amber\">Reaching out</span>\n <span *ngIf=\"!t.contacted\" [ngClass]=\"statusPillClass(t.status)\">{{ statusLabel(t.status) }}</span>\n </td>\n <td>\n <button *ngIf=\"t.status === 'needs_review' || t.status === 'unmatched'\"\n class=\"btn btn-sm btn-primary\" (click)=\"openResolve(t)\">Resolve</button>\n </td>\n </tr>\n </tbody>\n </table>\n <lib-pagination class=\"text-start\" [itemsPerPage]=\"itemsPerPage\" [currentPage]=\"currentPage\"\n [totalItems]=\"totalItems\" [paginationSizes]=\"paginationSizes\" [pageSize]=\"pageSize\"\n (pageChange)=\"onPageChange($event)\" (pageSizeChange)=\"onPageSizeChange($event)\"></lib-pagination>\n </div>\n </div>\n</div>", styles: [".dropzone{display:block;border:1.5px dashed #E4E7EC;border-radius:14px;padding:34px;text-align:center;cursor:pointer;background:#fbfdff;transition:border-color .15s,background .15s}.dropzone:hover{border-color:#1493f5;background:#f5faff}.dz-ic{width:52px;height:52px;border-radius:14px;background:#e8f3fe;color:#1493f5;display:grid;place-items:center;margin:0 auto}.dz-title{font-weight:700;font-size:15px;color:#101828}.invoice-card{border:1px solid #E4E7EC;border-radius:12px;padding:18px 22px;background:#fff}.invoice-card.card-clickable{cursor:pointer;transition:border-color .12s,box-shadow .12s}.invoice-card.card-clickable:hover{border-color:#bcd9f7}.invoice-card.card-active{border-color:#1493f5;box-shadow:0 0 0 3px #1493f51f}.status-tab{border:0;border-radius:8px;padding:7px 14px;font-weight:600;color:#5b6472;background:transparent}.status-tab:hover{background:#f4f6f9}.status-tab.active{background:#e8f3fe;color:#1493f5}.status-tab.active .countchip{background:#d3e9fd;color:#1573c4}.invoice-card-label{color:#475467;font-size:13.5px;font-weight:500}.invoice-card-value{font-size:22px;font-weight:700;color:#101828;margin-top:6px;letter-spacing:-.3px}.invoice-card-value.text-success{color:#138a52}.invoice-card-value.text-danger{color:#d64545}.invoice-card-value.text-warning{color:#b9740a}.invoice-card-sub{color:#98a2b3;font-size:12.5px;margin-top:4px}.pill{display:inline-flex;align-items:center;padding:4px 10px;border-radius:999px;font-size:12px;font-weight:600;white-space:nowrap}.pill-green{background:#e7f7ee;color:#138a52}.pill-amber{background:#fdf0dc;color:#b9740a}.pill-red{background:#fdecec;color:#d64545}.pill-gray{background:#f1f3f6;color:#667085}.srcchip{display:inline-flex;align-items:center;gap:5px;font-size:11px;font-weight:600;padding:3px 9px;border-radius:999px;border:1px solid #E4E7EC;color:#475467;background:#fff;white-space:nowrap}.srcchip.srcchip-va{color:#7a3ea8;border-color:#e4d4f3;background:#f7f0fc}.countchip{background:#f1f3f6;color:#667085;font-weight:600;font-size:11px;border-radius:999px;padding:1px 8px}.payer-cell{max-width:230px;white-space:normal;line-height:1.35;font-weight:600}.narration-sub{max-width:230px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#98a2b3;font-size:11.5px;margin-top:2px}.result-note{max-width:220px;white-space:normal;line-height:1.4;color:#475467;font-size:12.5px}.mono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12.5px;color:#344054}.filter-panel{border:1px solid #E4E7EC;border-radius:14px;padding:16px 18px;background:#fbfdff}.invoice-link{color:#00a3ff;cursor:pointer;text-decoration:none}.invoice-link:hover{text-decoration:underline}\n"], dependencies: [{ kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i5.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i2.PaginationComponent, selector: "lib-pagination", inputs: ["collection", "itemsPerPage", "currentPage", "totalItems", "directionLinks", "pageSize", "paginationSizes"], outputs: ["pageChange", "pageSizeChange"] }, { kind: "pipe", type: i4.DecimalPipe, name: "number" }, { kind: "pipe", type: i4.DatePipe, name: "date" }] });
|
|
268
|
+
}
|
|
269
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: BankTransactionsComponent, decorators: [{
|
|
270
|
+
type: Component,
|
|
271
|
+
args: [{ selector: 'lib-bank-transactions', template: "<div>\n <!-- ============ Upload stage (no statements yet) ============ -->\n <div *ngIf=\"stage === 'upload' && !loading\" class=\"px-4 pb-4\">\n <div class=\"billingheader ms-1 mt-6\">Bank Statement Reconciliation</div>\n <div class=\"text-muted small ms-1 mt-1\">Upload a bank statement \u2014 transactions are stored and split into\n Reconciled, Needs review, Unmatched and Excluded.</div>\n <label class=\"dropzone mt-4\" for=\"stmt-file\">\n <div class=\"dz-ic\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\"\n stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M12 21V9M8 13l4-4 4 4M5 5h14\" />\n </svg>\n </div>\n <div class=\"dz-title mt-3\">Upload bank statement</div>\n <div class=\"text-muted small mt-1\">Drag & drop or click to browse \u00B7 <strong>Excel (.xlsx, .xls) or CSV</strong></div>\n <button type=\"button\" class=\"btn btn-primary btn-sm mt-3\" [disabled]=\"uploading\"\n onclick=\"document.getElementById('stmt-file').click(); event.preventDefault();\">\n {{ uploading ? 'Parsing\u2026' : 'Upload & parse' }}\n </button>\n </label>\n <input id=\"stmt-file\" type=\"file\" accept=\".xlsx,.xls,.csv\" class=\"d-none\" (change)=\"onFileSelected($event)\">\n </div>\n\n <!-- ============ Results stage ============ -->\n <div *ngIf=\"stage === 'results'\">\n <!-- Upload-another action -->\n <div class=\"d-flex justify-content-end align-items-center mt-4 me-4\">\n <input id=\"stmt-file-again\" type=\"file\" accept=\".xlsx,.xls,.csv\" class=\"d-none\"\n (change)=\"onFileSelected($event)\">\n <button type=\"button\" class=\"btn-outline btn align-items-end text-nowrap invheader\" [disabled]=\"uploading\"\n onclick=\"document.getElementById('stmt-file-again').click()\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\">\n <path d=\"M17.5 12.5V15.8333C17.5 16.2754 17.3244 16.6993 17.0118 17.0118C16.6993 17.3244 16.2754 17.5 15.8333 17.5H4.16667C3.72464 17.5 3.30072 17.3244 2.98816 17.0118C2.67559 16.6993 2.5 16.2754 2.5 15.8333V12.5M14.1667 6.66667L10 2.5M10 2.5L5.83333 6.66667M10 2.5V12.5\"\n stroke=\"#344054\" stroke-width=\"1.67\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n <span class=\"ms-2\">{{ uploading ? 'Parsing\u2026' : 'Upload another statement' }}</span>\n </button>\n </div>\n\n <!-- Status cards \u2014 clicking a card filters the table (click again to clear) -->\n <div class=\"row g-3 mt-1 mb-2 mx-2\">\n <div class=\"col\">\n <div class=\"invoice-card card-clickable\" [class.card-active]=\"activeStatus === 'reconciled'\"\n (click)=\"toggleCardFilter('reconciled')\">\n <div class=\"invoice-card-label\">Reconciled</div>\n <div class=\"invoice-card-value text-success\">{{ cards.reconciled.count }}</div>\n <div class=\"invoice-card-sub\">\u20B9{{ cards.reconciled.amount | number:'1.2-2':'en-IN' }}</div>\n </div>\n </div>\n <div class=\"col\">\n <div class=\"invoice-card card-clickable\" [class.card-active]=\"activeStatus === 'needs_review'\"\n (click)=\"toggleCardFilter('needs_review')\">\n <div class=\"invoice-card-label\">Needs review</div>\n <div class=\"invoice-card-value text-warning\">{{ cards.needs_review.count }}</div>\n <div class=\"invoice-card-sub\">\u20B9{{ cards.needs_review.amount | number:'1.2-2':'en-IN' }}</div>\n </div>\n </div>\n <div class=\"col\">\n <div class=\"invoice-card card-clickable\" [class.card-active]=\"activeStatus === 'unmatched'\"\n (click)=\"toggleCardFilter('unmatched')\">\n <div class=\"invoice-card-label\">Unmatched</div>\n <div class=\"invoice-card-value text-danger\">{{ cards.unmatched.count }}</div>\n <div class=\"invoice-card-sub\">\u20B9{{ cards.unmatched.amount | number:'1.2-2':'en-IN' }}</div>\n </div>\n </div>\n <div class=\"col\">\n <div class=\"invoice-card card-clickable\" [class.card-active]=\"activeStatus === 'excluded'\"\n (click)=\"toggleCardFilter('excluded')\">\n <div class=\"invoice-card-label\">Excluded</div>\n <div class=\"invoice-card-value\">{{ cards.excluded.count }}</div>\n <div class=\"invoice-card-sub\">\u20B9{{ cards.excluded.amount | number:'1.2-2':'en-IN' }}</div>\n </div>\n </div>\n </div>\n\n <!-- Status tabs + search/filter -->\n <div class=\"card-header paymenthistory border-0\">\n <div class=\"d-flex align-items-center gap-2 flex-wrap\">\n <button *ngFor=\"let tab of statusTabs\" class=\"btn btn-sm status-tab\"\n [class.active]=\"activeStatus === tab.id\"\n (click)=\"setStatus(tab.id)\">\n {{ tab.label }}\n <span *ngIf=\"countOf(tab.id)\" class=\"countchip ms-1\">{{ countOf(tab.id) }}</span>\n </button>\n </div>\n <div class=\"card-toolbar ms-auto\">\n <div class=\"d-flex align-items-center position-relative my-1\">\n <span class=\"svg-icon invoicesearch svg-icon-1 position-absolute mt-6 ms-3\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\">\n <rect opacity=\"0.5\" x=\"17.0365\" y=\"15.1223\" width=\"8.15546\" height=\"2\" rx=\"1\"\n transform=\"rotate(45 17.0365 15.1223)\" fill=\"currentColor\"></rect>\n <path d=\"M11 19C6.55556 19 3 15.4444 3 11C3 6.55556 6.55556 3 11 3C15.4444 3 19 6.55556 19 11C19 15.4444 15.4444 19 11 19ZM11 5C7.53333 5 5 7.53333 5 11C5 14.4667 7.53333 17 11 17C14.4667 17 17 14.4667 17 11C17 7.53333 14.4667 5 11 5Z\"\n fill=\"currentColor\"></path>\n </svg>\n </span>\n <input [(ngModel)]=\"searchValue\" type=\"text\" class=\"form-control ps-14 invoicesearch\"\n placeholder=\"Search payer, narration, UTR...\" autocomplete=\"off\" (change)=\"searchField()\" />\n <button type=\"button\" class=\"btn-outline btn align-items-end text-nowrap invheader\"\n (click)=\"toggleFilter()\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\"\n stroke=\"#344054\" stroke-width=\"2\">\n <path d=\"M3 5h18M6 12h12M10 19h4\" />\n </svg>\n <span class=\"ms-2\">Filter</span>\n <span *ngIf=\"activeFilterCount\" class=\"countchip ms-1\">{{ activeFilterCount }}</span>\n </button>\n </div>\n </div>\n </div>\n\n <!-- Filter panel -->\n <div *ngIf=\"filterOpen\" class=\"filter-panel mx-4 mb-3\">\n <div class=\"row g-3\">\n <div class=\"col-md-4\">\n <label class=\"form-label small fw-semibold\">Date \u2014 from</label>\n <input type=\"date\" class=\"form-control\" [(ngModel)]=\"fromDate\" (change)=\"applyFilters()\">\n </div>\n <div class=\"col-md-4\">\n <label class=\"form-label small fw-semibold\">Date \u2014 to</label>\n <input type=\"date\" class=\"form-control\" [(ngModel)]=\"toDate\" (change)=\"applyFilters()\">\n </div>\n <div class=\"col-md-4\">\n <label class=\"form-label small fw-semibold\">Source</label>\n <select class=\"form-select\" [(ngModel)]=\"source\" (change)=\"applyFilters()\">\n <option value=\"all\">All sources</option>\n <option value=\"bank\">Bank Statement</option>\n <option value=\"va\">Virtual Account</option>\n <option value=\"gateway\">Gateway</option>\n </select>\n </div>\n </div>\n <div class=\"d-flex justify-content-between align-items-center mt-3\" *ngIf=\"activeFilterCount\">\n <span class=\"text-muted small\">{{ totalItems }} transactions match</span>\n <button class=\"btn btn-link btn-sm p-0\" (click)=\"clearFilters()\">Clear all filters</button>\n </div>\n </div>\n\n <!-- Loading shimmer -->\n <ng-container *ngIf=\"loading\">\n <div class=\"row loader d-flex justify-content-center align-items-center\">\n <div class=\"shimmer\">\n <div class=\"wrapper\">\n <div class=\"stroke animate title\"></div>\n <div class=\"stroke animate link\"></div>\n <div class=\"stroke animate description\"></div>\n </div>\n </div>\n </div>\n </ng-container>\n\n <!-- Empty -->\n <ng-container *ngIf=\"!loading && noData\">\n <div class=\"row\">\n <div class=\"col-lg-12 mb-3\">\n <div class=\"card-body d-flex justify-content-center align-items-center flex-column\">\n <img class=\"img-src w-25\" src=\"./assets/tango/Icons/Nodata.svg\" alt=\"\">\n </div>\n </div>\n </div>\n </ng-container>\n\n <!-- Transactions table -->\n <div *ngIf=\"!loading && !noData\" class=\"table-responsive\">\n <table class=\"table accordion table bottom-border invoivetable text-nowrap\">\n <thead>\n <tr>\n <th>Date</th>\n <th>Source</th>\n <th>Payer (from narration)</th>\n <th>Reference / UTR</th>\n <th>Amount</th>\n <th>Brand Name</th>\n <th>Invoice</th>\n <th>Result</th>\n <th>Status</th>\n <th>Action</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let t of rows\">\n <td>\n <div class=\"table-title\">{{ t.valueDate | date: 'dd MMM, yyyy' }}</div>\n </td>\n <td>\n <span class=\"srcchip\" [class.srcchip-va]=\"t.source === 'va'\">{{ sourceLabel(t.source) }}</span>\n </td>\n <td>\n <div class=\"table-title payer-cell\">{{ t.payer || '\u2014' }}</div>\n <div class=\"narration-sub\" [title]=\"t.narration\">{{ t.narration }}</div>\n </td>\n <td>\n <span class=\"mono\">{{ t.refNo || '\u2014' }}</span>\n </td>\n <td>\n <div class=\"table-title\"><strong>\u20B9{{ t.amount | number:'1.2-2':'en-IN' }}</strong></div>\n </td>\n <td>\n <div class=\"table-title\">{{ t.identifiedClientName || '\u2014' }}</div>\n </td>\n <td>\n <div class=\"table-title\">\n <a *ngIf=\"t.invoice && t.invoiceId\" class=\"invoice-link\"\n (click)=\"openInvoicePreview(t); $event.stopPropagation()\">{{ t.invoice }}</a>\n <span *ngIf=\"t.invoice && !t.invoiceId\">{{ t.invoice }}</span>\n <span *ngIf=\"!t.invoice\">\u2014</span>\n </div>\n </td>\n <td>\n <div class=\"result-note\" [title]=\"t.resultNote\">{{ t.resultNote || '\u2014' }}</div>\n </td>\n <td>\n <span *ngIf=\"t.contacted\" class=\"pill pill-amber\">Reaching out</span>\n <span *ngIf=\"!t.contacted\" [ngClass]=\"statusPillClass(t.status)\">{{ statusLabel(t.status) }}</span>\n </td>\n <td>\n <button *ngIf=\"t.status === 'needs_review' || t.status === 'unmatched'\"\n class=\"btn btn-sm btn-primary\" (click)=\"openResolve(t)\">Resolve</button>\n </td>\n </tr>\n </tbody>\n </table>\n <lib-pagination class=\"text-start\" [itemsPerPage]=\"itemsPerPage\" [currentPage]=\"currentPage\"\n [totalItems]=\"totalItems\" [paginationSizes]=\"paginationSizes\" [pageSize]=\"pageSize\"\n (pageChange)=\"onPageChange($event)\" (pageSizeChange)=\"onPageSizeChange($event)\"></lib-pagination>\n </div>\n </div>\n</div>", styles: [".dropzone{display:block;border:1.5px dashed #E4E7EC;border-radius:14px;padding:34px;text-align:center;cursor:pointer;background:#fbfdff;transition:border-color .15s,background .15s}.dropzone:hover{border-color:#1493f5;background:#f5faff}.dz-ic{width:52px;height:52px;border-radius:14px;background:#e8f3fe;color:#1493f5;display:grid;place-items:center;margin:0 auto}.dz-title{font-weight:700;font-size:15px;color:#101828}.invoice-card{border:1px solid #E4E7EC;border-radius:12px;padding:18px 22px;background:#fff}.invoice-card.card-clickable{cursor:pointer;transition:border-color .12s,box-shadow .12s}.invoice-card.card-clickable:hover{border-color:#bcd9f7}.invoice-card.card-active{border-color:#1493f5;box-shadow:0 0 0 3px #1493f51f}.status-tab{border:0;border-radius:8px;padding:7px 14px;font-weight:600;color:#5b6472;background:transparent}.status-tab:hover{background:#f4f6f9}.status-tab.active{background:#e8f3fe;color:#1493f5}.status-tab.active .countchip{background:#d3e9fd;color:#1573c4}.invoice-card-label{color:#475467;font-size:13.5px;font-weight:500}.invoice-card-value{font-size:22px;font-weight:700;color:#101828;margin-top:6px;letter-spacing:-.3px}.invoice-card-value.text-success{color:#138a52}.invoice-card-value.text-danger{color:#d64545}.invoice-card-value.text-warning{color:#b9740a}.invoice-card-sub{color:#98a2b3;font-size:12.5px;margin-top:4px}.pill{display:inline-flex;align-items:center;padding:4px 10px;border-radius:999px;font-size:12px;font-weight:600;white-space:nowrap}.pill-green{background:#e7f7ee;color:#138a52}.pill-amber{background:#fdf0dc;color:#b9740a}.pill-red{background:#fdecec;color:#d64545}.pill-gray{background:#f1f3f6;color:#667085}.srcchip{display:inline-flex;align-items:center;gap:5px;font-size:11px;font-weight:600;padding:3px 9px;border-radius:999px;border:1px solid #E4E7EC;color:#475467;background:#fff;white-space:nowrap}.srcchip.srcchip-va{color:#7a3ea8;border-color:#e4d4f3;background:#f7f0fc}.countchip{background:#f1f3f6;color:#667085;font-weight:600;font-size:11px;border-radius:999px;padding:1px 8px}.payer-cell{max-width:230px;white-space:normal;line-height:1.35;font-weight:600}.narration-sub{max-width:230px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#98a2b3;font-size:11.5px;margin-top:2px}.result-note{max-width:220px;white-space:normal;line-height:1.4;color:#475467;font-size:12.5px}.mono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12.5px;color:#344054}.filter-panel{border:1px solid #E4E7EC;border-radius:14px;padding:16px 18px;background:#fbfdff}.invoice-link{color:#00a3ff;cursor:pointer;text-decoration:none}.invoice-link:hover{text-decoration:underline}\n"] }]
|
|
272
|
+
}], ctorParameters: () => [{ type: i1.BillingService }, { type: i2.ToastService }, { type: i0.ChangeDetectorRef }, { type: i3.NgbModal }] });
|
|
273
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFuay10cmFuc2FjdGlvbnMuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvdGFuZ28tbWFuYWdlLWJpbGxpbmcvc3JjL2xpYi9jb21wb25lbnRzL2JhbmstdHJhbnNhY3Rpb25zL2JhbmstdHJhbnNhY3Rpb25zLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3RhbmdvLW1hbmFnZS1iaWxsaW5nL3NyYy9saWIvY29tcG9uZW50cy9iYW5rLXRyYW5zYWN0aW9ucy9iYW5rLXRyYW5zYWN0aW9ucy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQXFCLFNBQVMsRUFBcUIsTUFBTSxlQUFlLENBQUM7QUFDaEYsT0FBTyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFJMUMsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sOENBQThDLENBQUM7QUFDdkYsT0FBTyxFQUFFLDJCQUEyQixFQUFFLE1BQU0scURBQXFELENBQUM7Ozs7Ozs7QUFFbEcsMkVBQTJFO0FBQzNFLDRFQUE0RTtBQUM1RSw2RUFBNkU7QUFDN0UseUVBQXlFO0FBTXpFLE1BQU0sT0FBTyx5QkFBeUI7SUEyQzFCO0lBQ0E7SUFDQTtJQUNBO0lBN0NWLDRFQUE0RTtJQUM1RSxLQUFLLEdBQXlCLFFBQVEsQ0FBQztJQUN2QyxPQUFPLEdBQUcsSUFBSSxDQUFDO0lBQ2YsU0FBUyxHQUFHLEtBQUssQ0FBQztJQUNsQixNQUFNLEdBQUcsS0FBSyxDQUFDO0lBRWYsSUFBSSxHQUFVLEVBQUUsQ0FBQztJQUNqQixVQUFVLEdBQUcsQ0FBQyxDQUFDO0lBQ2YsS0FBSyxHQUFHO1FBQ04sVUFBVSxFQUFFLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFO1FBQ25DLFlBQVksRUFBRSxFQUFFLEtBQUssRUFB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RGV0ZWN0b3JSZWYsIENvbXBvbmVudCwgT25EZXN0cm95LCBPbkluaXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFN1YmplY3QsIHRha2VVbnRpbCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgTmdiTW9kYWwgfSBmcm9tICdAbmctYm9vdHN0cmFwL25nLWJvb3RzdHJhcCc7XG5pbXBvcnQgeyBUb2FzdFNlcnZpY2UgfSBmcm9tICd0YW5nby1hcHAtdWktc2hhcmVkJztcbmltcG9ydCB7IEJpbGxpbmdTZXJ2aWNlIH0gZnJvbSAnLi4vc2VydmljZXMvYmlsbGluZy5zZXJ2aWNlJztcbmltcG9ydCB7IEludm9pY2VQcmV2aWV3Q29tcG9uZW50IH0gZnJvbSAnLi4vaW52b2ljZS1wcmV2aWV3L2ludm9pY2UtcHJldmlldy5jb21wb25lbnQnO1xuaW1wb3J0IHsgUmVzb2x2ZVRyYW5zYWN0aW9uQ29tcG9uZW50IH0gZnJvbSAnLi9yZXNvbHZlLXRyYW5zYWN0aW9uL3Jlc29sdmUtdHJhbnNhY3Rpb24uY29tcG9uZW50JztcblxuLy8gQmFuay1zdGF0ZW1lbnQgcmVjb25jaWxpYXRpb24gdGFiLiBVcGxvYWQgYSBzdGF0ZW1lbnQgZXhwb3J0IChDU1YvWExTWCksXG4vLyByb3dzIGxhbmQgaW4gdGhlIGBiYW5rdHJhbnNhY3Rpb25gIGNvbGxlY3Rpb24gYW5kIGFyZSBidWNrZXRlZCBieSBzdGF0dXM6XG4vLyByZWNvbmNpbGVkIC8gbmVlZHNfcmV2aWV3IC8gdW5tYXRjaGVkIC8gZXhjbHVkZWQuIENsYXNzaWZpY2F0aW9uIHJ1bGVzIGFyZVxuLy8gbm90IHdpcmVkIHlldCDigJQgbmV3IHJvd3MgYXJyaXZlIGFzICd1bm1hdGNoZWQnIHVudGlsIHRoYXQgcGFzcyBleGlzdHMuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdsaWItYmFuay10cmFuc2FjdGlvbnMnLFxuICB0ZW1wbGF0ZVVybDogJy4vYmFuay10cmFuc2FjdGlvbnMuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybDogJy4vYmFuay10cmFuc2FjdGlvbnMuY29tcG9uZW50LnNjc3MnXG59KVxuZXhwb3J0IGNsYXNzIEJhbmtUcmFuc2FjdGlvbnNDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSB7XG4gIC8vICd1cGxvYWQnIHNob3dzIHRoZSBkcm9wem9uZSAoZW1wdHkgY29sbGVjdGlvbik7ICdyZXN1bHRzJyB0aGUgdGFibGUgdmlldy5cbiAgc3RhZ2U6ICd1cGxvYWQnIHwgJ3Jlc3VsdHMnID0gJ3VwbG9hZCc7XG4gIGxvYWRpbmcgPSB0cnVlO1xuICB1cGxvYWRpbmcgPSBmYWxzZTtcbiAgbm9EYXRhID0gZmFsc2U7XG5cbiAgcm93czogYW55W10gPSBbXTtcbiAgdG90YWxJdGVtcyA9IDA7XG4gIGNhcmRzID0ge1xuICAgIHJlY29uY2lsZWQ6IHsgY291bnQ6IDAsIGFtb3VudDogMCB9LFxuICAgIG5lZWRzX3JldmlldzogeyBjb3VudDogMCwgYW1vdW50OiAwIH0sXG4gICAgdW5tYXRjaGVkOiB7IGNvdW50OiAwLCBhbW91bnQ6IDAgfSxcbiAgICBleGNsdWRlZDogeyBjb3VudDogMCwgYW1vdW50OiAwIH0sXG4gICAgdG90YWw6IDAsXG4gIH07XG5cbiAgLy8gU3RhdHVzIHNlZ21lbnQgdGFicyDigJQgaWRzIG1hdGNoIHRoZSBiYWNrZW5kIGVudW0uXG4gIHN0YXR1c1RhYnMgPSBbXG4gICAgeyBpZDogJ2FsbCcsIGxhYmVsOiAnQWxsJyB9LFxuICAgIHsgaWQ6ICdyZWNvbmNpbGVkJywgbGFiZWw6ICdSZWNvbmNpbGVkJyB9LFxuICAgIHsgaWQ6ICduZWVkc19yZXZpZXcnLCBsYWJlbDogJ05lZWRzIHJldmlldycgfSxcbiAgICB7IGlkOiAndW5tYXRjaGVkJywgbGFiZWw6ICdVbm1hdGNoZWQnIH0sXG4gICAgeyBpZDogJ2V4Y2x1ZGVkJywgbGFiZWw6ICdFeGNsdWRlZCcgfSxcbiAgXTtcbiAgYWN0aXZlU3RhdHVzID0gJ2FsbCc7XG5cbiAgLy8gRmlsdGVyIHBvcG92ZXIgc3RhdGUuXG4gIGZpbHRlck9wZW4gPSBmYWxzZTtcbiAgZnJvbURhdGUgPSAnJztcbiAgdG9EYXRlID0gJyc7XG4gIHNvdXJjZSA9ICdhbGwnO1xuICBzZWFyY2hWYWx1ZSA9ICcnO1xuXG4gIC8vIFBhZ2luYXRpb24g4oCUIG1pcnJvcnMgdGhlIEFsbCBJbnZvaWNlcyB0YWJsZS5cbiAgY3VycmVudFBhZ2UgPSAxO1xuICBwYWdlU2l6ZSA9IDEwO1xuICBpdGVtc1BlclBhZ2UgPSAxMDtcbiAgcGFnaW5hdGlvblNpemVzID0gWzEwLCAyMCwgMzBdO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgZGVzdHJveSQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgYmlsbGluZ1NlcnZpY2U6IEJpbGxpbmdTZXJ2aWNlLFxuICAgIHByaXZhdGUgdG9hc3Q6IFRvYXN0U2VydmljZSxcbiAgICBwcml2YXRlIGNoYW5nZURldGVjdG9yOiBDaGFuZ2VEZXRlY3RvclJlZixcbiAgICBwcml2YXRlIG1vZGFsU2VydmljZTogTmdiTW9kYWwsXG4gICkge31cblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLmxvYWRMaXN0KHRydWUpO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5kZXN0cm95JC5uZXh0KCk7XG4gICAgdGhpcy5kZXN0cm95JC5jb21wbGV0ZSgpO1xuICB9XG5cbiAgLy8gZmlyc3RMb2FkIGRlY2lkZXMgdGhlIHN0YWdlOiBhbiBlbXB0eSwgdW5maWx0ZXJlZCBjb2xsZWN0aW9uIG1lYW5zIHRoZVxuICAvLyB1c2VyIGhhcyBuZXZlciB1cGxvYWRlZCDigJQgc2hvdyB0aGUgZHJvcHpvbmUgaW5zdGVhZCBvZiBhbiBlbXB0eSB0YWJsZS5cbiAgbG9hZExpc3QoZmlyc3RMb2FkID0gZmFsc2UpIHtcbiAgICB0aGlzLmxvYWRpbmcgPSB0cnVlO1xuICAgIGNvbnN0IGZpbHRlcnMgPSB7XG4gICAgICBzdGF0dXM6IHRoaXMuYWN0aXZlU3RhdHVzLFxuICAgICAgZnJvbTogdGhpcy5mcm9tRGF0ZSxcbiAgICAgIHRvOiB0aGlzLnRvRGF0ZSxcbiAgICAgIHNvdXJjZTogdGhpcy5zb3VyY2UsXG4gICAgICBzZWFyY2hWYWx1ZTogdGhpcy5zZWFyY2hWYWx1ZSxcbiAgICAgIGxpbWl0OiB0aGlzLnBhZ2VTaXplLFxuICAgICAgb2Zmc2V0OiB0aGlzLmN1cnJlbnRQYWdlLFxuICAgIH07XG4gICAgdGhpcy5iaWxsaW5nU2VydmljZS5iYW5rVHJhbnNhY3Rpb25MaXN0KGZpbHRlcnMpLnBpcGUodGFrZVVudGlsKHRoaXMuZGVzdHJveSQpKS5zdWJzY3JpYmUoe1xuICAgICAgbmV4dDogKHJlcykgPT4ge1xuICAgICAgICB0aGlzLmxvYWRpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5yb3dzID0gcmVzPy5kYXRhPy5kYXRhIHx8IFtdO1xuICAgICAgICB0aGlzLnRvdGFsSXRlbXMgPSByZXM/LmRhdGE/LmNvdW50IHx8IDA7XG4gICAgICAgIGlmIChyZXM/LmRhdGE/LmNhcmRzKSB7XG4gICAgICAgICAgdGhpcy5jYXJkcyA9IHJlcy5kYXRhLmNhcmRzO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMubm9EYXRhID0gdGhpcy5yb3dzLmxlbmd0aCA9PT0gMDtcbiAgICAgICAgaWYgKGZpcnN0TG9hZCkge1xuICAgICAgICAgIHRoaXMuc3RhZ2UgPSB0aGlzLmNhcmRzLnRvdGFsID4gMCA/ICdyZXN1bHRzJyA6ICd1cGxvYWQnO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY2hhbmdlRGV0ZWN0b3IuZGV0ZWN0Q2hhbmdlcygpO1xuICAgICAgfSxcbiAgICAgIGVycm9yOiAoKSA9PiB7XG4gICAgICAgIHRoaXMubG9hZGluZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLnJvd3MgPSBbXTtcbiAgICAgICAgdGhpcy50b3RhbEl0ZW1zID0gMDtcbiAgICAgICAgdGhpcy5ub0RhdGEgPSB0cnVlO1xuICAgICAgICBpZiAoZmlyc3RMb2FkKSB7XG4gICAgICAgICAgdGhpcy5zdGFnZSA9ICd1cGxvYWQnO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY2hhbmdlRGV0ZWN0b3IuZGV0ZWN0Q2hhbmdlcygpO1xuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuXG4gIG9uRmlsZVNlbGVjdGVkKGV2ZW50OiBhbnkpIHtcbiAgICBjb25zdCBmaWxlOiBGaWxlID0gZXZlbnQ/LnRhcmdldD8uZmlsZXM/LlswXTtcbiAgICBpZiAoIWZpbGUpIHJldHVybjtcbiAgICBjb25zdCBvayA9IC9cXC4oeGxzeHx4bHN8Y3N2KSQvaS50ZXN0KGZpbGUubmFtZSk7XG4gICAgaWYgKCFvaykge1xuICAgICAgdGhpcy50b2FzdC5nZXRFcnJvclRvYXN0KCdVcGxvYWQgdGhlIGJhbmsgc3RhdGVtZW50IGFzIEV4Y2VsICgueGxzeCwgLnhscykgb3IgQ1NWJyk7XG4gICAgICBldmVudC50YXJnZXQudmFsdWUgPSAnJztcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy51cGxvYWRpbmcgPSB0cnVlO1xuICAgIHRoaXMuYmlsbGluZ1NlcnZpY2UudXBsb2FkQmFua1N0YXRlbWVudChmaWxlKS5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSkuc3Vic2NyaWJlKHtcbiAgICAgIG5leHQ6IChyZXMpID0+IHtcbiAgICAgICAgdGhpcy51cGxvYWRpbmcgPSBmYWxzZTtcbiAgICAgICAgY29uc3QgZCA9IHJlcz8uZGF0YSB8fCB7fTtcbiAgICAgICAgY29uc3QgcyA9IGQuc3VtbWFyeSB8fCB7fTtcbiAgICAgICAgbGV0IG1zZyA9IGBcIiR7ZmlsZS5uYW1lfVwiIOKAlCAke2QuaW5zZXJ0ZWQgfHwgMH0gdHJhbnNhY3Rpb25zIGFkZGVkYDtcbiAgICAgICAgaWYgKGQuaW5zZXJ0ZWQpIHtcbiAgICAgICAgICBtc2cgKz0gYDogJHtzLnJlY29uY2lsZWQgfHwgMH0gcmVjb25jaWxlZCwgJHtzLm5lZWRzX3JldmlldyB8fCAwfSBuZWVkIHJldmlldywgYCArXG4gICAgICAgICAgICAgICAgIGAke3MudW5tYXRjaGVkIHx8IDB9IHVubWF0Y2hlZCwgJHtzLmV4Y2x1ZGVkIHx8IDB9IGV4Y2x1ZGVkYDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZC5kdXBsaWNhdGVzKSBtc2cgKz0gYCAoJHtkLmR1cGxpY2F0ZXN9IGR1cGxpY2F0ZXMgc2tpcHBlZClgO1xuICAgICAgICBpZiAoZC5jbG9zZWRJbnZvaWNlcz8ubGVuZ3RoKSBtc2cgKz0gYCDCtyAke2QuY2xvc2VkSW52b2ljZXMubGVuZ3RofSBpbnZvaWNlKHMpIGNsb3NlZCBhcyBwYWlkYDtcbiAgICAgICAgdGhpcy50b2FzdC5nZXRQcmltYXJ5VG9hc3QobXNnKTtcbiAgICAgICAgLy8gQXV0by1yZWNvbmNpbGlhdGlvbiBtYXkgaGF2ZSBjbG9zZWQgaW52b2ljZXMg4oCUIHJlZmV0Y2ggb3B0aW9ucyBuZXh0IHRpbWUuXG4gICAgICAgIHRoaXMucmVzb2x2ZU9wdGlvbnNDYWNoZSA9IG51bGw7XG4gICAgICAgIHRoaXMuc3RhZ2UgPSAncmVzdWx0cyc7XG4gICAgICAgIHRoaXMuYWN0aXZlU3RhdHVzID0gJ2FsbCc7XG4gICAgICAgIHRoaXMuY3VycmVudFBhZ2UgPSAxO1xuICAgICAgICB0aGlzLmxvYWRMaXN0KCk7XG4gICAgICB9LFxuICAgICAgZXJyb3I6IChlcnIpID0+IHtcbiAgICAgICAgdGhpcy51cGxvYWRpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy50b2FzdC5nZXRFcnJvclRvYXN0KGVycj8uZXJyb3I/Lm1lc3NhZ2UgfHwgJ0ZhaWxlZCB0byBwYXJzZSB0aGUgc3RhdGVtZW50IGZpbGUnKTtcbiAgICAgICAgdGhpcy5jaGFuZ2VEZXRlY3Rvci5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgICB9LFxuICAgIH0pO1xuICAgIGV2ZW50LnRhcmdldC52YWx1ZSA9ICcnO1xuICB9XG5cbiAgc2V0U3RhdHVzKGlkOiBzdHJpbmcpIHtcbiAgICB0aGlzLmFjdGl2ZVN0YXR1cyA9IGlkO1xuICAgIHRoaXMuY3VycmVudFBhZ2UgPSAxO1xuICAgIHRoaXMubG9hZExpc3QoKTtcbiAgfVxuXG4gIC8vIFN0YXQgY2FyZHMgZG91YmxlIGFzIGZpbHRlcnM6IGNsaWNraW5nIHNlbGVjdHMgdGhhdCBzdGF0dXMsIGNsaWNraW5nIHRoZVxuICAvLyBhbHJlYWR5LXNlbGVjdGVkIGNhcmQgY2xlYXJzIGJhY2sgdG8gQWxsLlxuICB0b2dnbGVDYXJkRmlsdGVyKGlkOiBzdHJpbmcpIHtcbiAgICB0aGlzLnNldFN0YXR1cyh0aGlzLmFjdGl2ZVN0YXR1cyA9PT0gaWQgPyAnYWxsJyA6IGlkKTtcbiAgfVxuXG4gIHRvZ2dsZUZpbHRlcigpIHtcbiAgICB0aGlzLmZpbHRlck9wZW4gPSAhdGhpcy5maWx0ZXJPcGVuO1xuICB9XG5cbiAgYXBwbHlGaWx0ZXJzKCkge1xuICAgIHRoaXMuY3VycmVudFBhZ2UgPSAxO1xuICAgIHRoaXMubG9hZExpc3QoKTtcbiAgfVxuXG4gIGNsZWFyRmlsdGVycygpIHtcbiAgICB0aGlzLmZyb21EYXRlID0gJyc7XG4gICAgdGhpcy50b0RhdGUgPSAnJztcbiAgICB0aGlzLnNvdXJjZSA9ICdhbGwnO1xuICAgIHRoaXMuY3VycmVudFBhZ2UgPSAxO1xuICAgIHRoaXMubG9hZExpc3QoKTtcbiAgfVxuXG4gIGdldCBhY3RpdmVGaWx0ZXJDb3VudCgpOiBudW1iZXIge1xuICAgIHJldHVybiAodGhpcy5mcm9tRGF0ZSA/IDEgOiAwKSArICh0aGlzLnRvRGF0ZSA/IDEgOiAwKSArICh0aGlzLnNvdXJjZSAhPT0gJ2FsbCcgPyAxIDogMCk7XG4gIH1cblxuICBzZWFyY2hGaWVsZCgpIHtcbiAgICB0aGlzLmN1cnJlbnRQYWdlID0gMTtcbiAgICB0aGlzLmxvYWRMaXN0KCk7XG4gIH1cblxuICBvblBhZ2VDaGFuZ2UocGFnZTogbnVtYmVyKSB7XG4gICAgdGhpcy5jdXJyZW50UGFnZSA9IHBhZ2U7XG4gICAgdGhpcy5sb2FkTGlzdCgpO1xuICB9XG5cbiAgb25QYWdlU2l6ZUNoYW5nZShzaXplOiBudW1iZXIpIHtcbiAgICB0aGlzLnBhZ2VTaXplID0gc2l6ZTtcbiAgICB0aGlzLml0ZW1zUGVyUGFnZSA9IHNpemU7XG4gICAgdGhpcy5jdXJyZW50UGFnZSA9IDE7XG4gICAgdGhpcy5sb2FkTGlzdCgpO1xuICB9XG5cbiAgLy8gUmVjb25jaWxlZCByb3dzIGNhcnJ5IHRoZSBtYXRjaGVkIGludm9pY2UncyBfaWQg4oCUIG9wZW4gdGhlIHNhbWUgcHJldmlld1xuICAvLyBwb3B1cCB0aGUgQWxsIEludm9pY2VzIHRhYmxlIHVzZXMuXG4gIG9wZW5JbnZvaWNlUHJldmlldyh0OiBhbnkpIHtcbiAgICBpZiAoIXQ/Lmludm9pY2VJZCkgcmV0dXJuO1xuICAgIHRoaXMuYmlsbGluZ1NlcnZpY2UuZ2V0SW52b2ljZUJ5SWQodC5pbnZvaWNlSWQpLnBpcGUodGFrZVVudGlsKHRoaXMuZGVzdHJveSQpKS5zdWJzY3JpYmUoe1xuICAgICAgbmV4dDogKHJlczogYW55KSA9PiB7XG4gICAgICAgIGNvbnN0IGludm9pY2VEYXRhID0gcmVzPy5kYXRhO1xuICAgICAgICBpZiAoIWludm9pY2VEYXRhKSB7XG4gICAgICAgICAgdGhpcy50b2FzdC5nZXRFcnJvclRvYXN0KCdGYWlsZWQgdG8gbG9hZCBpbnZvaWNlJyk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IG1vZGFsUmVmID0gdGhpcy5tb2RhbFNlcnZpY2Uub3BlbihJbnZvaWNlUHJldmlld0NvbXBvbmVudCwge1xuICAgICAgICAgIGNlbnRlcmVkOiB0cnVlLCBzaXplOiAneGwnLCBzY3JvbGxhYmxlOiB0cnVlLFxuICAgICAgICB9KTtcbiAgICAgICAgbW9kYWxSZWYuY29tcG9uZW50SW5zdGFuY2UuaW52b2ljZURhdGEgPSBpbnZvaWNlRGF0YTtcbiAgICAgIH0sXG4gICAgICBlcnJvcjogKCkgPT4gdGhpcy50b2FzdC5nZXRFcnJvclRvYXN0KCdGYWlsZWQgdG8gbG9hZCBpbnZvaWNlJyksXG4gICAgfSk7XG4gIH1cblxuICAvLyBcIlJlc29sdmUgJiByZWNvbmNpbGVcIiBwb3B1cCBmb3IgbmVlZHMtcmV2aWV3IC8gdW5tYXRjaGVkIHJvd3MuIFRoZVxuICAvLyBjdXN0b21lci9pbnZvaWNlIG9wdGlvbnMgYXJlIGNhY2hlZCBmb3IgdGhlIHBhZ2Ugc2Vzc2lvbiDigJQgZmV0Y2hlZCBvbmNlLFxuICAvLyBpbnZhbGlkYXRlZCBvbmx5IHdoZW4gYW4gYWN0aW9uIGNoYW5nZXMgaW52b2ljZSBzdGF0ZSAocmVjb25jaWxlKSBvciBhXG4gIC8vIG5ldyBzdGF0ZW1lbnQgaXMgdXBsb2FkZWQuXG4gIHByaXZhdGUgcmVzb2x2ZU9wdGlvbnNDYWNoZTogYW55W10gfCBudWxsID0gbnVsbDtcblxuICBvcGVuUmVzb2x2ZSh0OiBhbnkpIHtcbiAgICBpZiAodGhpcy5yZXNvbHZlT3B0aW9uc0NhY2hlKSB7XG4gICAgICB0aGlzLnNob3dSZXNvbHZlTW9kYWwodCwgdGhpcy5yZXNvbHZlT3B0aW9uc0NhY2hlKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5iaWxsaW5nU2VydmljZS5iYW5rUmVzb2x2ZU9wdGlvbnMoKS5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSkuc3Vic2NyaWJlKHtcbiAgICAgIG5leHQ6IChyZXMpID0+IHtcbiAgICAgICAgdGhpcy5yZXNvbHZlT3B0aW9uc0NhY2hlID0gcmVzPy5kYXRhIHx8IFtdO1xuICAgICAgICB0aGlzLnNob3dSZXNvbHZlTW9kYWwodCwgdGhpcy5yZXNvbHZlT3B0aW9uc0NhY2hlISk7XG4gICAgICB9LFxuICAgICAgZXJyb3I6ICgpID0+IHRoaXMudG9hc3QuZ2V0RXJyb3JUb2FzdCgnRmFpbGVkIHRvIGxvYWQgY3VzdG9tZXJzIGFuZCBpbnZvaWNlcycpLFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBzaG93UmVzb2x2ZU1vZGFsKHQ6IGFueSwgb3B0aW9uczogYW55W10pIHtcbiAgICBjb25zdCBtb2RhbFJlZiA9IHRoaXMubW9kYWxTZXJ2aWNlLm9wZW4oUmVzb2x2ZVRyYW5zYWN0aW9uQ29tcG9uZW50LCB7XG4gICAgICBjZW50ZXJlZDogdHJ1ZSwgc2l6ZTogJ21kJywgc2Nyb2xsYWJsZTogdHJ1ZSxcbiAgICB9KTtcbiAgICBtb2RhbFJlZi5jb21wb25lbnRJbnN0YW5jZS50eG4gPSB0O1xuICAgIG1vZGFsUmVmLmNvbXBvbmVudEluc3RhbmNlLm9wdGlvbnMgPSBvcHRpb25zO1xuICAgIG1vZGFsUmVmLnJlc3VsdC50aGVuKChtc2c6IGFueSkgPT4ge1xuICAgICAgaWYgKG1zZykge1xuICAgICAgICB0aGlzLnRvYXN0LmdldFByaW1hcnlUb2FzdChTdHJpbmcobXNnKSk7XG4gICAgICAgIC8vIEEgcmVzb2x2ZSBtYXkgaGF2ZSBjbG9zZWQvcGFydGlhbGx5LXBhaWQgYW4gaW52b2ljZSDigJQgcmVmZXRjaCBuZXh0IHRpbWUuXG4gICAgICAgIHRoaXMucmVzb2x2ZU9wdGlvbnNDYWNoZSA9IG51bGw7XG4gICAgICAgIHRoaXMubG9hZExpc3QoKTtcbiAgICAgIH1cbiAgICB9KS5jYXRjaCgoKSA9PiB7fSk7XG4gIH1cblxuICAvLyA9PT09PSBEaXNwbGF5IGhlbHBlcnMgPT09PT1cbiAgc3RhdHVzTGFiZWwoczogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCBtYXA6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7XG4gICAgICByZWNvbmNpbGVkOiAnUmVjb25jaWxlZCcsIG5lZWRzX3JldmlldzogJ05lZWRzIHJldmlldycsXG4gICAgICB1bm1hdGNoZWQ6ICdVbm1hdGNoZWQnLCBleGNsdWRlZDogJ0V4Y2x1ZGVkJyxcbiAgICB9O1xuICAgIHJldHVybiBtYXBbc10gfHwgcztcbiAgfVxuXG4gIHN0YXR1c1BpbGxDbGFzcyhzOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGNvbnN0IG1hcDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHtcbiAgICAgIHJlY29uY2lsZWQ6ICdwaWxsIHBpbGwtZ3JlZW4nLCBuZWVkc19yZXZpZXc6ICdwaWxsIHBpbGwtYW1iZXInLFxuICAgICAgdW5tYXRjaGVkOiAncGlsbCBwaWxsLXJlZCcsIGV4Y2x1ZGVkOiAncGlsbCBwaWxsLWdyYXknLFxuICAgIH07XG4gICAgcmV0dXJuIG1hcFtzXSB8fCAncGlsbCBwaWxsLWdyYXknO1xuICB9XG5cbiAgc291cmNlTGFiZWwoczogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCBtYXA6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7IGJhbms6ICdCYW5rIFN0YXRlbWVudCcsIHZhOiAnVmlydHVhbCBBY2NvdW50JywgZ2F0ZXdheTogJ0dhdGV3YXknIH07XG4gICAgcmV0dXJuIG1hcFtzXSB8fCBzO1xuICB9XG5cbiAgY291bnRPZihpZDogc3RyaW5nKTogbnVtYmVyIHtcbiAgICBpZiAoaWQgPT09ICdhbGwnKSByZXR1cm4gdGhpcy5jYXJkcy50b3RhbDtcbiAgICByZXR1cm4gKHRoaXMuY2FyZHMgYXMgYW55KVtpZF0/LmNvdW50IHx8IDA7XG4gIH1cbn0iLCI8ZGl2PlxuICAgIDwhLS0gPT09PT09PT09PT09IFVwbG9hZCBzdGFnZSAobm8gc3RhdGVtZW50cyB5ZXQpID09PT09PT09PT09PSAtLT5cbiAgICA8ZGl2ICpuZ0lmPVwic3RhZ2UgPT09ICd1cGxvYWQnICYmICFsb2FkaW5nXCIgY2xhc3M9XCJweC00IHBiLTRcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImJpbGxpbmdoZWFkZXIgbXMtMSBtdC02XCI+QmFuayBTdGF0ZW1lbnQgUmVjb25jaWxpYXRpb248L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cInRleHQtbXV0ZWQgc21hbGwgbXMtMSBtdC0xXCI+VXBsb2FkIGEgYmFuayBzdGF0ZW1lbnQg4oCUIHRyYW5zYWN0aW9ucyBhcmUgc3RvcmVkIGFuZCBzcGxpdCBpbnRvXG4gICAgICAgICAgICBSZWNvbmNpbGVkLCBOZWVkcyByZXZpZXcsIFVubWF0Y2hlZCBhbmQgRXhjbHVkZWQuPC9kaXY+XG4gICAgICAgIDxsYWJlbCBjbGFzcz1cImRyb3B6b25lIG10LTRcIiBmb3I9XCJzdG10LWZpbGVcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkei1pY1wiPlxuICAgICAgICAgICAgICAgIDxzdmcgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiIHdpZHRoPVwiMjRcIiBoZWlnaHQ9XCIyNFwiIHZpZXdCb3g9XCIwIDAgMjQgMjRcIiBmaWxsPVwibm9uZVwiXG4gICAgICAgICAgICAgICAgICAgIHN0cm9rZT1cImN1cnJlbnRDb2xvclwiIHN0cm9rZS13aWR0aD1cIjJcIj5cbiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD1cIk0xMiAyMVY5TTggMTNsNC00IDQgNE01IDVoMTRcIiAvPlxuICAgICAgICAgICAgICAgIDwvc3ZnPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZHotdGl0bGUgbXQtM1wiPlVwbG9hZCBiYW5rIHN0YXRlbWVudDwvZGl2PlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInRleHQtbXV0ZWQgc21hbGwgbXQtMVwiPkRyYWcgJmFtcDsgZHJvcCBvciBjbGljayB0byBicm93c2UgwrcgPHN0cm9uZz5FeGNlbCAoLnhsc3gsIC54bHMpIG9yIENTVjwvc3Ryb25nPjwvZGl2PlxuICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidG4gYnRuLXByaW1hcnkgYnRuLXNtIG10LTNcIiBbZGlzYWJsZWRdPVwidXBsb2FkaW5nXCJcbiAgICAgICAgICAgICAgICBvbmNsaWNrPVwiZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3N0bXQtZmlsZScpLmNsaWNrKCk7IGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XCI+XG4gICAgICAgICAgICAgICAge3sgdXBsb2FkaW5nID8gJ1BhcnNpbmfigKYnIDogJ1VwbG9hZCAmIHBhcnNlJyB9fVxuICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDwvbGFiZWw+XG4gICAgICAgIDxpbnB1dCBpZD1cInN0bXQtZmlsZVwiIHR5cGU9XCJmaWxlXCIgYWNjZXB0PVwiLnhsc3gsLnhscywuY3N2XCIgY2xhc3M9XCJkLW5vbmVcIiAoY2hhbmdlKT1cIm9uRmlsZVNlbGVjdGVkKCRldmVudClcIj5cbiAgICA8L2Rpdj5cblxuICAgIDwhLS0gPT09PT09PT09PT09IFJlc3VsdHMgc3RhZ2UgPT09PT09PT09PT09IC0tPlxuICAgIDxkaXYgKm5nSWY9XCJzdGFnZSA9PT0gJ3Jlc3VsdHMnXCI+XG4gICAgICAgIDwhLS0gVXBsb2FkLWFub3RoZXIgYWN0aW9uIC0tPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiZC1mbGV4IGp1c3RpZnktY29udGVudC1lbmQgYWxpZ24taXRlbXMtY2VudGVyIG10LTQgbWUtNFwiPlxuICAgICAgICAgICAgPGlucHV0IGlkPVwic3RtdC1maWxlLWFnYWluXCIgdHlwZT1cImZpbGVcIiBhY2NlcHQ9XCIueGxzeCwueGxzLC5jc3ZcIiBjbGFzcz1cImQtbm9uZVwiXG4gICAgICAgICAgICAgICAgKGNoYW5nZSk9XCJvbkZpbGVTZWxlY3RlZCgkZXZlbnQpXCI+XG4gICAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJ0bi1vdXRsaW5lIGJ0biBhbGlnbi1pdGVtcy1lbmQgdGV4dC1ub3dyYXAgaW52aGVhZGVyXCIgW2Rpc2FibGVkXT1cInVwbG9hZGluZ1wiXG4gICAgICAgICAgICAgICAgb25jbGljaz1cImRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdzdG10LWZpbGUtYWdhaW4nKS5jbGljaygpXCI+XG4gICAgICAgICAgICAgICAgPHN2ZyB4bWxucz1cImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIgd2lkdGg9XCIyMFwiIGhlaWdodD1cIjIwXCIgdmlld0JveD1cIjAgMCAyMCAyMFwiIGZpbGw9XCJub25lXCI+XG4gICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9XCJNMTcuNSAxMi41VjE1LjgzMzNDMTcuNSAxNi4yNzU0IDE3LjMyNDQgMTYuNjk5MyAxNy4wMTE4IDE3LjAxMThDMTYuNjk5MyAxNy4zMjQ0IDE2LjI3NTQgMTcuNSAxNS44MzMzIDE3LjVINC4xNjY2N0MzLjcyNDY0IDE3LjUgMy4zMDA3MiAxNy4zMjQ0IDIuOTg4MTYgMTcuMDExOEMyLjY3NTU5IDE2LjY5OTMgMi41IDE2LjI3NTQgMi41IDE1LjgzMzNWMTIuNU0xNC4xNjY3IDYuNjY2NjdMMTAgMi41TTEwIDIuNUw1LjgzMzMzIDYuNjY2NjdNMTAgMi41VjEyLjVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgc3Ryb2tlPVwiIzM0NDA1NFwiIHN0cm9rZS13aWR0aD1cIjEuNjdcIiBzdHJva2UtbGluZWNhcD1cInJvdW5kXCIgc3Ryb2tlLWxpbmVqb2luPVwicm91bmRcIiAvPlxuICAgICAgICAgICAgICAgIDwvc3ZnPlxuICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwibXMtMlwiPnt7IHVwbG9hZGluZyA/ICdQYXJzaW5n4oCmJyA6ICdVcGxvYWQgYW5vdGhlciBzdGF0ZW1lbnQnIH19PC9zcGFuPlxuICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDwvZGl2PlxuXG4gICAgICAgIDwhLS0gU3RhdHVzIGNhcmRzIOKAlCBjbGlja2luZyBhIGNhcmQgZmlsdGVycyB0aGUgdGFibGUgKGNsaWNrIGFnYWluIHRvIGNsZWFyKSAtLT5cbiAgICAgICAgPGRpdiBjbGFzcz1cInJvdyBnLTMgbXQtMSBtYi0yIG14LTJcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjb2xcIj5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiaW52b2ljZS1jYXJkIGNhcmQtY2xpY2thYmxlXCIgW2NsYXNzLmNhcmQtYWN0aXZlXT1cImFjdGl2ZVN0YXR1cyA9PT0gJ3JlY29uY2lsZWQnXCJcbiAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cInRvZ2dsZUNhcmRGaWx0ZXIoJ3JlY29uY2lsZWQnKVwiPlxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiaW52b2ljZS1jYXJkLWxhYmVsXCI+UmVjb25jaWxlZDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiaW52b2ljZS1jYXJkLXZhbHVlIHRleHQtc3VjY2Vzc1wiPnt7IGNhcmRzLnJlY29uY2lsZWQuY291bnQgfX08L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImludm9pY2UtY2FyZC1zdWJcIj7igrl7eyBjYXJkcy5yZWNvbmNpbGVkLmFtb3VudCB8IG51bWJlcjonMS4yLTInOidlbi1JTicgfX08L2Rpdj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNvbFwiPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpbnZvaWNlLWNhcmQgY2FyZC1jbGlja2FibGVcIiBbY2xhc3MuY2FyZC1hY3RpdmVdPVwiYWN0aXZlU3RhdHVzID09PSAnbmVlZHNfcmV2aWV3J1wiXG4gICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJ0b2dnbGVDYXJkRmlsdGVyKCduZWVkc19yZXZpZXcnKVwiPlxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiaW52b2ljZS1jYXJkLWxhYmVsXCI+TmVlZHMgcmV2aWV3PC9kaXY+XG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpbnZvaWNlLWNhcmQtdmFsdWUgdGV4dC13YXJuaW5nXCI+e3sgY2FyZHMubmVlZHNfcmV2aWV3LmNvdW50IH19PC9kaXY+XG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpbnZvaWNlLWNhcmQtc3ViXCI+4oK5e3sgY2FyZHMubmVlZHNfcmV2aWV3LmFtb3VudCB8IG51bWJlcjonMS4yLTInOidlbi1JTicgfX08L2Rpdj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNvbFwiPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpbnZvaWNlLWNhcmQgY2FyZC1jbGlja2FibGVcIiBbY2xhc3MuY2FyZC1hY3RpdmVdPVwiYWN0aXZlU3RhdHVzID09PSAndW5tYXRjaGVkJ1wiXG4gICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJ0b2dnbGVDYXJkRmlsdGVyKCd1bm1hdGNoZWQnKVwiPlxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiaW52b2ljZS1jYXJkLWxhYmVsXCI+VW5tYXRjaGVkPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpbnZvaWNlLWNhcmQtdmFsdWUgdGV4dC1kYW5nZXJcIj57eyBjYXJkcy51bm1hdGNoZWQuY291bnQgfX08L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImludm9pY2UtY2FyZC1zdWJcIj7igrl7eyBjYXJkcy51bm1hdGNoZWQuYW1vdW50IHwgbnVtYmVyOicxLjItMic6J2VuLUlOJyB9fTwvZGl2PlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY29sXCI+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImludm9pY2UtY2FyZCBjYXJkLWNsaWNrYWJsZVwiIFtjbGFzcy5jYXJkLWFjdGl2ZV09XCJhY3RpdmVTdGF0dXMgPT09ICdleGNsdWRlZCdcIlxuICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwidG9nZ2xlQ2FyZEZpbHRlcignZXhjbHVkZWQnKVwiPlxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiaW52b2ljZS1jYXJkLWxhYmVsXCI+RXhjbHVkZWQ8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImludm9pY2UtY2FyZC12YWx1ZVwiPnt7IGNhcmRzLmV4Y2x1ZGVkLmNvdW50IH19PC9kaXY+XG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpbnZvaWNlLWNhcmQtc3ViXCI+4oK5e3sgY2FyZHMuZXhjbHVkZWQuYW1vdW50IHwgbnVtYmVyOicxLjItMic6J2VuLUlOJyB9fTwvZGl2PlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuXG4gICAgICAgIDwhLS0gU3RhdHVzIHRhYnMgKyBzZWFyY2gvZmlsdGVyIC0tPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY2FyZC1oZWFkZXIgcGF5bWVudGhpc3RvcnkgYm9yZGVyLTBcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkLWZsZXggYWxpZ24taXRlbXMtY2VudGVyIGdhcC0yIGZsZXgtd3JhcFwiPlxuICAgICAgICAgICAgICAgIDxidXR0b24gKm5nRm9yPVwibGV0IHRhYiBvZiBzdGF0dXNUYWJzXCIgY2xhc3M9XCJidG4gYnRuLXNtIHN0YXR1cy10YWJcIlxuICAgICAgICAgICAgICAgICAgICBbY2xhc3MuYWN0aXZlXT1cImFjdGl2ZVN0YXR1cyA9PT0gdGFiLmlkXCJcbiAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cInNldFN0YXR1cyh0YWIuaWQpXCI+XG4gICAgICAgICAgICAgICAgICAgIHt7IHRhYi5sYWJlbCB9fVxuICAgICAgICAgICAgICAgICAgICA8c3BhbiAqbmdJZj1cImNvdW50T2YodGFiLmlkKVwiIGNsYXNzPVwiY291bnRjaGlwIG1zLTFcIj57eyBjb3VudE9mKHRhYi5pZCkgfX08L3NwYW4+XG4gICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjYXJkLXRvb2xiYXIgbXMtYXV0b1wiPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkLWZsZXggYWxpZ24taXRlbXMtY2VudGVyIHBvc2l0aW9uLXJlbGF0aXZlIG15LTFcIj5cbiAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJzdmctaWNvbiBpbnZvaWNlc2VhcmNoIHN2Zy1pY29uLTEgcG9zaXRpb24tYWJzb2x1dGUgbXQtNiBtcy0zXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8c3ZnIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiB3aWR0aD1cIjI0XCIgaGVpZ2h0PVwiMjRcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCIgZmlsbD1cIm5vbmVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cmVjdCBvcGFjaXR5PVwiMC41XCIgeD1cIjE3LjAzNjVcIiB5PVwiMTUuMTIyM1wiIHdpZHRoPVwiOC4xNTU0NlwiIGhlaWdodD1cIjJcIiByeD1cIjFcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm09XCJyb3RhdGUoNDUgMTcuMDM2NSAxNS4xMjIzKVwiIGZpbGw9XCJjdXJyZW50Q29sb3JcIj48L3JlY3Q+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPHBhdGggZD1cIk0xMSAxOUM2LjU1NTU2IDE5IDMgMTUuNDQ0NCAzIDExQzMgNi41NTU1NiA2LjU1NTU2IDMgMTEgM0MxNS40NDQ0IDMgMTkgNi41NTU1NiAxOSAxMUMxOSAxNS40NDQ0IDE1LjQ0NDQgMTkgMTEgMTlaTTExIDVDNy41MzMzMyA1IDUgNy41MzMzMyA1IDExQzUgMTQuNDY2NyA3LjUzMzMzIDE3IDExIDE3QzE0LjQ2NjcgMTcgMTcgMTQuNDY2NyAxNyAxMUMxNyA3LjUzMzMzIDE0LjQ2NjcgNSAxMSA1WlwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGw9XCJjdXJyZW50Q29sb3JcIj48L3BhdGg+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICA8aW5wdXQgWyhuZ01vZGVsKV09XCJzZWFyY2hWYWx1ZVwiIHR5cGU9XCJ0ZXh0XCIgY2xhc3M9XCJmb3JtLWNvbnRyb2wgcHMtMTQgaW52b2ljZXNlYXJjaFwiXG4gICAgICAgICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cIlNlYXJjaCBwYXllciwgbmFycmF0aW9uLCBVVFIuLi5cIiBhdXRvY29tcGxldGU9XCJvZmZcIiAoY2hhbmdlKT1cInNlYXJjaEZpZWxkKClcIiAvPlxuICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJ0bi1vdXRsaW5lIGJ0biBhbGlnbi1pdGVtcy1lbmQgdGV4dC1ub3dyYXAgaW52aGVhZGVyXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJ0b2dnbGVGaWx0ZXIoKVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPHN2ZyB4bWxucz1cImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIgd2lkdGg9XCIyMFwiIGhlaWdodD1cIjIwXCIgdmlld0JveD1cIjAgMCAyNCAyNFwiIGZpbGw9XCJub25lXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJva2U9XCIjMzQ0MDU0XCIgc3Ryb2tlLXdpZHRoPVwiMlwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9XCJNMyA1aDE4TTYgMTJoMTJNMTAgMTloNFwiIC8+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwibXMtMlwiPkZpbHRlcjwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuICpuZ0lmPVwiYWN0aXZlRmlsdGVyQ291bnRcIiBjbGFzcz1cImNvdW50Y2hpcCBtcy0xXCI+e3sgYWN0aXZlRmlsdGVyQ291bnQgfX08L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuXG4gICAgICAgIDwhLS0gRmlsdGVyIHBhbmVsIC0tPlxuICAgICAgICA8ZGl2ICpuZ0lmPVwiZmlsdGVyT3BlblwiIGNsYXNzPVwiZmlsdGVyLXBhbmVsIG14LTQgbWItM1wiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInJvdyBnLTNcIj5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLW1kLTRcIj5cbiAgICAgICAgICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwiZm9ybS1sYWJlbCBzbWFsbCBmdy1zZW1pYm9sZFwiPkRhdGUg4oCUIGZyb208L2xhYmVsPlxuICAgICAgICAgICAgICAgICAgICA8aW5wdXQgdHlwZT1cImRhdGVcIiBjbGFzcz1cImZvcm0tY29udHJvbFwiIFsobmdNb2RlbCldPVwiZnJvbURhdGVcIiAoY2hhbmdlKT1cImFwcGx5RmlsdGVycygpXCI+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNvbC1tZC00XCI+XG4gICAgICAgICAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImZvcm0tbGFiZWwgc21hbGwgZnctc2VtaWJvbGRcIj5EYXRlIOKAlCB0bzwvbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgIDxpbnB1dCB0eXBlPVwiZGF0ZVwiIGNsYXNzPVwiZm9ybS1jb250cm9sXCIgWyhuZ01vZGVsKV09XCJ0b0RhdGVcIiAoY2hhbmdlKT1cImFwcGx5RmlsdGVycygpXCI+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNvbC1tZC00XCI+XG4gICAgICAgICAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImZvcm0tbGFiZWwgc21hbGwgZnctc2VtaWJvbGRcIj5Tb3VyY2U8L2xhYmVsPlxuICAgICAgICAgICAgICAgICAgICA8c2VsZWN0IGNsYXNzPVwiZm9ybS1zZWxlY3RcIiBbKG5nTW9kZWwpXT1cInNvdXJjZVwiIChjaGFuZ2UpPVwiYXBwbHlGaWx0ZXJzKClcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxvcHRpb24gdmFsdWU9XCJhbGxcIj5BbGwgc291cmNlczwvb3B0aW9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiB2YWx1ZT1cImJhbmtcIj5CYW5rIFN0YXRlbWVudDwvb3B0aW9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiB2YWx1ZT1cInZhXCI+VmlydHVhbCBBY2NvdW50PC9vcHRpb24+XG4gICAgICAgICAgICAgICAgICAgICAgICA8b3B0aW9uIHZhbHVlPVwiZ2F0ZXdheVwiPkdhdGV3YXk8L29wdGlvbj5cbiAgICAgICAgICAgICAgICAgICAgPC9zZWxlY3Q+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkLWZsZXgganVzdGlmeS1jb250ZW50LWJldHdlZW4gYWxpZ24taXRlbXMtY2VudGVyIG10LTNcIiAqbmdJZj1cImFjdGl2ZUZpbHRlckNvdW50XCI+XG4gICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJ0ZXh0LW11dGVkIHNtYWxsXCI+e3sgdG90YWxJdGVtcyB9fSB0cmFuc2FjdGlvbnMgbWF0Y2g8L3NwYW4+XG4gICAgICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz1cImJ0biBidG4tbGluayBidG4tc20gcC0wXCIgKGNsaWNrKT1cImNsZWFyRmlsdGVycygpXCI+Q2xlYXIgYWxsIGZpbHRlcnM8L2J1dHRvbj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cblxuICAgICAgICA8IS0tIExvYWRpbmcgc2hpbW1lciAtLT5cbiAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImxvYWRpbmdcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJyb3cgbG9hZGVyIGQtZmxleCBqdXN0aWZ5LWNvbnRlbnQtY2VudGVyIGFsaWduLWl0ZW1zLWNlbnRlclwiPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzaGltbWVyXCI+XG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ3cmFwcGVyXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3Ryb2tlIGFuaW1hdGUgdGl0bGVcIj48L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzdHJva2UgYW5pbWF0ZSBsaW5rXCI+PC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3Ryb2tlIGFuaW1hdGUgZGVzY3JpcHRpb25cIj48L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgICAgPCEtLSBFbXB0eSAtLT5cbiAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIiFsb2FkaW5nICYmIG5vRGF0YVwiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInJvd1wiPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtbGctMTIgbWItM1wiPlxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY2FyZC1ib2R5IGQtZmxleCBqdXN0aWZ5LWNvbnRlbnQtY2VudGVyIGFsaWduLWl0ZW1zLWNlbnRlciBmbGV4LWNvbHVtblwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGltZyBjbGFzcz1cImltZy1zcmMgdy0yNVwiIHNyYz1cIi4vYXNzZXRzL3RhbmdvL0ljb25zL05vZGF0YS5zdmdcIiBhbHQ9XCJcIj5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgICAgPCEtLSBUcmFuc2FjdGlvbnMgdGFibGUgLS0+XG4gICAgICAgIDxkaXYgKm5nSWY9XCIhbG9hZGluZyAmJiAhbm9EYXRhXCIgY2xhc3M9XCJ0YWJsZS1yZXNwb25zaXZlXCI+XG4gICAgICAgICAgICA8dGFibGUgY2xhc3M9XCJ0YWJsZSBhY2NvcmRpb24gdGFibGUgYm90dG9tLWJvcmRlciBpbnZvaXZldGFibGUgdGV4dC1ub3dyYXBcIj5cbiAgICAgICAgICAgICAgICA8dGhlYWQ+XG4gICAgICAgICAgICAgICAgICAgIDx0cj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDx0aD5EYXRlPC90aD5cbiAgICAgICAgICAgICAgICAgICAgICAgIDx0aD5Tb3VyY2U8L3RoPlxuICAgICAgICAgICAgICAgICAgICAgICAgPHRoPlBheWVyIChmcm9tIG5hcnJhdGlvbik8L3RoPlxuICAgICAgICAgICAgICAgICAgICAgICAgPHRoPlJlZmVyZW5jZSAvIFVUUjwvdGg+XG4gICAgICAgICAgICAgICAgICAgICAgICA8dGg+QW1vdW50PC90aD5cbiAgICAgICAgICAgICAgICAgICAgICAgIDx0aD5CcmFuZCBOYW1lPC90aD5cbiAgICAgICAgICAgICAgICAgICAgICAgIDx0aD5JbnZvaWNlPC90aD5cbiAgICAgICAgICAgICAgICAgICAgICAgIDx0aD5SZXN1bHQ8L3RoPlxuICAgICAgICAgICAgICAgICAgICAgICAgPHRoPlN0YXR1czwvdGg+XG4gICAgICAgICAgICAgICAgICAgICAgICA8dGg+QWN0aW9uPC90aD5cbiAgICAgICAgICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICAgICAgICA8L3RoZWFkPlxuICAgICAgICAgICAgICAgIDx0Ym9keT5cbiAgICAgICAgICAgICAgICAgICAgPHRyICpuZ0Zvcj1cImxldCB0IG9mIHJvd3NcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDx0ZD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwidGFibGUtdGl0bGVcIj57eyB0LnZhbHVlRGF0ZSB8IGRhdGU6ICdkZCBNTU0sIHl5eXknIH19PC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICAgICAgICAgICAgPHRkPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwic3JjY2hpcFwiIFtjbGFzcy5zcmNjaGlwLXZhXT1cInQuc291cmNlID09PSAndmEnXCI+e3sgc291cmNlTGFiZWwodC5zb3VyY2UpIH19PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgICAgICAgICAgICAgIDx0ZD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwidGFibGUtdGl0bGUgcGF5ZXItY2VsbFwiPnt7IHQucGF5ZXIgfHwgJ+KAlCcgfX08L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibmFycmF0aW9uLXN1YlwiIFt0aXRsZV09XCJ0Lm5hcnJhdGlvblwiPnt7IHQubmFycmF0aW9uIH19PC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICAgICAgICAgICAgPHRkPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwibW9ub1wiPnt7IHQucmVmTm8gfHwgJ+KAlCcgfX08L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICAgICAgICAgICAgPHRkPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0YWJsZS10aXRsZVwiPjxzdHJvbmc+4oK5e3sgdC5hbW91bnQgfCBudW1iZXI6JzEuMi0yJzonZW4tSU4nIH19PC9zdHJvbmc+PC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICAgICAgICAgICAgPHRkPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0YWJsZS10aXRsZVwiPnt7IHQuaWRlbnRpZmllZENsaWVudE5hbWUgfHwgJ+KAlCcgfX08L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICAgICAgICAgICAgICA8dGQ+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInRhYmxlLXRpdGxlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxhICpuZ0lmPVwidC5pbnZvaWNlICYmIHQuaW52b2ljZUlkXCIgY2xhc3M9XCJpbnZvaWNlLWxpbmtcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cIm9wZW5JbnZvaWNlUHJldmlldyh0KTsgJGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpXCI+e3sgdC5pbnZvaWNlIH19PC9hPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiAqbmdJZj1cInQuaW52b2ljZSAmJiAhdC5pbnZvaWNlSWRcIj57eyB0Lmludm9pY2UgfX08L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuICpuZ0lmPVwiIXQuaW52b2ljZVwiPuKAlDwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICAgICAgICAgICAgICA8dGQ+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInJlc3VsdC1ub3RlXCIgW3RpdGxlXT1cInQucmVzdWx0Tm90ZVwiPnt7IHQucmVzdWx0Tm90ZSB8fCAn4oCUJyB9fTwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgICAgICAgICAgICAgIDx0ZD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiAqbmdJZj1cInQuY29udGFjdGVkXCIgY2xhc3M9XCJwaWxsIHBpbGwtYW1iZXJcIj5SZWFjaGluZyBvdXQ8L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gKm5nSWY9XCIhdC5jb250YWN0ZWRcIiBbbmdDbGFzc109XCJzdGF0dXNQaWxsQ2xhc3ModC5zdGF0dXMpXCI+e3sgc3RhdHVzTGFiZWwodC5zdGF0dXMpIH19PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgICAgICAgICAgICAgIDx0ZD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uICpuZ0lmPVwidC5zdGF0dXMgPT09ICduZWVkc19yZXZpZXcnIHx8IHQuc3RhdHVzID09PSAndW5tYXRjaGVkJ1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1zbSBidG4tcHJpbWFyeVwiIChjbGljayk9XCJvcGVuUmVzb2x2ZSh0KVwiPlJlc29sdmU8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgICAgICAgPC90Ym9keT5cbiAgICAgICAgICAgIDwvdGFibGU+XG4gICAgICAgICAgICA8bGliLXBhZ2luYXRpb24gY2xhc3M9XCJ0ZXh0LXN0YXJ0XCIgW2l0ZW1zUGVyUGFnZV09XCJpdGVtc1BlclBhZ2VcIiBbY3VycmVudFBhZ2VdPVwiY3VycmVudFBhZ2VcIlxuICAgICAgICAgICAgICAgIFt0b3RhbEl0ZW1zXT1cInRvdGFsSXRlbXNcIiBbcGFnaW5hdGlvblNpemVzXT1cInBhZ2luYXRpb25TaXplc1wiIFtwYWdlU2l6ZV09XCJwYWdlU2l6ZVwiXG4gICAgICAgICAgICAgICAgKHBhZ2VDaGFuZ2UpPVwib25QYWdlQ2hhbmdlKCRldmVudClcIiAocGFnZVNpemVDaGFuZ2UpPVwib25QYWdlU2l6ZUNoYW5nZSgkZXZlbnQpXCI+PC9saWItcGFnaW5hdGlvbj5cbiAgICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG48L2Rpdj4iXX0=
|