@posiwise/smart-crm 0.0.53 → 0.0.55

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/fesm2022/posiwise-smart-crm.mjs +244 -246
  2. package/fesm2022/posiwise-smart-crm.mjs.map +1 -1
  3. package/lib/private/components/smart-crm-accounts/smart-crm-accounts.component.d.ts +1 -0
  4. package/lib/private/components/smart-crm-insight/smart-crm-account-insight/smart-crm-account-insight.component.d.ts +1 -1
  5. package/lib/private/components/smart-crm-opportunities/smart-crm-opportunities-list/smart-crm-opportunities-list.component.d.ts +1 -0
  6. package/package.json +3 -5
  7. package/esm2022/index.mjs +0 -52
  8. package/esm2022/lib/private/components/smart-crm-accounts/smart-crm-account-details/smart-crm-account-details.component.mjs +0 -210
  9. package/esm2022/lib/private/components/smart-crm-accounts/smart-crm-account-files/smart-crm-account-files.component.mjs +0 -191
  10. package/esm2022/lib/private/components/smart-crm-accounts/smart-crm-account-info/smart-crm-account-info.component.mjs +0 -612
  11. package/esm2022/lib/private/components/smart-crm-accounts/smart-crm-account-invoices/smart-crm-account-invoices.component.mjs +0 -71
  12. package/esm2022/lib/private/components/smart-crm-accounts/smart-crm-accounts.component.mjs +0 -361
  13. package/esm2022/lib/private/components/smart-crm-actions/smart-crm-actions.component.mjs +0 -267
  14. package/esm2022/lib/private/components/smart-crm-competition/smart-crm-competition/smart-crm-competition.component.mjs +0 -12
  15. package/esm2022/lib/private/components/smart-crm-configuration/smart-crm-actions/smart-crm-actions-details/smart-crm-actions-details.component.mjs +0 -103
  16. package/esm2022/lib/private/components/smart-crm-configuration/smart-crm-actions/smart-crm-actions.component.mjs +0 -126
  17. package/esm2022/lib/private/components/smart-crm-configuration/smart-crm-configuration.component.mjs +0 -35
  18. package/esm2022/lib/private/components/smart-crm-configuration/smart-crm-opportunity-categories/smart-crm-opportunity-categories-details/smart-crm-opportunity-categories-details.component.mjs +0 -88
  19. package/esm2022/lib/private/components/smart-crm-configuration/smart-crm-opportunity-categories/smart-crm-opportunity-categories.component.mjs +0 -120
  20. package/esm2022/lib/private/components/smart-crm-configuration/smart-crm-source/smart-crm-source-details/smart-crm-source-details.component.mjs +0 -79
  21. package/esm2022/lib/private/components/smart-crm-configuration/smart-crm-source/smart-crm-source.component.mjs +0 -107
  22. package/esm2022/lib/private/components/smart-crm-configuration/smart-crm-stages/smart-crm-stage-details/smart-crm-stage-details.component.mjs +0 -97
  23. package/esm2022/lib/private/components/smart-crm-configuration/smart-crm-stages/smart-crm-stages.component.mjs +0 -156
  24. package/esm2022/lib/private/components/smart-crm-configuration/smart-crm-widgets/smart-crm-widgets-details/smart-crm-widgets-details.component.mjs +0 -99
  25. package/esm2022/lib/private/components/smart-crm-configuration/smart-crm-widgets/smart-crm-widgets.component.mjs +0 -125
  26. package/esm2022/lib/private/components/smart-crm-contacts/smart-crm-contact-details/smart-crm-contact-details.component.mjs +0 -197
  27. package/esm2022/lib/private/components/smart-crm-contacts/smart-crm-contact-info/smart-crm-contact-info.component.mjs +0 -481
  28. package/esm2022/lib/private/components/smart-crm-contacts/smart-crm-contacts.component.mjs +0 -301
  29. package/esm2022/lib/private/components/smart-crm-customer/smart-crm-customer-success/smart-crm-customer-success.component.mjs +0 -12
  30. package/esm2022/lib/private/components/smart-crm-insight/smart-crm-account-insight/smart-crm-account-insight.component.mjs +0 -314
  31. package/esm2022/lib/private/components/smart-crm-insight/smart-crm-analysis-insight/smart-crm-analysis.component.mjs +0 -104
  32. package/esm2022/lib/private/components/smart-crm-insight/smart-crm-contact-insight/smart-crm-contact-insight.component.mjs +0 -105
  33. package/esm2022/lib/private/components/smart-crm-insight/smart-crm-insight.component.mjs +0 -27
  34. package/esm2022/lib/private/components/smart-crm-insight/smart-crm-marketing-insight/smart-crm-marketing-insight.component.mjs +0 -80
  35. package/esm2022/lib/private/components/smart-crm-insight/smart-crm-opportunities-insight/smart-crm-opportunities-insight.component.mjs +0 -160
  36. package/esm2022/lib/private/components/smart-crm-leads/smart-crm-leads-details/smart-crm-leads-details.component.mjs +0 -227
  37. package/esm2022/lib/private/components/smart-crm-leads/smart-crm-leads.component.mjs +0 -146
  38. package/esm2022/lib/private/components/smart-crm-marketing/smart-crm-marketing-list/smart-crm-marketing-contacts/smart-crm-marketing-contacts.component.mjs +0 -79
  39. package/esm2022/lib/private/components/smart-crm-marketing/smart-crm-marketing-list/smart-crm-marketing-details/smart-crm-marketing-details.component.mjs +0 -269
  40. package/esm2022/lib/private/components/smart-crm-marketing/smart-crm-marketing-list/smart-crm-marketing-list.component.mjs +0 -157
  41. package/esm2022/lib/private/components/smart-crm-marketing/smart-crm-marketing-list/smart-crm-marketing-view-details/smart-crm-marketing-view-details.component.mjs +0 -60
  42. package/esm2022/lib/private/components/smart-crm-marketing/smart-crm-marketing.component.mjs +0 -18
  43. package/esm2022/lib/private/components/smart-crm-media/smart-crm-social-media/smart-crm-social-media.component.mjs +0 -12
  44. package/esm2022/lib/private/components/smart-crm-opportunities/smart-crm-board/smart-crm-board.component.mjs +0 -236
  45. package/esm2022/lib/private/components/smart-crm-opportunities/smart-crm-opportunities-list/smart-crm-opportunities-details/smart-crm-opportunities-details.component.mjs +0 -376
  46. package/esm2022/lib/private/components/smart-crm-opportunities/smart-crm-opportunities-list/smart-crm-opportunities-info/smart-crm-opportunities-info.component.mjs +0 -483
  47. package/esm2022/lib/private/components/smart-crm-opportunities/smart-crm-opportunities-list/smart-crm-opportunities-list.component.mjs +0 -256
  48. package/esm2022/lib/private/components/smart-crm-opportunities/smart-crm-opportunities.component.mjs +0 -14
  49. package/esm2022/lib/private/components/smart-crm-tabs/smart-crm-tabs.component.mjs +0 -99
  50. package/esm2022/lib/private/smart-crm-private.module.mjs +0 -356
  51. package/esm2022/lib/private/smart-crm-private.routing.module.mjs +0 -318
  52. package/esm2022/lib/public/components/smart-crm-newsletter-confirmation/smart-crm-newsletter-confirmation.component.mjs +0 -56
  53. package/esm2022/lib/public/components/smart-crm-newsletter-unsubscribe/smart-crm-newsletter-unsubscribe.component.mjs +0 -57
  54. package/esm2022/lib/public/components/smart-crm-signup/smart-crm-signup.component.mjs +0 -38
  55. package/esm2022/lib/public/smart-crm-public.module.mjs +0 -46
  56. package/esm2022/lib/public/smart-crm-public.routing.module.mjs +0 -44
  57. package/esm2022/lib/shared/interface/crm-account.interface.mjs +0 -2
  58. package/esm2022/lib/shared/interface/crm-action.interface.mjs +0 -2
  59. package/esm2022/lib/shared/interface/crm-contact.interface.mjs +0 -2
  60. package/esm2022/lib/shared/interface/crm-lead.interface.mjs +0 -2
  61. package/esm2022/lib/shared/interface/crm-newsletter.interface.mjs +0 -2
  62. package/esm2022/lib/shared/interface/crm-opportunity.interface.mjs +0 -2
  63. package/esm2022/lib/shared/interface/crm-source.interface.mjs +0 -2
  64. package/esm2022/lib/shared/interface/crm-stages.interface.mjs +0 -2
  65. package/esm2022/lib/shared/interface/crm-widget.interface.mjs +0 -2
  66. package/esm2022/lib/shared/interface/smart-crm-module.interface.mjs +0 -2
  67. package/esm2022/lib/shared/models/smart-crm.model.mjs +0 -191
  68. package/esm2022/lib/shared/routers/routers.mjs +0 -24
  69. package/esm2022/posiwise-smart-crm.mjs +0 -5
@@ -1,612 +0,0 @@
1
- import { DOCUMENT } from '@angular/common';
2
- import { ChangeDetectorRef, Component, EventEmitter, Inject, Injector } from '@angular/core';
3
- import { Validators } from '@angular/forms';
4
- import { AppBaseComponent } from '@posiwise/app-base-component';
5
- import { AuthService, CommonService, FormHelperService, GeoService, LogoCacheService, SubscriptionService } from '@posiwise/common-services';
6
- import { DOCUMENT_TYPE_EXT, PAGE_SIZE, TOKEN_HEADER_KEY } from '@posiwise/common-utilities';
7
- import { HelperService } from '@posiwise/helper-service';
8
- import { CRM_ACCOUNT_FILES_PATH, CrmService } from '@posiwise/smart-crm-shared';
9
- import moment from 'moment';
10
- import { UploadStatus } from 'ngx-uploader';
11
- import swal from 'sweetalert2';
12
- import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
13
- import { AppSmartCrm } from '../../../../shared/models/smart-crm.model';
14
- import { ROUTERS } from '../../../../shared/routers/routers';
15
- import * as i0 from "@angular/core";
16
- import * as i1 from "@posiwise/smart-crm-shared";
17
- import * as i2 from "@posiwise/common-services";
18
- import * as i3 from "@ng-bootstrap/ng-bootstrap";
19
- import * as i4 from "@angular/common";
20
- import * as i5 from "@angular/forms";
21
- import * as i6 from "primeng/inputtext";
22
- import * as i7 from "ngx-ui-switch";
23
- import * as i8 from "@posiwise/directives";
24
- import * as i9 from "@angular-magic/ngx-gp-autocomplete";
25
- import * as i10 from "@angular/router";
26
- import * as i11 from "primeng/table";
27
- import * as i12 from "primeng/api";
28
- import * as i13 from "primeng/dropdown";
29
- import * as i14 from "primeng/progressspinner";
30
- import * as i15 from "primeng/autocomplete";
31
- import * as i16 from "@posiwise/shared-components";
32
- import * as i17 from "ngx-uploader";
33
- import * as i18 from "ngx-infinite-scroll";
34
- import * as i19 from "../smart-crm-account-files/smart-crm-account-files.component";
35
- import * as i20 from "../smart-crm-account-invoices/smart-crm-account-invoices.component";
36
- import * as i21 from "@posiwise/pipes";
37
- import * as i22 from "@jsverse/transloco";
38
- export class SmartCrmCompanyInfoComponent extends AppBaseComponent {
39
- constructor(injector, crmService, subscriptionService, geoService, commonService, modalService, authService, cdr, logoCacheService, document) {
40
- super(injector);
41
- this.crmService = crmService;
42
- this.subscriptionService = subscriptionService;
43
- this.geoService = geoService;
44
- this.commonService = commonService;
45
- this.modalService = modalService;
46
- this.authService = authService;
47
- this.cdr = cdr;
48
- this.logoCacheService = logoCacheService;
49
- this.document = document;
50
- this.page = 1;
51
- this.totalContacts = 0;
52
- this.isContactValid = true;
53
- this.accountComments = [];
54
- this.potential = ['low', 'medium', 'high'];
55
- this.selector = '.timeline-container';
56
- this.searchText = '';
57
- this.totalRecordsUnFiltered = 0;
58
- this.currentPage = 1;
59
- this.hasAccess = false;
60
- this.isDataLoaded = false;
61
- this.isLoaded = false;
62
- this.loading = true;
63
- this.isFormEdit = true;
64
- this.submitted = false;
65
- this.editComment = false;
66
- this.showFullComment = false;
67
- this.submitAction = false;
68
- this.isDisabled = false;
69
- this.buttonBusy = false;
70
- this.updating = false;
71
- this.direction = '';
72
- this.routers = ROUTERS;
73
- this.options = { concurrency: 1, maxUploads: 3 };
74
- this.uploadInput = new EventEmitter();
75
- this.token = btoa(this.authService.getToken());
76
- this.files = [];
77
- this.actionControls = AppSmartCrm.getAccountActionsForm(this.isDisabled);
78
- this.aboutControls = AppSmartCrm.getAccountsForm();
79
- }
80
- ngOnInit() {
81
- this.countries$ = this.geoService.getCountries();
82
- this.organizationIndustries$ = this.commonService.getOrganizationIndustries();
83
- this.organizationTypes$ = this.commonService.getOrganizationTypes();
84
- this.organizationSizes$ = this.commonService.getOrganizationSizes();
85
- this.userStore().subscribe(res => {
86
- if (res) {
87
- this.userId = res.id;
88
- this.actionControls.get('owner_id').setValue(res.id);
89
- }
90
- });
91
- this.getUserSubscription().subscribe(response => {
92
- this.subscription = response;
93
- if (this.subscription?.id) {
94
- this.hasAccess = this.hasAdminAccess(this.subscription.id);
95
- this.getActions();
96
- this.accountDefaultValues(this.subscription.id);
97
- this.aboutControls.get('subscription_id').setValue(this.subscription?.id);
98
- }
99
- this.route.params.subscribe(data => {
100
- this.accountId = Number(data['id']);
101
- if (this.accountId) {
102
- this.getAccountContacts({
103
- page: this.page,
104
- page_size: PAGE_SIZE,
105
- search: this.searchText
106
- });
107
- this.getAccountDetails();
108
- this.getContactVersion();
109
- }
110
- });
111
- });
112
- this.getAllComments();
113
- }
114
- ngAfterViewChecked() {
115
- this.cdr.detectChanges();
116
- }
117
- onLazyLoad(event) {
118
- const pageDetails = HelperService.onTableLazyLoad(event);
119
- this.page = pageDetails.page;
120
- this.getAccountContacts({
121
- page: this.page,
122
- page_size: PAGE_SIZE,
123
- order_by: pageDetails.sortField,
124
- order_direction: pageDetails.sortOrder,
125
- search: this.searchText
126
- });
127
- }
128
- /** Function to call account default values */
129
- accountDefaultValues(id) {
130
- this.crmService.getCrmAccountDefaultValues(id).subscribe(response => {
131
- this.status = response.status;
132
- this.priority = response.priority;
133
- this.source = response.source;
134
- });
135
- }
136
- handleImageError(event, fallbackPath) {
137
- HelperService.handleImageFallbackPath(event, fallbackPath);
138
- }
139
- /** Function to call account by ID */
140
- getAccountDetails() {
141
- this.isDataLoaded = false;
142
- this.crmService
143
- .getAccountDetail(this.subscription?.id, this.accountId)
144
- .subscribe(response => {
145
- this.data = response;
146
- const ownerData = {
147
- ...response.owner,
148
- displayName: HelperService.formatDisplayName(response.owner, true)
149
- };
150
- this.aboutControls.patchValue(response);
151
- this.aboutControls.get('owner_id').setValue(ownerData);
152
- })
153
- .add(() => {
154
- this.isDataLoaded = true;
155
- });
156
- }
157
- get f() {
158
- return this.aboutControls.controls;
159
- }
160
- updateAccountInfo() {
161
- this.buttonBusy = true;
162
- if (!this.aboutControls.valid) {
163
- this.buttonBusy = false;
164
- this.submitted = true;
165
- }
166
- else {
167
- this.aboutControls
168
- .get('owner_id')
169
- .setValue(this.aboutControls.get('owner_id').value.id);
170
- this.crmService
171
- .updateAccount(this.subscription?.id, this.accountId, this.aboutControls.value)
172
- .subscribe(() => {
173
- this.toast.success(this.translation.translate('Crm.AccountMessage.UpdatedMessage'));
174
- this.isFormEdit = true;
175
- this.getAccountDetails();
176
- })
177
- .add(() => {
178
- this.buttonBusy = false;
179
- this.submitted = false;
180
- });
181
- }
182
- }
183
- onScrollTimeline() {
184
- this.currentPage++;
185
- const totalPages = Math.ceil(this.totalContacts / 5);
186
- // Prevent API call if all messages have been fetched
187
- if (this.currentPage <= totalPages) {
188
- this.getAllComments();
189
- }
190
- }
191
- /** Function to save comment */
192
- onSave() {
193
- this.submitAction = true;
194
- const form = this.actionControls.value;
195
- form.owner_id = this.data?.owner_id;
196
- form.crm_account_id = this.accountId;
197
- form.crm_contact_id = form?.crm_contact_id?.id;
198
- form.when = HelperService.dateFormat(form.when);
199
- if (this.actionControls.invalid) {
200
- FormHelperService.validateAllFormFields(this.actionControls);
201
- }
202
- else {
203
- this.buttonBusy = true;
204
- this.crmService
205
- .postAccountComment(this.subscription?.id, form)
206
- .subscribe(() => {
207
- this.actionControls.get('comment').reset();
208
- this.getAllComments();
209
- this.toast.success(this.translation.translate('Crm.AccountMessage.CommentSubmittedMessage'));
210
- })
211
- .add(() => {
212
- this.submitAction = false;
213
- this.buttonBusy = false;
214
- });
215
- }
216
- }
217
- showDatePicker(event, id) {
218
- this.actionControls.get('when').setValidators([Validators.required]);
219
- const actionButtons = this.document.getElementsByClassName('action-btn');
220
- for (const button of actionButtons) {
221
- button.classList.remove('active');
222
- }
223
- event.target.classList.add('active');
224
- this.actionControls.get('crm_action_id').setValue(id);
225
- }
226
- /** Function to get comments */
227
- getAllComments() {
228
- this.getUserSubscriptionId().subscribe(response => {
229
- this.subscriptionId = response;
230
- if (this.subscriptionId) {
231
- this.crmService
232
- .getAccountComments(this.accountId, this.subscriptionId, {
233
- page: this.currentPage,
234
- page_size: 5
235
- })
236
- .subscribe(resp => {
237
- this.totalContacts = resp.object_count;
238
- if (resp?.crm_account_actions?.length) {
239
- this.accountComments = resp.crm_account_actions;
240
- this.accountComments.forEach(data => {
241
- data.when_short_date = moment(data.when).format('DD-MMM-YYYY');
242
- const diff = moment(new Date(data.when)).diff(moment(new Date()), 'days');
243
- if (moment(new Date(data.when)) < moment(new Date())) {
244
- data['due'] = `Overdue by ${Math.abs(diff)} days`;
245
- data['color'] = this.dangerColor;
246
- }
247
- else {
248
- data['due'] = `In ${diff} days`;
249
- data['color'] = !this.dangerColor;
250
- }
251
- });
252
- this.accountComments.sort((a, b) => {
253
- return new Date(a.when).getTime() - new Date(b.when).getTime();
254
- });
255
- this.accountComments.forEach(item => {
256
- item['when'] = moment(item['when']).format('DD-MMM-YYYY');
257
- item['year'] = moment(item['when'], 'DD-MMM-YYYY').format('YYYY');
258
- item['month'] = moment(item['when'], 'DD-MMM-YYYY').format('MM');
259
- });
260
- const completedCancelledActions = this.accountComments.filter(action => action.completed === true || action.cancelled === true);
261
- completedCancelledActions.reverse();
262
- const notCompletedCancelledActions = this.accountComments.filter(action => action.completed === false && action.cancelled === false);
263
- this.accountComments =
264
- notCompletedCancelledActions.concat(completedCancelledActions);
265
- this.isLoaded = true;
266
- }
267
- else {
268
- this.isLoaded = true;
269
- }
270
- });
271
- }
272
- });
273
- }
274
- /** Function to update comment */
275
- updateComment(item) {
276
- const commentObj = {
277
- comment: item.comment,
278
- completed: item.completed,
279
- cancelled: item.cancelled,
280
- crm_account_id: item.crm_account_id,
281
- crm_contact_id: this.contactId
282
- };
283
- this.crmService
284
- .updateAccountComment(this.subscription?.id, item.id, commentObj)
285
- .subscribe(() => {
286
- this.toast.success('comment updated successfully');
287
- this.showEditControls(undefined, '');
288
- this.getAllComments();
289
- });
290
- }
291
- /** Function to execute on location select */
292
- handleAddressChange(event) {
293
- this.aboutControls.get('location').setValue(event.formatted_address);
294
- }
295
- /** Function to get subscription members */
296
- getAllSubscriptionMembers() {
297
- this.subscriptionService
298
- .getEnrolledSubscription(this.subscription?.id)
299
- .subscribe(member => {
300
- this.allSubscriptionMembers = member.members;
301
- });
302
- }
303
- /** Function to show edit comment section */
304
- showEditControls(event, action) {
305
- if (action?.crm_contact) {
306
- this.contactId = action.crm_contact.id;
307
- }
308
- const comments = this.document.getElementsByClassName('card-header');
309
- for (const comment of comments) {
310
- comment.classList.remove('show-controls');
311
- }
312
- if (event && event !== undefined) {
313
- event.target.closest('.card-header').classList.add('show-controls');
314
- }
315
- }
316
- /** Function to get and show all the actions */
317
- getActions() {
318
- this.crmService.getAllActions(this.subscription?.id).subscribe(resp => {
319
- if (resp?.crm_actions?.length) {
320
- this.actions = resp.crm_actions.sort((a, b) => a.name.localeCompare(b.name));
321
- this.buttonDisable = this.actions.every(x => x.visible === false || x.visible === null);
322
- }
323
- else {
324
- this.buttonDisable = true;
325
- }
326
- });
327
- this.hasAccess = this.hasAdminAccess(this.subscription?.id);
328
- }
329
- /** Function to set the action as completed */
330
- setAsCompletedOrUncompleted(id, action, completedOrUncompleted) {
331
- const alertTitle = completedOrUncompleted ? 'InCompleted' : 'Completed';
332
- return swal
333
- .fire({
334
- title: alertTitle,
335
- html: `Are you sure you want to set as ${alertTitle}?`,
336
- showCancelButton: true,
337
- reverseButtons: true,
338
- icon: 'warning'
339
- })
340
- .then(res => {
341
- if (res.value) {
342
- const actionObj = {
343
- comment: action.comment,
344
- completed: !completedOrUncompleted,
345
- cancelled: action.cancelled,
346
- crm_account_id: action.crm_account_id
347
- };
348
- this.crmService
349
- .updateAccountComment(this.subscription?.id, id, actionObj)
350
- .subscribe(() => {
351
- this.toast.success(this.translation.translate('Crm.Settings.UpdatedMessage'));
352
- this.actions.splice(action, 1);
353
- this.getActions();
354
- this.getAllComments();
355
- });
356
- }
357
- });
358
- }
359
- /** Function to set the action as cancelled */
360
- setAsCancelled(id, action) {
361
- return swal
362
- .fire({
363
- title: 'Cancel',
364
- html: `Are you sure you want to set as cancelled?`,
365
- showCancelButton: true,
366
- reverseButtons: true,
367
- icon: 'warning'
368
- })
369
- .then(res => {
370
- if (res.value) {
371
- const actionObj = {
372
- comment: action.comment,
373
- completed: action.completed,
374
- cancelled: true,
375
- crm_account_id: action.crm_account_id
376
- };
377
- this.crmService
378
- .updateAccountComment(this.subscription?.id, id, actionObj)
379
- .subscribe(() => {
380
- this.toast.success(this.translation.translate('Crm.Settings.UpdatedMessage'));
381
- this.actions.splice(action, 1);
382
- this.getActions();
383
- this.getAllComments();
384
- });
385
- }
386
- });
387
- }
388
- /** Function to update the date */
389
- onDateSelect(event, action) {
390
- const commentObj = {
391
- when: HelperService.dateFormat(event),
392
- comment: action.comment,
393
- completed: action.completed,
394
- cancelled: action.cancelled,
395
- crm_account_id: action.crm_account_id
396
- };
397
- this.crmService
398
- .updateAccountComment(this.subscription?.id, action.id, commentObj)
399
- .subscribe(() => {
400
- this.toast.success('date updated successfully');
401
- this.getAllComments();
402
- this.updating = false;
403
- });
404
- }
405
- /** Function to show DatePicker */
406
- showDatePickerUpdate(actionId) {
407
- this.updating = !this.updating;
408
- this.actionId = actionId;
409
- }
410
- /** Function to get the contacts related to account */
411
- getAccountContacts(paging) {
412
- this.getUserSubscriptionId().subscribe(id => {
413
- this.subscriptionId = id;
414
- if (this.subscriptionId) {
415
- this.crmService
416
- .getAccountContacts(this.accountId, this.subscriptionId, this.filterByPotentials || '', paging)
417
- .subscribe(response => {
418
- if (response.contacts) {
419
- this.contacts = response.contacts;
420
- this.totalRecords = response.object_count;
421
- this.totalRecordsUnFiltered = response.unfiltered_count;
422
- this.contacts.forEach(member => {
423
- member.displayName = `${member.first_name || ''} ${member.last_name || ''} - ${member.email}`.trim();
424
- });
425
- }
426
- })
427
- .add(() => {
428
- this.loading = false;
429
- });
430
- }
431
- });
432
- }
433
- /** Function when auto-complete dropdown selected */
434
- onDropdownClick() {
435
- if (this.contacts?.length === 0) {
436
- this.filteredContact = [{ displayName: 'No contact to choose' }];
437
- this.filteredContactComment = [{ first_name: 'No contact to choose' }];
438
- }
439
- }
440
- /** search owner */
441
- search(event) {
442
- const values = [];
443
- if (event.query) {
444
- this.filteredOwner = this.allSubscriptionMembers?.filter((x) => {
445
- return x.first_name.toLowerCase().includes(event.query.toLowerCase());
446
- });
447
- }
448
- else {
449
- this.allSubscriptionMembers?.forEach(element => {
450
- values.push(element);
451
- });
452
- }
453
- this.filteredOwner = values.map(owner => {
454
- return {
455
- ...owner,
456
- displayName: HelperService.formatDisplayName(owner, true)
457
- };
458
- });
459
- }
460
- searchContact(event) {
461
- this.isContactValid = false;
462
- let values = [];
463
- if (event.query) {
464
- values = this.contacts?.filter((x) => {
465
- return x.displayName.toLowerCase().includes(event.query.toLowerCase());
466
- });
467
- }
468
- else {
469
- this.contacts?.forEach(element => {
470
- values.push(element);
471
- });
472
- }
473
- this.filteredContact = values;
474
- }
475
- selectContact(event) {
476
- this.isContactValid = this.contacts.some(x => x.id === event.value.id);
477
- }
478
- OnContactBlur() {
479
- if (!this.isContactValid) {
480
- this.actionControls.get('crm_contact_id').setValue('');
481
- }
482
- }
483
- searchContactInComment(event) {
484
- let values = [];
485
- if (event.query) {
486
- values = this.contacts?.filter((x) => {
487
- return x.displayName.toLowerCase().includes(event.query.toLowerCase());
488
- });
489
- }
490
- else {
491
- this.contacts?.forEach(element => {
492
- values.push(element);
493
- });
494
- }
495
- this.filteredContactComment = values;
496
- }
497
- selectCommentContact(event) {
498
- this.contactId = event?.value?.id;
499
- }
500
- /** Function to delete contact */
501
- onDeleteContact(id) {
502
- HelperService.raiseDeletePopup().then(resp => {
503
- if (resp.value) {
504
- this.crmService.deleteContact(this.subscription?.id, id).subscribe(() => {
505
- this.toast.success(this.translation.translate('Crm.ContactMessage.DeletedMessage'));
506
- this.getAccountContacts({
507
- page: this.page,
508
- page_size: PAGE_SIZE
509
- });
510
- });
511
- }
512
- });
513
- }
514
- /** Function to get contact versions */
515
- getContactVersion() {
516
- this.crmService
517
- .getContactVersion(this.subscription?.id, this.accountId, 'CrmAccount')
518
- .subscribe(response => {
519
- this.accountVersioning = response.versions;
520
- });
521
- }
522
- openModal(content) {
523
- this.modalService.open(content, { centered: true, windowClass: 'modal-holder' });
524
- }
525
- onClose() {
526
- this.modalService.dismissAll();
527
- }
528
- onUploadOutput(output) {
529
- switch (output.type) {
530
- case 'allAddedToQueue':
531
- if (this.files.length > 0) {
532
- const event = {
533
- type: 'uploadAll',
534
- url: CRM_ACCOUNT_FILES_PATH,
535
- method: 'POST',
536
- data: {
537
- owner_id: `${this.userId}`,
538
- crm_account_id: `${this.accountId}`
539
- },
540
- headers: {
541
- [TOKEN_HEADER_KEY]: this.token
542
- }
543
- };
544
- this.uploadInput.emit(event);
545
- }
546
- break;
547
- case 'addedToQueue':
548
- if (typeof output.file !== 'undefined') {
549
- const ext = output.file.name.split('.').pop();
550
- if (DOCUMENT_TYPE_EXT.includes(ext)) {
551
- this.files.push(output.file);
552
- }
553
- else {
554
- this.toast.error('file formats is not supported.');
555
- }
556
- }
557
- break;
558
- case 'uploading':
559
- if (typeof output.file !== 'undefined') {
560
- const index = this.files.findIndex(file => typeof output.file !== 'undefined' && file.id === output.file.id);
561
- this.files[index] = output.file;
562
- }
563
- break;
564
- case 'removed':
565
- this.files = this.files.filter((file) => file !== output.file);
566
- break;
567
- case 'dragOver':
568
- this.dragOver = true;
569
- break;
570
- case 'dragOut':
571
- case 'drop':
572
- this.dragOver = false;
573
- break;
574
- case 'done':
575
- break;
576
- default:
577
- }
578
- this.files.forEach(file => {
579
- if (file.progress.status === UploadStatus.Done) {
580
- file['uploaded'] = true;
581
- }
582
- });
583
- // wait for 500ms before filter files
584
- setTimeout(() => {
585
- this.files = this.files.filter(file => file.progress.status !== UploadStatus.Done);
586
- }, 500);
587
- }
588
- getAccountLogo(url) {
589
- if (url) {
590
- return this.logoCacheService.getLogo(HelperService.getLogoByUrl(url));
591
- }
592
- return '';
593
- }
594
- navigateToAddOpportunities() {
595
- this.router.navigate([`/${this.subscription?.slug}${this.routers.opportunityAdd}`], {
596
- queryParams: { account_id: this.accountId }
597
- });
598
- }
599
- ngOnDestroy() {
600
- super.ngOnDestroy();
601
- }
602
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: SmartCrmCompanyInfoComponent, deps: [{ token: i0.Injector }, { token: i1.CrmService }, { token: i2.SubscriptionService }, { token: i2.GeoService }, { token: i2.CommonService }, { token: i3.NgbModal }, { token: i2.AuthService }, { token: i0.ChangeDetectorRef }, { token: i2.LogoCacheService }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Component }); }
603
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.11", type: SmartCrmCompanyInfoComponent, selector: "pw-smart-crm-company-info", usesInheritance: true, ngImport: i0, template: "<div class=\"row\">\n <div class=\"col-12 mb-0\">\n <div class=\"me-auto mb-0\">\n <h2 class=\"mb-0\">\n <a aria-label=\"Navigate to Target\"\n (click)=\"back()\"\n class=\"previous\"><i class=\"fa fa-arrow-alt-circle-left\" aria-hidden=\"true\"></i></a>\n Account Info\n </h2>\n </div>\n <a class=\"btn btn-sm btn-outline-primary float-end mb-3\"\n data-cy=\"add-opportunities\"\n (click)=\"navigateToAddOpportunities()\">\n <i class=\"fa fa-plus-circle\" aria-hidden=\"true\"></i>\n {{ 'Crm.OpportunitiesMessage.AddOpportunity' | transloco }}\n </a>\n </div>\n <div class=\"w-100 text-center mt-3\"\n *ngIf=\"!isDataLoaded\">\n <p-progressSpinner> </p-progressSpinner>\n </div>\n <div *ngIf=\"isDataLoaded\">\n <div class=\"row\">\n <div class=\"col-12 col-md-4\">\n <div class=\"user-info p-3 card pb-0 h-auto\">\n <div class=\"mb-2 text-center\">\n <a class=\"profile-image\">\n <img alt=\"Profile Logo\"\n width=\"100\"\n height=\"100\"\n [src]=\"getAccountLogo(data?.company_url)\"\n class=\"img-fluid company-logo\"\n (error)=\"handleImageError($event, 'assets/img/icons/company.png')\" />\n </a>\n </div>\n <div class=\"mb-4 d-flex justify-content-between align-items-center\">\n <h4 class=\"d-inline-block name-block\">\n About <span *ngIf=\"data?.id\">{{ data.name }}</span>\n </h4>\n <a href=\"javascript:void(0);\"\n *ngIf=\"isFormEdit && (userId === data?.owner?.id || hasAccess)\"\n class=\"btn btn-sm btn-outline-primary float-end\"\n (click)=\"isFormEdit = !isFormEdit; this.getAllSubscriptionMembers()\">{{ 'Button.Edit' | transloco }}</a>\n </div>\n <form [formGroup]=\"aboutControls\"\n [class.isDisabled]=\"isFormEdit\">\n <div class=\"mb-3\">\n <label class=\"label mb-0\" for=\"name\">{{ 'Crm.AccountMessage.Name' | transloco }}</label>\n <input type=\"text\"\n class=\"form-control rounded-0 ps-1 user-value\"\n formControlName=\"name\"\n [ngClass]=\"{ 'is-invalid': submitted && f['name'].errors }\" />\n </div>\n <div class=\"mb-3\">\n <label class=\"label mb-0\" for=\"Location\">{{\n 'Crm.AccountMessage.Location' | transloco\n }}</label>\n <input ngx-gp-autocomplete\n class=\"form-control rounded-0 ps-1 user-value\"\n #places=\"ngx-places\"\n formControlName=\"location\"\n (onAddressChange)=\"handleAddressChange($event)\"\n [ngClass]=\"{ 'is-invalid': submitted && f['location'].errors }\" />\n </div>\n <div class=\"mb-3\"\n *ngIf=\"countries$ | async as countries\">\n <label for=\"country\">{{ 'Crm.AccountMessage.Country' | transloco\n }}<span class=\"text-danger required-icon\">*</span>\n </label>\n <p-dropdown\n [options]=\"countries\"\n formControlName=\"country\"\n [ngClass]=\"{ 'is-invalid': submitted && f['country'].errors }\"\n [placeholder]=\"'Select Country'\"\n optionValue=\"code\"\n optionLabel=\"name\">\n </p-dropdown>\n </div>\n <div class=\"mb-3 ui-fluid skills-modal\">\n <label class=\"label mb-2\" for=\"Message\">{{ 'Crm.AccountMessage.Owner' | transloco }}</label>\n <p class=\"form-control d-block pb-2 ps-1 user-value\"\n *ngIf=\"isFormEdit && data?.owner_id\">\n {{ data?.owner?.first_name }} {{ data?.owner?.last_name }}\n </p>\n <p-autoComplete *ngIf=\"!isFormEdit || !data?.owner_id\"\n [suggestions]=\"filteredOwner\"\n formControlName=\"owner_id\"\n dataKey=\"id\"\n field=\"displayName\"\n [dropdown]=\"true\"\n (completeMethod)=\"search($event)\"\n styleClass=\"w-100\"\n placeholder=\"Search owner\"\n [multiple]=\"false\">\n </p-autoComplete>\n </div>\n <div class=\"mb-3\">\n <label class=\"label mb-0\" for=\"CompanyUrl\">{{\n 'Crm.AccountMessage.CompanyUrl' | transloco\n }}</label>\n <a [href]=\"data?.company_url\"\n target=\"blank\"\n class=\"form-control d-block pb-2 ps-1 user-value\"\n *ngIf=\"isFormEdit && data?.company_url\">{{ data?.company_url }}</a>\n <input *ngIf=\"!isFormEdit || !data?.company_url\"\n type=\"text\"\n class=\"form-control rounded-0 ps-1 user-value\"\n formControlName=\"company_url\"\n [ngClass]=\"{ 'is-invalid': submitted && f['company_url'].errors }\" />\n </div>\n <div class=\"mb-3\"\n *ngIf=\"data?.tel\">\n <label class=\"label mb-0\" for=\"AccountMessage\">{{ 'Crm.AccountMessage.Tel' | transloco }}</label>\n <input type=\"text\"\n class=\"form-control rounded-0 ps-1 user-value\"\n formControlName=\"tel\" />\n </div>\n <div class=\"mb-3\"\n *ngIf=\"organizationTypes$ | async as types\">\n <label for=\"organizationType\">{{ 'Organization.OrganizationType' | transloco }}</label>\n <p-dropdown\n [options]=\"types['organization_types']\"\n formControlName=\"organization_type_id\"\n [ngClass]=\"{ 'is-invalid': submitted && f['organization_type_id'].errors }\"\n [placeholder]=\"'Select Organization Type'\"\n optionValue=\"id\"\n optionLabel=\"name\">\n </p-dropdown>\n </div>\n <div class=\"mb-3\"\n *ngIf=\"organizationIndustries$ | async as industries\">\n <label for=\"file\">{{ 'Organization.OrganizationIndustry' | transloco }}</label>\n <p-dropdown\n [options]=\"industries['organization_industries']\"\n formControlName=\"organization_industry_id\"\n [ngClass]=\"{ 'is-invalid': submitted && f['organization_industry_id'].errors }\"\n [placeholder]=\"'Select Industry'\"\n optionValue=\"id\"\n optionLabel=\"name\">\n </p-dropdown>\n </div>\n <div class=\"mb-3\"\n *ngIf=\"organizationSizes$ | async as sizes\">\n <label for=\"size\">{{ 'Crm.AccountMessage.Size' | transloco }}</label>\n <p-dropdown\n [options]=\"sizes['organization_sizes']\"\n formControlName=\"organization_size_id\"\n [ngClass]=\"{ 'is-invalid': submitted && f['organization_size_id'].errors }\"\n [placeholder]=\"'Select Size'\"\n optionValue=\"id\"\n optionLabel=\"name\">\n </p-dropdown>\n </div>\n <div class=\"mb-3\">\n <label for=\"status\">{{ 'Crm.AccountMessage.Status' | transloco }}</label>\n <p-dropdown\n [options]=\"status\"\n formControlName=\"status\"\n [ngClass]=\"{ 'is-invalid': submitted && f['status'].errors }\"\n [placeholder]=\"'Select Status'\">\n </p-dropdown>\n </div>\n <div class=\"mb-3\">\n <label for=\"priority\">{{ 'Crm.AccountMessage.Priority' | transloco }}</label>\n <p-dropdown\n [options]=\"priority\"\n formControlName=\"priority\"\n [ngClass]=\"{ 'is-invalid': submitted && f['priority'].errors }\"\n [placeholder]=\"'Select Priority'\">\n </p-dropdown>\n </div>\n <div class=\"mb-3\">\n <label for=\"message\">{{ 'Crm.AccountMessage.Source' | transloco }}</label>\n <p-dropdown\n [options]=\"source\"\n formControlName=\"crm_source_id\"\n [ngClass]=\"{ 'is-invalid': submitted && f['crm_source_id'].errors }\"\n [placeholder]=\"'Select Source'\"\n optionValue=\"id\"\n optionLabel=\"name\">\n </p-dropdown>\n </div>\n <div class=\"mb-3\">\n <pw-input-container [label]=\"'Crm.AccountMessage.Description' | transloco\"\n name=\"description\">\n <textarea rows=\"5\"\n type=\"text\"\n class=\"form-control\"\n formControlName=\"description\"\n id=\"description\"\n [ngClass]=\"{ 'is-invalid': submitted && f['description'].errors }\"></textarea>\n </pw-input-container>\n </div>\n <div *ngIf=\"!isFormEdit\"\n class=\"text-end form-action-buttons\">\n <input type=\"button\"\n class=\"btn btn-outline-primary\"\n (click)=\"isFormEdit = !isFormEdit; getAccountDetails()\"\n value=\"Cancel\" />\n <button type=\"submit\"\n [buttonBusy]=\"buttonBusy\"\n class=\"btn btn-primary ms-3\"\n (click)=\"updateAccountInfo()\">\n {{ 'Button.Submit' | transloco }}\n </button>\n </div>\n </form>\n </div>\n </div>\n <div class=\"col-12 col-md-8\">\n <ul ngbNav\n #nav=\"ngbNav\"\n class=\"nav-tabs\">\n <li [ngbNavItem]=\"1\">\n <a ngbNavLink>Notes</a>\n <ng-template ngbNavContent>\n <form [formGroup]=\"actionControls\"\n (ngSubmit)=\"onSave()\">\n <textarea class=\"form-control\"\n formControlName=\"comment\"\n rows=\"6\"></textarea>\n <p class=\"text-danger\"\n *ngIf=\"\n actionControls.get('comment').touched &&\n actionControls.get('comment').invalid\n \">\n Note Required\n </p>\n <div *ngIf=\"actions?.length\"\n class=\"d-block clear-both pt-3\">\n <ng-container *ngFor=\"let action of actions; index as i\">\n <button *ngIf=\"action.visible\"\n type=\"button\"\n [class.active]=\"\"\n class=\"btn btn-sm me-2 btn-outline-primary mb-2 action-btn\"\n (click)=\"showDatePicker($event, action.id); d.toggle()\">\n {{ action.name }}\n </button>\n </ng-container>\n <div class=\"text-danger\"\n *ngIf=\"submitAction && actionControls.get('crm_action_id').invalid\">\n Please select an action\n </div>\n <div class=\"row mt-3\">\n <div class=\"col-12 col-sm-4\">\n <div class=\"input-group\">\n <input class=\"form-control\"\n placeholder=\"dd-mmm-yyyy\"\n formControlName=\"when\"\n ngbDatepicker\n #d=\"ngbDatepicker\"\n (click)=\"d.toggle()\" />\n </div>\n </div>\n <div class=\"ui-fluid skills-modal col-sm-4 ps-0\">\n <p-autoComplete [suggestions]=\"filteredContact\"\n formControlName=\"crm_contact_id\"\n dataKey=\"id\"\n field=\"displayName\"\n [dropdown]=\"true\"\n (completeMethod)=\"searchContact($event)\"\n (onSelect)=\"selectContact($event)\"\n (onBlur)=\"OnContactBlur()\"\n styleClass=\"w-100\"\n placeholder=\"Search contact\"\n [multiple]=\"false\"\n (onDropdownClick)=\"onDropdownClick()\">\n </p-autoComplete>\n </div>\n <div class=\"col-sm-4 pe-0 completed-toggle\">\n <div class=\"mb-3\">\n <ui-switch checkedLabel=\"completed\"\n uncheckedLabel=\"open\"\n formControlName=\"completed\"\n name=\"completed\">\n </ui-switch>\n </div>\n </div>\n </div>\n </div>\n <div class=\"float-end\">\n <a class=\"btn btn-outline-primary me-0 me-sm-2\"\n (keydown.enter)=\"openModal(content)\"\n (click)=\"openModal(content)\">{{ 'Upload file' | transloco }}</a>\n <button type=\"submit\"\n [buttonBusy]=\"buttonBusy\"\n [disabled]=\"buttonDisable\"\n class=\"btn btn-primary mt-2 mb-2\">Submit Note</button>\n </div>\n <div *ngIf=\"buttonDisable\"\n class=\"no-actions pt-4\">\n <pw-no-data [withImage]=\"true\" [message]=\"\n 'Crm.AccountMessage.NoActionsInAccountInfoMessage' | transloco\n \">\n </pw-no-data>\n </div>\n </form>\n <div class=\"w-100 text-center mt-3\"\n *ngIf=\"!isLoaded\">\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </div>\n <div *ngIf=\"!accountComments?.length && isLoaded\"\n class=\"no-actions pt-2\">\n <pw-no-data [withImage]=\"true\" [message]=\"'Crm.AccountMessage.NoActionsMessage' | transloco\">\n </pw-no-data>\n </div>\n <div *ngIf=\"accountComments?.length\">\n <div id=\"timeline\"\n class=\"pt-3 clear-both timeline-center timeline-wrapper timeline-container\"\n infiniteScroll\n [infiniteScrollDistance]=\"2\"\n [infiniteScrollThrottle]=\"50\"\n [infiniteScrollContainer]=\"selector\"\n [fromRoot]=\"true\"\n (scrolled)=\"onScrollTimeline()\">\n <ul class=\"timeline\">\n <li class=\"timeline-line\"></li>\n </ul>\n <ul class=\"timeline\">\n <li class=\"timeline-line\"></li>\n <li class=\"timeline-item\"\n [ngClass]=\"{ 'mt-5': odd || last }\"\n *ngFor=\"\n let item of accountComments;\n index as i;\n let odd = odd;\n let even = even;\n let last = last;\n let first = first\n \">\n <div class=\"timeline-badge\">\n <span class=\"bg-red bg-lighten-1\">\n <span class=\"timeline-year\">\n <span class=\"d-block date-year\">{{\n item.when | date: 'medium' | slice: 0:3\n }}</span>\n <span>{{ item.year }}</span></span>\n </span>\n </div>\n <div class=\"timeline-card shadow card pb-0 rounded border-grey border-lighten-2 position-static\">\n <div class=\"card-header py-4\">\n <div class=\"mb-0 clearfix\">\n <textarea type=\"text\"\n name=\"comment\"\n class=\"comment-field form-control p-0\"\n [(ngModel)]=\"item.comment\">{{ item.comment }}</textarea>\n <div class=\"auto-complete mb-3 ui-fluid skills-modal\">\n <p-autoComplete [(ngModel)]=\"item.crm_contact\"\n [suggestions]=\"filteredContactComment\"\n dataKey=\"id\"\n field=\"first_name\"\n dropdown=\" true \"\n (completeMethod)=\"\n searchContactInComment($event)\n \"\n (onSelect)=\"selectCommentContact($event)\"\n (onBlur)=\"OnContactBlur()\"\n styleClass=\" w-100 \"\n placeholder=\" Search contact \"\n [multiple]=\"false\"\n (onDropdownClick)=\"onDropdownClick()\">\n </p-autoComplete>\n </div>\n <p class=\"float-start mb-0\"\n *ngIf=\"\n !showFullComment || item.id !== commentId\n \">\n {{ item.comment | slice: 0:170\n }}<a *ngIf=\"item.comment.length > 170\"\n class=\"text-secondary\"\n (click)=\"\n showFullComment = true;\n commentId = item.id\n \">...show more\n </a>\n </p>\n <p class=\"float-start mb-0\"\n *ngIf=\"showFullComment && item.id === commentId\">\n {{ item.comment }}\n <a *ngIf=\"\n item.comment.length > 170 &&\n showFullComment\n \"\n (click)=\"showFullComment = false\"\n class=\"text-secondary\">...show less</a>\n </p>\n <button class=\"btn btn-md edit-btn float-end py-0\"\n (click)=\"showEditControls($event, item)\"\n *ngIf=\"userId === item.owner_id || hasAccess\">\n <i\n class=\"fa fa-edit edit-icon\"\n aria-hidden=\"true\"\n ></i>\n </button>\n </div>\n <div class=\"card-subtitle text-muted my-0 clearfix\">\n <div class=\"float-start\">\n <span *ngIf=\"!updating || actionId !== item.id\"\n class=\"font-small-3\">\n {{ item.when }}</span>\n <input *ngIf=\"updating && actionId === item.id\"\n placeholder=\"dd-mmm-yyyy\"\n value=\"{{ item.when }}\"\n ngbDatepicker\n #d=\"ngbDatepicker\"\n (focus)=\"d.toggle()\"\n (dateSelect)=\"onDateSelect($event, item)\" />\n </div>\n <button type=\" button\"\n class=\"btn btn-sm float-end when-btn py-0\"\n *ngIf=\"userId === item.owner_id || hasAccess\"\n (click)=\"showDatePickerUpdate(item.id)\">\n <i\n class=\"fa fa-edit edit-icon\"\n aria-hidden=\"true\"\n ></i>\n </button>\n </div>\n <p [class.text-danger]=\"!item.color\"\n *ngIf=\"!item.cancelled && !item.completed\"\n class=\"mb-0\">\n {{ item.due }}\n </p>\n <a class=\"text-secondary action-owner\"\n *ngIf=\"item.crm_contact\"\n [routerLink]=\"[\n '/' + subscription?.slug + routers.contactInfo,\n item.crm_contact.id\n ]\">{{ item.crm_contact.first_name }}\n {{ item.crm_contact.last_name || '' }}</a>\n <p>\n By\n {{\n item.owner.first_name +\n ' ' +\n item.owner.last_name\n }}\n </p>\n <span class=\"badge bg-primary\">{{\n item?.crm_action?.name\n }}</span>\n <span *ngIf=\"\n !item.completed &&\n (userId === item.owner_id || hasAccess)\n \"\n class=\"badge bg-success ms-2\">Open</span>\n <a *ngIf=\"\n !item.completed &&\n (userId === item.owner_id || hasAccess)\n \"\n ngbTooltip=\"Set as completed\"\n aria-label=\"Set as completed\"\n class=\"me-3 ms-3\"\n href=\"javascript:void(0);\"\n (click)=\"\n setAsCompletedOrUncompleted(\n item.id,\n item,\n item.completed\n )\n \">\n <i\n class=\"fa fa-tasks completed\"\n aria-hidden=\"true\"\n ></i>\n </a>\n <a *ngIf=\"\n !item.cancelled &&\n !item.completed &&\n (userId === item.owner_id || hasAccess)\n \"\n ngbTooltip=\"Set as cancelled\"\n aria-label=\"Set as cancelled\"\n href=\"javascript:void(0);\"\n (click)=\"setAsCancelled(item.id, item)\">\n <i\n class=\"fa fa-times delete-icon\"\n aria-hidden=\"true\"\n ></i>\n </a>\n <a *ngIf=\"\n item.completed &&\n (userId === item.owner_id || hasAccess)\n \"\n ngbTooltip=\"Set as UnCompleted\"\n aria-label=\"Set as UnCompleted\"\n href=\"javascript:void(0);\"\n (click)=\"\n setAsCompletedOrUncompleted(\n item.id,\n item,\n item.completed\n )\n \"\n class=\"ms-2\">\n <i\n class=\"far fa-window-close\"\n aria-hidden=\"true\"\n ></i>\n </a>\n <div class=\"control-btns mt-3 text-end form-action-buttons\">\n <button type=\"button\"\n class=\"btn btn-sm btn-outline-default me-2\"\n (click)=\"showEditControls(undefined, '')\">\n {{ 'Button.Cancel' | transloco }}\n </button>\n <button class=\"btn btn-sm btn-primary\"\n type=\"button\"\n (click)=\"updateComment(item)\">\n {{ 'Button.Submit' | transloco }}\n </button>\n </div>\n </div>\n </div>\n </li>\n </ul>\n </div>\n </div>\n </ng-template>\n </li>\n <li [ngbNavItem]=\"2\" *ngIf=\"hasAccess || userId === data?.owner?.id\">\n <a ngbNavLink>Contacts</a>\n <ng-template ngbNavContent>\n <div class=\"row\">\n <div class=\"col-12 mb-3\">\n <a class=\"btn btn-sm btn-outline-primary float-end\"\n data-cy=\"add-contact\"\n [routerLink]=\"[\n '/' + subscription?.slug + routers.contactAdd,\n accountId\n ]\">\n <i class=\"fa fa-plus-circle\" aria-hidden=\"true\"></i>\n {{ 'Crm.ContactMessage.AddContact' | transloco }}\n </a>\n </div>\n </div>\n <div class=\"primeng-datatable-container table-responsive\"\n [class.hideTable]=\"totalRecordsUnFiltered === 0\">\n <p-table class=\"table\"\n #dt\n [value]=\"contacts\"\n [paginator]=\"totalRecords !== 0\"\n [rows]=\"PAGE_SIZE\"\n [totalRecords]=\"totalRecords\"\n [loading]=\"loading\"\n [lazy]=\"true\"\n (onLazyLoad)=\"onLazyLoad($event)\"\n [customSort]=\"true\">\n <ng-template pTemplate=\"caption\">\n <div class=\"text-end\">\n <i class=\"fa fa-search mt-2 me-2\" aria-hidden=\"true\"></i>\n <input type=\"text\"\n [(ngModel)]=\"searchText\"\n pInputText\n size=\"50\"\n placeholder=\"Search contact...\"\n (input)=\"dt.filterGlobal($event.target.value, 'contains')\"\n class=\"mw-90\" />\n </div>\n </ng-template>\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"true\"\n pSortableColumn=\"first_name\">\n {{ 'Label.Name' | transloco }}\n <p-sortIcon field=\"first_name\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"owner_id\">\n {{ 'Crm.ContactMessage.ContactOwner' | transloco }}\n <p-sortIcon field=\"owner_id\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"headline\">\n {{ 'Crm.ContactMessage.Headline' | transloco }}\n <p-sortIcon field=\"headline\"></p-sortIcon>\n </th>\n <th scope=\"true\">{{ 'Label.Actions' | transloco }}</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\"\n let-contact>\n <tr>\n <td data-head=\"Name\"\n class=\"contactname\">\n <a [routerLink]=\"[\n '/' + subscription?.slug + routers.contactInfo,\n contact.id\n ]\"> {{ (contact.first_name || '') + ' ' + (contact.last_name || '') | textTruncate: 20 }}</a>\n </td>\n <td data-head=\"OwnerName\">\n {{ contact.owner | ifNameNullShowEmail }}\n </td>\n <td data-head=\"Headline\"\n class=\"headline-content\">\n {{ contact?.headline | textTruncate: 20 }}\n </td>\n <td data-head=\"Action\">\n <ul class=\"list-unstyled list-inline list-action\">\n <li ngbTooltip=\"Show\"\n class=\"me-2 me-sm-3\"\n [routerLink]=\"[\n '/' + subscription?.slug + routers.contactInfo,\n contact.id\n ]\">\n <i\n class=\"fa fa-eye see-icon\"\n aria-hidden=\"true\"\n ></i>\n </li>\n <li *ngIf=\"\n hasAccess ||\n contact.owner_id === userId ||\n contact.crm_account.owner_id === userId\n \"\n ngbTooltip=\"Add opportunity\"\n class=\"me-2 me-sm-3\"\n [routerLink]=\"[\n '/' +\n subscription?.slug +\n routers.opportunityAdd\n ]\"\n [queryParams]=\"{ contact_id: contact.id }\">\n <i\n class=\"fa fa-plus-circle add-icon\"\n aria-hidden=\"true\"\n ></i>\n </li>\n <li *ngIf=\"\n hasAccess ||\n contact.owner_id === userId ||\n contact.crm_account.owner_id === userId\n \"\n ngbTooltip=\"Edit\"\n class=\"me-2 me-sm-3\"\n [routerLink]=\"[\n '/' +\n subscription?.slug +\n routers.contactDetails,\n contact.id\n ]\">\n <i\n class=\"fa fa-edit edit-icon\"\n aria-hidden=\"true\"\n ></i>\n </li>\n <li *ngIf=\"\n hasAccess ||\n contact.owner_id === userId ||\n contact.crm_account.owner_id === userId\n \"\n ngbTooltip=\"Delete\"\n class=\"me-2 me-sm-3\">\n <i\n class=\"fa fa-trash delete-icon\"\n (keydown.enter)=\"onDeleteContact(contact.id)\"\n (keydown.space)=\"onDeleteContact(contact.id)\"\n (click)=\"onDeleteContact(contact.id)\"\n aria-hidden=\"true\"\n ></i>\n </li>\n </ul>\n </td>\n </tr>\n </ng-template>\n </p-table>\n <div *ngIf=\"totalRecords === 0 && totalRecordsUnFiltered !== 0\">\n <pw-no-data [withImage]=\"true\" [message]=\"'Search.NoDataMessage'| transloco\" [description]=\"'Search.NoDataDescription' | transloco\" >\n </pw-no-data>\n </div>\n <span class=\"total-records-count\" *ngIf=\"totalRecords !== 0\">{{ 'Label.Total' | transloco }}: {{ totalRecords }}</span>\n </div>\n <div *ngIf=\"totalRecordsUnFiltered === 0\">\n <pw-no-data [withImage]=\"true\" [message]=\"'Crm.ContactMessage.ContactsAdminMessage' | transloco\">\n </pw-no-data>\n </div>\n </ng-template>\n </li>\n <li [ngbNavItem]=\"3\" *ngIf=\"hasAccess\">\n <a ngbNavLink>Versioning</a>\n <ng-template ngbNavContent>\n <div *ngFor=\"let versioning of accountVersioning\">\n <p>\n <strong>Event: </strong>{{ versioning.event }} |\n <strong>Author: </strong><a *ngIf=\"versioning?.author\"\n [routerLink]=\"['/members', versioning?.author?.slug]\">{{ versioning?.author | ifNameNullShowEmail }}</a>\n | <strong>Created at: </strong>{{ versioning.created_at | dateFormat: 'datetime' }}<br />\n <strong>Object: </strong>{{ versioning.object | json }}\n </p>\n <hr />\n </div>\n <div *ngIf=\"accountVersioning?.length === 0\">\n <pw-no-data [withImage]=\"true\" [message]=\"'Crm.AccountMessage.NoVersionsMessage' | transloco\">\n </pw-no-data>\n </div>\n </ng-template>\n </li>\n <li [ngbNavItem]=\"4\">\n <a ngbNavLink>Files</a>\n <ng-template ngbNavContent>\n <pw-smart-crm-company-files [accountId]=\"accountId\"></pw-smart-crm-company-files>\n </ng-template>\n </li>\n <li [ngbNavItem]=\"5\" *ngIf=\"hasAccess\">\n <a ngbNavLink>Invoices</a>\n <ng-template ngbNavContent>\n <pw-smart-crm-account-invoices [accountId]=\"accountId\"/>\n </ng-template>\n </li>\n </ul>\n <div [ngbNavOutlet]=\"nav\"></div>\n </div>\n </div>\n </div>\n</div>\n<ng-template #content\n let-modal>\n <div class=\"modal-header\">\n <h3 class=\"modal-title mb-0 p-0\">{{ 'Upload File' | transloco }}</h3>\n <button type=\"button\"\n class=\"btn-close float-end\"\n aria-label=\"Close\"\n (click)=\"modal.dismiss()\">\n\n </button>\n </div>\n <div class=\"modal-body\">\n <small> {{ 'User.Profile.PictureMessage' | transloco }}</small>\n <div class=\"row p-2\">\n <div class=\"col-12\">\n <div class=\"upload-box\">\n <div class=\"upload-box-content\">\n <div class=\"drop-container\"\n ngFileDrop\n [options]=\"options\"\n (uploadOutput)=\"onUploadOutput($event)\"\n [uploadInput]=\"uploadInput\">\n <p>\n Drag files here or\n <label class=\"upload-button\">\n <input type=\"file\"\n ngFileSelect\n [options]=\"options\"\n (uploadOutput)=\"onUploadOutput($event)\"\n [uploadInput]=\"uploadInput\"\n multiple />\n browse\n </label>\n to upload.\n </p>\n </div>\n <div class=\"upload-item\"\n *ngFor=\"let f of files; let i = index\">\n <div class=\"upload-item-content\">\n <div class=\"filename\">\n <div class=\"filename-left\">\n <i class=\"ionicon ion-ios-copy\" aria-hidden=\"true\"></i>\n <span>{{ f.name }}</span>\n </div>\n </div>\n <div class=\"progress-content\">\n <div class=\"progress\">\n <span class=\"bar\"\n [style.width]=\"f?.progress?.data?.percentage + '%'\"\n [class.is-done]=\"f['uploaded']\"></span>\n </div>\n </div>\n <div class=\"progress-text-content\">\n <span class=\"progress-text\"\n [class.is-done]=\"f['uploaded']\">\n <span *ngIf=\"!f['uploaded']\">{{ f.progress?.data?.percentage - 1 }}%\n </span>\n <span *ngIf=\"f['uploaded']\">100 %</span>\n <span *ngIf=\"!f['uploaded']\">Uploading...</span>\n <span *ngIf=\"f['uploaded']\">Done</span>\n </span>\n <span class=\"speed-and-eta-text\"\n *ngIf=\"f.progress?.data?.percentage !== 0 && !f['uploaded']\">\n <span>{{ f.progress?.data?.speedHuman }} </span>\n <span>ETA {{ f.progress?.data?.etaHuman }}</span>\n </span>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</ng-template>\n", styles: [":root{--first: rgb(23 105 225);--second: rgb(54 194 131);--third: rgb(255 171 0);--text: rgb(34 34 34);--tabs_bg: rgb(23 105 225);--tabs_sub_bg: rgb(70, 136, 236);--tabs_text: rgb(255 255 255);--titles: rgb(34 34 34);--sidebar_bg: rgb(0, 48, 63);--sidebar_text: rgb(255 255 255)}.user-info .label{color:#777;font-size:14px;text-transform:capitalize}.user-info .user-value{border:0;border-bottom:1px solid rgb(119,119,119)}.user-info .user-value:focus{box-shadow:none}.user-info .user-value.is-invalid{border-color:#ff586b}.control-btns{display:none}::ng-deep .p-overlay{width:100%!important;min-width:100%!important;max-width:100%!important;left:0!important}::ng-deep .p-autocomplete-items li{white-space:nowrap!important;overflow:auto!important;text-overflow:ellipsis!important}::ng-deep .p-autocomplete-items li:hover{text-overflow:clip!important}.name-block{width:85%}.comment-field{border:0;border-bottom:1px solid rgb(242,242,242);color:#1769e1;display:none;font-size:15px;min-height:100px;padding:2px 5px!important}.comment-field:focus{border:1px solid rgb(23,105,225)!important;border-bottom:0;box-shadow:none}p{max-width:85%;white-space:pre-wrap}.auto-complete{display:none;margin-top:10px}.show-controls .comment-field,.show-controls .auto-complete,.show-controls .control-btns{display:block}.show-controls p,.show-controls .edit-btn,.show-controls .action-owner{display:none}select{appearance:none}textarea{resize:none}.clear-both{clear:both}.isDisabled input[type=text],.isDisabled input,.isDisabled textarea,.isDisabled p-dropdown,.isDisabled select{pointer-events:none}.isDisabled select{appearance:none;-webkit-appearance:none;-moz-appearance:none;background-image:none!important}.timeline-card.card{min-height:auto}@media (max-width: 768px){.completed-toggle{padding-top:10px}}.when-btn:focus{border:0;box-shadow:none}.no-actions{clear:both}.timeline-container{height:700px;overflow-y:scroll}.action-btn.active{color:#fff!important;background-color:var(--first)}.form-action-buttons{margin-bottom:14px;margin-top:15px}\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.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i6.InputText, selector: "[pInputText]", inputs: ["variant"] }, { kind: "directive", type: i3.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: i7.UiSwitchComponent, selector: "ui-switch", inputs: ["size", "color", "switchOffColor", "switchColor", "defaultBgColor", "defaultBoColor", "checkedLabel", "uncheckedLabel", "checkedTextColor", "uncheckedTextColor", "beforeChange", "ariaLabel", "checked", "disabled", "reverse", "loading"], outputs: ["change", "changeEvent", "valueChange"] }, { kind: "directive", type: i8.ButtonBusyDirective, selector: "[buttonBusy]", inputs: ["buttonBusy", "busyText"] }, { kind: "directive", type: i8.LazyImgDirective, selector: "img" }, { kind: "directive", type: i5.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i5.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i9.NgxGpAutocompleteDirective, selector: "[ngx-gp-autocomplete]", inputs: ["options"], outputs: ["onAddressChange"], exportAs: ["ngx-places"] }, { kind: "directive", type: i10.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i3.NgbNavContent, selector: "ng-template[ngbNavContent]" }, { kind: "directive", type: i3.NgbNav, selector: "[ngbNav]", inputs: ["activeId", "animation", "destroyOnHide", "orientation", "roles", "keyboard"], outputs: ["activeIdChange", "shown", "hidden", "navChange"], exportAs: ["ngbNav"] }, { kind: "directive", type: i3.NgbNavItem, selector: "[ngbNavItem]", inputs: ["destroyOnHide", "disabled", "domId", "ngbNavItem"], outputs: ["shown", "hidden"], exportAs: ["ngbNavItem"] }, { kind: "directive", type: i3.NgbNavItemRole, selector: "[ngbNavItem]:not(ng-container)" }, { kind: "directive", type: i3.NgbNavLink, selector: "a[ngbNavLink]" }, { kind: "directive", type: i3.NgbNavLinkBase, selector: "[ngbNavLink]" }, { kind: "component", type: i3.NgbNavOutlet, selector: "[ngbNavOutlet]", inputs: ["paneRole", "ngbNavOutlet"] }, { kind: "component", type: i11.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "style", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "scrollDirection", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "responsive", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "autoLayout", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll", "virtualRowHeight"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i12.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i11.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "component", type: i11.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { kind: "component", type: i13.Dropdown, selector: "p-dropdown", inputs: ["id", "scrollHeight", "filter", "name", "style", "panelStyle", "styleClass", "panelStyleClass", "readonly", "required", "editable", "appendTo", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "variant", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "autoDisplayFirst", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "maxlength", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "disabled", "itemSize", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "filterValue", "options"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: i14.ProgressSpinner, selector: "p-progressSpinner", inputs: ["styleClass", "style", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "component", type: i15.AutoComplete, selector: "p-autoComplete", inputs: ["minLength", "delay", "style", "panelStyle", "styleClass", "panelStyleClass", "inputStyle", "inputId", "inputStyleClass", "placeholder", "readonly", "disabled", "scrollHeight", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "maxlength", "name", "required", "size", "appendTo", "autoHighlight", "forceSelection", "type", "autoZIndex", "baseZIndex", "ariaLabel", "dropdownAriaLabel", "ariaLabelledBy", "dropdownIcon", "unique", "group", "completeOnFocus", "showClear", "field", "dropdown", "showEmptyMessage", "dropdownMode", "multiple", "tabindex", "dataKey", "emptyMessage", "showTransitionOptions", "hideTransitionOptions", "autofocus", "autocomplete", "optionGroupChildren", "optionGroupLabel", "overlayOptions", "suggestions", "itemSize", "optionLabel", "optionValue", "id", "searchMessage", "emptySelectionMessage", "selectionMessage", "autoOptionFocus", "selectOnFocus", "searchLocale", "optionDisabled", "focusOnHover", "variant"], outputs: ["completeMethod", "onSelect", "onUnselect", "onFocus", "onBlur", "onDropdownClick", "onClear", "onKeyUp", "onShow", "onHide", "onLazyLoad"] }, { kind: "component", type: i16.InputContainerComponent, selector: "pw-input-container", inputs: ["name", "label", "labelClass", "tooltipPosition", "required", "errorMsg", "isReadOnly", "showTooltip", "tooltipText", "showTriangle", "afterLabel", "showAfterLabel", "showTriangleText", "isLeftTooltip"] }, { kind: "component", type: i16.NoDataComponent, selector: "pw-no-data", inputs: ["message", "description", "withImage"] }, { kind: "directive", type: i17.NgFileDropDirective, selector: "[ngFileDrop]", inputs: ["options", "uploadInput"], outputs: ["uploadOutput"] }, { kind: "directive", type: i17.NgFileSelectDirective, selector: "[ngFileSelect]", inputs: ["options", "uploadInput"], outputs: ["uploadOutput"] }, { kind: "directive", type: i18.InfiniteScrollDirective, selector: "[infiniteScroll], [infinite-scroll], [data-infinite-scroll]", inputs: ["infiniteScrollDistance", "infiniteScrollUpDistance", "infiniteScrollThrottle", "infiniteScrollDisabled", "infiniteScrollContainer", "scrollWindow", "immediateCheck", "horizontal", "alwaysCallback", "fromRoot"], outputs: ["scrolled", "scrolledUp"] }, { kind: "directive", type: i3.NgbInputDatepicker, selector: "input[ngbDatepicker]", inputs: ["autoClose", "contentTemplate", "datepickerClass", "dayTemplate", "dayTemplateData", "displayMonths", "firstDayOfWeek", "footerTemplate", "markDisabled", "minDate", "maxDate", "navigation", "outsideDays", "placement", "popperOptions", "restoreFocus", "showWeekNumbers", "startDate", "container", "positionTarget", "weekdays", "disabled"], outputs: ["dateSelect", "navigate", "closed"], exportAs: ["ngbDatepicker"] }, { kind: "component", type: i19.SmartCrmCompanyFilesComponent, selector: "pw-smart-crm-company-files", inputs: ["accountId", "contactId", "opportunityId"] }, { kind: "component", type: i20.SmartCrmCompanyAccountInvoiceComponent, selector: "pw-smart-crm-account-invoices", inputs: ["accountId"] }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.JsonPipe, name: "json" }, { kind: "pipe", type: i4.SlicePipe, name: "slice" }, { kind: "pipe", type: i4.DatePipe, name: "date" }, { kind: "pipe", type: i21.DateFormatPipe, name: "dateFormat" }, { kind: "pipe", type: i21.TextTruncatePipe, name: "textTruncate" }, { kind: "pipe", type: i21.IfNameNullShowEmailPipe, name: "ifNameNullShowEmail" }, { kind: "pipe", type: i22.TranslocoPipe, name: "transloco" }] }); }
604
- }
605
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: SmartCrmCompanyInfoComponent, decorators: [{
606
- type: Component,
607
- args: [{ selector: 'pw-smart-crm-company-info', template: "<div class=\"row\">\n <div class=\"col-12 mb-0\">\n <div class=\"me-auto mb-0\">\n <h2 class=\"mb-0\">\n <a aria-label=\"Navigate to Target\"\n (click)=\"back()\"\n class=\"previous\"><i class=\"fa fa-arrow-alt-circle-left\" aria-hidden=\"true\"></i></a>\n Account Info\n </h2>\n </div>\n <a class=\"btn btn-sm btn-outline-primary float-end mb-3\"\n data-cy=\"add-opportunities\"\n (click)=\"navigateToAddOpportunities()\">\n <i class=\"fa fa-plus-circle\" aria-hidden=\"true\"></i>\n {{ 'Crm.OpportunitiesMessage.AddOpportunity' | transloco }}\n </a>\n </div>\n <div class=\"w-100 text-center mt-3\"\n *ngIf=\"!isDataLoaded\">\n <p-progressSpinner> </p-progressSpinner>\n </div>\n <div *ngIf=\"isDataLoaded\">\n <div class=\"row\">\n <div class=\"col-12 col-md-4\">\n <div class=\"user-info p-3 card pb-0 h-auto\">\n <div class=\"mb-2 text-center\">\n <a class=\"profile-image\">\n <img alt=\"Profile Logo\"\n width=\"100\"\n height=\"100\"\n [src]=\"getAccountLogo(data?.company_url)\"\n class=\"img-fluid company-logo\"\n (error)=\"handleImageError($event, 'assets/img/icons/company.png')\" />\n </a>\n </div>\n <div class=\"mb-4 d-flex justify-content-between align-items-center\">\n <h4 class=\"d-inline-block name-block\">\n About <span *ngIf=\"data?.id\">{{ data.name }}</span>\n </h4>\n <a href=\"javascript:void(0);\"\n *ngIf=\"isFormEdit && (userId === data?.owner?.id || hasAccess)\"\n class=\"btn btn-sm btn-outline-primary float-end\"\n (click)=\"isFormEdit = !isFormEdit; this.getAllSubscriptionMembers()\">{{ 'Button.Edit' | transloco }}</a>\n </div>\n <form [formGroup]=\"aboutControls\"\n [class.isDisabled]=\"isFormEdit\">\n <div class=\"mb-3\">\n <label class=\"label mb-0\" for=\"name\">{{ 'Crm.AccountMessage.Name' | transloco }}</label>\n <input type=\"text\"\n class=\"form-control rounded-0 ps-1 user-value\"\n formControlName=\"name\"\n [ngClass]=\"{ 'is-invalid': submitted && f['name'].errors }\" />\n </div>\n <div class=\"mb-3\">\n <label class=\"label mb-0\" for=\"Location\">{{\n 'Crm.AccountMessage.Location' | transloco\n }}</label>\n <input ngx-gp-autocomplete\n class=\"form-control rounded-0 ps-1 user-value\"\n #places=\"ngx-places\"\n formControlName=\"location\"\n (onAddressChange)=\"handleAddressChange($event)\"\n [ngClass]=\"{ 'is-invalid': submitted && f['location'].errors }\" />\n </div>\n <div class=\"mb-3\"\n *ngIf=\"countries$ | async as countries\">\n <label for=\"country\">{{ 'Crm.AccountMessage.Country' | transloco\n }}<span class=\"text-danger required-icon\">*</span>\n </label>\n <p-dropdown\n [options]=\"countries\"\n formControlName=\"country\"\n [ngClass]=\"{ 'is-invalid': submitted && f['country'].errors }\"\n [placeholder]=\"'Select Country'\"\n optionValue=\"code\"\n optionLabel=\"name\">\n </p-dropdown>\n </div>\n <div class=\"mb-3 ui-fluid skills-modal\">\n <label class=\"label mb-2\" for=\"Message\">{{ 'Crm.AccountMessage.Owner' | transloco }}</label>\n <p class=\"form-control d-block pb-2 ps-1 user-value\"\n *ngIf=\"isFormEdit && data?.owner_id\">\n {{ data?.owner?.first_name }} {{ data?.owner?.last_name }}\n </p>\n <p-autoComplete *ngIf=\"!isFormEdit || !data?.owner_id\"\n [suggestions]=\"filteredOwner\"\n formControlName=\"owner_id\"\n dataKey=\"id\"\n field=\"displayName\"\n [dropdown]=\"true\"\n (completeMethod)=\"search($event)\"\n styleClass=\"w-100\"\n placeholder=\"Search owner\"\n [multiple]=\"false\">\n </p-autoComplete>\n </div>\n <div class=\"mb-3\">\n <label class=\"label mb-0\" for=\"CompanyUrl\">{{\n 'Crm.AccountMessage.CompanyUrl' | transloco\n }}</label>\n <a [href]=\"data?.company_url\"\n target=\"blank\"\n class=\"form-control d-block pb-2 ps-1 user-value\"\n *ngIf=\"isFormEdit && data?.company_url\">{{ data?.company_url }}</a>\n <input *ngIf=\"!isFormEdit || !data?.company_url\"\n type=\"text\"\n class=\"form-control rounded-0 ps-1 user-value\"\n formControlName=\"company_url\"\n [ngClass]=\"{ 'is-invalid': submitted && f['company_url'].errors }\" />\n </div>\n <div class=\"mb-3\"\n *ngIf=\"data?.tel\">\n <label class=\"label mb-0\" for=\"AccountMessage\">{{ 'Crm.AccountMessage.Tel' | transloco }}</label>\n <input type=\"text\"\n class=\"form-control rounded-0 ps-1 user-value\"\n formControlName=\"tel\" />\n </div>\n <div class=\"mb-3\"\n *ngIf=\"organizationTypes$ | async as types\">\n <label for=\"organizationType\">{{ 'Organization.OrganizationType' | transloco }}</label>\n <p-dropdown\n [options]=\"types['organization_types']\"\n formControlName=\"organization_type_id\"\n [ngClass]=\"{ 'is-invalid': submitted && f['organization_type_id'].errors }\"\n [placeholder]=\"'Select Organization Type'\"\n optionValue=\"id\"\n optionLabel=\"name\">\n </p-dropdown>\n </div>\n <div class=\"mb-3\"\n *ngIf=\"organizationIndustries$ | async as industries\">\n <label for=\"file\">{{ 'Organization.OrganizationIndustry' | transloco }}</label>\n <p-dropdown\n [options]=\"industries['organization_industries']\"\n formControlName=\"organization_industry_id\"\n [ngClass]=\"{ 'is-invalid': submitted && f['organization_industry_id'].errors }\"\n [placeholder]=\"'Select Industry'\"\n optionValue=\"id\"\n optionLabel=\"name\">\n </p-dropdown>\n </div>\n <div class=\"mb-3\"\n *ngIf=\"organizationSizes$ | async as sizes\">\n <label for=\"size\">{{ 'Crm.AccountMessage.Size' | transloco }}</label>\n <p-dropdown\n [options]=\"sizes['organization_sizes']\"\n formControlName=\"organization_size_id\"\n [ngClass]=\"{ 'is-invalid': submitted && f['organization_size_id'].errors }\"\n [placeholder]=\"'Select Size'\"\n optionValue=\"id\"\n optionLabel=\"name\">\n </p-dropdown>\n </div>\n <div class=\"mb-3\">\n <label for=\"status\">{{ 'Crm.AccountMessage.Status' | transloco }}</label>\n <p-dropdown\n [options]=\"status\"\n formControlName=\"status\"\n [ngClass]=\"{ 'is-invalid': submitted && f['status'].errors }\"\n [placeholder]=\"'Select Status'\">\n </p-dropdown>\n </div>\n <div class=\"mb-3\">\n <label for=\"priority\">{{ 'Crm.AccountMessage.Priority' | transloco }}</label>\n <p-dropdown\n [options]=\"priority\"\n formControlName=\"priority\"\n [ngClass]=\"{ 'is-invalid': submitted && f['priority'].errors }\"\n [placeholder]=\"'Select Priority'\">\n </p-dropdown>\n </div>\n <div class=\"mb-3\">\n <label for=\"message\">{{ 'Crm.AccountMessage.Source' | transloco }}</label>\n <p-dropdown\n [options]=\"source\"\n formControlName=\"crm_source_id\"\n [ngClass]=\"{ 'is-invalid': submitted && f['crm_source_id'].errors }\"\n [placeholder]=\"'Select Source'\"\n optionValue=\"id\"\n optionLabel=\"name\">\n </p-dropdown>\n </div>\n <div class=\"mb-3\">\n <pw-input-container [label]=\"'Crm.AccountMessage.Description' | transloco\"\n name=\"description\">\n <textarea rows=\"5\"\n type=\"text\"\n class=\"form-control\"\n formControlName=\"description\"\n id=\"description\"\n [ngClass]=\"{ 'is-invalid': submitted && f['description'].errors }\"></textarea>\n </pw-input-container>\n </div>\n <div *ngIf=\"!isFormEdit\"\n class=\"text-end form-action-buttons\">\n <input type=\"button\"\n class=\"btn btn-outline-primary\"\n (click)=\"isFormEdit = !isFormEdit; getAccountDetails()\"\n value=\"Cancel\" />\n <button type=\"submit\"\n [buttonBusy]=\"buttonBusy\"\n class=\"btn btn-primary ms-3\"\n (click)=\"updateAccountInfo()\">\n {{ 'Button.Submit' | transloco }}\n </button>\n </div>\n </form>\n </div>\n </div>\n <div class=\"col-12 col-md-8\">\n <ul ngbNav\n #nav=\"ngbNav\"\n class=\"nav-tabs\">\n <li [ngbNavItem]=\"1\">\n <a ngbNavLink>Notes</a>\n <ng-template ngbNavContent>\n <form [formGroup]=\"actionControls\"\n (ngSubmit)=\"onSave()\">\n <textarea class=\"form-control\"\n formControlName=\"comment\"\n rows=\"6\"></textarea>\n <p class=\"text-danger\"\n *ngIf=\"\n actionControls.get('comment').touched &&\n actionControls.get('comment').invalid\n \">\n Note Required\n </p>\n <div *ngIf=\"actions?.length\"\n class=\"d-block clear-both pt-3\">\n <ng-container *ngFor=\"let action of actions; index as i\">\n <button *ngIf=\"action.visible\"\n type=\"button\"\n [class.active]=\"\"\n class=\"btn btn-sm me-2 btn-outline-primary mb-2 action-btn\"\n (click)=\"showDatePicker($event, action.id); d.toggle()\">\n {{ action.name }}\n </button>\n </ng-container>\n <div class=\"text-danger\"\n *ngIf=\"submitAction && actionControls.get('crm_action_id').invalid\">\n Please select an action\n </div>\n <div class=\"row mt-3\">\n <div class=\"col-12 col-sm-4\">\n <div class=\"input-group\">\n <input class=\"form-control\"\n placeholder=\"dd-mmm-yyyy\"\n formControlName=\"when\"\n ngbDatepicker\n #d=\"ngbDatepicker\"\n (click)=\"d.toggle()\" />\n </div>\n </div>\n <div class=\"ui-fluid skills-modal col-sm-4 ps-0\">\n <p-autoComplete [suggestions]=\"filteredContact\"\n formControlName=\"crm_contact_id\"\n dataKey=\"id\"\n field=\"displayName\"\n [dropdown]=\"true\"\n (completeMethod)=\"searchContact($event)\"\n (onSelect)=\"selectContact($event)\"\n (onBlur)=\"OnContactBlur()\"\n styleClass=\"w-100\"\n placeholder=\"Search contact\"\n [multiple]=\"false\"\n (onDropdownClick)=\"onDropdownClick()\">\n </p-autoComplete>\n </div>\n <div class=\"col-sm-4 pe-0 completed-toggle\">\n <div class=\"mb-3\">\n <ui-switch checkedLabel=\"completed\"\n uncheckedLabel=\"open\"\n formControlName=\"completed\"\n name=\"completed\">\n </ui-switch>\n </div>\n </div>\n </div>\n </div>\n <div class=\"float-end\">\n <a class=\"btn btn-outline-primary me-0 me-sm-2\"\n (keydown.enter)=\"openModal(content)\"\n (click)=\"openModal(content)\">{{ 'Upload file' | transloco }}</a>\n <button type=\"submit\"\n [buttonBusy]=\"buttonBusy\"\n [disabled]=\"buttonDisable\"\n class=\"btn btn-primary mt-2 mb-2\">Submit Note</button>\n </div>\n <div *ngIf=\"buttonDisable\"\n class=\"no-actions pt-4\">\n <pw-no-data [withImage]=\"true\" [message]=\"\n 'Crm.AccountMessage.NoActionsInAccountInfoMessage' | transloco\n \">\n </pw-no-data>\n </div>\n </form>\n <div class=\"w-100 text-center mt-3\"\n *ngIf=\"!isLoaded\">\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </div>\n <div *ngIf=\"!accountComments?.length && isLoaded\"\n class=\"no-actions pt-2\">\n <pw-no-data [withImage]=\"true\" [message]=\"'Crm.AccountMessage.NoActionsMessage' | transloco\">\n </pw-no-data>\n </div>\n <div *ngIf=\"accountComments?.length\">\n <div id=\"timeline\"\n class=\"pt-3 clear-both timeline-center timeline-wrapper timeline-container\"\n infiniteScroll\n [infiniteScrollDistance]=\"2\"\n [infiniteScrollThrottle]=\"50\"\n [infiniteScrollContainer]=\"selector\"\n [fromRoot]=\"true\"\n (scrolled)=\"onScrollTimeline()\">\n <ul class=\"timeline\">\n <li class=\"timeline-line\"></li>\n </ul>\n <ul class=\"timeline\">\n <li class=\"timeline-line\"></li>\n <li class=\"timeline-item\"\n [ngClass]=\"{ 'mt-5': odd || last }\"\n *ngFor=\"\n let item of accountComments;\n index as i;\n let odd = odd;\n let even = even;\n let last = last;\n let first = first\n \">\n <div class=\"timeline-badge\">\n <span class=\"bg-red bg-lighten-1\">\n <span class=\"timeline-year\">\n <span class=\"d-block date-year\">{{\n item.when | date: 'medium' | slice: 0:3\n }}</span>\n <span>{{ item.year }}</span></span>\n </span>\n </div>\n <div class=\"timeline-card shadow card pb-0 rounded border-grey border-lighten-2 position-static\">\n <div class=\"card-header py-4\">\n <div class=\"mb-0 clearfix\">\n <textarea type=\"text\"\n name=\"comment\"\n class=\"comment-field form-control p-0\"\n [(ngModel)]=\"item.comment\">{{ item.comment }}</textarea>\n <div class=\"auto-complete mb-3 ui-fluid skills-modal\">\n <p-autoComplete [(ngModel)]=\"item.crm_contact\"\n [suggestions]=\"filteredContactComment\"\n dataKey=\"id\"\n field=\"first_name\"\n dropdown=\" true \"\n (completeMethod)=\"\n searchContactInComment($event)\n \"\n (onSelect)=\"selectCommentContact($event)\"\n (onBlur)=\"OnContactBlur()\"\n styleClass=\" w-100 \"\n placeholder=\" Search contact \"\n [multiple]=\"false\"\n (onDropdownClick)=\"onDropdownClick()\">\n </p-autoComplete>\n </div>\n <p class=\"float-start mb-0\"\n *ngIf=\"\n !showFullComment || item.id !== commentId\n \">\n {{ item.comment | slice: 0:170\n }}<a *ngIf=\"item.comment.length > 170\"\n class=\"text-secondary\"\n (click)=\"\n showFullComment = true;\n commentId = item.id\n \">...show more\n </a>\n </p>\n <p class=\"float-start mb-0\"\n *ngIf=\"showFullComment && item.id === commentId\">\n {{ item.comment }}\n <a *ngIf=\"\n item.comment.length > 170 &&\n showFullComment\n \"\n (click)=\"showFullComment = false\"\n class=\"text-secondary\">...show less</a>\n </p>\n <button class=\"btn btn-md edit-btn float-end py-0\"\n (click)=\"showEditControls($event, item)\"\n *ngIf=\"userId === item.owner_id || hasAccess\">\n <i\n class=\"fa fa-edit edit-icon\"\n aria-hidden=\"true\"\n ></i>\n </button>\n </div>\n <div class=\"card-subtitle text-muted my-0 clearfix\">\n <div class=\"float-start\">\n <span *ngIf=\"!updating || actionId !== item.id\"\n class=\"font-small-3\">\n {{ item.when }}</span>\n <input *ngIf=\"updating && actionId === item.id\"\n placeholder=\"dd-mmm-yyyy\"\n value=\"{{ item.when }}\"\n ngbDatepicker\n #d=\"ngbDatepicker\"\n (focus)=\"d.toggle()\"\n (dateSelect)=\"onDateSelect($event, item)\" />\n </div>\n <button type=\" button\"\n class=\"btn btn-sm float-end when-btn py-0\"\n *ngIf=\"userId === item.owner_id || hasAccess\"\n (click)=\"showDatePickerUpdate(item.id)\">\n <i\n class=\"fa fa-edit edit-icon\"\n aria-hidden=\"true\"\n ></i>\n </button>\n </div>\n <p [class.text-danger]=\"!item.color\"\n *ngIf=\"!item.cancelled && !item.completed\"\n class=\"mb-0\">\n {{ item.due }}\n </p>\n <a class=\"text-secondary action-owner\"\n *ngIf=\"item.crm_contact\"\n [routerLink]=\"[\n '/' + subscription?.slug + routers.contactInfo,\n item.crm_contact.id\n ]\">{{ item.crm_contact.first_name }}\n {{ item.crm_contact.last_name || '' }}</a>\n <p>\n By\n {{\n item.owner.first_name +\n ' ' +\n item.owner.last_name\n }}\n </p>\n <span class=\"badge bg-primary\">{{\n item?.crm_action?.name\n }}</span>\n <span *ngIf=\"\n !item.completed &&\n (userId === item.owner_id || hasAccess)\n \"\n class=\"badge bg-success ms-2\">Open</span>\n <a *ngIf=\"\n !item.completed &&\n (userId === item.owner_id || hasAccess)\n \"\n ngbTooltip=\"Set as completed\"\n aria-label=\"Set as completed\"\n class=\"me-3 ms-3\"\n href=\"javascript:void(0);\"\n (click)=\"\n setAsCompletedOrUncompleted(\n item.id,\n item,\n item.completed\n )\n \">\n <i\n class=\"fa fa-tasks completed\"\n aria-hidden=\"true\"\n ></i>\n </a>\n <a *ngIf=\"\n !item.cancelled &&\n !item.completed &&\n (userId === item.owner_id || hasAccess)\n \"\n ngbTooltip=\"Set as cancelled\"\n aria-label=\"Set as cancelled\"\n href=\"javascript:void(0);\"\n (click)=\"setAsCancelled(item.id, item)\">\n <i\n class=\"fa fa-times delete-icon\"\n aria-hidden=\"true\"\n ></i>\n </a>\n <a *ngIf=\"\n item.completed &&\n (userId === item.owner_id || hasAccess)\n \"\n ngbTooltip=\"Set as UnCompleted\"\n aria-label=\"Set as UnCompleted\"\n href=\"javascript:void(0);\"\n (click)=\"\n setAsCompletedOrUncompleted(\n item.id,\n item,\n item.completed\n )\n \"\n class=\"ms-2\">\n <i\n class=\"far fa-window-close\"\n aria-hidden=\"true\"\n ></i>\n </a>\n <div class=\"control-btns mt-3 text-end form-action-buttons\">\n <button type=\"button\"\n class=\"btn btn-sm btn-outline-default me-2\"\n (click)=\"showEditControls(undefined, '')\">\n {{ 'Button.Cancel' | transloco }}\n </button>\n <button class=\"btn btn-sm btn-primary\"\n type=\"button\"\n (click)=\"updateComment(item)\">\n {{ 'Button.Submit' | transloco }}\n </button>\n </div>\n </div>\n </div>\n </li>\n </ul>\n </div>\n </div>\n </ng-template>\n </li>\n <li [ngbNavItem]=\"2\" *ngIf=\"hasAccess || userId === data?.owner?.id\">\n <a ngbNavLink>Contacts</a>\n <ng-template ngbNavContent>\n <div class=\"row\">\n <div class=\"col-12 mb-3\">\n <a class=\"btn btn-sm btn-outline-primary float-end\"\n data-cy=\"add-contact\"\n [routerLink]=\"[\n '/' + subscription?.slug + routers.contactAdd,\n accountId\n ]\">\n <i class=\"fa fa-plus-circle\" aria-hidden=\"true\"></i>\n {{ 'Crm.ContactMessage.AddContact' | transloco }}\n </a>\n </div>\n </div>\n <div class=\"primeng-datatable-container table-responsive\"\n [class.hideTable]=\"totalRecordsUnFiltered === 0\">\n <p-table class=\"table\"\n #dt\n [value]=\"contacts\"\n [paginator]=\"totalRecords !== 0\"\n [rows]=\"PAGE_SIZE\"\n [totalRecords]=\"totalRecords\"\n [loading]=\"loading\"\n [lazy]=\"true\"\n (onLazyLoad)=\"onLazyLoad($event)\"\n [customSort]=\"true\">\n <ng-template pTemplate=\"caption\">\n <div class=\"text-end\">\n <i class=\"fa fa-search mt-2 me-2\" aria-hidden=\"true\"></i>\n <input type=\"text\"\n [(ngModel)]=\"searchText\"\n pInputText\n size=\"50\"\n placeholder=\"Search contact...\"\n (input)=\"dt.filterGlobal($event.target.value, 'contains')\"\n class=\"mw-90\" />\n </div>\n </ng-template>\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"true\"\n pSortableColumn=\"first_name\">\n {{ 'Label.Name' | transloco }}\n <p-sortIcon field=\"first_name\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"owner_id\">\n {{ 'Crm.ContactMessage.ContactOwner' | transloco }}\n <p-sortIcon field=\"owner_id\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"headline\">\n {{ 'Crm.ContactMessage.Headline' | transloco }}\n <p-sortIcon field=\"headline\"></p-sortIcon>\n </th>\n <th scope=\"true\">{{ 'Label.Actions' | transloco }}</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\"\n let-contact>\n <tr>\n <td data-head=\"Name\"\n class=\"contactname\">\n <a [routerLink]=\"[\n '/' + subscription?.slug + routers.contactInfo,\n contact.id\n ]\"> {{ (contact.first_name || '') + ' ' + (contact.last_name || '') | textTruncate: 20 }}</a>\n </td>\n <td data-head=\"OwnerName\">\n {{ contact.owner | ifNameNullShowEmail }}\n </td>\n <td data-head=\"Headline\"\n class=\"headline-content\">\n {{ contact?.headline | textTruncate: 20 }}\n </td>\n <td data-head=\"Action\">\n <ul class=\"list-unstyled list-inline list-action\">\n <li ngbTooltip=\"Show\"\n class=\"me-2 me-sm-3\"\n [routerLink]=\"[\n '/' + subscription?.slug + routers.contactInfo,\n contact.id\n ]\">\n <i\n class=\"fa fa-eye see-icon\"\n aria-hidden=\"true\"\n ></i>\n </li>\n <li *ngIf=\"\n hasAccess ||\n contact.owner_id === userId ||\n contact.crm_account.owner_id === userId\n \"\n ngbTooltip=\"Add opportunity\"\n class=\"me-2 me-sm-3\"\n [routerLink]=\"[\n '/' +\n subscription?.slug +\n routers.opportunityAdd\n ]\"\n [queryParams]=\"{ contact_id: contact.id }\">\n <i\n class=\"fa fa-plus-circle add-icon\"\n aria-hidden=\"true\"\n ></i>\n </li>\n <li *ngIf=\"\n hasAccess ||\n contact.owner_id === userId ||\n contact.crm_account.owner_id === userId\n \"\n ngbTooltip=\"Edit\"\n class=\"me-2 me-sm-3\"\n [routerLink]=\"[\n '/' +\n subscription?.slug +\n routers.contactDetails,\n contact.id\n ]\">\n <i\n class=\"fa fa-edit edit-icon\"\n aria-hidden=\"true\"\n ></i>\n </li>\n <li *ngIf=\"\n hasAccess ||\n contact.owner_id === userId ||\n contact.crm_account.owner_id === userId\n \"\n ngbTooltip=\"Delete\"\n class=\"me-2 me-sm-3\">\n <i\n class=\"fa fa-trash delete-icon\"\n (keydown.enter)=\"onDeleteContact(contact.id)\"\n (keydown.space)=\"onDeleteContact(contact.id)\"\n (click)=\"onDeleteContact(contact.id)\"\n aria-hidden=\"true\"\n ></i>\n </li>\n </ul>\n </td>\n </tr>\n </ng-template>\n </p-table>\n <div *ngIf=\"totalRecords === 0 && totalRecordsUnFiltered !== 0\">\n <pw-no-data [withImage]=\"true\" [message]=\"'Search.NoDataMessage'| transloco\" [description]=\"'Search.NoDataDescription' | transloco\" >\n </pw-no-data>\n </div>\n <span class=\"total-records-count\" *ngIf=\"totalRecords !== 0\">{{ 'Label.Total' | transloco }}: {{ totalRecords }}</span>\n </div>\n <div *ngIf=\"totalRecordsUnFiltered === 0\">\n <pw-no-data [withImage]=\"true\" [message]=\"'Crm.ContactMessage.ContactsAdminMessage' | transloco\">\n </pw-no-data>\n </div>\n </ng-template>\n </li>\n <li [ngbNavItem]=\"3\" *ngIf=\"hasAccess\">\n <a ngbNavLink>Versioning</a>\n <ng-template ngbNavContent>\n <div *ngFor=\"let versioning of accountVersioning\">\n <p>\n <strong>Event: </strong>{{ versioning.event }} |\n <strong>Author: </strong><a *ngIf=\"versioning?.author\"\n [routerLink]=\"['/members', versioning?.author?.slug]\">{{ versioning?.author | ifNameNullShowEmail }}</a>\n | <strong>Created at: </strong>{{ versioning.created_at | dateFormat: 'datetime' }}<br />\n <strong>Object: </strong>{{ versioning.object | json }}\n </p>\n <hr />\n </div>\n <div *ngIf=\"accountVersioning?.length === 0\">\n <pw-no-data [withImage]=\"true\" [message]=\"'Crm.AccountMessage.NoVersionsMessage' | transloco\">\n </pw-no-data>\n </div>\n </ng-template>\n </li>\n <li [ngbNavItem]=\"4\">\n <a ngbNavLink>Files</a>\n <ng-template ngbNavContent>\n <pw-smart-crm-company-files [accountId]=\"accountId\"></pw-smart-crm-company-files>\n </ng-template>\n </li>\n <li [ngbNavItem]=\"5\" *ngIf=\"hasAccess\">\n <a ngbNavLink>Invoices</a>\n <ng-template ngbNavContent>\n <pw-smart-crm-account-invoices [accountId]=\"accountId\"/>\n </ng-template>\n </li>\n </ul>\n <div [ngbNavOutlet]=\"nav\"></div>\n </div>\n </div>\n </div>\n</div>\n<ng-template #content\n let-modal>\n <div class=\"modal-header\">\n <h3 class=\"modal-title mb-0 p-0\">{{ 'Upload File' | transloco }}</h3>\n <button type=\"button\"\n class=\"btn-close float-end\"\n aria-label=\"Close\"\n (click)=\"modal.dismiss()\">\n\n </button>\n </div>\n <div class=\"modal-body\">\n <small> {{ 'User.Profile.PictureMessage' | transloco }}</small>\n <div class=\"row p-2\">\n <div class=\"col-12\">\n <div class=\"upload-box\">\n <div class=\"upload-box-content\">\n <div class=\"drop-container\"\n ngFileDrop\n [options]=\"options\"\n (uploadOutput)=\"onUploadOutput($event)\"\n [uploadInput]=\"uploadInput\">\n <p>\n Drag files here or\n <label class=\"upload-button\">\n <input type=\"file\"\n ngFileSelect\n [options]=\"options\"\n (uploadOutput)=\"onUploadOutput($event)\"\n [uploadInput]=\"uploadInput\"\n multiple />\n browse\n </label>\n to upload.\n </p>\n </div>\n <div class=\"upload-item\"\n *ngFor=\"let f of files; let i = index\">\n <div class=\"upload-item-content\">\n <div class=\"filename\">\n <div class=\"filename-left\">\n <i class=\"ionicon ion-ios-copy\" aria-hidden=\"true\"></i>\n <span>{{ f.name }}</span>\n </div>\n </div>\n <div class=\"progress-content\">\n <div class=\"progress\">\n <span class=\"bar\"\n [style.width]=\"f?.progress?.data?.percentage + '%'\"\n [class.is-done]=\"f['uploaded']\"></span>\n </div>\n </div>\n <div class=\"progress-text-content\">\n <span class=\"progress-text\"\n [class.is-done]=\"f['uploaded']\">\n <span *ngIf=\"!f['uploaded']\">{{ f.progress?.data?.percentage - 1 }}%\n </span>\n <span *ngIf=\"f['uploaded']\">100 %</span>\n <span *ngIf=\"!f['uploaded']\">Uploading...</span>\n <span *ngIf=\"f['uploaded']\">Done</span>\n </span>\n <span class=\"speed-and-eta-text\"\n *ngIf=\"f.progress?.data?.percentage !== 0 && !f['uploaded']\">\n <span>{{ f.progress?.data?.speedHuman }} </span>\n <span>ETA {{ f.progress?.data?.etaHuman }}</span>\n </span>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</ng-template>\n", styles: [":root{--first: rgb(23 105 225);--second: rgb(54 194 131);--third: rgb(255 171 0);--text: rgb(34 34 34);--tabs_bg: rgb(23 105 225);--tabs_sub_bg: rgb(70, 136, 236);--tabs_text: rgb(255 255 255);--titles: rgb(34 34 34);--sidebar_bg: rgb(0, 48, 63);--sidebar_text: rgb(255 255 255)}.user-info .label{color:#777;font-size:14px;text-transform:capitalize}.user-info .user-value{border:0;border-bottom:1px solid rgb(119,119,119)}.user-info .user-value:focus{box-shadow:none}.user-info .user-value.is-invalid{border-color:#ff586b}.control-btns{display:none}::ng-deep .p-overlay{width:100%!important;min-width:100%!important;max-width:100%!important;left:0!important}::ng-deep .p-autocomplete-items li{white-space:nowrap!important;overflow:auto!important;text-overflow:ellipsis!important}::ng-deep .p-autocomplete-items li:hover{text-overflow:clip!important}.name-block{width:85%}.comment-field{border:0;border-bottom:1px solid rgb(242,242,242);color:#1769e1;display:none;font-size:15px;min-height:100px;padding:2px 5px!important}.comment-field:focus{border:1px solid rgb(23,105,225)!important;border-bottom:0;box-shadow:none}p{max-width:85%;white-space:pre-wrap}.auto-complete{display:none;margin-top:10px}.show-controls .comment-field,.show-controls .auto-complete,.show-controls .control-btns{display:block}.show-controls p,.show-controls .edit-btn,.show-controls .action-owner{display:none}select{appearance:none}textarea{resize:none}.clear-both{clear:both}.isDisabled input[type=text],.isDisabled input,.isDisabled textarea,.isDisabled p-dropdown,.isDisabled select{pointer-events:none}.isDisabled select{appearance:none;-webkit-appearance:none;-moz-appearance:none;background-image:none!important}.timeline-card.card{min-height:auto}@media (max-width: 768px){.completed-toggle{padding-top:10px}}.when-btn:focus{border:0;box-shadow:none}.no-actions{clear:both}.timeline-container{height:700px;overflow-y:scroll}.action-btn.active{color:#fff!important;background-color:var(--first)}.form-action-buttons{margin-bottom:14px;margin-top:15px}\n"] }]
608
- }], ctorParameters: () => [{ type: i0.Injector }, { type: i1.CrmService }, { type: i2.SubscriptionService }, { type: i2.GeoService }, { type: i2.CommonService }, { type: i3.NgbModal }, { type: i2.AuthService }, { type: i0.ChangeDetectorRef }, { type: i2.LogoCacheService }, { type: Document, decorators: [{
609
- type: Inject,
610
- args: [DOCUMENT]
611
- }] }] });
612
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnQtY3JtLWFjY291bnQtaW5mby5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9saWJzL3NtYXJ0LWNybS9zcmMvbGliL3ByaXZhdGUvY29tcG9uZW50cy9zbWFydC1jcm0tYWNjb3VudHMvc21hcnQtY3JtLWFjY291bnQtaW5mby9zbWFydC1jcm0tYWNjb3VudC1pbmZvLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL2xpYnMvc21hcnQtY3JtL3NyYy9saWIvcHJpdmF0ZS9jb21wb25lbnRzL3NtYXJ0LWNybS1hY2NvdW50cy9zbWFydC1jcm0tYWNjb3VudC1pbmZvL3NtYXJ0LWNybS1hY2NvdW50LWluZm8uY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzNDLE9BQU8sRUFFSCxpQkFBaUIsRUFDakIsU0FBUyxFQUNULFlBQVksRUFDWixNQUFNLEVBQ04sUUFBUSxFQUdYLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBb0IsVUFBVSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFOUQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDaEUsT0FBTyxFQUNILFdBQVcsRUFDWCxhQUFhLEVBQ2IsaUJBQWlCLEVBQ2pCLFVBQVUsRUFDVixnQkFBZ0IsRUFDaEIsbUJBQW1CLEVBQ3RCLE1BQU0sMkJBQTJCLENBQUM7QUFDbkMsT0FBTyxFQUVILGlCQUFpQixFQUNqQixTQUFTLEVBR1QsZ0JBQWdCLEVBRW5CLE1BQU0sNEJBQTRCLENBQUM7QUFDcEMsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3pELE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxVQUFVLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQWFoRixP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LEVBQUUsQ0FBQztJQUN4QixDQUFDOytHQWxyQlEsNEJBQTRCLGtSQTJGekIsUUFBUTttR0EzRlgsNEJBQTRCLHdGQ3JFekMsNnJ3Q0FzeEJBOzs0RkRqdEJhLDRCQUE0QjtrQkFMeEMsU0FBUzsrQkFDSSwyQkFBMkI7OzBCQStGaEMsTUFBTTsyQkFBQyxRQUFRIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRE9DVU1FTlQgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtcbiAgICBBZnRlclZpZXdDaGVja2VkLFxuICAgIENoYW5nZURldGVjdG9yUmVmLFxuICAgIENvbXBvbmVudCxcbiAgICBFdmVudEVtaXR0ZXIsXG4gICAgSW5qZWN0LFxuICAgIEluamVjdG9yLFxuICAgIE9uRGVzdHJveSxcbiAgICBPbkluaXRcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBVbnR5cGVkRm9ybUdyb3VwLCBWYWxpZGF0b3JzIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuXG5pbXBvcnQgeyBBcHBCYXNlQ29tcG9uZW50IH0gZnJvbSAnQHBvc2l3aXNlL2FwcC1iYXNlLWNvbXBvbmVudCc7XG5pbXBvcnQge1xuICAgIEF1dGhTZXJ2aWNlLFxuICAgIENvbW1vblNlcnZpY2UsXG4gICAgRm9ybUhlbHBlclNlcnZpY2UsXG4gICAgR2VvU2VydmljZSxcbiAgICBMb2dvQ2FjaGVTZXJ2aWNlLFxuICAgIFN1YnNjcmlwdGlvblNlcnZpY2Vcbn0gZnJvbSAnQHBvc2l3aXNlL2NvbW1vbi1zZXJ2aWNlcyc7XG5pbXBvcnQge1xuICAgIENvdW50cnksXG4gICAgRE9DVU1FTlRfVFlQRV9FWFQsXG4gICAgUEFHRV9TSVpFLFxuICAgIFBhZ2luZyxcbiAgICBTdWJzY3JpcHRpb24sXG4gICAgVE9LRU5fSEVBREVSX0tFWSxcbiAgICBVc2VyXG59IGZyb20gJ0Bwb3Npd2lzZS9jb21tb24tdXRpbGl0aWVzJztcbmltcG9ydCB7IEhlbHBlclNlcnZpY2UgfSBmcm9tICdAcG9zaXdpc2UvaGVscGVyLXNlcnZpY2UnO1xuaW1wb3J0IHsgQ1JNX0FDQ09VTlRfRklMRVNfUEFUSCwgQ3JtU2VydmljZSB9IGZyb20gJ0Bwb3Npd2lzZS9zbWFydC1jcm0tc2hhcmVkJztcblxuaW1wb3J0IHsgQ3JtQWNjb3VudCB9IGZyb20gJ2xpYnMvc21hcnQtY3JtL3NyYy9saWIvc2hhcmVkL2ludGVyZmFjZS9jcm0tYWNjb3VudC5pbnRlcmZhY2UnO1xuaW1wb3J0IHtcbiAgICBDcm1PcHBvcnR1bml0eUNvbnRhY3QsXG4gICAgQ3JtT3duZXIsXG4gICAgRmlsdGVyZWRDcm1Db21tZW50LFxuICAgIEZpbHRlcmVkRGF0YSxcbiAgICBPcmdhbml6YXRpb25JbmR1c3RyeSxcbiAgICBPcmdhbml6YXRpb25TaXplLFxuICAgIE9yZ2FuaXphdGlvblR5cGUsXG4gICAgU21hcnRDcm1BY3Rpb25cbn0gZnJvbSAnbGlicy9zbWFydC1jcm0vc3JjL2xpYi9zaGFyZWQvaW50ZXJmYWNlL3NtYXJ0LWNybS1tb2R1bGUuaW50ZXJmYWNlJztcbmltcG9ydCBtb21lbnQgZnJvbSAnbW9tZW50JztcbmltcG9ydCB7IFVwbG9hZGVyT3B0aW9ucywgVXBsb2FkRmlsZSwgVXBsb2FkSW5wdXQsIFVwbG9hZE91dHB1dCwgVXBsb2FkU3RhdHVzIH0gZnJvbSAnbmd4LXVwbG9hZGVyJztcbmltcG9ydCB7IExhenlMb2FkRXZlbnQgfSBmcm9tICdwcmltZW5nL2FwaSc7XG5pbXBvcnQgeyBPYnNlcnZhYmxlIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgc3dhbCBmcm9tICdzd2VldGFsZXJ0Mic7XG5cbmltcG9ydCB7IE5nYk1vZGFsIH0gZnJvbSAnQG5nLWJvb3RzdHJhcC9uZy1ib290c3RyYXAnO1xuXG5pbXBvcnQgeyBBcHBTbWFydENybSB9IGZyb20gJy4uLy4uLy4uLy4uL3NoYXJlZC9tb2RlbHMvc21hcnQtY3JtLm1vZGVsJztcbmltcG9ydCB7IFJPVVRFUlMgfSBmcm9tICcuLi8uLi8uLi8uLi9zaGFyZWQvcm91dGVycy9yb3V0ZXJzJztcblxuaW50ZXJmYWNlIFN1YnNjcmlwdGlvbk1lbWJlciB7XG4gICAgaWQ6IG51bWJlcjtcbiAgICBmaXJzdF9uYW1lOiBzdHJpbmc7XG4gICAgbGFzdF9uYW1lOiBzdHJpbmc7XG4gICAgZW1haWw6IHN0cmluZztcbiAgICAvLyBPdGhlciBwcm9wZXJ0aWVzIG9mIFN1YnNjcmlwdGlvbk1lbWJlclxufVxuXG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogJ3B3LXNtYXJ0LWNybS1jb21wYW55LWluZm8nLFxuICAgIHRlbXBsYXRlVXJsOiAnLi9zbWFydC1jcm0tYWNjb3VudC1pbmZvLmNvbXBvbmVudC5odG1sJyxcbiAgICBzdHlsZVVybHM6IFsnLi9zbWFydC1jcm0tYWNjb3VudC1pbmZvLmNvbXBvbmVudC5zY3NzJ11cbn0pXG5leHBvcnQgY2xhc3MgU21hcnRDcm1Db21wYW55SW5mb0NvbXBvbmVudFxuICAgIGV4dGVuZHMgQXBwQmFzZUNvbXBvbmVudFxuICAgIGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3ksIEFmdGVyVmlld0NoZWNrZWRcbntcbiAgICBwcml2YXRlIHBhZ2UgPSAxO1xuICAgIHByaXZhdGUgdG90YWxDb250YWN0cyA9IDA7XG4gICAgcHJpdmF0ZSBpc0NvbnRhY3RWYWxpZCA9IHRydWU7XG5cbiAgICBzdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbjtcbiAgICBzdWJzY3JpcHRpb25JZDogbnVtYmVyO1xuXG4gICAgYWN0aW9uQ29udHJvbHM6IFVudHlwZWRGb3JtR3JvdXA7XG4gICAgYWJvdXRDb250cm9sczogVW50eXBlZEZvcm1Hcm91cDtcblxuICAgIHVzZXI6IFVzZXI7XG4gICAgdXNlcklkOiBudW1iZXI7XG4gICAgYWNjb3VudElkOiBudW1iZXI7XG4gICAgY29udGFjdElkOiBudW1iZXI7XG5cbiAgICBkYXRhOiBDcm1BY2NvdW50O1xuICAgIGFsbFN1YnNjcmlwdGlvbk1lbWJlcnM6IFN1YnNjcmlwdGlvbk1lbWJlcltdO1xuICAgIGZpbHRlcmVkT3duZXI6IFN1YnNjcmlwdGlvbk1lbWJlcltdO1xuICAgIGZpbHRlcmVkQ29udGFjdDogeyBkaXNwbGF5TmFtZTogc3RyaW5nIH1bXTtcbiAgICBmaWx0ZXJlZENvbnRhY3RDb21tZW50OiBGaWx0ZXJlZENybUNvbW1lbnRbXTtcbiAgICBjb250YWN0czogQ3JtT3Bwb3J0dW5pdHlDb250YWN0W107XG5cbiAgICBvd25lcjogQ3JtT3duZXI7XG4gICAgYWN0aW9uczogU21hcnRDcm1BY3Rpb25bXTtcblxuICAgIGFjY291bnRDb21tZW50cyA9IFtdO1xuICAgIGFjY291bnRWZXJzaW9uaW5nOiBzdHJpbmdbXTtcblxuICAgIG9yZ2FuaXphdGlvblNpemVzJDogT2JzZXJ2YWJsZTxPcmdhbml6YXRpb25TaXplW10+O1xuICAgIG9yZ2FuaXphdGlvbkluZHVzdHJpZXMkOiBPYnNlcnZhYmxlPE9yZ2FuaXphdGlvbkluZHVzdHJ5W10+O1xuICAgIG9yZ2FuaXphdGlvblR5cGVzJDogT2JzZXJ2YWJsZTxPcmdhbml6YXRpb25UeXBlW10+O1xuICAgIGNvdW50cmllcyQ6IE9ic2VydmFibGU8Q291bnRyeVtdPjtcblxuICAgIHN0YXR1czogc3RyaW5nW107XG4gICAgcHJpb3JpdHk6IEZpbHRlcmVkRGF0YVtdO1xuICAgIHNvdXJjZTogRmlsdGVyZWREYXRhW107XG5cbiAgICBwb3RlbnRpYWwgPSBbJ2xvdycsICdtZWRpdW0nLCAnaGlnaCddO1xuICAgIGZpbHRlckJ5UG90ZW50aWFsczogc3RyaW5nO1xuXG4gICAgb3B0aW9uczogVXBsb2FkZXJPcHRpb25zO1xuICAgIHVwbG9hZElucHV0OiBFdmVudEVtaXR0ZXI8VXBsb2FkSW5wdXQ+O1xuICAgIGZpbGVzOiBVcGxvYWRGaWxlW107XG5cbiAgICB0b2tlbjogc3RyaW5nO1xuICAgIHNlbGVjdG9yID0gJy50aW1lbGluZS1jb250YWluZXInO1xuXG4gICAgc2VhcmNoVGV4dCA9ICcnO1xuXG4gICAgdG90YWxSZWNvcmRzOiBudW1iZXI7XG4gICAgdG90YWxSZWNvcmRzVW5GaWx0ZXJlZCA9IDA7XG4gICAgY3VycmVudFBhZ2UgPSAxO1xuICAgIGFjdGlvbklkOiBudW1iZXI7XG4gICAgY29tbWVudElkOiBudW1iZXI7XG5cbiAgICBoYXNBY2Nlc3MgPSBmYWxzZTtcbiAgICBpc0RhdGFMb2FkZWQgPSBmYWxzZTtcbiAgICBpc0xvYWRlZCA9IGZhbHNlO1xuICAgIGxvYWRpbmcgPSB0cnVlO1xuICAgIGlzRm9ybUVkaXQgPSB0cnVlO1xuICAgIHN1Ym1pdHRlZCA9IGZhbHNlO1xuICAgIGVkaXRDb21tZW50ID0gZmFsc2U7XG4gICAgc2hvd0Z1bGxDb21tZW50ID0gZmFsc2U7XG4gICAgc3VibWl0QWN0aW9uID0gZmFsc2U7XG5cbiAgICBidXR0b25EaXNhYmxlOiBib29sZWFuO1xuICAgIGlzRGlzYWJsZWQgPSBmYWxzZTtcbiAgICBidXR0b25CdXN5ID0gZmFsc2U7XG4gICAgZGFuZ2VyQ29sb3I6IGJvb2xlYW47XG4gICAgdXBkYXRpbmcgPSBmYWxzZTtcbiAgICBkcmFnT3ZlcjogYm9vbGVhbjtcbiAgICBEb25lOiBib29sZWFuO1xuXG4gICAgZGlyZWN0aW9uID0gJyc7XG5cbiAgICByb3V0ZXJzID0gUk9VVEVSUztcblxuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBpbmplY3RvcjogSW5qZWN0b3IsXG4gICAgICAgIHByaXZhdGUgcmVhZG9ubHkgY3JtU2VydmljZTogQ3JtU2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSByZWFkb25seSBzdWJzY3JpcHRpb25TZXJ2aWNlOiBTdWJzY3JpcHRpb25TZXJ2aWNlLFxuICAgICAgICBwcml2YXRlIHJlYWRvbmx5IGdlb1NlcnZpY2U6IEdlb1NlcnZpY2UsXG4gICAgICAgIHByaXZhdGUgcmVhZG9ubHkgY29tbW9uU2VydmljZTogQ29tbW9uU2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSByZWFkb25seSBtb2RhbFNlcnZpY2U6IE5nYk1vZGFsLFxuICAgICAgICBwcml2YXRlIHJlYWRvbmx5IGF1dGhTZXJ2aWNlOiBBdXRoU2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSByZWFkb25seSBjZHI6IENoYW5nZURldGVjdG9yUmVmLFxuICAgICAgICBwcml2YXRlIHJlYWRvbmx5IGxvZ29DYWNoZVNlcnZpY2U6IExvZ29DYWNoZVNlcnZpY2UsXG4gICAgICAgIEBJbmplY3QoRE9DVU1FTlQpIHByaXZhdGUgcmVhZG9ubHkgZG9jdW1lbnQ6IERvY3VtZW50XG4gICAgKSB7XG4gICAgICAgIHN1cGVyKGluamVjdG9yKTtcbiAgICAgICAgdGhpcy5vcHRpb25zID0geyBjb25jdXJyZW5jeTogMSwgbWF4VXBsb2FkczogMyB9O1xuICAgICAgICB0aGlzLnVwbG9hZElucHV0ID0gbmV3IEV2ZW50RW1pdHRlcjxVcGxvYWRJbnB1dD4oKTtcbiAgICAgICAgdGhpcy50b2tlbiA9IGJ0b2EodGhpcy5hdXRoU2VydmljZS5nZXRUb2tlbigpKTtcbiAgICAgICAgdGhpcy5maWxlcyA9IFtdO1xuICAgICAgICB0aGlzLmFjdGlvbkNvbnRyb2xzID0gQXBwU21hcnRDcm0uZ2V0QWNjb3VudEFjdGlvbnNGb3JtKHRoaXMuaXNEaXNhYmxlZCk7XG4gICAgICAgIHRoaXMuYWJvdXRDb250cm9scyA9IEFwcFNtYXJ0Q3JtLmdldEFjY291bnRzRm9ybSgpO1xuICAgIH1cblxuICAgIG5nT25Jbml0KCkge1xuICAgICAgICB0aGlzLmNvdW50cmllcyQgPSB0aGlzLmdlb1NlcnZpY2UuZ2V0Q291bnRyaWVzKCk7XG4gICAgICAgIHRoaXMub3JnYW5pemF0aW9uSW5kdXN0cmllcyQgPSB0aGlzLmNvbW1vblNlcnZpY2UuZ2V0T3JnYW5pemF0aW9uSW5kdXN0cmllcygpO1xuICAgICAgICB0aGlzLm9yZ2FuaXphdGlvblR5cGVzJCA9IHRoaXMuY29tbW9uU2VydmljZS5nZXRPcmdhbml6YXRpb25UeXBlcygpO1xuICAgICAgICB0aGlzLm9yZ2FuaXphdGlvblNpemVzJCA9IHRoaXMuY29tbW9uU2VydmljZS5nZXRPcmdhbml6YXRpb25TaXplcygpO1xuICAgICAgICB0aGlzLnVzZXJTdG9yZSgpLnN1YnNjcmliZShyZXMgPT4ge1xuICAgICAgICAgICAgaWYgKHJlcykge1xuICAgICAgICAgICAgICAgIHRoaXMudXNlcklkID0gcmVzLmlkO1xuICAgICAgICAgICAgICAgIHRoaXMuYWN0aW9uQ29udHJvbHMuZ2V0KCdvd25lcl9pZCcpLnNldFZhbHVlKHJlcy5pZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmdldFVzZXJTdWJzY3JpcHRpb24oKS5zdWJzY3JpYmUocmVzcG9uc2UgPT4ge1xuICAgICAgICAgICAgdGhpcy5zdWJzY3JpcHRpb24gPSByZXNwb25zZTtcbiAgICAgICAgICAgIGlmICh0aGlzLnN1YnNjcmlwdGlvbj8uaWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhhc0FjY2VzcyA9IHRoaXMuaGFzQWRtaW5BY2Nlc3ModGhpcy5zdWJzY3JpcHRpb24uaWQpO1xuICAgICAgICAgICAgICAgIHRoaXMuZ2V0QWN0aW9ucygpO1xuICAgICAgICAgICAgICAgIHRoaXMuYWNjb3VudERlZmF1bHRWYWx1ZXModGhpcy5zdWJzY3JpcHRpb24uaWQpO1xuICAgICAgICAgICAgICAgIHRoaXMuYWJvdXRDb250cm9scy5nZXQoJ3N1YnNjcmlwdGlvbl9pZCcpLnNldFZhbHVlKHRoaXMuc3Vic2NyaXB0aW9uPy5pZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnJvdXRlLnBhcmFtcy5zdWJzY3JpYmUoZGF0YSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5hY2NvdW50SWQgPSBOdW1iZXIoZGF0YVsnaWQnXSk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuYWNjb3VudElkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZ2V0QWNjb3VudENvbnRhY3RzKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2U6IHRoaXMucGFnZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2Vfc2l6ZTogUEFHRV9TSVpFLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VhcmNoOiB0aGlzLnNlYXJjaFRleHRcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZ2V0QWNjb3VudERldGFpbHMoKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5nZXRDb250YWN0VmVyc2lvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5nZXRBbGxDb21tZW50cygpO1xuICAgIH1cblxuICAgIG5nQWZ0ZXJWaWV3Q2hlY2tlZCgpIHtcbiAgICAgICAgdGhpcy5jZHIuZGV0ZWN0Q2hhbmdlcygpO1xuICAgIH1cblxuICAgIG9uTGF6eUxvYWQoZXZlbnQ6IExhenlMb2FkRXZlbnQpIHtcbiAgICAgICAgY29uc3QgcGFnZURldGFpbHMgPSBIZWxwZXJTZXJ2aWNlLm9uVGFibGVMYXp5TG9hZChldmVudCk7XG4gICAgICAgIHRoaXMucGFnZSA9IHBhZ2VEZXRhaWxzLnBhZ2U7XG4gICAgICAgIHRoaXMuZ2V0QWNjb3VudENvbnRhY3RzKHtcbiAgICAgICAgICAgIHBhZ2U6IHRoaXMucGFnZSxcbiAgICAgICAgICAgIHBhZ2Vfc2l6ZTogUEFHRV9TSVpFLFxuICAgICAgICAgICAgb3JkZXJfYnk6IHBhZ2VEZXRhaWxzLnNvcnRGaWVsZCxcbiAgICAgICAgICAgIG9yZGVyX2RpcmVjdGlvbjogcGFnZURldGFpbHMuc29ydE9yZGVyLFxuICAgICAgICAgICAgc2VhcmNoOiB0aGlzLnNlYXJjaFRleHRcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqIEZ1bmN0aW9uIHRvIGNhbGwgYWNjb3VudCBkZWZhdWx0IHZhbHVlcyAqL1xuICAgIHByaXZhdGUgYWNjb3VudERlZmF1bHRWYWx1ZXMoaWQpIHtcbiAgICAgICAgdGhpcy5jcm1TZXJ2aWNlLmdldENybUFjY291bnREZWZhdWx0VmFsdWVzKGlkKS5zdWJzY3JpYmUocmVzcG9uc2UgPT4ge1xuICAgICAgICAgICAgdGhpcy5zdGF0dXMgPSByZXNwb25zZS5zdGF0dXM7XG4gICAgICAgICAgICB0aGlzLnByaW9yaXR5ID0gcmVzcG9uc2UucHJpb3JpdHk7XG4gICAgICAgICAgICB0aGlzLnNvdXJjZSA9IHJlc3BvbnNlLnNvdXJjZTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgaGFuZGxlSW1hZ2VFcnJvcihldmVudDogRXZlbnQsIGZhbGxiYWNrUGF0aCk6IHZvaWQge1xuICAgICAgICBIZWxwZXJTZXJ2aWNlLmhhbmRsZUltYWdlRmFsbGJhY2tQYXRoKGV2ZW50LCBmYWxsYmFja1BhdGgpO1xuICAgIH1cblxuICAgIC8qKiBGdW5jdGlvbiB0byBjYWxsIGFjY291bnQgYnkgSUQgKi9cbiAgICBnZXRBY2NvdW50RGV0YWlscygpIHtcbiAgICAgICAgdGhpcy5pc0RhdGFMb2FkZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5jcm1TZXJ2aWNlXG4gICAgICAgICAgICAuZ2V0QWNjb3VudERldGFpbCh0aGlzLnN1YnNjcmlwdGlvbj8uaWQsIHRoaXMuYWNjb3VudElkKVxuICAgICAgICAgICAgLnN1YnNjcmliZShyZXNwb25zZSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5kYXRhID0gcmVzcG9uc2U7XG4gICAgICAgICAgICAgICAgY29uc3Qgb3duZXJEYXRhID0ge1xuICAgICAgICAgICAgICAgICAgICAuLi5yZXNwb25zZS5vd25lcixcbiAgICAgICAgICAgICAgICAgICAgZGlzcGxheU5hbWU6IEhlbHBlclNlcnZpY2UuZm9ybWF0RGlzcGxheU5hbWUocmVzcG9uc2Uub3duZXIsIHRydWUpXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLmFib3V0Q29udHJvbHMucGF0Y2hWYWx1ZShyZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgdGhpcy5hYm91dENvbnRyb2xzLmdldCgnb3duZXJfaWQnKS5zZXRWYWx1ZShvd25lckRhdGEpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5hZGQoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuaXNEYXRhTG9hZGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIGdldCBmKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5hYm91dENvbnRyb2xzLmNvbnRyb2xzO1xuICAgIH1cblxuICAgIHVwZGF0ZUFjY291bnRJbmZvKCkge1xuICAgICAgICB0aGlzLmJ1dHRvbkJ1c3kgPSB0cnVlO1xuICAgICAgICBpZiAoIXRoaXMuYWJvdXRDb250cm9scy52YWxpZCkge1xuICAgICAgICAgICAgdGhpcy5idXR0b25CdXN5ID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLnN1Ym1pdHRlZCA9IHRydWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmFib3V0Q29udHJvbHNcbiAgICAgICAgICAgICAgICAuZ2V0KCdvd25lcl9pZCcpXG4gICAgICAgICAgICAgICAgLnNldFZhbHVlKHRoaXMuYWJvdXRDb250cm9scy5nZXQoJ293bmVyX2lkJykudmFsdWUuaWQpO1xuICAgICAgICAgICAgdGhpcy5jcm1TZXJ2aWNlXG4gICAgICAgICAgICAgICAgLnVwZGF0ZUFjY291bnQodGhpcy5zdWJzY3JpcHRpb24/LmlkLCB0aGlzLmFjY291bnRJZCwgdGhpcy5hYm91dENvbnRyb2xzLnZhbHVlKVxuICAgICAgICAgICAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnRvYXN0LnN1Y2Nlc3MoXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnRyYW5zbGF0aW9uLnRyYW5zbGF0ZSgnQ3JtLkFjY291bnRNZXNzYWdlLlVwZGF0ZWRNZXNzYWdlJylcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pc0Zvcm1FZGl0ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5nZXRBY2NvdW50RGV0YWlscygpO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmFkZCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuYnV0dG9uQnVzeSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnN1Ym1pdHRlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgb25TY3JvbGxUaW1lbGluZSgpIHtcbiAgICAgICAgdGhpcy5jdXJyZW50UGFnZSsrO1xuICAgICAgICBjb25zdCB0b3RhbFBhZ2VzID0gTWF0aC5jZWlsKHRoaXMudG90YWxDb250YWN0cyAvIDUpO1xuICAgICAgICAvLyBQcmV2ZW50IEFQSSBjYWxsIGlmIGFsbCBtZXNzYWdlcyBoYXZlIGJlZW4gZmV0Y2hlZFxuICAgICAgICBpZiAodGhpcy5jdXJyZW50UGFnZSA8PSB0b3RhbFBhZ2VzKSB7XG4gICAgICAgICAgICB0aGlzLmdldEFsbENvbW1lbnRzKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKiogRnVuY3Rpb24gdG8gc2F2ZSBjb21tZW50ICovXG4gICAgb25TYXZlKCkge1xuICAgICAgICB0aGlzLnN1Ym1pdEFjdGlvbiA9IHRydWU7XG4gICAgICAgIGNvbnN0IGZvcm0gPSB0aGlzLmFjdGlvbkNvbnRyb2xzLnZhbHVlO1xuICAgICAgICBmb3JtLm93bmVyX2lkID0gdGhpcy5kYXRhPy5vd25lcl9pZDtcbiAgICAgICAgZm9ybS5jcm1fYWNjb3VudF9pZCA9IHRoaXMuYWNjb3VudElkO1xuICAgICAgICBmb3JtLmNybV9jb250YWN0X2lkID0gZm9ybT8uY3JtX2NvbnRhY3RfaWQ/LmlkO1xuICAgICAgICBmb3JtLndoZW4gPSBIZWxwZXJTZXJ2aWNlLmRhdGVGb3JtYXQoZm9ybS53aGVuKTtcbiAgICAgICAgaWYgKHRoaXMuYWN0aW9uQ29udHJvbHMuaW52YWxpZCkge1xuICAgICAgICAgICAgRm9ybUhlbHBlclNlcnZpY2UudmFsaWRhdGVBbGxGb3JtRmllbGRzKHRoaXMuYWN0aW9uQ29udHJvbHMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5idXR0b25CdXN5ID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMuY3JtU2VydmljZVxuICAgICAgICAgICAgICAgIC5wb3N0QWNjb3VudENvbW1lbnQodGhpcy5zdWJzY3JpcHRpb24/LmlkLCBmb3JtKVxuICAgICAgICAgICAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmFjdGlvbkNvbnRyb2xzLmdldCgnY29tbWVudCcpLnJlc2V0KCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZ2V0QWxsQ29tbWVudHMoKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50b2FzdC5zdWNjZXNzKFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50cmFuc2xhdGlvbi50cmFuc2xhdGUoJ0NybS5BY2NvdW50TWVzc2FnZS5Db21tZW50U3VibWl0dGVkTWVzc2FnZScpXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuYWRkKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdWJtaXRBY3Rpb24gPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5idXR0b25CdXN5ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBzaG93RGF0ZVBpY2tlcihldmVudCwgaWQpIHtcbiAgICAgICAgdGhpcy5hY3Rpb25Db250cm9scy5nZXQoJ3doZW4nKS5zZXRWYWxpZGF0b3JzKFtWYWxpZGF0b3JzLnJlcXVpcmVkXSk7XG4gICAgICAgIGNvbnN0IGFjdGlvbkJ1dHRvbnMgPSB0aGlzLmRvY3VtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoXG4gICAgICAgICAgICAnYWN0aW9uLWJ0bidcbiAgICAgICAgKSBhcyBIVE1MQ29sbGVjdGlvbk9mPEVsZW1lbnQ+ICYgSXRlcmFibGU8RWxlbWVudD47XG4gICAgICAgIGZvciAoY29uc3QgYnV0dG9uIG9mIGFjdGlvbkJ1dHRvbnMpIHtcbiAgICAgICAgICAgIGJ1dHRvbi5jbGFzc0xpc3QucmVtb3ZlKCdhY3RpdmUnKTtcbiAgICAgICAgfVxuICAgICAgICBldmVudC50YXJnZXQuY2xhc3NMaXN0LmFkZCgnYWN0aXZlJyk7XG4gICAgICAgIHRoaXMuYWN0aW9uQ29udHJvbHMuZ2V0KCdjcm1fYWN0aW9uX2lkJykuc2V0VmFsdWUoaWQpO1xuICAgIH1cblxuICAgIC8qKiBGdW5jdGlvbiB0byBnZXQgY29tbWVudHMgKi9cbiAgICBwcml2YXRlIGdldEFsbENvbW1lbnRzKCkge1xuICAgICAgICB0aGlzLmdldFVzZXJTdWJzY3JpcHRpb25JZCgpLnN1YnNjcmliZShyZXNwb25zZSA9PiB7XG4gICAgICAgICAgICB0aGlzLnN1YnNjcmlwdGlvbklkID0gcmVzcG9uc2U7XG4gICAgICAgICAgICBpZiAodGhpcy5zdWJzY3JpcHRpb25JZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuY3JtU2VydmljZVxuICAgICAgICAgICAgICAgICAgICAuZ2V0QWNjb3VudENvbW1lbnRzKHRoaXMuYWNjb3VudElkLCB0aGlzLnN1YnNjcmlwdGlvbklkLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYWdlOiB0aGlzLmN1cnJlbnRQYWdlLFxuICAgICAgICAgICAgICAgICAgICAgICAgcGFnZV9zaXplOiA1XG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgIC5zdWJzY3JpYmUocmVzcCA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnRvdGFsQ29udGFjdHMgPSByZXNwLm9iamVjdF9jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXNwPy5jcm1fYWNjb3VudF9hY3Rpb25zPy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmFjY291bnRDb21tZW50cyA9IHJlc3AuY3JtX2FjY291bnRfYWN0aW9ucztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYWNjb3VudENvbW1lbnRzLmZvckVhY2goZGF0YSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEud2hlbl9zaG9ydF9kYXRlID0gbW9tZW50KGRhdGEud2hlbikuZm9ybWF0KCdERC1NTU0tWVlZWScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkaWZmID0gbW9tZW50KG5ldyBEYXRlKGRhdGEud2hlbikpLmRpZmYoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb21lbnQobmV3IERhdGUoKSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZGF5cydcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1vbWVudChuZXcgRGF0ZShkYXRhLndoZW4pKSA8IG1vbWVudChuZXcgRGF0ZSgpKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YVsnZHVlJ10gPSBgT3ZlcmR1ZSBieSAke01hdGguYWJzKGRpZmYpfSBkYXlzYDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGFbJ2NvbG9yJ10gPSB0aGlzLmRhbmdlckNvbG9yO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YVsnZHVlJ10gPSBgSW4gJHtkaWZmfSBkYXlzYDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGFbJ2NvbG9yJ10gPSAhdGhpcy5kYW5nZXJDb2xvcjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5hY2NvdW50Q29tbWVudHMuc29ydCgoYSwgYikgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IERhdGUoYS53aGVuKS5nZXRUaW1lKCkgLSBuZXcgRGF0ZShiLndoZW4pLmdldFRpbWUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmFjY291bnRDb21tZW50cy5mb3JFYWNoKGl0ZW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtWyd3aGVuJ10gPSBtb21lbnQoaXRlbVsnd2hlbiddKS5mb3JtYXQoJ0RELU1NTS1ZWVlZJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1bJ3llYXInXSA9IG1vbWVudChpdGVtWyd3aGVuJ10sICdERC1NTU0tWVlZWScpLmZvcm1hdCgnWVlZWScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtWydtb250aCddID0gbW9tZW50KGl0ZW1bJ3doZW4nXSwgJ0RELU1NTS1ZWVlZJykuZm9ybWF0KCdNTScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbXBsZXRlZENhbmNlbGxlZEFjdGlvbnM6IHN0cmluZ1tdID0gdGhpcy5hY2NvdW50Q29tbWVudHMuZmlsdGVyKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhY3Rpb24gPT4gYWN0aW9uLmNvbXBsZXRlZCA9PT0gdHJ1ZSB8fCBhY3Rpb24uY2FuY2VsbGVkID09PSB0cnVlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21wbGV0ZWRDYW5jZWxsZWRBY3Rpb25zLnJldmVyc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBub3RDb21wbGV0ZWRDYW5jZWxsZWRBY3Rpb25zOiBzdHJpbmdbXSA9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYWNjb3VudENvbW1lbnRzLmZpbHRlcihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFjdGlvbiA9PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFjdGlvbi5jb21wbGV0ZWQgPT09IGZhbHNlICYmIGFjdGlvbi5jYW5jZWxsZWQgPT09IGZhbHNlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5hY2NvdW50Q29tbWVudHMgPVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3RDb21wbGV0ZWRDYW5jZWxsZWRBY3Rpb25zLmNvbmNhdChjb21wbGV0ZWRDYW5jZWxsZWRBY3Rpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmlzTG9hZGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pc0xvYWRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKiogRnVuY3Rpb24gdG8gdXBkYXRlIGNvbW1lbnQgKi9cbiAgICB1cGRhdGVDb21tZW50KGl0ZW0pIHtcbiAgICAgICAgY29uc3QgY29tbWVudE9iaiA9IHtcbiAgICAgICAgICAgIGNvbW1lbnQ6IGl0ZW0uY29tbWVudCxcbiAgICAgICAgICAgIGNvbXBsZXRlZDogaXRlbS5jb21wbGV0ZWQsXG4gICAgICAgICAgICBjYW5jZWxsZWQ6IGl0ZW0uY2FuY2VsbGVkLFxuICAgICAgICAgICAgY3JtX2FjY291bnRfaWQ6IGl0ZW0uY3JtX2FjY291bnRfaWQsXG4gICAgICAgICAgICBjcm1fY29udGFjdF9pZDogdGhpcy5jb250YWN0SWRcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5jcm1TZXJ2aWNlXG4gICAgICAgICAgICAudXBkYXRlQWNjb3VudENvbW1lbnQodGhpcy5zdWJzY3JpcHRpb24/LmlkLCBpdGVtLmlkLCBjb21tZW50T2JqKVxuICAgICAgICAgICAgLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy50b2FzdC5zdWNjZXNzKCdjb21tZW50IHVwZGF0ZWQgc3VjY2Vzc2Z1bGx5Jyk7XG4gICAgICAgICAgICAgICAgdGhpcy5zaG93RWRpdENvbnRyb2xzKHVuZGVmaW5lZCwgJycpO1xuICAgICAgICAgICAgICAgIHRoaXMuZ2V0QWxsQ29tbWVudHMoKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKiBGdW5jdGlvbiB0byBleGVjdXRlIG9uIGxvY2F0aW9uIHNlbGVjdCAqL1xuICAgIGhhbmRsZUFkZHJlc3NDaGFuZ2UoZXZlbnQpIHtcbiAgICAgICAgdGhpcy5hYm91dENvbnRyb2xzLmdldCgnbG9jYXRpb24nKS5zZXRWYWx1ZShldmVudC5mb3JtYXR0ZWRfYWRkcmVzcyk7XG4gICAgfVxuXG4gICAgLyoqIEZ1bmN0aW9uIHRvIGdldCBzdWJzY3JpcHRpb24gbWVtYmVycyAqL1xuICAgIGdldEFsbFN1YnNjcmlwdGlvbk1lbWJlcnMoKSB7XG4gICAgICAgIHRoaXMuc3Vic2NyaXB0aW9uU2VydmljZVxuICAgICAgICAgICAgLmdldEVucm9sbGVkU3Vic2NyaXB0aW9uKHRoaXMuc3Vic2NyaXB0aW9uPy5pZClcbiAgICAgICAgICAgIC5zdWJzY3JpYmUobWVtYmVyID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmFsbFN1YnNjcmlwdGlvbk1lbWJlcnMgPSBtZW1iZXIubWVtYmVycztcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKiBGdW5jdGlvbiB0byBzaG93IGVkaXQgY29tbWVudCBzZWN0aW9uICovXG4gICAgc2hvd0VkaXRDb250cm9scyhldmVudCwgYWN0aW9uKSB7XG4gICAgICAgIGlmIChhY3Rpb24/LmNybV9jb250YWN0KSB7XG4gICAgICAgICAgICB0aGlzLmNvbnRhY3RJZCA9IGFjdGlvbi5jcm1fY29udGFjdC5pZDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjb21tZW50cyA9IHRoaXMuZG9jdW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShcbiAgICAgICAgICAgICdjYXJkLWhlYWRlcidcbiAgICAgICAgKSBhcyBIVE1MQ29sbGVjdGlvbk9mPEVsZW1lbnQ+ICYgSXRlcmFibGU8RWxlbWVudD47XG4gICAgICAgIGZvciAoY29uc3QgY29tbWVudCBvZiBjb21tZW50cykge1xuICAgICAgICAgICAgY29tbWVudC5jbGFzc0xpc3QucmVtb3ZlKCdzaG93LWNvbnRyb2xzJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGV2ZW50ICYmIGV2ZW50ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGV2ZW50LnRhcmdldC5jbG9zZXN0KCcuY2FyZC1oZWFkZXInKS5jbGFzc0xpc3QuYWRkKCdzaG93LWNvbnRyb2xzJyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKiogRnVuY3Rpb24gdG8gZ2V0IGFuZCBzaG93IGFsbCB0aGUgYWN0aW9ucyAqL1xuICAgIGdldEFjdGlvbnMoKSB7XG4gICAgICAgIHRoaXMuY3JtU2VydmljZS5nZXRBbGxBY3Rpb25zKHRoaXMuc3Vic2NyaXB0aW9uPy5pZCkuc3Vic2NyaWJlKHJlc3AgPT4ge1xuICAgICAgICAgICAgaWYgKHJlc3A/LmNybV9hY3Rpb25zPy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFjdGlvbnMgPSByZXNwLmNybV9hY3Rpb25zLnNvcnQoKGEsIGIpID0+IGEubmFtZS5sb2NhbGVDb21wYXJlKGIubmFtZSkpO1xuICAgICAgICAgICAgICAgIHRoaXMuYnV0dG9uRGlzYWJsZSA9IHRoaXMuYWN0aW9ucy5ldmVyeShcbiAgICAgICAgICAgICAgICAgICAgeCA9PiB4LnZpc2libGUgPT09IGZhbHNlIHx8IHgudmlzaWJsZSA9PT0gbnVsbFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuYnV0dG9uRGlzYWJsZSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmhhc0FjY2VzcyA9IHRoaXMuaGFzQWRtaW5BY2Nlc3ModGhpcy5zdWJzY3JpcHRpb24/LmlkKTtcbiAgICB9XG5cbiAgICAvKiogRnVuY3Rpb24gdG8gc2V0IHRoZSBhY3Rpb24gYXMgY29tcGxldGVkICovXG4gICAgc2V0QXNDb21wbGV0ZWRPclVuY29tcGxldGVkKGlkOiBudW1iZXIsIGFjdGlvbiwgY29tcGxldGVkT3JVbmNvbXBsZXRlZDogYm9vbGVhbikge1xuICAgICAgICBjb25zdCBhbGVydFRpdGxlID0gY29tcGxldGVkT3JVbmNvbXBsZXRlZCA/ICdJbkNvbXBsZXRlZCcgOiAnQ29tcGxldGVkJztcblxuICAgICAgICByZXR1cm4gc3dhbFxuICAgICAgICAgICAgLmZpcmUoe1xuICAgICAgICAgICAgICAgIHRpdGxlOiBhbGVydFRpdGxlLFxuICAgICAgICAgICAgICAgIGh0bWw6IGBBcmUgeW91IHN1cmUgeW91IHdhbnQgdG8gc2V0IGFzICR7YWxlcnRUaXRsZX0/YCxcbiAgICAgICAgICAgICAgICBzaG93Q2FuY2VsQnV0dG9uOiB0cnVlLFxuICAgICAgICAgICAgICAgIHJldmVyc2VCdXR0b25zOiB0cnVlLFxuICAgICAgICAgICAgICAgIGljb246ICd3YXJuaW5nJ1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC50aGVuKHJlcyA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHJlcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBhY3Rpb25PYmogPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb21tZW50OiBhY3Rpb24uY29tbWVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbXBsZXRlZDogIWNvbXBsZXRlZE9yVW5jb21wbGV0ZWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBjYW5jZWxsZWQ6IGFjdGlvbi5jYW5jZWxsZWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBjcm1fYWNjb3VudF9pZDogYWN0aW9uLmNybV9hY2NvdW50X2lkXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY3JtU2VydmljZVxuICAgICAgICAgICAgICAgICAgICAgICAgLnVwZGF0ZUFjY291bnRDb21tZW50KHRoaXMuc3Vic2NyaXB0aW9uPy5pZCwgaWQsIGFjdGlvbk9iailcbiAgICAgICAgICAgICAgICAgICAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudG9hc3Quc3VjY2VzcyhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50cmFuc2xhdGlvbi50cmFuc2xhdGUoJ0NybS5TZXR0aW5ncy5VcGRhdGVkTWVzc2FnZScpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmFjdGlvbnMuc3BsaWNlKGFjdGlvbiwgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5nZXRBY3Rpb25zKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5nZXRBbGxDb21tZW50cygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqIEZ1bmN0aW9uIHRvIHNldCB0aGUgYWN0aW9uIGFzIGNhbmNlbGxlZCAqL1xuICAgIHNldEFzQ2FuY2VsbGVkKGlkOiBudW1iZXIsIGFjdGlvbikge1xuICAgICAgICByZXR1cm4gc3dhbFxuICAgICAgICAgICAgLmZpcmUoe1xuICAgICAgICAgICAgICAgIHRpdGxlOiAnQ2FuY2VsJyxcbiAgICAgICAgICAgICAgICBodG1sOiBgQXJlIHlvdSBzdXJlIHlvdSB3YW50IHRvIHNldCBhcyBjYW5jZWxsZWQ/YCxcbiAgICAgICAgICAgICAgICBzaG93Q2FuY2VsQnV0dG9uOiB0cnVlLFxuICAgICAgICAgICAgICAgIHJldmVyc2VCdXR0b25zOiB0cnVlLFxuICAgICAgICAgICAgICAgIGljb246ICd3YXJuaW5nJ1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC50aGVuKHJlcyA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHJlcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBhY3Rpb25PYmogPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb21tZW50OiBhY3Rpb24uY29tbWVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbXBsZXRlZDogYWN0aW9uLmNvbXBsZXRlZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbmNlbGxlZDogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNybV9hY2NvdW50X2lkOiBhY3Rpb24uY3JtX2FjY291bnRfaWRcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jcm1TZXJ2aWNlXG4gICAgICAgICAgICAgICAgICAgICAgICAudXBkYXRlQWNjb3VudENvbW1lbnQodGhpcy5zdWJzY3JpcHRpb24/LmlkLCBpZCwgYWN0aW9uT2JqKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50b2FzdC5zdWNjZXNzKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnRyYW5zbGF0aW9uLnRyYW5zbGF0ZSgnQ3JtLlNldHRpbmdzLlVwZGF0ZWRNZXNzYWdlJylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYWN0aW9ucy5zcGxpY2UoYWN0aW9uLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmdldEFjdGlvbnMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmdldEFsbENvbW1lbnRzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKiogRnVuY3Rpb24gdG8gdXBkYXRlIHRoZSBkYXRlICovXG4gICAgb25EYXRlU2VsZWN0KGV2ZW50LCBhY3Rpb24pIHtcbiAgICAgICAgY29uc3QgY29tbWVudE9iaiA9IHtcbiAgICAgICAgICAgIHdoZW46IEhlbHBlclNlcnZpY2UuZGF0ZUZvcm1hdChldmVudCksXG4gICAgICAgICAgICBjb21tZW50OiBhY3Rpb24uY29tbWVudCxcbiAgICAgICAgICAgIGNvbXBsZXRlZDogYWN0aW9uLmNvbXBsZXRlZCxcbiAgICAgICAgICAgIGNhbmNlbGxlZDogYWN0aW9uLmNhbmNlbGxlZCxcbiAgICAgICAgICAgIGNybV9hY2NvdW50X2lkOiBhY3Rpb24uY3JtX2FjY291bnRfaWRcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5jcm1TZXJ2aWNlXG4gICAgICAgICAgICAudXBkYXRlQWNjb3VudENvbW1lbnQodGhpcy5zdWJzY3JpcHRpb24/LmlkLCBhY3Rpb24uaWQsIGNvbW1lbnRPYmopXG4gICAgICAgICAgICAuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnRvYXN0LnN1Y2Nlc3MoJ2RhdGUgdXBkYXRlZCBzdWNjZXNzZnVsbHknKTtcbiAgICAgICAgICAgICAgICB0aGlzLmdldEFsbENvbW1lbnRzKCk7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqIEZ1bmN0aW9uIHRvIHNob3cgRGF0ZVBpY2tlciAqL1xuICAgIHNob3dEYXRlUGlja2VyVXBkYXRlKGFjdGlvbklkKSB7XG4gICAgICAgIHRoaXMudXBkYXRpbmcgPSAhdGhpcy51cGRhdGluZztcbiAgICAgICAgdGhpcy5hY3Rpb25JZCA9IGFjdGlvbklkO1xuICAgIH1cblxuICAgIC8qKiBGdW5jdGlvbiB0byBnZXQgdGhlIGNvbnRhY3RzIHJlbGF0ZWQgdG8gYWNjb3VudCAqL1xuICAgIHByaXZhdGUgZ2V0QWNjb3VudENvbnRhY3RzKHBhZ2luZzogUGFnaW5nKSB7XG4gICAgICAgIHRoaXMuZ2V0VXNlclN1YnNjcmlwdGlvbklkKCkuc3Vic2NyaWJlKGlkID0+IHtcbiAgICAgICAgICAgIHRoaXMuc3Vic2NyaXB0aW9uSWQgPSBpZDtcbiAgICAgICAgICAgIGlmICh0aGlzLnN1YnNjcmlwdGlvbklkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jcm1TZXJ2aWNlXG4gICAgICAgICAgICAgICAgICAgIC5nZXRBY2NvdW50Q29udGFjdHMoXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmFjY291bnRJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3Vic2NyaXB0aW9uSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmZpbHRlckJ5UG90ZW50aWFscyB8fCAnJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2luZ1xuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgIC5zdWJzY3JpYmUocmVzcG9uc2UgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlLmNvbnRhY3RzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb250YWN0cyA9IHJlc3BvbnNlLmNvbnRhY3RzO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudG90YWxSZWNvcmRzID0gcmVzcG9uc2Uub2JqZWN0X2NvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudG90YWxSZWNvcmRzVW5GaWx0ZXJlZCA9IHJlc3BvbnNlLnVuZmlsdGVyZWRfY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb250YWN0cy5mb3JFYWNoKG1lbWJlciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lbWJlci5kaXNwbGF5TmFtZSA9IGAke21lbWJlci5maXJzdF9uYW1lIHx8ICcnfSAke1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVtYmVyLmxhc3RfbmFtZSB8fCAnJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IC0gJHttZW1iZXIuZW1haWx9YC50cmltKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgIC5hZGQoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2FkaW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKiogRnVuY3Rpb24gd2hlbiBhdXRvLWNvbXBsZXRlIGRyb3Bkb3duIHNlbGVjdGVkICovXG4gICAgb25Ecm9wZG93bkNsaWNrKCkge1xuICAgICAgICBpZiAodGhpcy5jb250YWN0cz8ubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICB0aGlzLmZpbHRlcmVkQ29udGFjdCA9IFt7IGRpc3BsYXlOYW1lOiAnTm8gY29udGFjdCB0byBjaG9vc2UnIH1dO1xuICAgICAgICAgICAgdGhpcy5maWx0ZXJlZENvbnRhY3RDb21tZW50ID0gW3sgZmlyc3RfbmFtZTogJ05vIGNvbnRhY3QgdG8gY2hvb3NlJyB9XTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKiBzZWFyY2ggb3duZXIgKi9cbiAgICBzZWFyY2goZXZlbnQpIHtcbiAgICAgICAgY29uc3QgdmFsdWVzID0gW107XG4gICAgICAgIGlmIChldmVudC5xdWVyeSkge1xuICAgICAgICAgICAgdGhpcy5maWx0ZXJlZE93bmVyID0gdGhpcy5hbGxTdWJzY3JpcHRpb25NZW1iZXJzPy5maWx0ZXIoKHg6IFN1YnNjcmlwdGlvbk1lbWJlcikgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiB4LmZpcnN0X25hbWUudG9Mb3dlckNhc2UoKS5pbmNsdWRlcyhldmVudC5xdWVyeS50b0xvd2VyQ2FzZSgpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5hbGxTdWJzY3JpcHRpb25NZW1iZXJzPy5mb3JFYWNoKGVsZW1lbnQgPT4ge1xuICAgICAgICAgICAgICAgIHZhbHVlcy5wdXNoKGVsZW1lbnQpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5maWx0ZXJlZE93bmVyID0gdmFsdWVzLm1hcChvd25lciA9PiB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIC4uLm93bmVyLFxuICAgICAgICAgICAgICAgIGRpc3BsYXlOYW1lOiBIZWxwZXJTZXJ2aWNlLmZvcm1hdERpc3BsYXlOYW1lKG93bmVyLCB0cnVlKVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgc2VhcmNoQ29udGFjdChldmVudCkge1xuICAgICAgICB0aGlzLmlzQ29udGFjdFZhbGlkID0gZmFsc2U7XG4gICAgICAgIGxldCB2YWx1ZXMgPSBbXTtcbiAgICAgICAgaWYgKGV2ZW50LnF1ZXJ5KSB7XG4gICAgICAgICAgICB2YWx1ZXMgPSB0aGlzLmNvbnRhY3RzPy5maWx0ZXIoKHg6IENybU9wcG9ydHVuaXR5Q29udGFjdCkgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiB4LmRpc3BsYXlOYW1lLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMoZXZlbnQucXVlcnkudG9Mb3dlckNhc2UoKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuY29udGFjdHM/LmZvckVhY2goZWxlbWVudCA9PiB7XG4gICAgICAgICAgICAgICAgdmFsdWVzLnB1c2goZWxlbWVudCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmZpbHRlcmVkQ29udGFjdCA9IHZhbHVlcztcbiAgICB9XG5cbiAgICBzZWxlY3RDb250YWN0KGV2ZW50KSB7XG4gICAgICAgIHRoaXMuaXNDb250YWN0VmFsaWQgPSB0aGlzLmNvbnRhY3RzLnNvbWUoeCA9PiB4LmlkID09PSBldmVudC52YWx1ZS5pZCk7XG4gICAgfVxuXG4gICAgT25Db250YWN0Qmx1cigpIHtcbiAgICAgICAgaWYgKCF0aGlzLmlzQ29udGFjdFZhbGlkKSB7XG4gICAgICAgICAgICB0aGlzLmFjdGlvbkNvbnRyb2xzLmdldCgnY3JtX2NvbnRhY3RfaWQnKS5zZXRWYWx1ZSgnJyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBzZWFyY2hDb250YWN0SW5Db21tZW50KGV2ZW50KSB7XG4gICAgICAgIGxldCB2YWx1ZXMgPSBbXTtcbiAgICAgICAgaWYgKGV2ZW50LnF1ZXJ5KSB7XG4gICAgICAgICAgICB2YWx1ZXMgPSB0aGlzLmNvbnRhY3RzPy5maWx0ZXIoKHg6IENybU9wcG9ydHVuaXR5Q29udGFjdCkgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiB4LmRpc3BsYXlOYW1lLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMoZXZlbnQucXVlcnkudG9Mb3dlckNhc2UoKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuY29udGFjdHM/LmZvckVhY2goZWxlbWVudCA9PiB7XG4gICAgICAgICAgICAgICAgdmFsdWVzLnB1c2goZWxlbWVudCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmZpbHRlcmVkQ29udGFjdENvbW1lbnQgPSB2YWx1ZXM7XG4gICAgfVxuXG4gICAgc2VsZWN0Q29tbWVudENvbnRhY3QoZXZlbnQpIHtcbiAgICAgICAgdGhpcy5jb250YWN0SWQgPSBldmVudD8udmFsdWU/LmlkO1xuICAgIH1cblxuICAgIC8qKiBGdW5jdGlvbiB0byBkZWxldGUgY29udGFjdCAqL1xuICAgIG9uRGVsZXRlQ29udGFjdChpZDogbnVtYmVyKSB7XG4gICAgICAgIEhlbHBlclNlcnZpY2UucmFpc2VEZWxldGVQb3B1cCgpLnRoZW4ocmVzcCA9PiB7XG4gICAgICAgICAgICBpZiAocmVzcC52YWx1ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuY3JtU2VydmljZS5kZWxldGVDb250YWN0KHRoaXMuc3Vic2NyaXB0aW9uPy5pZCwgaWQpLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudG9hc3Quc3VjY2VzcyhcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudHJhbnNsYXRpb24udHJhbnNsYXRlKCdDcm0uQ29udGFjdE1lc3NhZ2UuRGVsZXRlZE1lc3NhZ2UnKVxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmdldEFjY291bnRDb250YWN0cyh7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYWdlOiB0aGlzLnBhZ2UsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYWdlX3NpemU6IFBBR0VfU0laRVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqIEZ1bmN0aW9uIHRvIGdldCBjb250YWN0IHZlcnNpb25zICovXG4gICAgcHJpdmF0ZSBnZXRDb250YWN0VmVyc2lvbigpIHtcbiAgICAgICAgdGhpcy5jcm1TZXJ2aWNlXG4gICAgICAgICAgICAuZ2V0Q29udGFjdFZlcnNpb24odGhpcy5zdWJzY3JpcHRpb24/LmlkLCB0aGlzLmFjY291bnRJZCwgJ0NybUFjY291bnQnKVxuICAgICAgICAgICAgLnN1YnNjcmliZShyZXNwb25zZSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5hY2NvdW50VmVyc2lvbmluZyA9IHJlc3BvbnNlLnZlcnNpb25zO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgb3Blbk1vZGFsKGNvbnRlbnQpIHtcbiAgICAgICAgdGhpcy5tb2RhbFNlcnZpY2Uub3Blbihjb250ZW50LCB7IGNlbnRlcmVkOiB0cnVlLCB3aW5kb3dDbGFzczogJ21vZGFsLWhvbGRlcicgfSk7XG4gICAgfVxuXG4gICAgb25DbG9zZSgpIHtcbiAgICAgICAgdGhpcy5tb2RhbFNlcnZpY2UuZGlzbWlzc0FsbCgpO1xuICAgIH1cblxuICAgIG9uVXBsb2FkT3V0cHV0KG91dHB1dDogVXBsb2FkT3V0cHV0KTogdm9pZCB7XG4gICAgICAgIHN3aXRjaCAob3V0cHV0LnR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgJ2FsbEFkZGVkVG9RdWV1ZSc6XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZmlsZXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBldmVudDogVXBsb2FkSW5wdXQgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAndXBsb2FkQWxsJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHVybDogQ1JNX0FDQ09VTlRfRklMRVNfUEFUSCxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG93bmVyX2lkOiBgJHt0aGlzLnVzZXJJZH1gLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNybV9hY2NvdW50X2lkOiBgJHt0aGlzLmFjY291bnRJZH1gXG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtUT0tFTl9IRUFERVJfS0VZXTogdGhpcy50b2tlblxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnVwbG9hZElucHV0LmVtaXQoZXZlbnQpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnYWRkZWRUb1F1ZXVlJzpcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG91dHB1dC5maWxlICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBleHQgPSBvdXRwdXQuZmlsZS5uYW1lLnNwbGl0KCcuJykucG9wKCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChET0NVTUVOVF9UWVBFX0VYVC5pbmNsdWRlcyhleHQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmZpbGVzLnB1c2gob3V0cHV0LmZpbGUpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50b2FzdC5lcnJvcignZmlsZSBmb3JtYXRzIGlzIG5vdCBzdXBwb3J0ZWQuJyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICd1cGxvYWRpbmcnOlxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygb3V0cHV0LmZpbGUgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gdGhpcy5maWxlcy5maW5kSW5kZXgoXG4gICAgICAgICAgICAgICAgICAgICAgICBmaWxlID0+IHR5cGVvZiBvdXRwdXQuZmlsZSAhPT0gJ3VuZGVmaW5lZCcgJiYgZmlsZS5pZCA9PT0gb3V0cHV0LmZpbGUuaWRcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5maWxlc1tpbmRleF0gPSBvdXRwdXQuZmlsZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdyZW1vdmVkJzpcbiAgICAgICAgICAgICAgICB0aGlzLmZpbGVzID0gdGhpcy5maWxlcy5maWx0ZXIoKGZpbGU6IFVwbG9hZEZpbGUpID0+IGZpbGUgIT09IG91dHB1dC5maWxlKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ2RyYWdPdmVyJzpcbiAgICAgICAgICAgICAgICB0aGlzLmRyYWdPdmVyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ2RyYWdPdXQnOlxuICAgICAgICAgICAgY2FzZSAnZHJvcCc6XG4gICAgICAgICAgICAgICAgdGhpcy5kcmFnT3ZlciA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnZG9uZSc6XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5maWxlcy5mb3JFYWNoKGZpbGUgPT4ge1xuICAgICAgICAgICAgaWYgKGZpbGUucHJvZ3Jlc3Muc3RhdHVzID09PSBVcGxvYWRTdGF0dXMuRG9uZSkge1xuICAgICAgICAgICAgICAgIGZpbGVbJ3VwbG9hZGVkJ10gPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgLy8gd2FpdCBmb3IgNTAwbXMgYmVmb3JlIGZpbHRlciBmaWxlc1xuICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuZmlsZXMgPSB0aGlzLmZpbGVzLmZpbHRlcihmaWxlID0+IGZpbGUucHJvZ3Jlc3Muc3RhdHVzICE9PSBVcGxvYWRTdGF0dXMuRG9uZSk7XG4gICAgICAgIH0sIDUwMCk7XG4gICAgfVxuXG4gICAgZ2V0QWNjb3VudExvZ28odXJsOiBzdHJpbmcpIHtcbiAgICAgICAgaWYgKHVybCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubG9nb0NhY2hlU2VydmljZS5nZXRMb2dvKEhlbHBlclNlcnZpY2UuZ2V0TG9nb0J5VXJsKHVybCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuICcnO1xuICAgIH1cblxuICAgIG5hdmlnYXRlVG9BZGRPcHBvcnR1bml0aWVzKCkge1xuICAgICAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbYC8ke3RoaXMuc3Vic2NyaXB0aW9uPy5zbHVnfSR7dGhpcy5yb3V0ZXJzLm9wcG9ydHVuaXR5QWRkfWBdLCB7XG4gICAgICAgICAgICBxdWVyeVBhcmFtczogeyBhY2NvdW50X2lkOiB0aGlzLmFjY291bnRJZCB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIG92ZXJyaWRlIG5nT25EZXN0cm95KCkge1xuICAgICAgICBzdXBlci5uZ09uRGVzdHJveSgpO1xuICAgIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJyb3dcIj5cbiAgPGRpdiBjbGFzcz1cImNvbC0xMiBtYi0wXCI+XG4gICAgPGRpdiBjbGFzcz1cIm1lLWF1dG8gbWItMFwiPlxuICAgICAgPGgyIGNsYXNzPVwibWItMFwiPlxuICAgICAgICA8YSBhcmlhLWxhYmVsPVwiTmF2aWdhdGUgdG8gVGFyZ2V0XCJcbiAgICAgICAgICAoY2xpY2spPVwiYmFjaygpXCJcbiAgICAgICAgICBjbGFzcz1cInByZXZpb3VzXCI+PGkgY2xhc3M9XCJmYSBmYS1hcnJvdy1hbHQtY2lyY2xlLWxlZnRcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+PC9hPlxuICAgICAgICBBY2NvdW50IEluZm9cbiAgICAgIDwvaDI+XG4gICAgPC9kaXY+XG4gICAgPGEgY2xhc3M9XCJidG4gYnRuLXNtIGJ0bi1vdXRsaW5lLXByaW1hcnkgZmxvYXQtZW5kIG1iLTNcIlxuICAgICAgZGF0YS1jeT1cImFkZC1vcHBvcnR1bml0aWVzXCJcbiAgICAgIChjbGljayk9XCJuYXZpZ2F0ZVRvQWRkT3Bwb3J0dW5pdGllcygpXCI+XG4gICAgICA8aSBjbGFzcz1cImZhIGZhLXBsdXMtY2lyY2xlXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAge3sgJ0NybS5PcHBvcnR1bml0aWVzTWVzc2FnZS5BZGRPcHBvcnR1bml0eScgfCB0cmFuc2xvY28gfX1cbiAgICA8L2E+XG4gIDwvZGl2PlxuICA8ZGl2IGNsYXNzPVwidy0xMDAgdGV4dC1jZW50ZXIgbXQtM1wiXG4gICpuZ0lmPVwiIWlzRGF0YUxvYWRlZFwiPlxuICA8cC1wcm9ncmVzc1NwaW5uZXI+IDwvcC1wcm9ncmVzc1NwaW5uZXI+XG4gIDwvZGl2PlxuICA8ZGl2ICpuZ0lmPVwiaXNEYXRhTG9hZGVkXCI+XG4gICAgPGRpdiBjbGFzcz1cInJvd1wiPlxuICAgICAgPGRpdiBjbGFzcz1cImNvbC0xMiBjb2wtbWQtNFwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwidXNlci1pbmZvIHAtMyBjYXJkIHBiLTAgaC1hdXRvXCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cIm1iLTIgdGV4dC1jZW50ZXJcIj5cbiAgICAgICAgICAgIDxhIGNsYXNzPVwicHJvZmlsZS1pbWFnZVwiPlxuICAgICAgICAgICAgICA8aW1nIGFsdD1cIlByb2ZpbGUgTG9nb1wiXG4gICAgICAgICAgICAgICAgd2lkdGg9XCIxMDBcIlxuICAgICAgICAgICAgICAgIGhlaWdodD1cIjEwMFwiXG4gICAgICAgICAgICAgICAgW3NyY109XCJnZXRBY2NvdW50TG9nbyhkYXRhPy5jb21wYW55X3VybClcIlxuICAgICAgICAgICAgICAgIGNsYXNzPVwiaW1nLWZsdWlkIGNvbXBhbnktbG9nb1wiXG4gICAgICAgICAgICAgICAgKGVycm9yKT1cImhhbmRsZUltYWdlRXJyb3IoJGV2ZW50LCAnYXNzZXRzL2ltZy9pY29ucy9jb21wYW55LnBuZycpXCIgLz5cbiAgICAgICAgICAgIDwvYT5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwibWItNCBkLWZsZXgganVzdGlmeS1jb250ZW50LWJldHdlZW4gYWxpZ24taXRlbXMtY2VudGVyXCI+XG4gICAgICAgICAgICA8aDQgY2xhc3M9XCJkLWlubGluZS1ibG9jayBuYW1lLWJsb2NrXCI+XG4gICAgICAgICAgICAgIEFib3V0IDxzcGFuICpuZ0lmPVwiZGF0YT8uaWRcIj57eyBkYXRhLm5hbWUgfX08L3NwYW4+XG4gICAgICAgICAgICA8L2g0PlxuICAgICAgICAgICAgPGEgaHJlZj1cImphdmFzY3JpcHQ6dm9pZCgwKTtcIlxuICAgICAgICAgICAgICAqbmdJZj1cImlzRm9ybUVkaXQgJiYgKHVzZXJJZCA9PT0gZGF0YT8ub3duZXI/LmlkIHx8IGhhc0FjY2VzcylcIlxuICAgICAgICAgICAgICBjbGFzcz1cImJ0biBidG4tc20gYnRuLW91dGxpbmUtcHJpbWFyeSBmbG9hdC1lbmRcIlxuICAgICAgICAgICAgICAoY2xpY2spPVwiaXNGb3JtRWRpdCA9ICFpc0Zvcm1FZGl0OyB0aGlzLmdldEFsbFN1YnNjcmlwdGlvbk1lbWJlcnMoKVwiPnt7ICdCdXR0b24uRWRpdCcgfCB0cmFuc2xvY28gfX08L2E+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPGZvcm0gW2Zvcm1Hcm91cF09XCJhYm91dENvbnRyb2xzXCJcbiAgICAgICAgICAgIFtjbGFzcy5pc0Rpc2FibGVkXT1cImlzRm9ybUVkaXRcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtYi0zXCI+XG4gICAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImxhYmVsIG1iLTBcIiBmb3I9XCJuYW1lXCI+e3sgJ0NybS5BY2NvdW50TWVzc2FnZS5OYW1lJyB8IHRyYW5zbG9jbyB9fTwvbGFiZWw+XG4gICAgICAgICAgICAgIDxpbnB1dCB0eXBlPVwidGV4dFwiXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2wgcm91bmRlZC0wIHBzLTEgdXNlci12YWx1ZVwiXG4gICAgICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwibmFtZVwiXG4gICAgICAgICAgICAgICAgW25nQ2xhc3NdPVwieyAnaXMtaW52YWxpZCc6IHN1Ym1pdHRlZCAmJiBmWyduYW1lJ10uZXJyb3JzIH1cIiAvPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWItM1wiPlxuICAgICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJsYWJlbCBtYi0wXCIgZm9yPVwiTG9jYXRpb25cIj57e1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdDcm0uQWNjb3VudE1lc3NhZ2UuTG9jYXRpb24nIHwgdHJhbnNsb2NvXG4gICAgICAgICAgICAgICAgICAgICAgICB9fTwvbGFiZWw+XG4gICAgICAgICAgICAgIDxpbnB1dCBuZ3gtZ3AtYXV0b2NvbXBsZXRlXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2wgcm91bmRlZC0wIHBzLTEgdXNlci12YWx1ZVwiXG4gICAgICAgICAgICAgICAgI3BsYWNlcz1cIm5neC1wbGFjZXNcIlxuICAgICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cImxvY2F0aW9uXCJcbiAgICAgICAgICAgICAgICAob25BZGRyZXNzQ2hhbmdlKT1cImhhbmRsZUFkZHJlc3NDaGFuZ2UoJGV2ZW50KVwiXG4gICAgICAgICAgICAgICAgW25nQ2xhc3NdPVwieyAnaXMtaW52YWxpZCc6IHN1Ym1pdHRlZCAmJiBmWydsb2NhdGlvbiddLmVycm9ycyB9XCIgLz5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1iLTNcIlxuICAgICAgICAgICAgICAqbmdJZj1cImNvdW50cmllcyQgfCBhc3luYyBhcyBjb3VudHJpZXNcIj5cbiAgICAgICAgICAgICAgPGxhYmVsIGZvcj1cImNvdW50cnlcIj57eyAnQ3JtLkFjY291bnRNZXNzYWdlLkNvdW50cnknIHwgdHJhbnNsb2NvXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfX08c3BhbiBjbGFzcz1cInRleHQtZGFuZ2VyIHJlcXVpcmVkLWljb25cIj4qPC9zcGFuPlxuICAgICAgICAgICAgICA8L2xhYmVsPlxuICAgICAgICAgICAgICA8cC1kcm9wZG93blxuICAgICAgICAgICAgICBbb3B0aW9uc109XCJjb3VudHJpZXNcIlxuICAgICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJjb3VudHJ5XCJcbiAgICAgICAgICAgICAgW25nQ2xhc3NdPVwieyAnaXMtaW52YWxpZCc6IHN1Ym1pdHRlZCAmJiBmWydjb3VudHJ5J10uZXJyb3JzIH1cIlxuICAgICAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwiJ1NlbGVjdCBDb3VudHJ5J1wiXG4gICAgICAgICAgICAgIG9wdGlvblZhbHVlPVwiY29kZVwiXG4gICAgICAgICAgICAgIG9wdGlvbkxhYmVsPVwibmFtZVwiPlxuICAgICAgICAgICAgPC9wLWRyb3Bkb3duPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWItMyB1aS1mbHVpZCBza2lsbHMtbW9kYWxcIj5cbiAgICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwibGFiZWwgbWItMlwiIGZvcj1cIk1lc3NhZ2VcIj57eyAnQ3JtLkFjY291bnRNZXNzYWdlLk93bmVyJyB8IHRyYW5zbG9jbyB9fTwvbGFiZWw+XG4gICAgICAgICAgICAgIDxwIGNsYXNzPVwiZm9ybS1jb250cm9sIGQtYmxvY2sgcGItMiBwcy0xIHVzZXItdmFsdWVcIlxuICAgICAgICAgICAgICAgICpuZ0lmPVwiaXNGb3JtRWRpdCAmJiBkYXRhPy5vd25lcl9pZFwiPlxuICAgICAgICAgICAgICAgIHt7IGRhdGE/Lm93bmVyPy5maXJzdF9uYW1lIH19IHt7IGRhdGE/Lm93bmVyPy5sYXN0X25hbWUgfX1cbiAgICAgICAgICAgICAgPC9wPlxuICAgICAgICAgICAgICA8cC1hdXRvQ29tcGxldGUgKm5nSWY9XCIhaXNGb3JtRWRpdCB8fCAhZGF0YT8ub3duZXJfaWRcIlxuICAgICAgICAgICAgICAgIFtzdWdnZXN0aW9uc109XCJmaWx0ZXJlZE93bmVyXCJcbiAgICAgICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJvd25lcl9pZFwiXG4gICAgICAgICAgICAgICAgZGF0YUtleT1cImlkXCJcbiAgICAgICAgICAgICAgICBmaWVsZD1cImRpc3BsYXlOYW1lXCJcbiAgICAgICAgICAgICAgICBbZHJvcGRvd25dPVwidHJ1ZVwiXG4gICAgICAgICAgICAgICAgKGNvbXBsZXRlTWV0aG9kKT1cInNlYXJjaCgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgICBzdHlsZUNsYXNzPVwidy0xMDBcIlxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwiU2VhcmNoIG93bmVyXCJcbiAgICAgICAgICAgICAgICBbbXVsdGlwbGVdPVwiZmFsc2VcIj5cbiAgICAgICAgICAgICAgPC9wLWF1dG9Db21wbGV0ZT5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1iLTNcIj5cbiAgICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwibGFiZWwgbWItMFwiIGZvcj1cIkNvbXBhbnlVcmxcIj57e1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdDcm0uQWNjb3VudE1lc3NhZ2UuQ29tcGFueVVybCcgfCB0cmFuc2xvY29cbiAgICAgICAgICAgICAgICAgICAgICAgIH19PC9sYWJlbD5cbiAgICAgICAgICAgICAgPGEgW2hyZWZdPVwiZGF0YT8uY29tcGFueV91cmxcIlxuICAgICAgICAgICAgICAgIHRhcmdldD1cImJsYW5rXCJcbiAgICAgICAgICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbCBkLWJsb2NrIHBiLTIgcHMtMSB1c2VyLXZhbHVlXCJcbiAgICAgICAgICAgICAgICAqbmdJZj1cImlzRm9ybUVkaXQgJiYgZGF0YT8uY29tcGFueV91cmxcIj57eyBkYXRhPy5jb21wYW55X3VybCB9fTwvYT5cbiAgICAgICAgICAgICAgPGlucHV0ICpuZ0lmPVwiIWlzRm9ybUVkaXQgfHwgIWRhdGE/LmNvbXBhbnlfdXJsXCJcbiAgICAgICAgICAgICAgICB0eXBlPVwidGV4dFwiXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2wgcm91bmRlZC0wIHBzLTEgdXNlci12YWx1ZVwiXG4gICAgICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwiY29tcGFueV91cmxcIlxuICAgICAgICAgICAgICAgIFtuZ0NsYXNzXT1cInsgJ2lzLWludmFsaWQnOiBzdWJtaXR0ZWQgJiYgZlsnY29tcGFueV91cmwnXS5lcnJvcnMgfVwiIC8+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtYi0zXCJcbiAgICAgICAgICAgICAgKm5nSWY9XCJkYXRhPy50ZWxcIj5cbiAgICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwibGFiZWwgbWItMFwiIGZvcj1cIkFjY291bnRNZXNzYWdlXCI+e3sgJ0NybS5BY2NvdW50TWVzc2FnZS5UZWwnIHwgdHJhbnNsb2NvIH19PC9sYWJlbD5cbiAgICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJ0ZXh0XCJcbiAgICAgICAgICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbCByb3VuZGVkLTAgcHMtMSB1c2VyLXZhbHVlXCJcbiAgICAgICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJ0ZWxcIiAvPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWItM1wiXG4gICAgICAgICAgICAgICpuZ0lmPVwib3JnYW5pemF0aW9uVHlwZXMkIHwgYXN5bmMgYXMgdHlwZXNcIj5cbiAgICAgICAgICAgICAgPGxhYmVsIGZvcj1cIm9yZ2FuaXphdGlvblR5cGVcIj57eyAnT3JnYW5pemF0aW9uLk9yZ2FuaXphdGlvblR5cGUnIHwgdHJhbnNsb2NvIH19PC9sYWJlbD5cbiAgICAgICAgICAgICAgPHAtZHJvcGRvd25cbiAgICAgICAgICAgICAgICBbb3B0aW9uc109XCJ0eXBlc1snb3JnYW5pemF0aW9uX3R5cGVzJ11cIlxuICAgICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cIm9yZ2FuaXphdGlvbl90eXBlX2lkXCJcbiAgICAgICAgICAgICAgICBbbmdDbGFzc109XCJ7ICdpcy1pbnZhbGlkJzogc3VibWl0dGVkICYmIGZbJ29yZ2FuaXphdGlvbl90eXBlX2lkJ10uZXJyb3JzIH1cIlxuICAgICAgICAgICAgICAgIFtwbGFjZWhvbGRlcl09XCInU2VsZWN0IE9yZ2FuaXphdGlvbiBUeXBlJ1wiXG4gICAgICAgICAgICAgICAgb3B0aW9uVmFsdWU9XCJpZFwiXG4gICAgICAgICAgICAgICAgb3B0aW9uTGFiZWw9XCJuYW1lXCI+XG4gICAgICAgICAgICAgIDwvcC1kcm9wZG93bj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1iLTNcIlxuICAgICAgICAgICAgICAqbmdJZj1cIm9yZ2FuaXphdGlvbkluZHVzdHJpZXMkIHwgYXN5bmMgYXMgaW5kdXN0cmllc1wiPlxuICAgICAgICAgICAgICA8bGFiZWwgZm9yPVwiZmlsZVwiPnt7ICdPcmdhbml6YXRpb24uT3JnYW5pemF0aW9uSW5kdXN0cnknIHwgdHJhbnNsb2NvIH19PC9sYWJlbD5cbiAgICAgICAgICAgICAgPHAtZHJvcGRvd25cbiAgICAgICAgICAgICAgICBbb3B0aW9uc109XCJpbmR1c3RyaWVzWydvcmdhbml6YXRpb25faW5kdXN0cmllcyddXCJcbiAgICAgICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJvcmdhbml6YXRpb25faW5kdXN0cnlfaWRcIlxuICAgICAgICAgICAgICAgIFtuZ0NsYXNzXT1cInsgJ2lzLWludmFsaWQnOiBzdWJtaXR0ZWQgJiYgZlsnb3JnYW5pemF0aW9uX2luZHVzdHJ5X2lkJ10uZXJyb3JzIH1cIlxuICAgICAgICAgICAgICAgIFtwbGFjZWhvbGRlcl09XCInU2VsZWN0IEluZHVzdHJ5J1wiXG4gICAgICAgICAgICAgICAgb3B0aW9uVmFsdWU9XCJpZFwiXG4gICAgICAgICAgICAgICAgb3B0aW9uTGFiZWw9XCJuYW1lXCI+XG4gICAgICAgICAgICAgIDwvcC1kcm9wZG93bj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1iLTNcIlxuICAgICAgICAgICAgICAqbmdJZj1cIm9yZ2FuaXphdGlvblNpemVzJCB8IGFzeW5jIGFzIHNpemVzXCI+XG4gICAgICAgICAgICAgIDxsYWJlbCBmb3I9XCJzaXplXCI+e3sgJ0NybS5BY2NvdW50TWVzc2FnZS5TaXplJyB8IHRyYW5zbG9jbyB9fTwvbGFiZWw+XG4gICAgICAgICAgICAgIDxwLWRyb3Bkb3duXG4gICAgICAgICAgICAgICAgW29wdGlvbnNdPVwic2l6ZXNbJ29yZ2FuaXphdGlvbl9zaXplcyddXCJcbiAgICAgICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJvcmdhbml6YXRpb25fc2l6ZV9pZFwiXG4gICAgICAgICAgICAgICAgW25nQ2xhc3NdPVwieyAnaXMtaW52YWxpZCc6IHN1Ym1pdHRlZCAmJiBmWydvcmdhbml6YXRpb25fc2l6ZV9pZCddLmVycm9ycyB9XCJcbiAgICAgICAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwiJ1NlbGVjdCBTaXplJ1wiXG4gICAgICAgICAgICAgICAgb3B0aW9uVmFsdWU9XCJpZFwiXG4gICAgICAgICAgICAgICAgb3B0aW9uTGFiZWw9XCJuYW1lXCI+XG4gICAgICAgICAgICAgIDwvcC1kcm9wZG93bj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1iLTNcIj5cbiAgICAgICAgICAgICAgPGxhYmVsIGZvcj1cInN0YXR1c1wiPnt7ICdDcm0uQWNjb3VudE1lc3NhZ2UuU3RhdHVzJyB8IHRyYW5zbG9jbyB9fTwvbGFiZWw+XG4gICAgICAgICAgICAgIDxwLWRyb3Bkb3duXG4gICAgICAgICAgICAgICAgW29wdGlvbnNdPVwic3RhdHVzXCJcbiAgICAgICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJzdGF0dXNcIlxuICAgICAgICAgICAgICAgIFtuZ0NsYXNzXT1cInsgJ2lzLWludmFsaWQnOiBzdWJtaXR0ZWQgJiYgZlsnc3RhdHVzJ10uZXJyb3JzIH1cIlxuICAgICAgICAgICAgICAgIFtwbGFjZWhvbGRlcl09XCInU2VsZWN0IFN0YXR1cydcIj5cbiAgICAgICAgICAgICAgPC9wLWRyb3Bkb3duPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWItM1wiPlxuICAgICAgICAgICAgICA8bGFiZWwgZm9yPVwicHJpb3JpdHlcIj57eyAnQ3JtLkFjY291bnRNZXNzYWdlLlByaW9yaXR5JyB8IHRyYW5zbG9jbyB9fTwvbGFiZWw+XG4gICAgICAgICAgICAgIDxwLWRyb3Bkb3duXG4gICAgICAgICAgICAgICAgW29wdGlvbnNdPVwicHJpb3JpdHlcIlxuICAgICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cInByaW9yaXR5XCJcbiAgICAgICAgICAgICAgICBbbmdDbGFzc109XCJ7ICdpcy1pbnZhbGlkJzogc3VibWl0dGVkICYmIGZbJ3ByaW9yaXR5J10uZXJyb3JzIH1cIlxuICAgICAgICAgICAgICAgIFtwbGFjZWhvbGRlcl09XCInU2VsZWN0IFByaW9yaXR5J1wiPlxuICAgICAgICAgICAgICA8L3AtZHJvcGRvd24+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtYi0zXCI+XG4gICAgICAgICAgICAgIDxsYWJlbCBmb3I9XCJtZXNzYWdlXCI+e3sgJ0NybS5BY2NvdW50TWVzc2FnZS5Tb3VyY2UnIHwgdHJhbnNsb2NvIH19PC9sYWJlbD5cbiAgICAgICAgICAgICAgPHAtZHJvcGRvd25cbiAgICAgICAgICAgICAgICBbb3B0aW9uc109XCJzb3VyY2VcIlxuICAgICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cImNybV9zb3VyY2VfaWRcIlxuICAgICAgICAgICAgICAgIFtuZ0NsYXNzXT1cInsgJ2lzLWludmFsaWQnOiBzdWJtaXR0ZWQgJiYgZlsnY3JtX3NvdXJjZV9pZCddLmVycm9ycyB9XCJcbiAgICAgICAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwiJ1NlbGVjdCBTb3VyY2UnXCJcbiAgICAgICAgICAgICAgICBvcHRpb25WYWx1ZT1cImlkXCJcbiAgICAgICAgICAgICAgICBvcHRpb25MYWJlbD1cIm5hbWVcIj5cbiAgICAgICAgICAgICAgPC9wLWRyb3Bkb3duPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWItM1wiPlxuICAgICAgICAgICAgICA8cHctaW5wdXQtY29udGFpbmVyIFtsYWJlbF09XCInQ3JtLkFjY291bnRNZXNzYWdlLkRlc2NyaXB0aW9uJyB8IHRyYW5zbG9jb1wiXG4gICAgICAgICAgICAgICAgbmFtZT1cImRlc2NyaXB0aW9uXCI+XG4gICAgICAgICAgICAgICAgPHRleHRhcmVhIHJvd3M9XCI1XCJcbiAgICAgICAgICAgICAgICAgIHR5cGU9XCJ0ZXh0XCJcbiAgICAgICAgICAgICAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sXCJcbiAgICAgICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cImRlc2NyaXB0aW9uXCJcbiAgICAgICAgICAgICAgICAgIGlkPVwiZGVzY3JpcHRpb25cIlxuICAgICAgICAgICAgICAgICAgW25nQ2xhc3NdPVwieyAnaXMtaW52YWxpZCc6IHN1Ym1pdHRlZCAmJiBmWydkZXNjcmlwdGlvbiddLmVycm9ycyB9XCI+PC90ZXh0YXJlYT5cbiAgICAgICAgICAgICAgPC9wdy1pbnB1dC1jb250YWluZXI+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDxkaXYgKm5nSWY9XCIhaXNGb3JtRWRpdFwiXG4gICAgICAgICAgICAgIGNsYXNzPVwidGV4dC1lbmQgZm9ybS1hY3Rpb24tYnV0dG9uc1wiPlxuICAgICAgICAgICAgICA8aW5wdXQgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJidG4gYnRuLW91dGxpbmUtcHJpbWFyeVwiXG4gICAgICAgICAgICAgICAgKGNsaWNrKT1cImlzRm9ybUVkaXQgPSAhaXNGb3JtRWRpdDsgZ2V0QWNjb3VudERldGFpbHMoKVwiXG4gICAgICAgICAgICAgICAgdmFsdWU9XCJDYW5jZWxcIiAvPlxuICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT1cInN1Ym1pdFwiXG4gICAgICAgICAgICAgICAgW2J1dHRvbkJ1c3ldPVwiYnV0dG9uQnVzeVwiXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJidG4gYnRuLXByaW1hcnkgbXMtM1wiXG4gICAgICAgICAgICAgICAgKGNsaWNrKT1cInVwZGF0ZUFjY291bnRJbmZvKClcIj5cbiAgICAgICAgICAgICAgICB7eyAnQnV0dG9uLlN1Ym1pdCcgfCB0cmFuc2xvY28gfX1cbiAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L2Zvcm0+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwiY29sLTEyIGNvbC1tZC04XCI+XG4gICAgICAgIDx1bCBuZ2JOYXZcbiAgICAgICAgICAjbmF2PVwibmdiTmF2XCJcbiAgICAgICAgICBjbGFzcz1cIm5hdi10YWJzXCI+XG4gICAgICAgICAgPGxpIFtuZ2JOYXZJdGVtXT1cIjFcIj5cbiAgICAgICAgICAgIDxhIG5nYk5hdkxpbms+Tm90ZXM8L2E+XG4gICAgICAgICAgICA8bmctdGVtcGxhdGUgbmdiTmF2Q29udGVudD5cbiAgICAgICAgICAgICAgPGZvcm0gW2Zvcm1Hcm91cF09XCJhY3Rpb25Db250cm9sc1wiXG4gICAgICAgICAgICAgICAgKG5nU3VibWl0KT1cIm9uU2F2ZSgpXCI+XG4gICAgICAgICAgICAgICAgPHRleHRhcmVhIGNsYXNzPVwiZm9ybS1jb250cm9sXCJcbiAgICAgICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cImNvbW1lbnRcIlxuICAgICAgICAgICAgICAgICAgcm93cz1cIjZcIj48L3RleHRhcmVhPlxuICAgICAgICAgICAgICAgIDxwIGNsYXNzPVwidGV4dC1kYW5nZXJcIlxuICAgICAgICAgICAgICAgICAgKm5nSWY9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFjdGlvbkNvbnRyb2xzLmdldCgnY29tbWVudCcpLnRvdWNoZWQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFjdGlvbkNvbnRyb2xzLmdldCgnY29tbWVudCcpLmludmFsaWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCI+XG4gICAgICAgICAgICAgICAgICBOb3RlIFJlcXVpcmVkXG4gICAgICAgICAgICAgICAgPC9wPlxuICAgICAgICAgICAgICAgIDxkaXYgKm5nSWY9XCJhY3Rpb25zPy5sZW5ndGhcIlxuICAgICAgICAgICAgICAgICAgY2xhc3M9XCJkLWJsb2NrIGNsZWFyLWJvdGggcHQtM1wiPlxuICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdGb3I9XCJsZXQgYWN0aW9uIG9mIGFjdGlvbnM7IGluZGV4IGFzIGlcIj5cbiAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiAqbmdJZj1cImFjdGlvbi52aXNpYmxlXCJcbiAgICAgICAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgICAgICAgICAgICBbY2xhc3MuYWN0aXZlXT1cIlwiXG4gICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJidG4gYnRuLXNtIG1lLTIgYnRuLW91dGxpbmUtcHJpbWFyeSBtYi0yIGFjdGlvbi1idG5cIlxuICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJzaG93RGF0ZVBpY2tlcigkZXZlbnQsIGFjdGlvbi5pZCk7IGQudG9nZ2xlKClcIj5cbiAgICAgICAgICAgICAgICAgICAgICB7eyBhY3Rpb24ubmFtZSB9fVxuICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInRleHQtZGFuZ2VyXCJcbiAgICAgICAgICAgICAgICAgICAgKm5nSWY9XCJzdWJtaXRBY3Rpb24gJiYgYWN0aW9uQ29udHJvbHMuZ2V0KCdjcm1fYWN0aW9uX2lkJykuaW52YWxpZFwiPlxuICAgICAgICAgICAgICAgICAgICBQbGVhc2Ugc2VsZWN0IGFuIGFjdGlvblxuICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwicm93IG10LTNcIj5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNvbC0xMiBjb2wtc20tNFwiPlxuICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1ncm91cFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IGNsYXNzPVwiZm9ybS1jb250cm9sXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJkZC1tbW0teXl5eVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cIndoZW5cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICBuZ2JEYXRlcGlja2VyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICNkPVwibmdiRGF0ZXBpY2tlclwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJkLnRvZ2dsZSgpXCIgLz5cbiAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ1aS1mbHVpZCBza2lsbHMtbW9kYWwgY29sLXNtLTQgcHMtMFwiPlxuICAgICAgICAgICAgICAgICAgICAgIDxwLWF1dG9Db21wbGV0ZSBbc3VnZ2VzdGlvbnNdPVwiZmlsdGVyZWRDb250YWN0XCJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cImNybV9jb250YWN0X2lkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGFLZXk9XCJpZFwiXG4gICAgICAgICAgICAgICAgICAgICAgICBmaWVsZD1cImRpc3BsYXlOYW1lXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtkcm9wZG93bl09XCJ0cnVlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIChjb21wbGV0ZU1ldGhvZCk9XCJzZWFyY2hDb250YWN0KCRldmVudClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgKG9uU2VsZWN0KT1cInNlbGVjdENvbnRhY3QoJGV2ZW50KVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAob25CbHVyKT1cIk9uQ29udGFjdEJsdXIoKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICBzdHlsZUNsYXNzPVwidy0xMDBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJTZWFyY2ggY29udGFjdFwiXG4gICAgICAgICAgICAgICAgICAgICAgICBbbXVsdGlwbGVdPVwiZmFsc2VcIlxuICAgICAgICAgICAgICAgICAgICAgICAgKG9uRHJvcGRvd25DbGljayk9XCJvbkRyb3Bkb3duQ2xpY2soKVwiPlxuICAgICAgICAgICAgICAgICAgICAgIDwvcC1hdXRvQ29tcGxldGU+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLXNtLTQgcGUtMCBjb21wbGV0ZWQtdG9nZ2xlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1iLTNcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDx1aS1zd2l0Y2ggY2hlY2tlZExhYmVsPVwiY29tcGxldGVkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgdW5jaGVja2VkTGFiZWw9XCJvcGVuXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwiY29tcGxldGVkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZT1cImNvbXBsZXRlZFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPC91aS1zd2l0Y2g+XG4gICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZsb2F0LWVuZFwiPlxuICAgICAgICAgICAgICAgICAgPGEgY2xhc3M9XCJidG4gYnRuLW91dGxpbmUtcHJpbWFyeSBtZS0wIG1lLXNtLTJcIlxuICAgICAgICAgICAgICAgICAgICAoa2V5ZG93bi5lbnRlcik9XCJvcGVuTW9kYWwoY29udGVudClcIlxuICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwib3Blbk1vZGFsKGNvbnRlbnQpXCI+e3sgJ1VwbG9hZCBmaWxlJyB8IHRyYW5zbG9jbyB9fTwvYT5cbiAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT1cInN1Ym1pdFwiXG4gICAgICAgICAgICAgICAgICAgIFtidXR0b25CdXN5XT1cImJ1dHRvbkJ1c3lcIlxuICAgICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiYnV0dG9uRGlzYWJsZVwiXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1wcmltYXJ5IG10LTIgbWItMlwiPlN1Ym1pdCBOb3RlPC9idXR0b24+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPGRpdiAqbmdJZj1cImJ1dHRvbkRpc2FibGVcIlxuICAgICAgICAgICAgICAgICAgY2xhc3M9XCJuby1hY3Rpb25zIHB0LTRcIj5cbiAgICAgICAgICAgICAgICAgIDxwdy1uby1kYXRhIFt3aXRoSW1hZ2VdPVwidHJ1ZVwiIFttZXNzYWdlXT1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdDcm0uQWNjb3VudE1lc3NhZ2UuTm9BY3Rpb25zSW5BY2NvdW50SW5mb01lc3NhZ2UnIHwgdHJhbnNsb2NvXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIj5cbiAgICAgICAgICAgICAgICAgIDwvcHctbm8tZGF0YT5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgPC9mb3JtPlxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwidy0xMDAgdGV4dC1jZW50ZXIgbXQtM1wiXG4gICAgICAgICAgICAgICAgKm5nSWY9XCIhaXNMb2FkZWRcIj5cbiAgICAgICAgICAgICAgICA8cC1wcm9ncmVzc1NwaW5uZXIgc3Ryb2tlV2lkdGg9XCIyXCI+IDwvcC1wcm9ncmVzc1NwaW5uZXI+XG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICA8ZGl2ICpuZ0lmPVwiIWFjY291bnRDb21tZW50cz8ubGVuZ3RoICYmIGlzTG9hZGVkXCJcbiAgICAgICAgICAgICAgICBjbGFzcz1cIm5vLWFjdGlvbnMgcHQtMlwiPlxuICAgICAgICAgICAgICAgIDxwdy1uby1kYXRhIFt3aXRoSW1hZ2VdPVwidHJ1ZVwiIFttZXNzYWdlXT1cIidDcm0uQWNjb3VudE1lc3NhZ2UuTm9BY3Rpb25zTWVzc2FnZScgfCB0cmFuc2xvY29cIj5cbiAgICAgICAgICAgICAgICA8L3B3LW5vLWRhdGE+XG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICA8ZGl2ICpuZ0lmPVwiYWNjb3VudENvbW1lbnRzPy5sZW5ndGhcIj5cbiAgICAgICAgICAgICAgICA8ZGl2IGlkPVwidGltZWxpbmVcIlxuICAgICAgICAgICAgICAgICAgY2xhc3M9XCJwdC0zIGNsZWFyLWJvdGggdGltZWxpbmUtY2VudGVyIHRpbWVsaW5lLXdyYXBwZXIgdGltZWxpbmUtY29udGFpbmVyXCJcbiAgICAgICAgICAgICAgICAgIGluZmluaXRlU2Nyb2xsXG4gICAgICAgICAgICAgICAgICBbaW5maW5pdGVTY3JvbGxEaXN0YW5jZV09XCIyXCJcbiAgICAgICAgICAgICAgICAgIFtpbmZpbml0ZVNjcm9sbFRocm90dGxlXT1cIjUwXCJcbiAgICAgICAgICAgICAgICAgIFtpbmZpbml0ZVNjcm9sbENvbnRhaW5lcl09XCJzZWxlY3RvclwiXG4gICAgICAgICAgICAgICAgICBbZnJvbVJvb3RdPVwidHJ1ZVwiXG4gICAgICAgICAgICAgICAgICAoc2Nyb2xsZWQpPVwib25TY3JvbGxUaW1lbGluZSgpXCI+XG4gICAgICAgICAgICAgICAgICA8dWwgY2xhc3M9XCJ0aW1lbGluZVwiPlxuICAgICAgICAgICAgICAgICAgICA8bGkgY2xhc3M9XCJ0aW1lbGluZS1saW5lXCI+PC9saT5cbiAgICAgICAgICAgICAgICAgIDwvdWw+XG4gICAgICAgICAgICAgICAgICA8dWwgY2xhc3M9XCJ0aW1lbGluZVwiPlxuICAgICAgICAgICAgICAgICAgICA8bGkgY2xhc3M9XCJ0aW1lbGluZS1saW5lXCI+PC9saT5cbiAgICAgICAgICAgICAgICAgICAgPGxpIGNsYXNzPVwidGltZWxpbmUtaXRlbVwiXG4gICAgICAgICAgICAgICAgICAgICAgW25nQ2xhc3NdPVwieyAnbXQtNSc6IG9kZCB8fCBsYXN0IH1cIlxuICAgICAgICAgICAgICAgICAgICAgICpuZ0Zvcj1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgaXRlbSBvZiBhY2NvdW50Q29tbWVudHM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4IGFzIGk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBvZGQgPSBvZGQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBldmVuID0gZXZlbjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGxhc3QgPSBsYXN0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgZmlyc3QgPSBmaXJzdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiPlxuICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0aW1lbGluZS1iYWRnZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJiZy1yZWQgYmctbGlnaHRlbi0xXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidGltZWxpbmUteWVhclwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZC1ibG9jayBkYXRlLXllYXJcIj57e1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtLndoZW4gfCBkYXRlOiAnbWVkaXVtJyB8IHNsaWNlOiAwOjNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3Bhbj57eyBpdGVtLnllYXIgfX08L3NwYW4+PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0aW1lbGluZS1jYXJkIHNoYWRvdyBjYXJkIHBiLTAgcm91bmRlZCBib3JkZXItZ3JleSBib3JkZXItbGlnaHRlbi0yIHBvc2l0aW9uLXN0YXRpY1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNhcmQtaGVhZGVyIHB5LTRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1iLTAgY2xlYXJmaXhcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dGV4dGFyZWEgdHlwZT1cInRleHRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZT1cImNvbW1lbnRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJjb21tZW50LWZpZWxkIGZvcm0tY29udHJvbCBwLTBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJpdGVtLmNvbW1lbnRcIj57eyBpdGVtLmNvbW1lbnQgfX08L3RleHRhcmVhPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJhdXRvLWNvbXBsZXRlIG1iLTMgdWktZmx1aWQgc2tpbGxzLW1vZGFsXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cC1hdXRvQ29tcGxldGUgWyhuZ01vZGVsKV09XCJpdGVtLmNybV9jb250YWN0XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3N1Z2dlc3Rpb25zXT1cImZpbHRlcmVkQ29udGFjdENvbW1lbnRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhS2V5PVwiaWRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWVsZD1cImZpcnN0X25hbWVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkcm9wZG93bj1cIiB0cnVlIFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjb21wbGV0ZU1ldGhvZCk9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWFyY2hDb250YWN0SW5Db21tZW50KCRldmVudClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChvblNlbGVjdCk9XCJzZWxlY3RDb21tZW50Q29udGFjdCgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKG9uQmx1cik9XCJPbkNvbnRhY3RCbHVyKClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHlsZUNsYXNzPVwiIHctMTAwIFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwiIFNlYXJjaCBjb250YWN0IFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFttdWx0aXBsZV09XCJmYWxzZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChvbkRyb3Bkb3duQ2xpY2spPVwib25Ecm9wZG93bkNsaWNrKClcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvcC1hdXRvQ29tcGxldGU+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPHAgY2xhc3M9XCJmbG9hdC1zdGFydCBtYi0wXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpuZ0lmPVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAhc2hvd0Z1bGxDb21tZW50IHx8IGl0ZW0uaWQgIT09IGNvbW1lbnRJZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7IGl0ZW0uY29tbWVudCB8IHNsaWNlOiAwOjE3MFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9fTxhICpuZ0lmPVwiaXRlbS5jb21tZW50Lmxlbmd0aCA+IDE3MFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwidGV4dC1zZWNvbmRhcnlcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hvd0Z1bGxDb21tZW50ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21tZW50SWQgPSBpdGVtLmlkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIj4uLi5zaG93IG1vcmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvYT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L3A+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPHAgY2xhc3M9XCJmbG9hdC1zdGFydCBtYi0wXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpuZ0lmPVwic2hvd0Z1bGxDb21tZW50ICYmIGl0ZW0uaWQgPT09IGNvbW1lbnRJZFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge3sgaXRlbS5jb21tZW50IH19XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YSAqbmdJZj1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW0uY29tbWVudC5sZW5ndGggPiAxNzAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaG93RnVsbENvbW1lbnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJzaG93RnVsbENvbW1lbnQgPSBmYWxzZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwidGV4dC1zZWNvbmRhcnlcIj4uLi5zaG93IGxlc3M8L2E+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9wPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJidG4gYnRuLW1kIGVkaXQtYnRuIGZsb2F0LWVuZCBweS0wXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJzaG93RWRpdENvbnRyb2xzKCRldmVudCwgaXRlbSlcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKm5nSWY9XCJ1c2VySWQgPT09IGl0ZW0ub3duZXJfaWQgfHwgaGFzQWNjZXNzXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJmYSBmYS1lZGl0IGVkaXQtaWNvblwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcmlhLWhpZGRlbj1cInRydWVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA+PC9pPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNhcmQtc3VidGl0bGUgdGV4dC1tdXRlZCBteS0wIGNsZWFyZml4XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZsb2F0LXN0YXJ0XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiAqbmdJZj1cIiF1cGRhdGluZyB8fCBhY3Rpb25JZCAhPT0gaXRlbS5pZFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiZm9udC1zbWFsbC0zXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7IGl0ZW0ud2hlbiB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCAqbmdJZj1cInVwZGF0aW5nICYmIGFjdGlvbklkID09PSBpdGVtLmlkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJkZC1tbW0teXl5eVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlPVwie3sgaXRlbS53aGVuIH19XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmdiRGF0ZXBpY2tlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjZD1cIm5nYkRhdGVwaWNrZXJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZm9jdXMpPVwiZC50b2dnbGUoKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChkYXRlU2VsZWN0KT1cIm9uRGF0ZVNlbGVjdCgkZXZlbnQsIGl0ZW0pXCIgLz5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9XCIgYnV0dG9uXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1zbSBmbG9hdC1lbmQgd2hlbi1idG4gcHktMFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqbmdJZj1cInVzZXJJZCA9PT0gaXRlbS5vd25lcl9pZCB8fCBoYXNBY2Nlc3NcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cInNob3dEYXRlUGlja2VyVXBkYXRlKGl0ZW0uaWQpXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJmYSBmYS1lZGl0IGVkaXQtaWNvblwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcmlhLWhpZGRlbj1cInRydWVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA+PC9pPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPHAgW2NsYXNzLnRleHQtZGFuZ2VyXT1cIiFpdGVtLmNvbG9yXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAqbmdJZj1cIiFpdGVtLmNhbmNlbGxlZCAmJiAhaXRlbS5jb21wbGV0ZWRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwibWItMFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7IGl0ZW0uZHVlIH19XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDwvcD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPGEgY2xhc3M9XCJ0ZXh0LXNlY29uZGFyeSBhY3Rpb24tb3duZXJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICpuZ0lmPVwiaXRlbS5jcm1fY29udGFjdFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW3JvdXRlckxpbmtdPVwiW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLycgKyBzdWJzY3JpcHRpb24/LnNsdWcgKyByb3V0ZXJzLmNvbnRhY3RJbmZvLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtLmNybV9jb250YWN0LmlkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXVwiPnt7IGl0ZW0uY3JtX2NvbnRhY3QuZmlyc3RfbmFtZSB9fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7IGl0ZW0uY3JtX2NvbnRhY3QubGFzdF9uYW1lIHx8ICcnIH19PC9hPlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8cD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBCeVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW0ub3duZXIuZmlyc3RfbmFtZSArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnICcgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbS5vd25lci5sYXN0X25hbWVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9fVxuICAgICAgICAgICAgICAgICAgICAgICAgICA8L3A+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiYmFkZ2UgYmctcHJpbWFyeVwiPnt7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbT8uY3JtX2FjdGlvbj8ubmFtZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfX08L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuICpuZ0lmPVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICFpdGVtLmNvbXBsZXRlZCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAodXNlcklkID09PSBpdGVtLm93bmVyX2lkIHx8IGhhc0FjY2VzcylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiYmFkZ2UgYmctc3VjY2VzcyBtcy0yXCI+T3Blbjwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPGEgKm5nSWY9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIWl0ZW0uY29tcGxldGVkICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh1c2VySWQgPT09IGl0ZW0ub3duZXJfaWQgfHwgaGFzQWNjZXNzKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmdiVG9vbHRpcD1cIlNldCBhcyBjb21wbGV0ZWRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyaWEtbGFiZWw9XCJTZXQgYXMgY29tcGxldGVkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cIm1lLTMgbXMtM1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaHJlZj1cImphdmFzY3JpcHQ6dm9pZCgwKTtcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0QXNDb21wbGV0ZWRPclVuY29tcGxldGVkKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbS5pZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtLmNvbXBsZXRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJmYSBmYS10YXNrcyBjb21wbGV0ZWRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcmlhLWhpZGRlbj1cInRydWVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID48L2k+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDwvYT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPGEgKm5nSWY9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIWl0ZW0uY2FuY2VsbGVkICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICFpdGVtLmNvbXBsZXRlZCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAodXNlcklkID09PSBpdGVtLm93bmVyX2lkIHx8IGhhc0FjY2VzcylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5nYlRvb2x0aXA9XCJTZXQgYXMgY2FuY2VsbGVkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcmlhLWxhYmVsPVwiU2V0IGFzIGNhbmNlbGxlZFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaHJlZj1cImphdmFzY3JpcHQ6dm9pZCgwKTtcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJzZXRBc0NhbmNlbGxlZChpdGVtLmlkLCBpdGVtKVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiZmEgZmEtdGltZXMgZGVsZXRlLWljb25cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcmlhLWhpZGRlbj1cInRydWVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID48L2k+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDwvYT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPGEgKm5nSWY9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbS5jb21wbGV0ZWQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHVzZXJJZCA9PT0gaXRlbS5vd25lcl9pZCB8fCBoYXNBY2Nlc3MpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZ2JUb29sdGlwPVwiU2V0IGFzIFVuQ29tcGxldGVkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcmlhLWxhYmVsPVwiU2V0IGFzIFVuQ29tcGxldGVkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBocmVmPVwiamF2YXNjcmlwdDp2b2lkKDApO1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXRBc0NvbXBsZXRlZE9yVW5jb21wbGV0ZWQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtLmlkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW0uY29tcGxldGVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwibXMtMlwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiZmFyIGZhLXdpbmRvdy1jbG9zZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyaWEtaGlkZGVuPVwidHJ1ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPjwvaT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9hPlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY29udHJvbC1idG5zIG10LTMgdGV4dC1lbmQgZm9ybS1hY3Rpb24tYnV0dG9uc1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImJ0biBidG4tc20gYnRuLW91dGxpbmUtZGVmYXVsdCBtZS0yXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJzaG93RWRpdENvbnRyb2xzKHVuZGVmaW5lZCwgJycpXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7eyAnQnV0dG9uLkNhbmNlbCcgfCB0cmFuc2xvY28gfX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwiYnRuIGJ0bi1zbSBidG4tcHJpbWFyeVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJ1cGRhdGVDb21tZW50KGl0ZW0pXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7eyAnQnV0dG9uLlN1Ym1pdCcgfCB0cmFuc2xvY28gfX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPC9saT5cbiAgICAgICAgICAgICAgICAgIDwvdWw+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICA8L2xpPlxuICAgICAgICAgIDxsaSBbbmdiTmF2SXRlbV09XCIyXCIgKm5nSWY9XCJoYXNBY2Nlc3MgfHwgdXNlcklkID09PSBkYXRhPy5vd25lcj8uaWRcIj5cbiAgICAgICAgICAgIDxhIG5nYk5hdkxpbms+Q29udGFjdHM8L2E+XG4gICAgICAgICAgICA8bmctdGVtcGxhdGUgbmdiTmF2Q29udGVudD5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInJvd1wiPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtMTIgbWItM1wiPlxuICAgICAgICAgICAgICAgICAgPGEgY2xhc3M9XCJidG4gYnRuLXNtIGJ0bi1vdXRsaW5lLXByaW1hcnkgZmxvYXQtZW5kXCJcbiAgICAgICAgICAgICAgICAgICAgZGF0YS1jeT1cImFkZC1jb250YWN0XCJcbiAgICAgICAgICAgICAgICAgICAgW3JvdXRlckxpbmtdPVwiW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcvJyArIHN1YnNjcmlwdGlvbj8uc2x1ZyArIHJvdXRlcnMuY29udGFjdEFkZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhY2NvdW50SWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF1cIj5cbiAgICAgICAgICAgICAgICAgICAgPGkgY2xhc3M9XCJmYSBmYS1wbHVzLWNpcmNsZVwiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICAgICAgICAgICAgICAgICAge3sgJ0NybS5Db250YWN0TWVzc2FnZS5BZGRDb250YWN0JyB8IHRyYW5zbG9jbyB9fVxuICAgICAgICAgICAgICAgICAgPC9hPlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInByaW1lbmctZGF0YXRhYmxlLWNvbnRhaW5lciB0YWJsZS1yZXNwb25zaXZlXCJcbiAgICAgICAgICAgICAgICBbY2xhc3MuaGlkZVRhYmxlXT1cInRvdGFsUmVjb3Jkc1VuRmlsdGVyZWQgPT09IDBcIj5cbiAgICAgICAgICAgICAgICA8cC10YWJsZSBjbGFzcz1cInRhYmxlXCJcbiAgICAgICAgICAgICAgICAgICNkdFxuICAgICAgICAgICAgICAgICAgW3ZhbHVlXT1cImNvbnRhY3RzXCJcbiAgICAgICAgICAgICAgICAgIFtwYWdpbmF0b3JdPVwidG90YWxSZWNvcmRzICE9PSAwXCJcbiAgICAgICAgICAgICAgICAgIFtyb3dzXT1cIlBBR0VfU0laRVwiXG4gICAgICAgICAgICAgICAgICBbdG90YWxSZWNvcmRzXT1cInRvdGFsUmVjb3Jkc1wiXG4gICAgICAgICAgICAgICAgICBbbG9hZGluZ109XCJsb2FkaW5nXCJcbiAgICAgICAgICAgICAgICAgIFtsYXp5XT1cInRydWVcIlxuICAgICAgICAgICAgICAgICAgKG9uTGF6eUxvYWQpPVwib25MYXp5TG9hZCgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgICAgIFtjdXN0b21Tb3J0XT1cInRydWVcIj5cbiAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBwVGVtcGxhdGU9XCJjYXB0aW9uXCI+XG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0ZXh0LWVuZFwiPlxuICAgICAgICAgICAgICAgICAgICAgIDxpIGNsYXNzPVwiZmEgZmEtc2VhcmNoIG10LTIgbWUtMlwiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgdHlwZT1cInRleHRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJzZWFyY2hUZXh0XCJcbiAgICAgICAgICAgICAgICAgICAgICAgIHBJbnB1dFRleHRcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpemU9XCI1MFwiXG4gICAgICAgICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cIlNlYXJjaCBjb250YWN0Li4uXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIChpbnB1dCk9XCJkdC5maWx0ZXJHbG9iYWwoJGV2ZW50LnRhcmdldC52YWx1ZSwgJ2NvbnRhaW5zJylcIlxuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJtdy05MFwiIC8+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBwVGVtcGxhdGU9XCJoZWFkZXJcIj5cbiAgICAgICAgICAgICAgICAgICAgPHRyPlxuICAgICAgICAgICAgICAgICAgICAgIDx0aCBzY29wZT1cInRydWVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgcFNvcnRhYmxlQ29sdW1uPVwiZmlyc3RfbmFtZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAge3sgJ0xhYmVsLk5hbWUnIHwgdHJhbnNsb2NvIH19XG4gICAgICAgICAgICAgICAgICAgICAgICA8cC1zb3J0SWNvbiBmaWVsZD1cImZpcnN0X25hbWVcIj48L3Atc29ydEljb24+XG4gICAgICAgICAgICAgICAgICAgICAgPC90aD5cbiAgICAgICAgICAgICAgICAgICAgICA8dGggc2NvcGU9XCJ0cnVlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIHBTb3J0YWJsZUNvbHVtbj1cIm93bmVyX2lkXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICB7eyAnQ3JtLkNvbnRhY3RNZXNzYWdlLkNvbnRhY3RPd25lcicgfCB0cmFuc2xvY28gfX1cbiAgICAgICAgICAgICAgICAgICAgICAgIDxwLXNvcnRJY29uIGZpZWxkPVwib3duZXJfaWRcIj48L3Atc29ydEljb24+XG4gICAgICAgICAgICAgICAgICAgICAgPC90aD5cbiAgICAgICAgICAgICAgICAgICAgICA8dGggc2NvcGU9XCJ0cnVlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIHBTb3J0YWJsZUNvbHVtbj1cImhlYWRsaW5lXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICB7eyAnQ3JtLkNvbnRhY3RNZXNzYWdlLkhlYWRsaW5lJyB8IHRyYW5zbG9jbyB9fVxuICAgICAgICAgICAgICAgICAgICAgICAgPHAtc29ydEljb24gZmllbGQ9XCJoZWFkbGluZVwiPjwvcC1zb3J0SWNvbj5cbiAgICAgICAgICAgICAgICAgICAgICA8L3RoPlxuICAgICAgICAgICAgICAgICAgICAgIDx0aCBzY29wZT1cInRydWVcIj57eyAnTGFiZWwuQWN0aW9ucycgfCB0cmFuc2xvY28gfX08L3RoPlxuICAgICAgICAgICAgICAgICAgICA8L3RyPlxuICAgICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBwVGVtcGxhdGU9XCJib2R5XCJcbiAgICAgICAgICAgICAgICAgICAgbGV0LWNvbnRhY3Q+XG4gICAgICAgICAgICAgICAgICAgIDx0cj5cbiAgICAgICAgICAgICAgICAgICAgICA8dGQgZGF0YS1oZWFkPVwiTmFtZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImNvbnRhY3RuYW1lXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8YSBbcm91dGVyTGlua109XCJbXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJy8nICsgc3Vic2NyaXB0aW9uPy5zbHVnICsgcm91dGVycy5jb250YWN0SW5mbyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250YWN0LmlkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBdXCI+IHt7IChjb250YWN0LmZpcnN0X25hbWUgfHwgJycpICsgJyAnICsgKGNvbnRhY3QubGFzdF9uYW1lIHx8ICcnKSB8IHRleHRUcnVuY2F0ZTogMjAgfX08L2E+XG4gICAgICAgICAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgICAgICAgICAgICA8dGQgZGF0YS1oZWFkPVwiT3duZXJOYW1lXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICB7eyBjb250YWN0Lm93bmVyIHwgaWZOYW1lTnVsbFNob3dFbWFpbCB9fVxuICAgICAgICAgICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICAgICAgICAgICAgPHRkIGRhdGEtaGVhZD1cIkhlYWRsaW5lXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiaGVhZGxpbmUtY29udGVudFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAge3sgY29udGFjdD8uaGVhZGxpbmUgfCB0ZXh0VHJ1bmNhdGU6IDIwIH19XG4gICAgICAgICAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgICAgICAgICAgICA8dGQgZGF0YS1oZWFkPVwiQWN0aW9uXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8dWwgY2xhc3M9XCJsaXN0LXVuc3R5bGVkIGxpc3QtaW5saW5lIGxpc3QtYWN0aW9uXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxsaSBuZ2JUb29sdGlwPVwiU2hvd1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJtZS0yIG1lLXNtLTNcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtyb3V0ZXJMaW5rXT1cIltcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJy8nICsgc3Vic2NyaXB0aW9uPy5zbHVnICsgcm91dGVycy5jb250YWN0SW5mbyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGFjdC5pZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF1cIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImZhIGZhLWV5ZSBzZWUtaWNvblwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyaWEtaGlkZGVuPVwidHJ1ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPjwvaT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9saT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPGxpICpuZ0lmPVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc0FjY2VzcyB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250YWN0Lm93bmVyX2lkID09PSB1c2VySWQgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGFjdC5jcm1fYWNjb3VudC5vd25lcl9pZCA9PT0gdXNlcklkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZ2JUb29sdGlwPVwiQWRkIG9wcG9ydHVuaXR5XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cIm1lLTIgbWUtc20tM1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW3JvdXRlckxpbmtdPVwiW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLycgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3Vic2NyaXB0aW9uPy5zbHVnICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvdXRlcnMub3Bwb3J0dW5pdHlBZGRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBdXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbcXVlcnlQYXJhbXNdPVwieyBjb250YWN0X2lkOiBjb250YWN0LmlkIH1cIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImZhIGZhLXBsdXMtY2lyY2xlIGFkZC1pY29uXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJpYS1oaWRkZW49XCJ0cnVlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA+PC9pPlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8L2xpPlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8bGkgKm5nSWY9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzQWNjZXNzIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRhY3Qub3duZXJfaWQgPT09IHVzZXJJZCB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250YWN0LmNybV9hY2NvdW50Lm93bmVyX2lkID09PSB1c2VySWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5nYlRvb2x0aXA9XCJFZGl0XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cIm1lLTIgbWUtc20tM1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW3JvdXRlckxpbmtdPVwiW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLycgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3Vic2NyaXB0aW9uPy5zbHVnICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvdXRlcnMuY29udGFjdERldGFpbHMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRhY3QuaWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBdXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJmYSBmYS1lZGl0IGVkaXQtaWNvblwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyaWEtaGlkZGVuPVwidHJ1ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPjwvaT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9saT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPGxpICpuZ0lmPVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc0FjY2VzcyB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250YWN0Lm93bmVyX2lkID09PSB1c2VySWQgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGFjdC5jcm1fYWNjb3VudC5vd25lcl9pZCA9PT0gdXNlcklkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZ2JUb29sdGlwPVwiRGVsZXRlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cIm1lLTIgbWUtc20tM1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiZmEgZmEtdHJhc2ggZGVsZXRlLWljb25cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoa2V5ZG93bi5lbnRlcik9XCJvbkRlbGV0ZUNvbnRhY3QoY29udGFjdC5pZClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoa2V5ZG93bi5zcGFjZSk9XCJvbkRlbGV0ZUNvbnRhY3QoY29udGFjdC5pZClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwib25EZWxldGVDb250YWN0KGNvbnRhY3QuaWQpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJpYS1oaWRkZW49XCJ0cnVlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA+PC9pPlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8L2xpPlxuICAgICAgICAgICAgICAgICAgICAgICAgPC91bD5cbiAgICAgICAgICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICAgICAgICA8L3RyPlxuICAgICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICA8L3AtdGFibGU+XG4gICAgICAgICAgICAgICAgPGRpdiAqbmdJZj1cInRvdGFsUmVjb3JkcyA9PT0gMCAmJiB0b3RhbFJlY29yZHNVbkZpbHRlcmVkICE9PSAwXCI+XG4gICAgICAgICAgICAgICAgICA8cHctbm8tZGF0YSBbd2l0aEltYWdlXT1cInRydWVcIiBbbWVzc2FnZV09XCInU2VhcmNoLk5vRGF0YU1lc3NhZ2UnfCB0cmFuc2xvY29cIiBbZGVzY3JpcHRpb25dPVwiJ1NlYXJjaC5Ob0RhdGFEZXNjcmlwdGlvbicgfCB0cmFuc2xvY29cIiA+XG4gICAgICAgIDwvcHctbm8tZGF0YT5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInRvdGFsLXJlY29yZHMtY291bnRcIiAqbmdJZj1cInRvdGFsUmVjb3JkcyAhPT0gMFwiPnt7ICdMYWJlbC5Ub3RhbCcgfCB0cmFuc2xvY28gfX06IHt7IHRvdGFsUmVjb3JkcyB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgIDxkaXYgKm5nSWY9XCJ0b3RhbFJlY29yZHNVbkZpbHRlcmVkID09PSAwXCI+XG4gICAgICAgICAgICAgICAgPHB3LW5vLWRhdGEgW3dpdGhJbWFnZV09XCJ0cnVlXCIgW21lc3NhZ2VdPVwiJ0NybS5Db250YWN0TWVzc2FnZS5Db250YWN0c0FkbWluTWVzc2FnZScgfCB0cmFuc2xvY29cIj5cbiAgICAgICAgICAgICAgICA8L3B3LW5vLWRhdGE+XG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICA8L2xpPlxuICAgICAgICAgIDxsaSBbbmdiTmF2SXRlbV09XCIzXCIgKm5nSWY9XCJoYXNBY2Nlc3NcIj5cbiAgICAgICAgICAgIDxhIG5nYk5hdkxpbms+VmVyc2lvbmluZzwvYT5cbiAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBuZ2JOYXZDb250ZW50PlxuICAgICAgICAgICAgICA8ZGl2ICpuZ0Zvcj1cImxldCB2ZXJzaW9uaW5nIG9mIGFjY291bnRWZXJzaW9uaW5nXCI+XG4gICAgICAgICAgICAgICAgPHA+XG4gICAgICAgICAgICAgICAgICA8c3Ryb25nPkV2ZW50OiA8L3N0cm9uZz57eyB2ZXJzaW9uaW5nLmV2ZW50IH19IHxcbiAgICAgICAgICAgICAgICAgIDxzdHJvbmc+QXV0aG9yOiA8L3N0cm9uZz48YSAqbmdJZj1cInZlcnNpb25pbmc/LmF1dGhvclwiXG4gICAgICAgICAgICAgICAgICAgIFtyb3V0ZXJMaW5rXT1cIlsnL21lbWJlcnMnLCB2ZXJzaW9uaW5nPy5hdXRob3I/LnNsdWddXCI+e3sgdmVyc2lvbmluZz8uYXV0aG9yIHwgaWZOYW1lTnVsbFNob3dFbWFpbCB9fTwvYT5cbiAgICAgICAgICAgICAgICAgIHwgPHN0cm9uZz5DcmVhdGVkIGF0OiA8L3N0cm9uZz57eyB2ZXJzaW9uaW5nLmNyZWF0ZWRfYXQgfCBkYXRlRm9ybWF0OiAnZGF0ZXRpbWUnIH19PGJyIC8+XG4gICAgICAgICAgICAgICAgICA8c3Ryb25nPk9iamVjdDogPC9zdHJvbmc+e3sgdmVyc2lvbmluZy5vYmplY3QgfCBqc29uIH19XG4gICAgICAgICAgICAgICAgPC9wPlxuICAgICAgICAgICAgICAgIDxociAvPlxuICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgPGRpdiAqbmdJZj1cImFjY291bnRWZXJzaW9uaW5nPy5sZW5ndGggPT09IDBcIj5cbiAgICAgICAgICAgICAgICA8cHctbm8tZGF0YSBbd2l0aEltYWdlXT1cInRydWVcIiBbbWVzc2FnZV09XCInQ3JtLkFjY291bnRNZXNzYWdlLk5vVmVyc2lvbnNNZXNzYWdlJyB8IHRyYW5zbG9jb1wiPlxuICAgICAgICAgICAgICAgIDwvcHctbm8tZGF0YT5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgIDwvbGk+XG4gICAgICAgICAgPGxpIFtuZ2JOYXZJdGVtXT1cIjRcIj5cbiAgICAgICAgICAgIDxhIG5nYk5hdkxpbms+RmlsZXM8L2E+XG4gICAgICAgICAgICA8bmctdGVtcGxhdGUgbmdiTmF2Q29udGVudD5cbiAgICAgICAgICAgICAgPHB3LXNtYXJ0LWNybS1jb21wYW55LWZpbGVzIFthY2NvdW50SWRdPVwiYWNjb3VudElkXCI+PC9wdy1zbWFydC1jcm0tY29tcGFueS1maWxlcz5cbiAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgPC9saT5cbiAgICAgICAgICA8bGkgW25nYk5hdkl0ZW1dPVwiNVwiICpuZ0lmPVwiaGFzQWNjZXNzXCI+XG4gICAgICAgICAgICA8YSBuZ2JOYXZMaW5rPkludm9pY2VzPC9hPlxuICAgICAgICAgICAgPG5nLXRlbXBsYXRlIG5nYk5hdkNvbnRlbnQ+XG4gICAgICAgICAgICAgIDxwdy1zbWFydC1jcm0tYWNjb3VudC1pbnZvaWNlcyBbYWNjb3VudElkXT1cImFjY291bnRJZFwiLz5cbiAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgPC9saT5cbiAgICAgICAgPC91bD5cbiAgICAgICAgPGRpdiBbbmdiTmF2T3V0bGV0XT1cIm5hdlwiPjwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuPC9kaXY+XG48bmctdGVtcGxhdGUgI2NvbnRlbnRcbiAgbGV0LW1vZGFsPlxuICA8ZGl2IGNsYXNzPVwibW9kYWwtaGVhZGVyXCI+XG4gICAgPGgzIGNsYXNzPVwibW9kYWwtdGl0bGUgbWItMCBwLTBcIj57eyAnVXBsb2FkIEZpbGUnIHwgdHJhbnNsb2NvIH19PC9oMz5cbiAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIlxuICAgICAgY2xhc3M9XCJidG4tY2xvc2UgZmxvYXQtZW5kXCJcbiAgICAgIGFyaWEtbGFiZWw9XCJDbG9zZVwiXG4gICAgICAoY2xpY2spPVwibW9kYWwuZGlzbWlzcygpXCI+XG5cbiAgICA8L2J1dHRvbj5cbiAgPC9kaXY+XG4gIDxkaXYgY2xhc3M9XCJtb2RhbC1ib2R5XCI+XG4gICAgPHNtYWxsPiB7eyAnVXNlci5Qcm9maWxlLlBpY3R1cmVNZXNzYWdlJyB8IHRyYW5zbG9jbyB9fTwvc21hbGw+XG4gICAgPGRpdiBjbGFzcz1cInJvdyBwLTJcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJjb2wtMTJcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cInVwbG9hZC1ib3hcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwidXBsb2FkLWJveC1jb250ZW50XCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZHJvcC1jb250YWluZXJcIlxuICAgICAgICAgICAgICBuZ0ZpbGVEcm9wXG4gICAgICAgICAgICAgIFtvcHRpb25zXT1cIm9wdGlvbnNcIlxuICAgICAgICAgICAgICAodXBsb2FkT3V0cHV0KT1cIm9uVXBsb2FkT3V0cHV0KCRldmVudClcIlxuICAgICAgICAgICAgICBbdXBsb2FkSW5wdXRdPVwidXBsb2FkSW5wdXRcIj5cbiAgICAgICAgICAgICAgPHA+XG4gICAgICAgICAgICAgICAgRHJhZyBmaWxlcyBoZXJlIG9yXG4gICAgICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwidXBsb2FkLWJ1dHRvblwiPlxuICAgICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJmaWxlXCJcbiAgICAgICAgICAgICAgICAgICAgbmdGaWxlU2VsZWN0XG4gICAgICAgICAgICAgICAgICAgIFtvcHRpb25zXT1cIm9wdGlvbnNcIlxuICAgICAgICAgICAgICAgICAgICAodXBsb2FkT3V0cHV0KT1cIm9uVXBsb2FkT3V0cHV0KCRldmVudClcIlxuICAgICAgICAgICAgICAgICAgICBbdXBsb2FkSW5wdXRdPVwidXBsb2FkSW5wdXRcIlxuICAgICAgICAgICAgICAgICAgICBtdWx0aXBsZSAvPlxuICAgICAgICAgICAgICAgICAgYnJvd3NlXG4gICAgICAgICAgICAgICAgPC9sYWJlbD5cbiAgICAgICAgICAgICAgICB0byB1cGxvYWQuXG4gICAgICAgICAgICAgIDwvcD5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInVwbG9hZC1pdGVtXCJcbiAgICAgICAgICAgICAgKm5nRm9yPVwibGV0IGYgb2YgZmlsZXM7IGxldCBpID0gaW5kZXhcIj5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInVwbG9hZC1pdGVtLWNvbnRlbnRcIj5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZmlsZW5hbWVcIj5cbiAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmaWxlbmFtZS1sZWZ0XCI+XG4gICAgICAgICAgICAgICAgICAgIDxpIGNsYXNzPVwiaW9uaWNvbiBpb24taW9zLWNvcHlcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICAgICAgICAgICAgICAgIDxzcGFuPnt7IGYubmFtZSB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJwcm9ncmVzcy1jb250ZW50XCI+XG4gICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwicHJvZ3Jlc3NcIj5cbiAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJiYXJcIlxuICAgICAgICAgICAgICAgICAgICAgIFtzdHlsZS53aWR0aF09XCJmPy5wcm9ncmVzcz8uZGF0YT8ucGVyY2VudGFnZSArICclJ1wiXG4gICAgICAgICAgICAgICAgICAgICAgW2NsYXNzLmlzLWRvbmVdPVwiZlsndXBsb2FkZWQnXVwiPjwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJwcm9ncmVzcy10ZXh0LWNvbnRlbnRcIj5cbiAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwicHJvZ3Jlc3MtdGV4dFwiXG4gICAgICAgICAgICAgICAgICAgIFtjbGFzcy5pcy1kb25lXT1cImZbJ3VwbG9hZGVkJ11cIj5cbiAgICAgICAgICAgICAgICAgICAgPHNwYW4gKm5nSWY9XCIhZlsndXBsb2FkZWQnXVwiPnt7IGYucHJvZ3Jlc3M/LmRhdGE/LnBlcmNlbnRhZ2UgLSAxIH19JVxuICAgICAgICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgIDxzcGFuICpuZ0lmPVwiZlsndXBsb2FkZWQnXVwiPjEwMCAlPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICA8c3BhbiAqbmdJZj1cIiFmWyd1cGxvYWRlZCddXCI+VXBsb2FkaW5nLi4uPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICA8c3BhbiAqbmdJZj1cImZbJ3VwbG9hZGVkJ11cIj5Eb25lPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJzcGVlZC1hbmQtZXRhLXRleHRcIlxuICAgICAgICAgICAgICAgICAgICAqbmdJZj1cImYucHJvZ3Jlc3M/LmRhdGE/LnBlcmNlbnRhZ2UgIT09IDAgJiYgIWZbJ3VwbG9hZGVkJ11cIj5cbiAgICAgICAgICAgICAgICAgICAgPHNwYW4+e3sgZi5wcm9ncmVzcz8uZGF0YT8uc3BlZWRIdW1hbiB9fSA8L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgIDxzcGFuPkVUQSB7eyBmLnByb2dyZXNzPy5kYXRhPy5ldGFIdW1hbiB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG48L25nLXRlbXBsYXRlPlxuIl19