@posiwise/smart-crm 0.0.34 → 0.0.35

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 (38) hide show
  1. package/esm2022/index.mjs +6 -3
  2. package/esm2022/lib/private/components/smart-crm-accounts/smart-crm-account-files/smart-crm-account-files.component.mjs +3 -3
  3. package/esm2022/lib/private/components/smart-crm-accounts/smart-crm-account-info/smart-crm-account-info.component.mjs +16 -15
  4. package/esm2022/lib/private/components/smart-crm-accounts/smart-crm-accounts.component.mjs +3 -3
  5. package/esm2022/lib/private/components/smart-crm-configuration/smart-crm-actions/smart-crm-actions.component.mjs +2 -2
  6. package/esm2022/lib/private/components/smart-crm-configuration/smart-crm-configuration.component.mjs +2 -2
  7. package/esm2022/lib/private/components/smart-crm-contacts/smart-crm-contact-info/smart-crm-contact-info.component.mjs +6 -5
  8. package/esm2022/lib/private/components/smart-crm-contacts/smart-crm-contacts.component.mjs +21 -9
  9. package/esm2022/lib/private/components/smart-crm-insight/smart-crm-account-insight/smart-crm-account-insight.component.mjs +196 -0
  10. package/esm2022/lib/private/components/smart-crm-insight/smart-crm-analysis-insight/smart-crm-analysis.component.mjs +128 -0
  11. package/esm2022/lib/private/components/smart-crm-insight/smart-crm-contact-insight/smart-crm-contact-insight.component.mjs +94 -0
  12. package/esm2022/lib/private/components/smart-crm-insight/smart-crm-insight.component.mjs +19 -6
  13. package/esm2022/lib/private/components/smart-crm-insight/smart-crm-marketing-insight/smart-crm-marketing-insight.component.mjs +78 -0
  14. package/esm2022/lib/private/components/smart-crm-insight/smart-crm-opportunities-insight/smart-crm-opportunities-insight.component.mjs +145 -0
  15. package/esm2022/lib/private/components/smart-crm-marketing/smart-crm-marketing-list/smart-crm-marketing-list.component.mjs +3 -3
  16. package/esm2022/lib/private/components/smart-crm-opportunities/smart-crm-board/smart-crm-board.component.mjs +2 -2
  17. package/esm2022/lib/private/components/smart-crm-opportunities/smart-crm-opportunities-list/smart-crm-opportunities-details/smart-crm-opportunities-details.component.mjs +3 -3
  18. package/esm2022/lib/private/components/smart-crm-opportunities/smart-crm-opportunities-list/smart-crm-opportunities-info/smart-crm-opportunities-info.component.mjs +5 -7
  19. package/esm2022/lib/private/components/smart-crm-opportunities/smart-crm-opportunities-list/smart-crm-opportunities-list.component.mjs +3 -4
  20. package/esm2022/lib/private/components/smart-crm-opportunities/smart-crm-opportunities.component.mjs +2 -2
  21. package/esm2022/lib/private/components/smart-crm-summary/smart-crm-summary-actions/smart-crm-summary-actions.component.mjs +2 -2
  22. package/esm2022/lib/private/components/smart-crm-summary/smart-crm-summary.component.mjs +6 -8
  23. package/esm2022/lib/private/smart-crm-private.module.mjs +26 -11
  24. package/esm2022/lib/public/components/smart-crm-signup/smart-crm-signup.component.mjs +2 -2
  25. package/fesm2022/posiwise-smart-crm.mjs +761 -400
  26. package/fesm2022/posiwise-smart-crm.mjs.map +1 -1
  27. package/index.d.ts +5 -2
  28. package/lib/private/components/{smart-crm-summary/smart-crm-summary-others/smart-crm-summary-others.component.d.ts → smart-crm-insight/smart-crm-account-insight/smart-crm-account-insight.component.d.ts} +9 -7
  29. package/lib/private/components/smart-crm-insight/smart-crm-analysis-insight/smart-crm-analysis.component.d.ts +56 -0
  30. package/lib/private/components/smart-crm-insight/smart-crm-contact-insight/smart-crm-contact-insight.component.d.ts +61 -0
  31. package/lib/private/components/smart-crm-insight/smart-crm-insight.component.d.ts +4 -0
  32. package/lib/private/components/smart-crm-insight/smart-crm-marketing-insight/smart-crm-marketing-insight.component.d.ts +52 -0
  33. package/lib/private/components/smart-crm-insight/smart-crm-opportunities-insight/smart-crm-opportunities-insight.component.d.ts +79 -0
  34. package/lib/private/smart-crm-private.module.d.ts +47 -44
  35. package/package.json +1 -1
  36. package/esm2022/lib/private/components/smart-crm-insight/smart-crm-overview/smart-crm-overview.component.mjs +0 -55
  37. package/esm2022/lib/private/components/smart-crm-summary/smart-crm-summary-others/smart-crm-summary-others.component.mjs +0 -195
  38. package/lib/private/components/smart-crm-insight/smart-crm-overview/smart-crm-overview.component.d.ts +0 -20
@@ -0,0 +1,196 @@
1
+ import { Component, Injector } from '@angular/core';
2
+ import { CrmService } from '@posiwise/smart-crm-shared';
3
+ import { AppBaseComponent } from '@posiwise/app-base-component';
4
+ import { ROUTERS } from '../../../../shared/routers/routers';
5
+ import * as i0 from "@angular/core";
6
+ import * as i1 from "@posiwise/smart-crm-shared";
7
+ import * as i2 from "@angular/common";
8
+ import * as i3 from "@posiwise/directives";
9
+ import * as i4 from "@ng-bootstrap/ng-bootstrap";
10
+ import * as i5 from "angular-plotly.js";
11
+ import * as i6 from "@angular/router";
12
+ import * as i7 from "primeng/api";
13
+ import * as i8 from "primeng/progressspinner";
14
+ import * as i9 from "primeng/table";
15
+ import * as i10 from "@posiwise/shared-components";
16
+ import * as i11 from "@posiwise/pipes";
17
+ import * as i12 from "@jsverse/transloco";
18
+ export class SmartCrmAccountInsightComponent extends AppBaseComponent {
19
+ constructor(crmService, injector) {
20
+ super(injector);
21
+ this.crmService = crmService;
22
+ this.routers = ROUTERS;
23
+ this.signUpLastNinetyDaysLoaded = false;
24
+ this.accountLastActivitiesLoaded = false;
25
+ this.churnedAccountLoaded = false;
26
+ this.activeOpportunitiesLoaded = false;
27
+ this.accountAtRiskDetailsLoaded = false;
28
+ this.contactRenewalLoaded = false;
29
+ this.creditCardExpiringDetailsLoaded = false;
30
+ this.accountGeographyLoaded = false;
31
+ this.accountInsightLoaded = false;
32
+ this.magicMomentLoaded = false;
33
+ }
34
+ ngOnInit() {
35
+ this.getUserSubscription().subscribe(response => {
36
+ this.subscription = response;
37
+ if (this.subscription?.id) {
38
+ this.hasAccess = this.hasAdminAccess(this.subscription.id);
39
+ this.getUserInfo();
40
+ }
41
+ });
42
+ }
43
+ getUserInfo() {
44
+ this.userStore().subscribe(user => {
45
+ if (user) {
46
+ this.user = user;
47
+ this.userId = user.id;
48
+ if (this.permissionService.isGranted('Pages.Beta') ||
49
+ this.permissionService.isSuperAdmin()) {
50
+ this.getSignedUpLastNinetyDays();
51
+ this.getActiveOpportunities();
52
+ this.getChurnedAccounts();
53
+ this.getAccountLastActivities();
54
+ this.getAccountAtRiskDetails();
55
+ this.getContactRenewal();
56
+ this.getAccountGeography();
57
+ this.getAccountInsights();
58
+ }
59
+ }
60
+ });
61
+ }
62
+ /** Function to call signed up last 90 days details */
63
+ getSignedUpLastNinetyDays() {
64
+ this.crmService
65
+ .getCrmAnalytics(this.subscription?.id, 'accounts_signed_up_last_90_days')
66
+ .subscribe(response => {
67
+ if (typeof response === 'object' && Object.keys(response).length === 0) {
68
+ this.signedUpLastThirtyDays = [];
69
+ }
70
+ else
71
+ this.signedUpLastThirtyDays = response;
72
+ })
73
+ .add(() => {
74
+ this.signUpLastNinetyDaysLoaded = true;
75
+ });
76
+ }
77
+ getAccountLastActivities() {
78
+ this.crmService
79
+ .getCrmAnalytics(this.subscription?.id, 'accounts_last_activities')
80
+ .subscribe(response => {
81
+ if (typeof response === 'object' && Object.keys(response).length === 0) {
82
+ this.accountLastActivities = [];
83
+ }
84
+ else {
85
+ this.accountLastActivities = response;
86
+ this.actionNames = response?.map(action => {
87
+ return action?.crm_action?.name;
88
+ });
89
+ }
90
+ console.log(this.accountLastActivities);
91
+ })
92
+ .add(() => {
93
+ this.accountLastActivitiesLoaded = true;
94
+ });
95
+ }
96
+ getChurnedAccounts() {
97
+ this.crmService
98
+ .getCrmAnalytics(this.subscription?.id, 'accounts_accounts_churned')
99
+ .subscribe(response => {
100
+ if (typeof response === 'object' && Object.keys(response).length === 0) {
101
+ this.churnedAccounts = [];
102
+ }
103
+ else
104
+ this.churnedAccounts = response;
105
+ })
106
+ .add(() => {
107
+ this.churnedAccountLoaded = true;
108
+ });
109
+ }
110
+ /** Function to call Active Opportunities details */
111
+ getActiveOpportunities() {
112
+ this.crmService
113
+ .getCrmAnalytics(this.subscription?.id, 'accounts_active_opportunities')
114
+ .subscribe(response => {
115
+ if (typeof response === 'object' && Object.keys(response).length === 0) {
116
+ this.activeOpportunities = [];
117
+ }
118
+ else
119
+ this.activeOpportunities = response;
120
+ })
121
+ .add(() => {
122
+ this.activeOpportunitiesLoaded = true;
123
+ });
124
+ }
125
+ /** Function to call Account At Risk details */
126
+ getAccountAtRiskDetails() {
127
+ this.crmService
128
+ .getCrmAnalytics(this.subscription?.id, 'accounts_accounts_at_risk')
129
+ .subscribe(response => {
130
+ if (typeof response === 'object' && Object.keys(response).length === 0) {
131
+ this.accountAtRisk = [];
132
+ }
133
+ else
134
+ this.accountAtRisk = response;
135
+ })
136
+ .add(() => {
137
+ this.accountAtRiskDetailsLoaded = true;
138
+ });
139
+ }
140
+ /** Function to call Contract renewal details */
141
+ getContactRenewal() {
142
+ this.crmService
143
+ .getCrmAnalytics(this.subscription?.id, 'accounts_contract_renewal')
144
+ .subscribe(response => {
145
+ if (typeof response === 'object' && Object.keys(response).length === 0) {
146
+ this.ContractRenewal = [];
147
+ }
148
+ else
149
+ this.ContractRenewal = response;
150
+ })
151
+ .add(() => {
152
+ this.contactRenewalLoaded = true;
153
+ });
154
+ }
155
+ getAccountInsights() {
156
+ this.crmService
157
+ .getCrmAnalytics(this.subscription?.id, 'accounts_insights')
158
+ .subscribe(response => {
159
+ if (typeof response === 'object' && Object.keys(response).length === 0) {
160
+ this.accountInsight = [];
161
+ }
162
+ else
163
+ this.accountInsight = response;
164
+ })
165
+ .add(() => {
166
+ this.accountInsightLoaded = true;
167
+ });
168
+ }
169
+ getAccountGeography() {
170
+ this.crmService
171
+ .getCrmAnalytics(this.subscription?.id, 'accounts_geography')
172
+ .subscribe(response => {
173
+ if (typeof response === 'object' && Object.keys(response).length === 0) {
174
+ this.accountGeography = [];
175
+ }
176
+ else
177
+ this.accountGeography = response;
178
+ })
179
+ .add(() => {
180
+ this.accountGeographyLoaded = true;
181
+ });
182
+ }
183
+ checkPermission(permission) {
184
+ return this.permissionService.evaluatePermissions(permission);
185
+ }
186
+ ngOnDestroy() {
187
+ super.ngOnDestroy();
188
+ }
189
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: SmartCrmAccountInsightComponent, deps: [{ token: i1.CrmService }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Component }); }
190
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.11", type: SmartCrmAccountInsightComponent, selector: "pw-smart-crm-account-insight", usesInheritance: true, ngImport: i0, template: "<div class=\"row\">\n <ng-container class=\"mt-5\"\n *rbacAllow=\"'Pages.Beta'\">\n <!-- Signed up last 90 days -->\n <div class=\"col-12 col-md-6 mb-3 analytics\">\n <h5 class=\"accordion-heading\">Signed up Last 90 Days</h5>\n <div class=\"w-100 text-center mt-3\">\n <ng-template [ngIf]=\"!signUpLastNinetyDaysLoaded\">\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </ng-template>\n </div>\n <div class=\"primeng-datatable-container table-responsive\"\n *ngIf=\"signedUpLastThirtyDays?.length\">\n <p-table class=\"table\"\n #dt\n [value]=\"signedUpLastThirtyDays\"\n [paginator]=\"true\"\n [rows]=\"20\"\n [totalRecords]=\"signedUpLastThirtyDays.length\"\n>\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"true\">{{ 'Crm.Summary.Account' | transloco }}</th>\n <th scope=\"true\" class=\"mrr-header\">{{ 'Crm.AccountMessage.MRR' | transloco }}</th>\n <th scope=\"true\">{{ 'Crm.AccountMessage.SignUpAt' | transloco }}</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\"\n let-signUp>\n <tr>\n <td data-head=\"Account\">\n <a [routerLink]=\"['/' + subscription?.slug + routers.accountInfo, signUp.crm_account_id]\" class=\"name-link\">\n <span [ngbTooltip]=\"signUp.crm_account_name\">{{ signUp?.crm_account_name | textTruncate:20 }}</span>\n </a>\n </td>\n <td data-head=\"MRR\" class=\"expected-mrr\">\n {{ signUp.expected_mrr / 100 | currency: signUp.currency }}\n </td>\n <td data-head=\"SignUpAt\">\n {{ signUp.signed_up_at | dateFormat }}\n </td>\n </tr>\n </ng-template>\n </p-table>\n <span class=\"total-records-count\" *ngIf=\"signedUpLastThirtyDays.length!== 0\">{{ 'Label.Total' | transloco }}: {{ signedUpLastThirtyDays.length }}</span>\n </div>\n <div *ngIf=\"signedUpLastThirtyDays?.length === 0\">\n <pw-no-data [withImage]=\"true\" [message]=\"'Crm.Summary.NoInsightMessage' | transloco\"> </pw-no-data>\n </div>\n </div>\n <!-- Active Opportunities -->\n <div class=\"col-12 col-md-6 mb-3 analytics\">\n <h5 class=\"accordion-heading\">Active Opportunities</h5>\n <div class=\"w-100 text-center mt-3\">\n <ng-template [ngIf]=\"!activeOpportunitiesLoaded\">\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </ng-template>\n </div>\n <div class=\"primeng-datatable-container table-responsive\"\n *ngIf=\"activeOpportunities?.length\">\n <p-table class=\"table\"\n #dt\n [value]=\"activeOpportunities\"\n [paginator]=\"true\"\n [rows]=\"20\"\n\n [totalRecords]=\"activeOpportunities.length\"\n>\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"true\">{{ 'Crm.Summary.Account' | transloco }}</th>\n <th scope=\"true\">{{ 'Crm.Summary.Title' | transloco }}</th>\n <th scope=\"true\">{{ 'Crm.Summary.OneTimeAmount' | transloco }}</th>\n <th scope=\"true\" class=\"mrr-header\">{{ 'Crm.AccountMessage.MRR' | transloco }}</th>\n <th scope=\"true\">{{ 'Crm.Summary.WinChance' | transloco }}</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\"\n let-opportunities>\n <tr>\n <td data-head=\"Account\">\n <a [routerLink]=\"['/' + subscription?.slug + routers.accountInfo, opportunities.crm_account?.id]\" class=\"name-link\">\n <span [ngbTooltip]=\"opportunities.crm_account?.name\">{{ opportunities.crm_account?.name | textTruncate:20 }}</span>\n </a>\n </td>\n <td data-head=\"Title\">\n <a [ngbTooltip]=\"opportunities?.title\" *ngIf=\"\n hasAccess ||\n opportunities?.owner_id === userId ||\n checkPermission('Pages.Product.CRM.Role.Admin')\n \" [routerLink]=\"[\n '/' + subscription?.slug + routers.opportunityInfo,\n opportunities.id\n ]\">\n <span>{{ opportunities?.title | textTruncate: 20 }} </span>\n </a>\n </td>\n <td data-head=\"One Time Amount\"> {{ opportunities.one_time_amount / 100 | currency }} </td>\n <td data-head=\"Monthly Amount\" class=\"expected-mrr\"> {{ opportunities.monthly_amount / 100 | currency }} </td>\n <td data-head=\"Win Chance\"> {{ opportunities.win_chances / 100 | percent }} <span class=\"text-danger\"\n *ngIf=\"opportunities.cancelled\">!Cancelled!</span>\n </td>\n </tr>\n </ng-template>\n </p-table>\n <span class=\"total-records-count\" *ngIf=\"activeOpportunities.length !== 0\">{{ 'Label.Total' | transloco }}: {{ activeOpportunities.length }}</span>\n </div>\n <div *ngIf=\"activeOpportunities?.length === 0\">\n <pw-no-data [withImage]=\"true\" [message]=\"'Crm.Summary.NoInsightMessage' | transloco\"> </pw-no-data>\n </div>\n </div>\n <div class=\"col-12 col-md-6 mb-3 analytics\">\n <h5 class=\"accordion-heading\">Last Activities</h5>\n <div class=\"w-100 text-center mt-3\">\n <ng-template [ngIf]=\"!accountLastActivitiesLoaded\">\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </ng-template>\n </div>\n <div class=\"primeng-datatable-container table-responsive\"\n *ngIf=\"accountLastActivities?.length\">\n <p-table class=\"table\"\n #dt\n [value]=\"accountLastActivities\"\n [paginator]=\"true\"\n [rows]=\"20\"\n\n [totalRecords]=\"accountLastActivities.length\"\n>\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"true\">{{ 'Crm.AccountMessage.Owner' | transloco }}</th>\n <th scope=\"true\">{{ 'Crm.AccountMessage.Account' | transloco }}</th>\n <th scope=\"true\">{{ 'Crm.AccountMessage.Contact' | transloco }}</th>\n <th scope=\"true\">{{ 'Crm.AccountMessage.Action' | transloco }}</th>\n <th scope=\"true\">{{ 'Crm.AccountMessage.When' | transloco }}</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\" let-activities>\n <tr>\n <td data-head=\"Owner\"> {{ activities.owner?.first_name.charAt(0) }}. {{ activities.owner?.last_name }} </td>\n <td data-head=\"Account\">\n <a [routerLink]=\"['/' + subscription?.slug + routers.accountInfo, activities.crm_account_id]\" class=\"name-link\">\n <span [ngbTooltip]=\"activities.crm_account?.name\">{{ activities.crm_account?.name }}</span>\n </a>\n </td>\n <td data-head=\"Contact\">\n <a [routerLink]=\"['/' + subscription?.slug + routers.contactInfo, activities.crm_contact_id]\" class=\"name-link\">\n <span [ngbTooltip]=\"activities.crm_contact ? activities.crm_contact.first_name + ' ' + activities.crm_contact.last_name : ''\">{{ (activities.crm_contact?.first_name + ' ' + activities.crm_contact?.last_name) | textTruncate:20 }}</span>\n </a>\n </td>\n <td data-head=\"Action\">\n <span [ngbTooltip]=\"activities.comment\" [appDynamicBadge]=\"{\n itemsArray: actionNames,\n item: activities.crm_action?.name\n }\"\n color=\"blue-grey\"\n class=\"badge\">{{ activities.crm_action?.name }}</span>\n </td>\n <td data-head=\"When\">{{ activities.when | date:'dd-MMM-YYYY' }}</td>\n </tr>\n </ng-template>\n </p-table>\n <span class=\"total-records-count\" *ngIf=\"accountLastActivities.length !== 0\">{{ 'Label.Total' | transloco }}: {{ accountLastActivities.length }}</span>\n </div>\n <div *ngIf=\"accountLastActivities?.length === 0 && accountLastActivitiesLoaded\">\n <pw-no-data [withImage]=\"true\" [message]=\"'Crm.Summary.NoInsightMessage' | transloco\"> </pw-no-data>\n </div>\n </div>\n\n\n <div class=\"col-12 col-md-6 mb-3 analytics\">\n <h5 class=\"accordion-heading\">Churned Last 90 Days</h5>\n <div class=\"w-100 text-center mt-3\">\n <ng-template [ngIf]=\"!churnedAccountLoaded\">\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </ng-template>\n </div>\n <div class=\"primeng-datatable-container table-responsive\"\n *ngIf=\"churnedAccounts?.length\">\n <p-table class=\"table\"\n #dt\n [value]=\"churnedAccounts\"\n [paginator]=\"true\"\n [rows]=\"20\"\n [totalRecords]=\"churnedAccounts.length\"\n>\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"true\">{{ 'Crm.AccountMessage.Account' | transloco }}</th>\n <th scope=\"true\" class=\"mrr-header\">{{ 'Crm.AccountMessage.MRR' | transloco }}</th>\n\n <th scope=\"true\">{{ 'Crm.AccountMessage.Quarter' | transloco }}</th>\n <th scope=\"true\"> {{ 'Crm.AccountMessage.Month' | transloco }}</th>\n\n <th scope=\"true\">{{ 'Crm.AccountMessage.UnsubscribedAt' | transloco }}</th>\n <th scope=\"true\">{{ 'Crm.AccountMessage.CCExpAt' | transloco }}</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\"\n let-account>\n <tr>\n <td data-head=\"Account\">\n <a [routerLink]=\"['/' + subscription?.slug + routers.accountInfo, account.crm_account_id]\" class=\"name-link\">\n <span [ngbTooltip]=\"account.crm_account_name\">{{ account.crm_account_name | textTruncate:20 }}</span>\n </a>\n </td>\n <td data-head=\"MRR\" class=\"expected-mrr\">\n {{ account.expected_mrr / 100 | currency: account.currency }}\n </td>\n <td data-head=\"Quarter\">{{ account.sessions_last_quarter }}</td>\n <td data-head=\"Month\">{{ account.sessions_last_month }}</td>\n <td data-head=\"SignUpAt\">\n {{ account.signed_up_at | dateFormat }}\n </td>\n <td data-head=\"ExpAt\">\n {{ account.cc_expiring_at | dateFormat }}\n </td>\n </tr>\n </ng-template>\n </p-table>\n <span class=\"total-records-count\" *ngIf=\"churnedAccounts?.length !== 0\">{{ 'Label.Total' | transloco }}: {{ churnedAccounts.length }}</span>\n </div>\n <div *ngIf=\"churnedAccounts?.length === 0 && churnedAccountLoaded\">\n <pw-no-data [withImage]=\"true\" [message]=\"'Crm.Summary.NoInsightMessage' | transloco\"> </pw-no-data>\n </div>\n </div>\n\n <!-- Accounts at risk -->\n <div class=\"col-12 col-md-6 mb-3 analytics\">\n <h5 class=\"accordion-heading\">Accounts at Risk</h5>\n <div class=\"w-100 text-center mt-3\">\n <ng-template [ngIf]=\"!accountAtRiskDetailsLoaded\">\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </ng-template>\n </div>\n <div class=\"primeng-datatable-container table-responsive\"\n *ngIf=\"accountAtRisk?.length\">\n <p-table class=\"table\"\n #dt\n [value]=\"accountAtRisk\"\n [paginator]=\"true\"\n [rows]=\"20\"\n\n [totalRecords]=\"accountAtRisk.length\"\n>\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"true\">{{ 'Crm.Summary.Account' | transloco }}</th>\n <th scope=\"true\" class=\"mrr-header\">{{ 'Crm.AccountMessage.MRR' | transloco }}</th>\n <th scope=\"true\">{{ 'Crm.AccountMessage.Quarter' | transloco }}</th>\n <th scope=\"true\"> {{ 'Crm.AccountMessage.Month' | transloco }}</th>\n <th scope=\"true\">{{ 'Crm.AccountMessage.SignUpAt' | transloco }}</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\"\n let-account>\n <tr>\n <td data-head=\"Account\">\n <a [routerLink]=\"['/' + subscription?.slug + routers.accountInfo, account.crm_account_id]\" class=\"name-link\">\n <span [ngbTooltip]=\"account.crm_account_name\">{{ account?.crm_account_name | textTruncate:20 }}</span>\n </a>\n </td>\n <td data-head=\"MRR\" class=\"expected-mrr\">\n {{ account.expected_mrr / 100 | currency: account.currency }}\n </td>\n <td data-head=\"Quarter\">{{ account.sessions_last_quarter }}</td>\n <td data-head=\"Month\">{{ account.sessions_last_month }}</td>\n <td data-head=\"SignUpAt\">\n {{ account.signed_up_at | dateFormat }}\n </td>\n </tr>\n </ng-template>\n </p-table>\n <span class=\"total-records-count\" *ngIf=\"accountAtRisk.length !== 0\">{{ 'Label.Total' | transloco }}: {{ accountAtRisk.length }}</span>\n </div>\n <div *ngIf=\"accountAtRisk?.length === 0\">\n <pw-no-data [withImage]=\"true\" [message]=\"'Crm.Summary.NoInsightMessage' | transloco\"> </pw-no-data>\n </div>\n </div>\n <!-- Contract renewal -->\n <div class=\"col-12 col-md-6 mb-3 analytics\">\n <h5 class=\"accordion-heading\">Contract Renewal</h5>\n <div class=\"w-100 text-center mt-3\">\n <ng-template [ngIf]=\"!contactRenewalLoaded\">\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </ng-template>\n </div>\n <div class=\"primeng-datatable-container table-responsive\"\n *ngIf=\"ContractRenewal?.length\">\n <p-table class=\"table\"\n #dt\n [value]=\"ContractRenewal\"\n [paginator]=\"true\"\n [rows]=\"20\"\n\n [totalRecords]=\"ContractRenewal.length\"\n>\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"true\">{{ 'Crm.AccountMessage.Account' | transloco }}</th>\n <th scope=\"true\" class=\"mrr-header\">{{ 'Crm.AccountMessage.MRR' | transloco }}</th>\n\n <th scope=\"true\">{{ 'Crm.AccountMessage.Quarter' | transloco }}</th>\n <th scope=\"true\"> {{ 'Crm.AccountMessage.Month' | transloco }}</th>\n\n <th scope=\"true\">{{ 'Crm.AccountMessage.SignUpAt' | transloco }}</th>\n <th scope=\"true\">{{ 'Crm.AccountMessage.CCExpAt' | transloco }}</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\"\n let-account>\n <tr>\n <td data-head=\"Account\">\n <a [routerLink]=\"['/' + subscription?.slug + routers.accountInfo, account.crm_account_id]\" class=\"name-link\">\n <span [ngbTooltip]=\"account.crm_account_name\">{{ account.crm_account_name | textTruncate:20 }}</span>\n </a>\n </td>\n <td data-head=\"MRR\" class=\"expected-mrr\">\n {{ account.expected_mrr / 100 | currency: account.currency }}\n </td>\n <td data-head=\"Quarter\">{{ account.sessions_last_quarter }}</td>\n <td data-head=\"Month\">{{ account.sessions_last_month }}</td>\n <td data-head=\"SignUpAt\">\n {{ account.signed_up_at | dateFormat }}\n </td>\n <td data-head=\"ExpAt\">\n {{ account.cc_expiring_at | dateFormat }}\n </td>\n </tr>\n </ng-template>\n </p-table>\n <span class=\"total-records-count\" *ngIf=\"ContractRenewal.length !== 0\">{{ 'Label.Total' | transloco }}: {{ ContractRenewal.length }}</span>\n </div>\n <div *ngIf=\"ContractRenewal?.length === 0\">\n <pw-no-data [withImage]=\"true\" [message]=\"'Crm.Summary.NoInsightMessage' | transloco\"> </pw-no-data>\n </div>\n </div>\n\n\n <!-- Account Insights -->\n <div class=\"col-12 col-md-6 mb-3 analytics\">\n <h5 class=\"accordion-heading\">Account Insights</h5>\n <div class=\"w-100 text-center mt-3\">\n <ng-template [ngIf]=\"!accountInsightLoaded\">\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </ng-template>\n </div>\n <div class=\"primeng-datatable-container table-responsive\"\n *ngIf=\"accountInsight?.length\">\n <p-table class=\"table\"\n #dt\n [value]=\"accountInsight\"\n [paginator]=\"true\"\n [rows]=\"20\"\n\n [totalRecords]=\"12\"\n>\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"true\">{{ 'Value' }}</th>\n <th scope=\"true\">{{ 'Crm.Summary.Title' | transloco }}</th>\n <th scope=\"true\"> {{ 'Crm.ContactMessage.Reason' | transloco }} </th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\"\n let-account>\n <tr>\n <td data-head=\"value\">{{ account.value }}</td>\n <td data-head=\"title\">{{ account.title }}</td>\n <td data-head=\"reason\">\n {{ account.reason }}\n </td>\n </tr>\n </ng-template>\n </p-table>\n </div>\n <div *ngIf=\"!accountInsight?.length && accountInsightLoaded\">\n <pw-no-data [withImage]=\"true\" [message]=\"'Crm.Summary.NoInsightMessage' | transloco\"> </pw-no-data>\n </div>\n </div>\n <div class=\"col-12 col-md-6 mb-3 analytics\">\n <h5 class=\"accordion-heading\">Geography</h5>\n <div>\n <ng-template [ngIf]=\"accountGeography\">\n <plotly-plot [data]=\"accountGeography?.data\"\n [layout]=\"accountGeography?.layout\" [useResizeHandler]=\"true\">\n </plotly-plot>\n </ng-template>\n </div>\n <div *ngIf=\"!accountGeography\">\n <pw-no-data [withImage]=\"true\" [message]=\"'Crm.ContactMessage.NoInsightMessage' | transloco\">\n </pw-no-data>\n </div>\n </div>\n </ng-container>\n</div>\n", dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.DynamicBadgeDirective, selector: "[appDynamicBadge]", inputs: ["appDynamicBadge", "color"] }, { kind: "directive", type: i3.RbacAllowDirective, selector: "[rbacAllow]", inputs: ["rbacAllow"] }, { kind: "directive", type: i4.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: i5.PlotlyComponent, selector: "plotly-plot", inputs: ["data", "layout", "config", "frames", "style", "theme", "divId", "revision", "className", "debug", "useResizeHandler", "updateOnLayoutChange", "updateOnDataChange", "updateOnlyWithRevision"], outputs: ["initialized", "update", "purge", "error", "afterExport", "afterPlot", "animated", "animatingFrame", "animationInterrupted", "autoSize", "beforeExport", "beforeHover", "buttonClicked", "click", "plotlyClick", "clickAnnotation", "deselect", "doubleClick", "framework", "hover", "legendClick", "legendDoubleClick", "react", "relayout", "relayouting", "restyle", "redraw", "selected", "selecting", "sliderChange", "sliderEnd", "sliderStart", "sunburstclick", "transitioning", "transitionInterrupted", "unhover", "treemapclick", "webglcontextlost"] }, { kind: "directive", type: i6.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i7.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "component", type: i8.ProgressSpinner, selector: "p-progressSpinner", inputs: ["styleClass", "style", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "component", type: i9.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: "component", type: i10.NoDataComponent, selector: "pw-no-data", inputs: ["message", "description", "withImage"] }, { kind: "pipe", type: i2.PercentPipe, name: "percent" }, { kind: "pipe", type: i2.CurrencyPipe, name: "currency" }, { kind: "pipe", type: i2.DatePipe, name: "date" }, { kind: "pipe", type: i11.DateFormatPipe, name: "dateFormat" }, { kind: "pipe", type: i11.TextTruncatePipe, name: "textTruncate" }, { kind: "pipe", type: i12.TranslocoPipe, name: "transloco" }] }); }
191
+ }
192
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: SmartCrmAccountInsightComponent, decorators: [{
193
+ type: Component,
194
+ args: [{ selector: 'pw-smart-crm-account-insight', template: "<div class=\"row\">\n <ng-container class=\"mt-5\"\n *rbacAllow=\"'Pages.Beta'\">\n <!-- Signed up last 90 days -->\n <div class=\"col-12 col-md-6 mb-3 analytics\">\n <h5 class=\"accordion-heading\">Signed up Last 90 Days</h5>\n <div class=\"w-100 text-center mt-3\">\n <ng-template [ngIf]=\"!signUpLastNinetyDaysLoaded\">\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </ng-template>\n </div>\n <div class=\"primeng-datatable-container table-responsive\"\n *ngIf=\"signedUpLastThirtyDays?.length\">\n <p-table class=\"table\"\n #dt\n [value]=\"signedUpLastThirtyDays\"\n [paginator]=\"true\"\n [rows]=\"20\"\n [totalRecords]=\"signedUpLastThirtyDays.length\"\n>\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"true\">{{ 'Crm.Summary.Account' | transloco }}</th>\n <th scope=\"true\" class=\"mrr-header\">{{ 'Crm.AccountMessage.MRR' | transloco }}</th>\n <th scope=\"true\">{{ 'Crm.AccountMessage.SignUpAt' | transloco }}</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\"\n let-signUp>\n <tr>\n <td data-head=\"Account\">\n <a [routerLink]=\"['/' + subscription?.slug + routers.accountInfo, signUp.crm_account_id]\" class=\"name-link\">\n <span [ngbTooltip]=\"signUp.crm_account_name\">{{ signUp?.crm_account_name | textTruncate:20 }}</span>\n </a>\n </td>\n <td data-head=\"MRR\" class=\"expected-mrr\">\n {{ signUp.expected_mrr / 100 | currency: signUp.currency }}\n </td>\n <td data-head=\"SignUpAt\">\n {{ signUp.signed_up_at | dateFormat }}\n </td>\n </tr>\n </ng-template>\n </p-table>\n <span class=\"total-records-count\" *ngIf=\"signedUpLastThirtyDays.length!== 0\">{{ 'Label.Total' | transloco }}: {{ signedUpLastThirtyDays.length }}</span>\n </div>\n <div *ngIf=\"signedUpLastThirtyDays?.length === 0\">\n <pw-no-data [withImage]=\"true\" [message]=\"'Crm.Summary.NoInsightMessage' | transloco\"> </pw-no-data>\n </div>\n </div>\n <!-- Active Opportunities -->\n <div class=\"col-12 col-md-6 mb-3 analytics\">\n <h5 class=\"accordion-heading\">Active Opportunities</h5>\n <div class=\"w-100 text-center mt-3\">\n <ng-template [ngIf]=\"!activeOpportunitiesLoaded\">\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </ng-template>\n </div>\n <div class=\"primeng-datatable-container table-responsive\"\n *ngIf=\"activeOpportunities?.length\">\n <p-table class=\"table\"\n #dt\n [value]=\"activeOpportunities\"\n [paginator]=\"true\"\n [rows]=\"20\"\n\n [totalRecords]=\"activeOpportunities.length\"\n>\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"true\">{{ 'Crm.Summary.Account' | transloco }}</th>\n <th scope=\"true\">{{ 'Crm.Summary.Title' | transloco }}</th>\n <th scope=\"true\">{{ 'Crm.Summary.OneTimeAmount' | transloco }}</th>\n <th scope=\"true\" class=\"mrr-header\">{{ 'Crm.AccountMessage.MRR' | transloco }}</th>\n <th scope=\"true\">{{ 'Crm.Summary.WinChance' | transloco }}</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\"\n let-opportunities>\n <tr>\n <td data-head=\"Account\">\n <a [routerLink]=\"['/' + subscription?.slug + routers.accountInfo, opportunities.crm_account?.id]\" class=\"name-link\">\n <span [ngbTooltip]=\"opportunities.crm_account?.name\">{{ opportunities.crm_account?.name | textTruncate:20 }}</span>\n </a>\n </td>\n <td data-head=\"Title\">\n <a [ngbTooltip]=\"opportunities?.title\" *ngIf=\"\n hasAccess ||\n opportunities?.owner_id === userId ||\n checkPermission('Pages.Product.CRM.Role.Admin')\n \" [routerLink]=\"[\n '/' + subscription?.slug + routers.opportunityInfo,\n opportunities.id\n ]\">\n <span>{{ opportunities?.title | textTruncate: 20 }} </span>\n </a>\n </td>\n <td data-head=\"One Time Amount\"> {{ opportunities.one_time_amount / 100 | currency }} </td>\n <td data-head=\"Monthly Amount\" class=\"expected-mrr\"> {{ opportunities.monthly_amount / 100 | currency }} </td>\n <td data-head=\"Win Chance\"> {{ opportunities.win_chances / 100 | percent }} <span class=\"text-danger\"\n *ngIf=\"opportunities.cancelled\">!Cancelled!</span>\n </td>\n </tr>\n </ng-template>\n </p-table>\n <span class=\"total-records-count\" *ngIf=\"activeOpportunities.length !== 0\">{{ 'Label.Total' | transloco }}: {{ activeOpportunities.length }}</span>\n </div>\n <div *ngIf=\"activeOpportunities?.length === 0\">\n <pw-no-data [withImage]=\"true\" [message]=\"'Crm.Summary.NoInsightMessage' | transloco\"> </pw-no-data>\n </div>\n </div>\n <div class=\"col-12 col-md-6 mb-3 analytics\">\n <h5 class=\"accordion-heading\">Last Activities</h5>\n <div class=\"w-100 text-center mt-3\">\n <ng-template [ngIf]=\"!accountLastActivitiesLoaded\">\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </ng-template>\n </div>\n <div class=\"primeng-datatable-container table-responsive\"\n *ngIf=\"accountLastActivities?.length\">\n <p-table class=\"table\"\n #dt\n [value]=\"accountLastActivities\"\n [paginator]=\"true\"\n [rows]=\"20\"\n\n [totalRecords]=\"accountLastActivities.length\"\n>\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"true\">{{ 'Crm.AccountMessage.Owner' | transloco }}</th>\n <th scope=\"true\">{{ 'Crm.AccountMessage.Account' | transloco }}</th>\n <th scope=\"true\">{{ 'Crm.AccountMessage.Contact' | transloco }}</th>\n <th scope=\"true\">{{ 'Crm.AccountMessage.Action' | transloco }}</th>\n <th scope=\"true\">{{ 'Crm.AccountMessage.When' | transloco }}</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\" let-activities>\n <tr>\n <td data-head=\"Owner\"> {{ activities.owner?.first_name.charAt(0) }}. {{ activities.owner?.last_name }} </td>\n <td data-head=\"Account\">\n <a [routerLink]=\"['/' + subscription?.slug + routers.accountInfo, activities.crm_account_id]\" class=\"name-link\">\n <span [ngbTooltip]=\"activities.crm_account?.name\">{{ activities.crm_account?.name }}</span>\n </a>\n </td>\n <td data-head=\"Contact\">\n <a [routerLink]=\"['/' + subscription?.slug + routers.contactInfo, activities.crm_contact_id]\" class=\"name-link\">\n <span [ngbTooltip]=\"activities.crm_contact ? activities.crm_contact.first_name + ' ' + activities.crm_contact.last_name : ''\">{{ (activities.crm_contact?.first_name + ' ' + activities.crm_contact?.last_name) | textTruncate:20 }}</span>\n </a>\n </td>\n <td data-head=\"Action\">\n <span [ngbTooltip]=\"activities.comment\" [appDynamicBadge]=\"{\n itemsArray: actionNames,\n item: activities.crm_action?.name\n }\"\n color=\"blue-grey\"\n class=\"badge\">{{ activities.crm_action?.name }}</span>\n </td>\n <td data-head=\"When\">{{ activities.when | date:'dd-MMM-YYYY' }}</td>\n </tr>\n </ng-template>\n </p-table>\n <span class=\"total-records-count\" *ngIf=\"accountLastActivities.length !== 0\">{{ 'Label.Total' | transloco }}: {{ accountLastActivities.length }}</span>\n </div>\n <div *ngIf=\"accountLastActivities?.length === 0 && accountLastActivitiesLoaded\">\n <pw-no-data [withImage]=\"true\" [message]=\"'Crm.Summary.NoInsightMessage' | transloco\"> </pw-no-data>\n </div>\n </div>\n\n\n <div class=\"col-12 col-md-6 mb-3 analytics\">\n <h5 class=\"accordion-heading\">Churned Last 90 Days</h5>\n <div class=\"w-100 text-center mt-3\">\n <ng-template [ngIf]=\"!churnedAccountLoaded\">\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </ng-template>\n </div>\n <div class=\"primeng-datatable-container table-responsive\"\n *ngIf=\"churnedAccounts?.length\">\n <p-table class=\"table\"\n #dt\n [value]=\"churnedAccounts\"\n [paginator]=\"true\"\n [rows]=\"20\"\n [totalRecords]=\"churnedAccounts.length\"\n>\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"true\">{{ 'Crm.AccountMessage.Account' | transloco }}</th>\n <th scope=\"true\" class=\"mrr-header\">{{ 'Crm.AccountMessage.MRR' | transloco }}</th>\n\n <th scope=\"true\">{{ 'Crm.AccountMessage.Quarter' | transloco }}</th>\n <th scope=\"true\"> {{ 'Crm.AccountMessage.Month' | transloco }}</th>\n\n <th scope=\"true\">{{ 'Crm.AccountMessage.UnsubscribedAt' | transloco }}</th>\n <th scope=\"true\">{{ 'Crm.AccountMessage.CCExpAt' | transloco }}</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\"\n let-account>\n <tr>\n <td data-head=\"Account\">\n <a [routerLink]=\"['/' + subscription?.slug + routers.accountInfo, account.crm_account_id]\" class=\"name-link\">\n <span [ngbTooltip]=\"account.crm_account_name\">{{ account.crm_account_name | textTruncate:20 }}</span>\n </a>\n </td>\n <td data-head=\"MRR\" class=\"expected-mrr\">\n {{ account.expected_mrr / 100 | currency: account.currency }}\n </td>\n <td data-head=\"Quarter\">{{ account.sessions_last_quarter }}</td>\n <td data-head=\"Month\">{{ account.sessions_last_month }}</td>\n <td data-head=\"SignUpAt\">\n {{ account.signed_up_at | dateFormat }}\n </td>\n <td data-head=\"ExpAt\">\n {{ account.cc_expiring_at | dateFormat }}\n </td>\n </tr>\n </ng-template>\n </p-table>\n <span class=\"total-records-count\" *ngIf=\"churnedAccounts?.length !== 0\">{{ 'Label.Total' | transloco }}: {{ churnedAccounts.length }}</span>\n </div>\n <div *ngIf=\"churnedAccounts?.length === 0 && churnedAccountLoaded\">\n <pw-no-data [withImage]=\"true\" [message]=\"'Crm.Summary.NoInsightMessage' | transloco\"> </pw-no-data>\n </div>\n </div>\n\n <!-- Accounts at risk -->\n <div class=\"col-12 col-md-6 mb-3 analytics\">\n <h5 class=\"accordion-heading\">Accounts at Risk</h5>\n <div class=\"w-100 text-center mt-3\">\n <ng-template [ngIf]=\"!accountAtRiskDetailsLoaded\">\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </ng-template>\n </div>\n <div class=\"primeng-datatable-container table-responsive\"\n *ngIf=\"accountAtRisk?.length\">\n <p-table class=\"table\"\n #dt\n [value]=\"accountAtRisk\"\n [paginator]=\"true\"\n [rows]=\"20\"\n\n [totalRecords]=\"accountAtRisk.length\"\n>\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"true\">{{ 'Crm.Summary.Account' | transloco }}</th>\n <th scope=\"true\" class=\"mrr-header\">{{ 'Crm.AccountMessage.MRR' | transloco }}</th>\n <th scope=\"true\">{{ 'Crm.AccountMessage.Quarter' | transloco }}</th>\n <th scope=\"true\"> {{ 'Crm.AccountMessage.Month' | transloco }}</th>\n <th scope=\"true\">{{ 'Crm.AccountMessage.SignUpAt' | transloco }}</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\"\n let-account>\n <tr>\n <td data-head=\"Account\">\n <a [routerLink]=\"['/' + subscription?.slug + routers.accountInfo, account.crm_account_id]\" class=\"name-link\">\n <span [ngbTooltip]=\"account.crm_account_name\">{{ account?.crm_account_name | textTruncate:20 }}</span>\n </a>\n </td>\n <td data-head=\"MRR\" class=\"expected-mrr\">\n {{ account.expected_mrr / 100 | currency: account.currency }}\n </td>\n <td data-head=\"Quarter\">{{ account.sessions_last_quarter }}</td>\n <td data-head=\"Month\">{{ account.sessions_last_month }}</td>\n <td data-head=\"SignUpAt\">\n {{ account.signed_up_at | dateFormat }}\n </td>\n </tr>\n </ng-template>\n </p-table>\n <span class=\"total-records-count\" *ngIf=\"accountAtRisk.length !== 0\">{{ 'Label.Total' | transloco }}: {{ accountAtRisk.length }}</span>\n </div>\n <div *ngIf=\"accountAtRisk?.length === 0\">\n <pw-no-data [withImage]=\"true\" [message]=\"'Crm.Summary.NoInsightMessage' | transloco\"> </pw-no-data>\n </div>\n </div>\n <!-- Contract renewal -->\n <div class=\"col-12 col-md-6 mb-3 analytics\">\n <h5 class=\"accordion-heading\">Contract Renewal</h5>\n <div class=\"w-100 text-center mt-3\">\n <ng-template [ngIf]=\"!contactRenewalLoaded\">\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </ng-template>\n </div>\n <div class=\"primeng-datatable-container table-responsive\"\n *ngIf=\"ContractRenewal?.length\">\n <p-table class=\"table\"\n #dt\n [value]=\"ContractRenewal\"\n [paginator]=\"true\"\n [rows]=\"20\"\n\n [totalRecords]=\"ContractRenewal.length\"\n>\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"true\">{{ 'Crm.AccountMessage.Account' | transloco }}</th>\n <th scope=\"true\" class=\"mrr-header\">{{ 'Crm.AccountMessage.MRR' | transloco }}</th>\n\n <th scope=\"true\">{{ 'Crm.AccountMessage.Quarter' | transloco }}</th>\n <th scope=\"true\"> {{ 'Crm.AccountMessage.Month' | transloco }}</th>\n\n <th scope=\"true\">{{ 'Crm.AccountMessage.SignUpAt' | transloco }}</th>\n <th scope=\"true\">{{ 'Crm.AccountMessage.CCExpAt' | transloco }}</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\"\n let-account>\n <tr>\n <td data-head=\"Account\">\n <a [routerLink]=\"['/' + subscription?.slug + routers.accountInfo, account.crm_account_id]\" class=\"name-link\">\n <span [ngbTooltip]=\"account.crm_account_name\">{{ account.crm_account_name | textTruncate:20 }}</span>\n </a>\n </td>\n <td data-head=\"MRR\" class=\"expected-mrr\">\n {{ account.expected_mrr / 100 | currency: account.currency }}\n </td>\n <td data-head=\"Quarter\">{{ account.sessions_last_quarter }}</td>\n <td data-head=\"Month\">{{ account.sessions_last_month }}</td>\n <td data-head=\"SignUpAt\">\n {{ account.signed_up_at | dateFormat }}\n </td>\n <td data-head=\"ExpAt\">\n {{ account.cc_expiring_at | dateFormat }}\n </td>\n </tr>\n </ng-template>\n </p-table>\n <span class=\"total-records-count\" *ngIf=\"ContractRenewal.length !== 0\">{{ 'Label.Total' | transloco }}: {{ ContractRenewal.length }}</span>\n </div>\n <div *ngIf=\"ContractRenewal?.length === 0\">\n <pw-no-data [withImage]=\"true\" [message]=\"'Crm.Summary.NoInsightMessage' | transloco\"> </pw-no-data>\n </div>\n </div>\n\n\n <!-- Account Insights -->\n <div class=\"col-12 col-md-6 mb-3 analytics\">\n <h5 class=\"accordion-heading\">Account Insights</h5>\n <div class=\"w-100 text-center mt-3\">\n <ng-template [ngIf]=\"!accountInsightLoaded\">\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </ng-template>\n </div>\n <div class=\"primeng-datatable-container table-responsive\"\n *ngIf=\"accountInsight?.length\">\n <p-table class=\"table\"\n #dt\n [value]=\"accountInsight\"\n [paginator]=\"true\"\n [rows]=\"20\"\n\n [totalRecords]=\"12\"\n>\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"true\">{{ 'Value' }}</th>\n <th scope=\"true\">{{ 'Crm.Summary.Title' | transloco }}</th>\n <th scope=\"true\"> {{ 'Crm.ContactMessage.Reason' | transloco }} </th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\"\n let-account>\n <tr>\n <td data-head=\"value\">{{ account.value }}</td>\n <td data-head=\"title\">{{ account.title }}</td>\n <td data-head=\"reason\">\n {{ account.reason }}\n </td>\n </tr>\n </ng-template>\n </p-table>\n </div>\n <div *ngIf=\"!accountInsight?.length && accountInsightLoaded\">\n <pw-no-data [withImage]=\"true\" [message]=\"'Crm.Summary.NoInsightMessage' | transloco\"> </pw-no-data>\n </div>\n </div>\n <div class=\"col-12 col-md-6 mb-3 analytics\">\n <h5 class=\"accordion-heading\">Geography</h5>\n <div>\n <ng-template [ngIf]=\"accountGeography\">\n <plotly-plot [data]=\"accountGeography?.data\"\n [layout]=\"accountGeography?.layout\" [useResizeHandler]=\"true\">\n </plotly-plot>\n </ng-template>\n </div>\n <div *ngIf=\"!accountGeography\">\n <pw-no-data [withImage]=\"true\" [message]=\"'Crm.ContactMessage.NoInsightMessage' | transloco\">\n </pw-no-data>\n </div>\n </div>\n </ng-container>\n</div>\n" }]
195
+ }], ctorParameters: () => [{ type: i1.CrmService }, { type: i0.Injector }] });
196
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnQtY3JtLWFjY291bnQtaW5zaWdodC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9saWJzL3NtYXJ0LWNybS9zcmMvbGliL3ByaXZhdGUvY29tcG9uZW50cy9zbWFydC1jcm0taW5zaWdodC9zbWFydC1jcm0tYWNjb3VudC1pbnNpZ2h0L3NtYXJ0LWNybS1hY2NvdW50LWluc2lnaHQuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vbGlicy9zbWFydC1jcm0vc3JjL2xpYi9wcml2YXRlL2NvbXBvbmVudHMvc21hcnQtY3JtLWluc2lnaHQvc21hcnQtY3JtLWFjY291bnQtaW5zaWdodC9zbWFydC1jcm0tYWNjb3VudC1pbnNpZ2h0LmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsUUFBUSxFQUFxQixNQUFNLGVBQWUsQ0FBQztBQUN2RSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFFeEQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFPaEUsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLG9DQUFvQyxDQUFDOzs7Ozs7Ozs7Ozs7OztBQU03RCxNQUFNLE9BQU8sK0JBQWdDLFNBQVEsZ0JBQWdCO0lBbURqRSxZQUNxQixVQUFzQixFQUN2QyxRQUFrQjtRQUVsQixLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7UUFIQyxlQUFVLEdBQVYsVUFBVSxDQUFZO1FBbkMzQyxZQUFPLEdBQUcsT0FBTyxDQUFDO1FBUWxCLCtCQUEwQixHQUFHLEtBQUssQ0FBQztRQUVuQyxnQ0FBMkIsR0FBRyxLQUFLLENBQUM7UUFFcEMseUJBQW9CLEdBQUcsS0FBSyxDQUFDO1FBRTdCLDhCQUF5QixHQUFHLEtBQUssQ0FBQztRQUVsQywrQkFBMEIsR0FBRyxLQUFL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USxDQUFDO1FBQzVDLENBQUMsQ0FBQzthQUNELEdBQUcsQ0FBQyxHQUFHLEVBQUU7WUFDTixJQUFJLENBQUMsc0JBQXNCLEdBQUcsSUFBSSxDQUFDO1FBQ3ZDLENBQUMsQ0FBQyxDQUFDO0lBQ1gsQ0FBQztJQUVELGVBQWUsQ0FBQyxVQUFrQjtRQUM5QixPQUFPLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxtQkFBbUIsQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUNsRSxDQUFDO0lBRVEsV0FBVztRQUNoQixLQUFLLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDeEIsQ0FBQzsrR0FsTlEsK0JBQStCO21HQUEvQiwrQkFBK0IsMkZDaEI1QyxzNmtCQTRZQTs7NEZENVhhLCtCQUErQjtrQkFKM0MsU0FBUzsrQkFDSSw4QkFBOEIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIEluamVjdG9yLCBPbkRlc3Ryb3ksIE9uSW5pdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ3JtU2VydmljZSB9IGZyb20gJ0Bwb3Npd2lzZS9zbWFydC1jcm0tc2hhcmVkJztcblxuaW1wb3J0IHsgQXBwQmFzZUNvbXBvbmVudCB9IGZyb20gJ0Bwb3Npd2lzZS9hcHAtYmFzZS1jb21wb25lbnQnO1xuaW1wb3J0IHtcbiAgICBTdWJzY3JpcHRpb24sXG4gICAgVXNlcixcbiAgICBhY3RpdmVPcHBvcnR1bml0aWVzLFxuICAgIHNpZ25lZFVwTGFzdFRoaXJ0eURheXNcbn0gZnJvbSAnQHBvc2l3aXNlL2NvbW1vbi11dGlsaXRpZXMnO1xuaW1wb3J0IHsgUk9VVEVSUyB9IGZyb20gJy4uLy4uLy4uLy4uL3NoYXJlZC9yb3V0ZXJzL3JvdXRlcnMnO1xuXG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogJ3B3LXNtYXJ0LWNybS1hY2NvdW50LWluc2lnaHQnLFxuICAgIHRlbXBsYXRlVXJsOiAnLi9zbWFydC1jcm0tYWNjb3VudC1pbnNpZ2h0LmNvbXBvbmVudC5odG1sJ1xufSlcbmV4cG9ydCBjbGFzcyBTbWFydENybUFjY291bnRJbnNpZ2h0Q29tcG9uZW50IGV4dGVuZHMgQXBwQmFzZUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcbiAgICBzaWduZWRVcExhc3RUaGlydHlEYXlzOiBzaWduZWRVcExhc3RUaGlydHlEYXlzW107XG5cbiAgICBhY3RpdmVPcHBvcnR1bml0aWVzOiBhY3RpdmVPcHBvcnR1bml0aWVzW107XG5cbiAgICBhY2NvdW50QXRSaXNrOiBbXTtcblxuICAgIENvbnRyYWN0UmVuZXdhbDogW107XG5cbiAgICBhY2NvdW50SW5zaWdodDogW107XG5cbiAgICBhY2NvdW50R2VvZ3JhcGh5OiBbXTtcblxuICAgIGNodXJuZWRBY2NvdW50czogW107XG5cbiAgICBhY2NvdW50TGFzdEFjdGl2aXRpZXM6IFtdO1xuXG4gICAgcm91dGVycyA9IFJPVVRFUlM7XG5cbiAgICBjcmVkaXRDYXJkRXhwaXJpbmc6IFtdO1xuXG4gICAgbWFnaWNNb21lbnQ6IFtdO1xuXG4gICAgdXNlcjogVXNlcjtcblxuICAgIHNpZ25VcExhc3ROaW5ldHlEYXlzTG9hZGVkID0gZmFsc2U7XG5cbiAgICBhY2NvdW50TGFzdEFjdGl2aXRpZXNMb2FkZWQgPSBmYWxzZTtcblxuICAgIGNodXJuZWRBY2NvdW50TG9hZGVkID0gZmFsc2U7XG5cbiAgICBhY3RpdmVPcHBvcnR1bml0aWVzTG9hZGVkID0gZmFsc2U7XG5cbiAgICBhY2NvdW50QXRSaXNrRGV0YWlsc0xvYWRlZCA9IGZhbHNlO1xuXG4gICAgY29udGFjdFJlbmV3YWxMb2FkZWQgPSBmYWxzZTtcblxuICAgIGNyZWRpdENhcmRFeHBpcmluZ0RldGFpbHNMb2FkZWQgPSBmYWxzZTtcblxuICAgIGFjY291bnRHZW9ncmFwaHlMb2FkZWQgPSBmYWxzZTtcblxuICAgIGFjY291bnRJbnNpZ2h0TG9hZGVkID0gZmFsc2U7XG5cbiAgICBtYWdpY01vbWVudExvYWRlZCA9IGZhbHNlO1xuXG4gICAgc3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb247XG4gICAgaGFzQWNjZXNzOiBib29sZWFuO1xuICAgIHVzZXJJZDogbnVtYmVyO1xuXG4gICAgYWN0aW9uTmFtZXM7XG5cbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgcHJpdmF0ZSByZWFkb25seSBjcm1TZXJ2aWNlOiBDcm1TZXJ2aWNlLFxuICAgICAgICBpbmplY3RvcjogSW5qZWN0b3JcbiAgICApIHtcbiAgICAgICAgc3VwZXIoaW5qZWN0b3IpO1xuICAgIH1cblxuICAgIG5nT25Jbml0KCk6IHZvaWQge1xuICAgICAgICB0aGlzLmdldFVzZXJTdWJzY3JpcHRpb24oKS5zdWJzY3JpYmUocmVzcG9uc2UgPT4ge1xuICAgICAgICAgICAgdGhpcy5zdWJzY3JpcHRpb24gPSByZXNwb25zZTtcbiAgICAgICAgICAgIGlmICh0aGlzLnN1YnNjcmlwdGlvbj8uaWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhhc0FjY2VzcyA9IHRoaXMuaGFzQWRtaW5BY2Nlc3ModGhpcy5zdWJzY3JpcHRpb24uaWQpO1xuICAgICAgICAgICAgICAgIHRoaXMuZ2V0VXNlckluZm8oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRVc2VySW5mbygpIHtcbiAgICAgICAgdGhpcy51c2VyU3RvcmUoKS5zdWJzY3JpYmUodXNlciA9PiB7XG4gICAgICAgICAgICBpZiAodXNlcikge1xuICAgICAgICAgICAgICAgIHRoaXMudXNlciA9IHVzZXI7XG4gICAgICAgICAgICAgICAgdGhpcy51c2VySWQgPSB1c2VyLmlkO1xuICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wZXJtaXNzaW9uU2VydmljZS5pc0dyYW50ZWQoJ1BhZ2VzLkJldGEnKSB8fFxuICAgICAgICAgICAgICAgICAgICB0aGlzLnBlcm1pc3Npb25TZXJ2aWNlLmlzU3VwZXJBZG1pbigpXG4gICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZ2V0U2lnbmVkVXBMYXN0TmluZXR5RGF5cygpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmdldEFjdGl2ZU9wcG9ydHVuaXRpZXMoKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5nZXRDaHVybmVkQWNjb3VudHMoKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5nZXRBY2NvdW50TGFzdEFjdGl2aXRpZXMoKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5nZXRBY2NvdW50QXRSaXNrRGV0YWlscygpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmdldENvbnRhY3RSZW5ld2FsKCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZ2V0QWNjb3VudEdlb2dyYXBoeSgpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmdldEFjY291bnRJbnNpZ2h0cygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqIEZ1bmN0aW9uIHRvIGNhbGwgc2lnbmVkIHVwIGxhc3QgOTAgZGF5cyBkZXRhaWxzICovXG4gICAgcHJpdmF0ZSBnZXRTaWduZWRVcExhc3ROaW5ldHlEYXlzKCkge1xuICAgICAgICB0aGlzLmNybVNlcnZpY2VcbiAgICAgICAgICAgIC5nZXRDcm1BbmFseXRpY3ModGhpcy5zdWJzY3JpcHRpb24/LmlkLCAnYWNjb3VudHNfc2lnbmVkX3VwX2xhc3RfOTBfZGF5cycpXG4gICAgICAgICAgICAuc3Vic2NyaWJlKHJlc3BvbnNlID0+IHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHJlc3BvbnNlID09PSAnb2JqZWN0JyAmJiBPYmplY3Qua2V5cyhyZXNwb25zZSkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2lnbmVkVXBMYXN0VGhpcnR5RGF5cyA9IFtdO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB0aGlzLnNpZ25lZFVwTGFzdFRoaXJ0eURheXMgPSByZXNwb25zZTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuYWRkKCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNpZ25VcExhc3ROaW5ldHlEYXlzTG9hZGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0QWNjb3VudExhc3RBY3Rpdml0aWVzKCkge1xuICAgICAgICB0aGlzLmNybVNlcnZpY2VcbiAgICAgICAgICAgIC5nZXRDcm1BbmFseXRpY3ModGhpcy5zdWJzY3JpcHRpb24/LmlkLCAnYWNjb3VudHNfbGFzdF9hY3Rpdml0aWVzJylcbiAgICAgICAgICAgIC5zdWJzY3JpYmUocmVzcG9uc2UgPT4ge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgcmVzcG9uc2UgPT09ICdvYmplY3QnICYmIE9iamVjdC5rZXlzKHJlc3BvbnNlKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5hY2NvdW50TGFzdEFjdGl2aXRpZXMgPSBbXTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmFjY291bnRMYXN0QWN0aXZpdGllcyA9IHJlc3BvbnNlO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmFjdGlvbk5hbWVzID0gcmVzcG9uc2U/Lm1hcChhY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFjdGlvbj8uY3JtX2FjdGlvbj8ubmFtZTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKHRoaXMuYWNjb3VudExhc3RBY3Rpdml0aWVzKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuYWRkKCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmFjY291bnRMYXN0QWN0aXZpdGllc0xvYWRlZCA9IHRydWU7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldENodXJuZWRBY2NvdW50cygpIHtcbiAgICAgICAgdGhpcy5jcm1TZXJ2aWNlXG4gICAgICAgICAgICAuZ2V0Q3JtQW5hbHl0aWNzKHRoaXMuc3Vic2NyaXB0aW9uPy5pZCwgJ2FjY291bnRzX2FjY291bnRzX2NodXJuZWQnKVxuICAgICAgICAgICAgLnN1YnNjcmliZShyZXNwb25zZSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiByZXNwb25zZSA9PT0gJ29iamVjdCcgJiYgT2JqZWN0LmtleXMocmVzcG9uc2UpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNodXJuZWRBY2NvdW50cyA9IFtdO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB0aGlzLmNodXJuZWRBY2NvdW50cyA9IHJlc3BvbnNlO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5hZGQoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuY2h1cm5lZEFjY291bnRMb2FkZWQgPSB0cnVlO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqIEZ1bmN0aW9uIHRvIGNhbGwgQWN0aXZlIE9wcG9ydHVuaXRpZXMgZGV0YWlscyAqL1xuICAgIHByaXZhdGUgZ2V0QWN0aXZlT3Bwb3J0dW5pdGllcygpIHtcbiAgICAgICAgdGhpcy5jcm1TZXJ2aWNlXG4gICAgICAgICAgICAuZ2V0Q3JtQW5hbHl0aWNzKHRoaXMuc3Vic2NyaXB0aW9uPy5pZCwgJ2FjY291bnRzX2FjdGl2ZV9vcHBvcnR1bml0aWVzJylcbiAgICAgICAgICAgIC5zdWJzY3JpYmUocmVzcG9uc2UgPT4ge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgcmVzcG9uc2UgPT09ICdvYmplY3QnICYmIE9iamVjdC5rZXlzKHJlc3BvbnNlKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5hY3RpdmVPcHBvcnR1bml0aWVzID0gW107XG4gICAgICAgICAgICAgICAgfSBlbHNlIHRoaXMuYWN0aXZlT3Bwb3J0dW5pdGllcyA9IHJlc3BvbnNlO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5hZGQoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuYWN0aXZlT3Bwb3J0dW5pdGllc0xvYWRlZCA9IHRydWU7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKiogRnVuY3Rpb24gdG8gY2FsbCBBY2NvdW50IEF0IFJpc2sgZGV0YWlscyAqL1xuICAgIHByaXZhdGUgZ2V0QWNjb3VudEF0Umlza0RldGFpbHMoKSB7XG4gICAgICAgIHRoaXMuY3JtU2VydmljZVxuICAgICAgICAgICAgLmdldENybUFuYWx5dGljcyh0aGlzLnN1YnNjcmlwdGlvbj8uaWQsICdhY2NvdW50c19hY2NvdW50c19hdF9yaXNrJylcbiAgICAgICAgICAgIC5zdWJzY3JpYmUocmVzcG9uc2UgPT4ge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgcmVzcG9uc2UgPT09ICdvYmplY3QnICYmIE9iamVjdC5rZXlzKHJlc3BvbnNlKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5hY2NvdW50QXRSaXNrID0gW107XG4gICAgICAgICAgICAgICAgfSBlbHNlIHRoaXMuYWNjb3VudEF0UmlzayA9IHJlc3BvbnNlO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5hZGQoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuYWNjb3VudEF0Umlza0RldGFpbHNMb2FkZWQgPSB0cnVlO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqIEZ1bmN0aW9uIHRvIGNhbGwgQ29udHJhY3QgcmVuZXdhbCBkZXRhaWxzICovXG4gICAgcHJpdmF0ZSBnZXRDb250YWN0UmVuZXdhbCgpIHtcbiAgICAgICAgdGhpcy5jcm1TZXJ2aWNlXG4gICAgICAgICAgICAuZ2V0Q3JtQW5hbHl0aWNzKHRoaXMuc3Vic2NyaXB0aW9uPy5pZCwgJ2FjY291bnRzX2NvbnRyYWN0X3JlbmV3YWwnKVxuICAgICAgICAgICAgLnN1YnNjcmliZShyZXNwb25zZSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiByZXNwb25zZSA9PT0gJ29iamVjdCcgJiYgT2JqZWN0LmtleXMocmVzcG9uc2UpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLkNvbnRyYWN0UmVuZXdhbCA9IFtdO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB0aGlzLkNvbnRyYWN0UmVuZXdhbCA9IHJlc3BvbnNlO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5hZGQoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuY29udGFjdFJlbmV3YWxMb2FkZWQgPSB0cnVlO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRBY2NvdW50SW5zaWdodHMoKSB7XG4gICAgICAgIHRoaXMuY3JtU2VydmljZVxuICAgICAgICAgICAgLmdldENybUFuYWx5dGljcyh0aGlzLnN1YnNjcmlwdGlvbj8uaWQsICdhY2NvdW50c19pbnNpZ2h0cycpXG4gICAgICAgICAgICAuc3Vic2NyaWJlKHJlc3BvbnNlID0+IHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHJlc3BvbnNlID09PSAnb2JqZWN0JyAmJiBPYmplY3Qua2V5cyhyZXNwb25zZSkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuYWNjb3VudEluc2lnaHQgPSBbXTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgdGhpcy5hY2NvdW50SW5zaWdodCA9IHJlc3BvbnNlO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5hZGQoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuYWNjb3VudEluc2lnaHRMb2FkZWQgPSB0cnVlO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRBY2NvdW50R2VvZ3JhcGh5KCkge1xuICAgICAgICB0aGlzLmNybVNlcnZpY2VcbiAgICAgICAgICAgIC5nZXRDcm1BbmFseXRpY3ModGhpcy5zdWJzY3JpcHRpb24/LmlkLCAnYWNjb3VudHNfZ2VvZ3JhcGh5JylcbiAgICAgICAgICAgIC5zdWJzY3JpYmUocmVzcG9uc2UgPT4ge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgcmVzcG9uc2UgPT09ICdvYmplY3QnICYmIE9iamVjdC5rZXlzKHJlc3BvbnNlKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5hY2NvdW50R2VvZ3JhcGh5ID0gW107XG4gICAgICAgICAgICAgICAgfSBlbHNlIHRoaXMuYWNjb3VudEdlb2dyYXBoeSA9IHJlc3BvbnNlO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5hZGQoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuYWNjb3VudEdlb2dyYXBoeUxvYWRlZCA9IHRydWU7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBjaGVja1Blcm1pc3Npb24ocGVybWlzc2lvbjogc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnBlcm1pc3Npb25TZXJ2aWNlLmV2YWx1YXRlUGVybWlzc2lvbnMocGVybWlzc2lvbik7XG4gICAgfVxuXG4gICAgb3ZlcnJpZGUgbmdPbkRlc3Ryb3koKSB7XG4gICAgICAgIHN1cGVyLm5nT25EZXN0cm95KCk7XG4gICAgfVxufVxuIiwiPGRpdiBjbGFzcz1cInJvd1wiPlxuICA8bmctY29udGFpbmVyIGNsYXNzPVwibXQtNVwiXG4gICAgKnJiYWNBbGxvdz1cIidQYWdlcy5CZXRhJ1wiPlxuICAgIDwhLS0gU2lnbmVkIHVwIGxhc3QgOTAgZGF5cyAtLT5cbiAgICA8ZGl2IGNsYXNzPVwiY29sLTEyIGNvbC1tZC02IG1iLTMgYW5hbHl0aWNzXCI+XG4gICAgICA8aDUgY2xhc3M9XCJhY2NvcmRpb24taGVhZGluZ1wiPlNpZ25lZCB1cCBMYXN0IDkwIERheXM8L2g1PlxuICAgICAgPGRpdiBjbGFzcz1cInctMTAwIHRleHQtY2VudGVyIG10LTNcIj5cbiAgICAgICAgPG5nLXRlbXBsYXRlIFtuZ0lmXT1cIiFzaWduVXBMYXN0TmluZXR5RGF5c0xvYWRlZFwiPlxuICAgICAgICAgIDxwLXByb2dyZXNzU3Bpbm5lciBzdHJva2VXaWR0aD1cIjJcIj4gPC9wLXByb2dyZXNzU3Bpbm5lcj5cbiAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cInByaW1lbmctZGF0YXRhYmxlLWNvbnRhaW5lciB0YWJsZS1yZXNwb25zaXZlXCJcbiAgICAgICAgKm5nSWY9XCJzaWduZWRVcExhc3RUaGlydHlEYXlzPy5sZW5ndGhcIj5cbiAgICAgICAgPHAtdGFibGUgY2xhc3M9XCJ0YWJsZVwiXG4gICAgICAgICAgI2R0XG4gICAgICAgICAgW3ZhbHVlXT1cInNpZ25lZFVwTGFzdFRoaXJ0eURheXNcIlxuICAgICAgICAgIFtwYWdpbmF0b3JdPVwidHJ1ZVwiXG4gICAgICAgICAgW3Jvd3NdPVwiMjBcIlxuICAgICAgICAgIFt0b3RhbFJlY29yZHNdPVwic2lnbmVkVXBMYXN0VGhpcnR5RGF5cy5sZW5ndGhcIlxuPlxuICAgICAgICAgIDxuZy10ZW1wbGF0ZSBwVGVtcGxhdGU9XCJoZWFkZXJcIj5cbiAgICAgICAgICAgIDx0cj5cbiAgICAgICAgICAgICAgPHRoIHNjb3BlPVwidHJ1ZVwiPnt7ICdDcm0uU3VtbWFyeS5BY2NvdW50JyB8IHRyYW5zbG9jbyB9fTwvdGg+XG4gICAgICAgICAgICAgIDx0aCBzY29wZT1cInRydWVcIiBjbGFzcz1cIm1yci1oZWFkZXJcIj57eyAnQ3JtLkFjY291bnRNZXNzYWdlLk1SUicgfCB0cmFuc2xvY28gfX08L3RoPlxuICAgICAgICAgICAgICA8dGggc2NvcGU9XCJ0cnVlXCI+e3sgJ0NybS5BY2NvdW50TWVzc2FnZS5TaWduVXBBdCcgfCB0cmFuc2xvY28gfX08L3RoPlxuICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgIDxuZy10ZW1wbGF0ZSBwVGVtcGxhdGU9XCJib2R5XCJcbiAgICAgICAgICAgIGxldC1zaWduVXA+XG4gICAgICAgICAgICA8dHI+XG4gICAgICAgICAgICAgIDx0ZCBkYXRhLWhlYWQ9XCJBY2NvdW50XCI+XG4gICAgICAgICAgICAgICAgPGEgW3JvdXRlckxpbmtdPVwiWycvJyArIHN1YnNjcmlwdGlvbj8uc2x1ZyArIHJvdXRlcnMuYWNjb3VudEluZm8sIHNpZ25VcC5jcm1fYWNjb3VudF9pZF1cIiBjbGFzcz1cIm5hbWUtbGlua1wiPlxuICAgICAgICAgICAgICAgICAgPHNwYW4gW25nYlRvb2x0aXBdPVwic2lnblVwLmNybV9hY2NvdW50X25hbWVcIj57eyBzaWduVXA/LmNybV9hY2NvdW50X25hbWUgfCB0ZXh0VHJ1bmNhdGU6MjAgfX08L3NwYW4+XG4gICAgICAgICAgICAgICAgPC9hPlxuICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICA8dGQgZGF0YS1oZWFkPVwiTVJSXCIgY2xhc3M9XCJleHBlY3RlZC1tcnJcIj5cbiAgICAgICAgICAgICAgICB7eyBzaWduVXAuZXhwZWN0ZWRfbXJyIC8gMTAwIHwgY3VycmVuY3k6IHNpZ25VcC5jdXJyZW5jeSB9fVxuICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICA8dGQgZGF0YS1oZWFkPVwiU2lnblVwQXRcIj5cbiAgICAgICAgICAgICAgICB7eyBzaWduVXAuc2lnbmVkX3VwX2F0IHwgZGF0ZUZvcm1hdCB9fVxuICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICA8L3AtdGFibGU+XG4gICAgICAgIDxzcGFuIGNsYXNzPVwidG90YWwtcmVjb3Jkcy1jb3VudFwiICpuZ0lmPVwic2lnbmVkVXBMYXN0VGhpcnR5RGF5cy5sZW5ndGghPT0gMFwiPnt7ICdMYWJlbC5Ub3RhbCcgfCB0cmFuc2xvY28gfX06IHt7IHNpZ25lZFVwTGFzdFRoaXJ0eURheXMubGVuZ3RoIH19PC9zcGFuPlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2ICpuZ0lmPVwic2lnbmVkVXBMYXN0VGhpcnR5RGF5cz8ubGVuZ3RoID09PSAwXCI+XG4gICAgICAgIDxwdy1uby1kYXRhIFt3aXRoSW1hZ2VdPVwidHJ1ZVwiIFttZXNzYWdlXT1cIidDcm0uU3VtbWFyeS5Ob0luc2lnaHRNZXNzYWdlJyB8IHRyYW5zbG9jb1wiPiA8L3B3LW5vLWRhdGE+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgICA8IS0tIEFjdGl2ZSBPcHBvcnR1bml0aWVzIC0tPlxuICAgIDxkaXYgY2xhc3M9XCJjb2wtMTIgY29sLW1kLTYgbWItMyBhbmFseXRpY3NcIj5cbiAgICAgIDxoNSBjbGFzcz1cImFjY29yZGlvbi1oZWFkaW5nXCI+QWN0aXZlIE9wcG9ydHVuaXRpZXM8L2g1PlxuICAgICAgPGRpdiBjbGFzcz1cInctMTAwIHRleHQtY2VudGVyIG10LTNcIj5cbiAgICAgICAgPG5nLXRlbXBsYXRlIFtuZ0lmXT1cIiFhY3RpdmVPcHBvcnR1bml0aWVzTG9hZGVkXCI+XG4gICAgICAgICAgPHAtcHJvZ3Jlc3NTcGlubmVyIHN0cm9rZVdpZHRoPVwiMlwiPiA8L3AtcHJvZ3Jlc3NTcGlubmVyPlxuICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwicHJpbWVuZy1kYXRhdGFibGUtY29udGFpbmVyIHRhYmxlLXJlc3BvbnNpdmVcIlxuICAgICAgICAqbmdJZj1cImFjdGl2ZU9wcG9ydHVuaXRpZXM/Lmxlbmd0aFwiPlxuICAgICAgICA8cC10YWJsZSBjbGFzcz1cInRhYmxlXCJcbiAgICAgICAgICAjZHRcbiAgICAgICAgICBbdmFsdWVdPVwiYWN0aXZlT3Bwb3J0dW5pdGllc1wiXG4gICAgICAgICAgW3BhZ2luYXRvcl09XCJ0cnVlXCJcbiAgICAgICAgICBbcm93c109XCIyMFwiXG5cbiAgICAgICAgICBbdG90YWxSZWNvcmRzXT1cImFjdGl2ZU9wcG9ydHVuaXRpZXMubGVuZ3RoXCJcbj5cbiAgICAgICAgICA8bmctdGVtcGxhdGUgcFRlbXBsYXRlPVwiaGVhZGVyXCI+XG4gICAgICAgICAgICA8dHI+XG4gICAgICAgICAgICAgIDx0aCBzY29wZT1cInRydWVcIj57eyAnQ3JtLlN1bW1hcnkuQWNjb3VudCcgfCB0cmFuc2xvY28gfX08L3RoPlxuICAgICAgICAgICAgICA8dGggc2NvcGU9XCJ0cnVlXCI+e3sgJ0NybS5TdW1tYXJ5LlRpdGxlJyB8IHRyYW5zbG9jbyB9fTwvdGg+XG4gICAgICAgICAgICAgIDx0aCBzY29wZT1cInRydWVcIj57eyAnQ3JtLlN1bW1hcnkuT25lVGltZUFtb3VudCcgfCB0cmFuc2xvY28gfX08L3RoPlxuICAgICAgICAgICAgICA8dGggc2NvcGU9XCJ0cnVlXCIgY2xhc3M9XCJtcnItaGVhZGVyXCI+e3sgJ0NybS5BY2NvdW50TWVzc2FnZS5NUlInIHwgdHJhbnNsb2NvIH19PC90aD5cbiAgICAgICAgICAgICAgPHRoIHNjb3BlPVwidHJ1ZVwiPnt7ICdDcm0uU3VtbWFyeS5XaW5DaGFuY2UnIHwgdHJhbnNsb2NvIH19PC90aD5cbiAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICA8bmctdGVtcGxhdGUgcFRlbXBsYXRlPVwiYm9keVwiXG4gICAgICAgICAgICBsZXQtb3Bwb3J0dW5pdGllcz5cbiAgICAgICAgICAgIDx0cj5cbiAgICAgICAgICAgICAgPHRkIGRhdGEtaGVhZD1cIkFjY291bnRcIj5cbiAgICAgICAgICAgICAgICA8YSBbcm91dGVyTGlua109XCJbJy8nICsgc3Vic2NyaXB0aW9uPy5zbHVnICsgcm91dGVycy5hY2NvdW50SW5mbywgb3Bwb3J0dW5pdGllcy5jcm1fYWNjb3VudD8uaWRdXCIgY2xhc3M9XCJuYW1lLWxpbmtcIj5cbiAgICAgICAgICAgICAgICAgIDxzcGFuIFtuZ2JUb29sdGlwXT1cIm9wcG9ydHVuaXRpZXMuY3JtX2FjY291bnQ/Lm5hbWVcIj57eyBvcHBvcnR1bml0aWVzLmNybV9hY2NvdW50Py5uYW1lIHwgdGV4dFRydW5jYXRlOjIwIH19PC9zcGFuPlxuICAgICAgICAgICAgICAgIDwvYT5cbiAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgICAgPHRkIGRhdGEtaGVhZD1cIlRpdGxlXCI+XG4gICAgICAgICAgICAgICAgPGEgW25nYlRvb2x0aXBdPVwib3Bwb3J0dW5pdGllcz8udGl0bGVcIiAqbmdJZj1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzQWNjZXNzIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHBvcnR1bml0aWVzPy5vd25lcl9pZCA9PT0gdXNlcklkIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVja1Blcm1pc3Npb24oJ1BhZ2VzLlByb2R1Y3QuQ1JNLlJvbGUuQWRtaW4nKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIiBbcm91dGVyTGlua109XCJbXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLycgKyBzdWJzY3JpcHRpb24/LnNsdWcgKyByb3V0ZXJzLm9wcG9ydHVuaXR5SW5mbyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wcG9ydHVuaXRpZXMuaWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXVwiPlxuICAgICAgICAgICAgICAgIDxzcGFuPnt7IG9wcG9ydHVuaXRpZXM/LnRpdGxlIHwgdGV4dFRydW5jYXRlOiAyMCB9fSA8L3NwYW4+XG4gICAgICAgICAgICAgIDwvYT5cbiAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgICAgPHRkIGRhdGEtaGVhZD1cIk9uZSBUaW1lIEFtb3VudFwiPiB7eyBvcHBvcnR1bml0aWVzLm9uZV90aW1lX2Ftb3VudCAvIDEwMCB8IGN1cnJlbmN5IH19IDwvdGQ+XG4gICAgICAgICAgICAgIDx0ZCBkYXRhLWhlYWQ9XCJNb250aGx5IEFtb3VudFwiIGNsYXNzPVwiZXhwZWN0ZWQtbXJyXCI+IHt7IG9wcG9ydHVuaXRpZXMubW9udGhseV9hbW91bnQgLyAxMDAgfCBjdXJyZW5jeSB9fSA8L3RkPlxuICAgICAgICAgICAgICA8dGQgZGF0YS1oZWFkPVwiV2luIENoYW5jZVwiPiB7eyBvcHBvcnR1bml0aWVzLndpbl9jaGFuY2VzIC8gMTAwIHwgcGVyY2VudCB9fSA8c3BhbiBjbGFzcz1cInRleHQtZGFuZ2VyXCJcbiAgICAgICAgICAgICAgICAgICpuZ0lmPVwib3Bwb3J0dW5pdGllcy5jYW5jZWxsZWRcIj4hQ2FuY2VsbGVkITwvc3Bhbj5cbiAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgPC9wLXRhYmxlPlxuICAgICAgICA8c3BhbiBjbGFzcz1cInRvdGFsLXJlY29yZHMtY291bnRcIiAqbmdJZj1cImFjdGl2ZU9wcG9ydHVuaXRpZXMubGVuZ3RoICE9PSAwXCI+e3sgJ0xhYmVsLlRvdGFsJyB8IHRyYW5zbG9jbyB9fToge3sgYWN0aXZlT3Bwb3J0dW5pdGllcy5sZW5ndGggfX08L3NwYW4+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXYgKm5nSWY9XCJhY3RpdmVPcHBvcnR1bml0aWVzPy5sZW5ndGggPT09IDBcIj5cbiAgICAgICAgPHB3LW5vLWRhdGEgW3dpdGhJbWFnZV09XCJ0cnVlXCIgW21lc3NhZ2VdPVwiJ0NybS5TdW1tYXJ5Lk5vSW5zaWdodE1lc3NhZ2UnIHwgdHJhbnNsb2NvXCI+IDwvcHctbm8tZGF0YT5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJjb2wtMTIgY29sLW1kLTYgbWItMyBhbmFseXRpY3NcIj5cbiAgICAgIDxoNSBjbGFzcz1cImFjY29yZGlvbi1oZWFkaW5nXCI+TGFzdCBBY3Rpdml0aWVzPC9oNT5cbiAgICAgIDxkaXYgY2xhc3M9XCJ3LTEwMCB0ZXh0LWNlbnRlciBtdC0zXCI+XG4gICAgICAgIDxuZy10ZW1wbGF0ZSBbbmdJZl09XCIhYWNjb3VudExhc3RBY3Rpdml0aWVzTG9hZGVkXCI+XG4gICAgICAgICAgPHAtcHJvZ3Jlc3NTcGlubmVyIHN0cm9rZVdpZHRoPVwiMlwiPiA8L3AtcHJvZ3Jlc3NTcGlubmVyPlxuICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwicHJpbWVuZy1kYXRhdGFibGUtY29udGFpbmVyIHRhYmxlLXJlc3BvbnNpdmVcIlxuICAgICAgICAqbmdJZj1cImFjY291bnRMYXN0QWN0aXZpdGllcz8ubGVuZ3RoXCI+XG4gICAgICAgIDxwLXRhYmxlIGNsYXNzPVwidGFibGVcIlxuICAgICAgICAgICNkdFxuICAgICAgICAgIFt2YWx1ZV09XCJhY2NvdW50TGFzdEFjdGl2aXRpZXNcIlxuICAgICAgICAgIFtwYWdpbmF0b3JdPVwidHJ1ZVwiXG4gICAgICAgICAgW3Jvd3NdPVwiMjBcIlxuXG4gICAgICAgICAgW3RvdGFsUmVjb3Jkc109XCJhY2NvdW50TGFzdEFjdGl2aXRpZXMubGVuZ3RoXCJcbj5cbiAgICAgICAgICA8bmctdGVtcGxhdGUgcFRlbXBsYXRlPVwiaGVhZGVyXCI+XG4gICAgICAgICAgICA8dHI+XG4gICAgICAgICAgICAgIDx0aCBzY29wZT1cInRydWVcIj57eyAnQ3JtLkFjY291bnRNZXNzYWdlLk93bmVyJyB8IHRyYW5zbG9jbyB9fTwvdGg+XG4gICAgICAgICAgICAgIDx0aCBzY29wZT1cInRydWVcIj57eyAnQ3JtLkFjY291bnRNZXNzYWdlLkFjY291bnQnIHwgdHJhbnNsb2NvIH19PC90aD5cbiAgICAgICAgICAgICAgPHRoIHNjb3BlPVwidHJ1ZVwiPnt7ICdDcm0uQWNjb3VudE1lc3NhZ2UuQ29udGFjdCcgfCB0cmFuc2xvY28gfX08L3RoPlxuICAgICAgICAgICAgICA8dGggc2NvcGU9XCJ0cnVlXCI+e3sgJ0NybS5BY2NvdW50TWVzc2FnZS5BY3Rpb24nIHwgdHJhbnNsb2NvIH19PC90aD5cbiAgICAgICAgICAgICAgPHRoIHNjb3BlPVwidHJ1ZVwiPnt7ICdDcm0uQWNjb3VudE1lc3NhZ2UuV2hlbicgfCB0cmFuc2xvY28gfX08L3RoPlxuICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgIDxuZy10ZW1wbGF0ZSBwVGVtcGxhdGU9XCJib2R5XCIgbGV0LWFjdGl2aXRpZXM+XG4gICAgICAgICAgICA8dHI+XG4gICAgICAgICAgICAgIDx0ZCBkYXRhLWhlYWQ9XCJPd25lclwiPiB7eyBhY3Rpdml0aWVzLm93bmVyPy5maXJzdF9uYW1lLmNoYXJBdCgwKSB9fS4ge3sgYWN0aXZpdGllcy5vd25lcj8ubGFzdF9uYW1lIH19IDwvdGQ+XG4gICAgICAgICAgICAgIDx0ZCBkYXRhLWhlYWQ9XCJBY2NvdW50XCI+XG4gICAgICAgICAgICAgICAgPGEgW3JvdXRlckxpbmtdPVwiWycvJyArIHN1YnNjcmlwdGlvbj8uc2x1ZyArIHJvdXRlcnMuYWNjb3VudEluZm8sIGFjdGl2aXRpZXMuY3JtX2FjY291bnRfaWRdXCIgY2xhc3M9XCJuYW1lLWxpbmtcIj5cbiAgICAgICAgICAgICAgICAgIDxzcGFuIFtuZ2JUb29sdGlwXT1cImFjdGl2aXRpZXMuY3JtX2FjY291bnQ/Lm5hbWVcIj57eyBhY3Rpdml0aWVzLmNybV9hY2NvdW50Py5uYW1lIH19PC9zcGFuPlxuICAgICAgICAgICAgICAgIDwvYT5cbiAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgICAgPHRkIGRhdGEtaGVhZD1cIkNvbnRhY3RcIj5cbiAgICAgICAgICAgICAgICA8YSBbcm91dGVyTGlua109XCJbJy8nICsgc3Vic2NyaXB0aW9uPy5zbHVnICsgcm91dGVycy5jb250YWN0SW5mbywgYWN0aXZpdGllcy5jcm1fY29udGFjdF9pZF1cIiBjbGFzcz1cIm5hbWUtbGlua1wiPlxuICAgICAgICAgICAgICAgICAgPHNwYW4gW25nYlRvb2x0aXBdPVwiYWN0aXZpdGllcy5jcm1fY29udGFjdCA/IGFjdGl2aXRpZXMuY3JtX2NvbnRhY3QuZmlyc3RfbmFtZSArICcgJyArIGFjdGl2aXRpZXMuY3JtX2NvbnRhY3QubGFzdF9uYW1lIDogJydcIj57eyAoYWN0aXZpdGllcy5jcm1fY29udGFjdD8uZmlyc3RfbmFtZSArICcgJyArIGFjdGl2aXRpZXMuY3JtX2NvbnRhY3Q/Lmxhc3RfbmFtZSkgfCB0ZXh0VHJ1bmNhdGU6MjAgfX08L3NwYW4+XG4gICAgICAgICAgICAgICAgPC9hPlxuICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICA8dGQgZGF0YS1oZWFkPVwiQWN0aW9uXCI+XG4gICAgICAgICAgICAgICAgPHNwYW4gW25nYlRvb2x0aXBdPVwiYWN0aXZpdGllcy5jb21tZW50XCIgW2FwcER5bmFtaWNCYWRnZV09XCJ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbXNBcnJheTogYWN0aW9uTmFtZXMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbTogYWN0aXZpdGllcy5jcm1fYWN0aW9uPy5uYW1lXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XCJcbiAgICAgICAgICAgICAgICAgIGNvbG9yPVwiYmx1ZS1ncmV5XCJcbiAgICAgICAgICAgICAgICAgIGNsYXNzPVwiYmFkZ2VcIj57eyBhY3Rpdml0aWVzLmNybV9hY3Rpb24/Lm5hbWUgfX08L3NwYW4+XG4gICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICAgIDx0ZCBkYXRhLWhlYWQ9XCJXaGVuXCI+e3sgYWN0aXZpdGllcy53aGVuIHwgZGF0ZTonZGQtTU1NLVlZWVknIH19PC90ZD5cbiAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgPC9wLXRhYmxlPlxuICAgICAgICA8c3BhbiBjbGFzcz1cInRvdGFsLXJlY29yZHMtY291bnRcIiAqbmdJZj1cImFjY291bnRMYXN0QWN0aXZpdGllcy5sZW5ndGggIT09IDBcIj57eyAnTGFiZWwuVG90YWwnIHwgdHJhbnNsb2NvIH19OiB7eyBhY2NvdW50TGFzdEFjdGl2aXRpZXMubGVuZ3RoIH19PC9zcGFuPlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2ICpuZ0lmPVwiYWNjb3VudExhc3RBY3Rpdml0aWVzPy5sZW5ndGggPT09IDAgJiYgYWNjb3VudExhc3RBY3Rpdml0aWVzTG9hZGVkXCI+XG4gICAgICAgIDxwdy1uby1kYXRhIFt3aXRoSW1hZ2VdPVwidHJ1ZVwiIFttZXNzYWdlXT1cIidDcm0uU3VtbWFyeS5Ob0luc2lnaHRNZXNzYWdlJyB8IHRyYW5zbG9jb1wiPiA8L3B3LW5vLWRhdGE+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cblxuXG4gICAgPGRpdiBjbGFzcz1cImNvbC0xMiBjb2wtbWQtNiBtYi0zIGFuYWx5dGljc1wiPlxuICAgICAgPGg1IGNsYXNzPVwiYWNjb3JkaW9uLWhlYWRpbmdcIj5DaHVybmVkIExhc3QgOTAgRGF5czwvaDU+XG4gICAgICA8ZGl2IGNsYXNzPVwidy0xMDAgdGV4dC1jZW50ZXIgbXQtM1wiPlxuICAgICAgICA8bmctdGVtcGxhdGUgW25nSWZdPVwiIWNodXJuZWRBY2NvdW50TG9hZGVkXCI+XG4gICAgICAgICAgPHAtcHJvZ3Jlc3NTcGlubmVyIHN0cm9rZVdpZHRoPVwiMlwiPiA8L3AtcHJvZ3Jlc3NTcGlubmVyPlxuICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwicHJpbWVuZy1kYXRhdGFibGUtY29udGFpbmVyIHRhYmxlLXJlc3BvbnNpdmVcIlxuICAgICAgICAqbmdJZj1cImNodXJuZWRBY2NvdW50cz8ubGVuZ3RoXCI+XG4gICAgICAgIDxwLXRhYmxlIGNsYXNzPVwidGFibGVcIlxuICAgICAgICAgICNkdFxuICAgICAgICAgIFt2YWx1ZV09XCJjaHVybmVkQWNjb3VudHNcIlxuICAgICAgICAgIFtwYWdpbmF0b3JdPVwidHJ1ZVwiXG4gICAgICAgICAgW3Jvd3NdPVwiMjBcIlxuICAgICAgICAgIFt0b3RhbFJlY29yZHNdPVwiY2h1cm5lZEFjY291bnRzLmxlbmd0aFwiXG4+XG4gICAgICAgICAgPG5nLXRlbXBsYXRlIHBUZW1wbGF0ZT1cImhlYWRlclwiPlxuICAgICAgICAgICAgPHRyPlxuICAgICAgICAgICAgICA8dGggc2NvcGU9XCJ0cnVlXCI+e3sgJ0NybS5BY2NvdW50TWVzc2FnZS5BY2NvdW50JyB8IHRyYW5zbG9jbyB9fTwvdGg+XG4gICAgICAgICAgICAgIDx0aCBzY29wZT1cInRydWVcIiBjbGFzcz1cIm1yci1oZWFkZXJcIj57eyAnQ3JtLkFjY291bnRNZXNzYWdlLk1SUicgfCB0cmFuc2xvY28gfX08L3RoPlxuXG4gICAgICAgICAgICAgIDx0aCBzY29wZT1cInRydWVcIj57eyAnQ3JtLkFjY291bnRNZXNzYWdlLlF1YXJ0ZXInIHwgdHJhbnNsb2NvIH19PC90aD5cbiAgICAgICAgICAgICAgPHRoIHNjb3BlPVwidHJ1ZVwiPiB7eyAnQ3JtLkFjY291bnRNZXNzYWdlLk1vbnRoJyB8IHRyYW5zbG9jbyB9fTwvdGg+XG5cbiAgICAgICAgICAgICAgPHRoIHNjb3BlPVwidHJ1ZVwiPnt7ICdDcm0uQWNjb3VudE1lc3NhZ2UuVW5zdWJzY3JpYmVkQXQnIHwgdHJhbnNsb2NvIH19PC90aD5cbiAgICAgICAgICAgICAgPHRoIHNjb3BlPVwidHJ1ZVwiPnt7ICdDcm0uQWNjb3VudE1lc3NhZ2UuQ0NFeHBBdCcgfCB0cmFuc2xvY28gfX08L3RoPlxuICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgIDxuZy10ZW1wbGF0ZSBwVGVtcGxhdGU9XCJib2R5XCJcbiAgICAgICAgICBsZXQtYWNjb3VudD5cbiAgICAgICAgICA8dHI+XG4gICAgICAgICAgICA8dGQgZGF0YS1oZWFkPVwiQWNjb3VudFwiPlxuICAgICAgICAgICAgICA8YSBbcm91dGVyTGlua109XCJbJy8nICsgc3Vic2NyaXB0aW9uPy5zbHVnICsgcm91dGVycy5hY2NvdW50SW5mbywgYWNjb3VudC5jcm1fYWNjb3VudF9pZF1cIiBjbGFzcz1cIm5hbWUtbGlua1wiPlxuICAgICAgICAgICAgICAgIDxzcGFuIFtuZ2JUb29sdGlwXT1cImFjY291bnQuY3JtX2FjY291bnRfbmFtZVwiPnt7IGFjY291bnQuY3JtX2FjY291bnRfbmFtZSB8IHRleHRUcnVuY2F0ZToyMCB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgPC9hPlxuICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgIDx0ZCBkYXRhLWhlYWQ9XCJNUlJcIiBjbGFzcz1cImV4cGVjdGVkLW1yclwiPlxuICAgICAgICAgICAgICB7eyBhY2NvdW50LmV4cGVjdGVkX21yciAvIDEwMCB8IGN1cnJlbmN5OiBhY2NvdW50LmN1cnJlbmN5IH19XG4gICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgPHRkIGRhdGEtaGVhZD1cIlF1YXJ0ZXJcIj57eyBhY2NvdW50LnNlc3Npb25zX2xhc3RfcXVhcnRlciB9fTwvdGQ+XG4gICAgICAgICAgICA8dGQgZGF0YS1oZWFkPVwiTW9udGhcIj57eyBhY2NvdW50LnNlc3Npb25zX2xhc3RfbW9udGggfX08L3RkPlxuICAgICAgICAgICAgPHRkIGRhdGEtaGVhZD1cIlNpZ25VcEF0XCI+XG4gICAgICAgICAgICAgIHt7IGFjY291bnQuc2lnbmVkX3VwX2F0IHwgZGF0ZUZvcm1hdCB9fVxuICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgIDx0ZCBkYXRhLWhlYWQ9XCJFeHBBdFwiPlxuICAgICAgICAgICAgICB7eyBhY2NvdW50LmNjX2V4cGlyaW5nX2F0IHwgZGF0ZUZvcm1hdCB9fVxuICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICA8L3RyPlxuICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICA8L3AtdGFibGU+XG4gICAgICAgIDxzcGFuIGNsYXNzPVwidG90YWwtcmVjb3Jkcy1jb3VudFwiICpuZ0lmPVwiY2h1cm5lZEFjY291bnRzPy5sZW5ndGggIT09IDBcIj57eyAnTGFiZWwuVG90YWwnIHwgdHJhbnNsb2NvIH19OiB7eyBjaHVybmVkQWNjb3VudHMubGVuZ3RoIH19PC9zcGFuPlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2ICpuZ0lmPVwiY2h1cm5lZEFjY291bnRzPy5sZW5ndGggPT09IDAgJiYgY2h1cm5lZEFjY291bnRMb2FkZWRcIj5cbiAgICAgICAgPHB3LW5vLWRhdGEgW3dpdGhJbWFnZV09XCJ0cnVlXCIgW21lc3NhZ2VdPVwiJ0NybS5TdW1tYXJ5Lk5vSW5zaWdodE1lc3NhZ2UnIHwgdHJhbnNsb2NvXCI+IDwvcHctbm8tZGF0YT5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuXG4gICAgPCEtLSBBY2NvdW50cyBhdCByaXNrIC0tPlxuICAgIDxkaXYgY2xhc3M9XCJjb2wtMTIgY29sLW1kLTYgbWItMyBhbmFseXRpY3NcIj5cbiAgICAgIDxoNSBjbGFzcz1cImFjY29yZGlvbi1oZWFkaW5nXCI+QWNjb3VudHMgYXQgUmlzazwvaDU+XG4gICAgICA8ZGl2IGNsYXNzPVwidy0xMDAgdGV4dC1jZW50ZXIgbXQtM1wiPlxuICAgICAgICA8bmctdGVtcGxhdGUgW25nSWZdPVwiIWFjY291bnRBdFJpc2tEZXRhaWxzTG9hZGVkXCI+XG4gICAgICAgICAgPHAtcHJvZ3Jlc3NTcGlubmVyIHN0cm9rZVdpZHRoPVwiMlwiPiA8L3AtcHJvZ3Jlc3NTcGlubmVyPlxuICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwicHJpbWVuZy1kYXRhdGFibGUtY29udGFpbmVyIHRhYmxlLXJlc3BvbnNpdmVcIlxuICAgICAgICAqbmdJZj1cImFjY291bnRBdFJpc2s/Lmxlbmd0aFwiPlxuICAgICAgICA8cC10YWJsZSBjbGFzcz1cInRhYmxlXCJcbiAgICAgICAgICAjZHRcbiAgICAgICAgICBbdmFsdWVdPVwiYWNjb3VudEF0Umlza1wiXG4gICAgICAgICAgW3BhZ2luYXRvcl09XCJ0cnVlXCJcbiAgICAgICAgICBbcm93c109XCIyMFwiXG5cbiAgICAgICAgICBbdG90YWxSZWNvcmRzXT1cImFjY291bnRBdFJpc2subGVuZ3RoXCJcbj5cbiAgICAgICAgICA8bmctdGVtcGxhdGUgcFRlbXBsYXRlPVwiaGVhZGVyXCI+XG4gICAgICAgICAgICA8dHI+XG4gICAgICAgICAgICAgIDx0aCBzY29wZT1cInRydWVcIj57eyAnQ3JtLlN1bW1hcnkuQWNjb3VudCcgfCB0cmFuc2xvY28gfX08L3RoPlxuICAgICAgICAgICAgICA8dGggc2NvcGU9XCJ0cnVlXCIgY2xhc3M9XCJtcnItaGVhZGVyXCI+e3sgJ0NybS5BY2NvdW50TWVzc2FnZS5NUlInIHwgdHJhbnNsb2NvIH19PC90aD5cbiAgICAgICAgICAgICAgPHRoIHNjb3BlPVwidHJ1ZVwiPnt7ICdDcm0uQWNjb3VudE1lc3NhZ2UuUXVhcnRlcicgfCB0cmFuc2xvY28gfX08L3RoPlxuICAgICAgICAgICAgICA8dGggc2NvcGU9XCJ0cnVlXCI+IHt7ICdDcm0uQWNjb3VudE1lc3NhZ2UuTW9udGgnIHwgdHJhbnNsb2NvIH19PC90aD5cbiAgICAgICAgICAgICAgPHRoIHNjb3BlPVwidHJ1ZVwiPnt7ICdDcm0uQWNjb3VudE1lc3NhZ2UuU2lnblVwQXQnIHwgdHJhbnNsb2NvIH19PC90aD5cbiAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICA8bmctdGVtcGxhdGUgcFRlbXBsYXRlPVwiYm9keVwiXG4gICAgICAgICAgICBsZXQtYWNjb3VudD5cbiAgICAgICAgICAgIDx0cj5cbiAgICAgICAgICAgICAgPHRkIGRhdGEtaGVhZD1cIkFjY291bnRcIj5cbiAgICAgICAgICAgICAgICA8YSBbcm91dGVyTGlua109XCJbJy8nICsgc3Vic2NyaXB0aW9uPy5zbHVnICsgcm91dGVycy5hY2NvdW50SW5mbywgYWNjb3VudC5jcm1fYWNjb3VudF9pZF1cIiBjbGFzcz1cIm5hbWUtbGlua1wiPlxuICAgICAgICAgICAgICAgICAgPHNwYW4gW25nYlRvb2x0aXBdPVwiYWNjb3VudC5jcm1fYWNjb3VudF9uYW1lXCI+e3sgYWNjb3VudD8uY3JtX2FjY291bnRfbmFtZSB8IHRleHRUcnVuY2F0ZToyMCB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICA8L2E+XG4gICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICAgIDx0ZCBkYXRhLWhlYWQ9XCJNUlJcIiBjbGFzcz1cImV4cGVjdGVkLW1yclwiPlxuICAgICAgICAgICAgICAgIHt7IGFjY291bnQuZXhwZWN0ZWRfbXJyIC8gMTAwIHwgY3VycmVuY3k6IGFjY291bnQuY3VycmVuY3kgfX1cbiAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgICAgPHRkIGRhdGEtaGVhZD1cIlF1YXJ0ZXJcIj57eyBhY2NvdW50LnNlc3Npb25zX2xhc3RfcXVhcnRlciB9fTwvdGQ+XG4gICAgICAgICAgICAgIDx0ZCBkYXRhLWhlYWQ9XCJNb250aFwiPnt7IGFjY291bnQuc2Vzc2lvbnNfbGFzdF9tb250aCB9fTwvdGQ+XG4gICAgICAgICAgICAgIDx0ZCBkYXRhLWhlYWQ9XCJTaWduVXBBdFwiPlxuICAgICAgICAgICAgICAgIHt7IGFjY291bnQuc2lnbmVkX3VwX2F0IHwgZGF0ZUZvcm1hdCB9fVxuICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICA8L3AtdGFibGU+XG4gICAgICAgIDxzcGFuIGNsYXNzPVwidG90YWwtcmVjb3Jkcy1jb3VudFwiICAqbmdJZj1cImFjY291bnRBdFJpc2subGVuZ3RoICE9PSAwXCI+e3sgJ0xhYmVsLlRvdGFsJyB8IHRyYW5zbG9jbyB9fToge3sgYWNjb3VudEF0Umlzay5sZW5ndGggfX08L3NwYW4+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXYgKm5nSWY9XCJhY2NvdW50QXRSaXNrPy5sZW5ndGggPT09IDBcIj5cbiAgICAgICAgPHB3LW5vLWRhdGEgW3dpdGhJbWFnZV09XCJ0cnVlXCIgW21lc3NhZ2VdPVwiJ0NybS5TdW1tYXJ5Lk5vSW5zaWdodE1lc3NhZ2UnIHwgdHJhbnNsb2NvXCI+IDwvcHctbm8tZGF0YT5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICAgIDwhLS0gQ29udHJhY3QgcmVuZXdhbCAtLT5cbiAgICA8ZGl2IGNsYXNzPVwiY29sLTEyIGNvbC1tZC02IG1iLTMgYW5hbHl0aWNzXCI+XG4gICAgICA8aDUgY2xhc3M9XCJhY2NvcmRpb24taGVhZGluZ1wiPkNvbnRyYWN0IFJlbmV3YWw8L2g1PlxuICAgICAgPGRpdiBjbGFzcz1cInctMTAwIHRleHQtY2VudGVyIG10LTNcIj5cbiAgICAgICAgPG5nLXRlbXBsYXRlIFtuZ0lmXT1cIiFjb250YWN0UmVuZXdhbExvYWRlZFwiPlxuICAgICAgICAgIDxwLXByb2dyZXNzU3Bpbm5lciBzdHJva2VXaWR0aD1cIjJcIj4gPC9wLXByb2dyZXNzU3Bpbm5lcj5cbiAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cInByaW1lbmctZGF0YXRhYmxlLWNvbnRhaW5lciB0YWJsZS1yZXNwb25zaXZlXCJcbiAgICAgICAgKm5nSWY9XCJDb250cmFjdFJlbmV3YWw/Lmxlbmd0aFwiPlxuICAgICAgICA8cC10YWJsZSBjbGFzcz1cInRhYmxlXCJcbiAgICAgICAgICAjZHRcbiAgICAgICAgICBbdmFsdWVdPVwiQ29udHJhY3RSZW5ld2FsXCJcbiAgICAgICAgICBbcGFnaW5hdG9yXT1cInRydWVcIlxuICAgICAgICAgIFtyb3dzXT1cIjIwXCJcblxuICAgICAgICAgIFt0b3RhbFJlY29yZHNdPVwiQ29udHJhY3RSZW5ld2FsLmxlbmd0aFwiXG4+XG4gICAgICAgICAgPG5nLXRlbXBsYXRlIHBUZW1wbGF0ZT1cImhlYWRlclwiPlxuICAgICAgICAgICAgPHRyPlxuICAgICAgICAgICAgICA8dGggc2NvcGU9XCJ0cnVlXCI+e3sgJ0NybS5BY2NvdW50TWVzc2FnZS5BY2NvdW50JyB8IHRyYW5zbG9jbyB9fTwvdGg+XG4gICAgICAgICAgICAgIDx0aCBzY29wZT1cInRydWVcIiBjbGFzcz1cIm1yci1oZWFkZXJcIj57eyAnQ3JtLkFjY291bnRNZXNzYWdlLk1SUicgfCB0cmFuc2xvY28gfX08L3RoPlxuXG4gICAgICAgICAgICAgIDx0aCBzY29wZT1cInRydWVcIj57eyAnQ3JtLkFjY291bnRNZXNzYWdlLlF1YXJ0ZXInIHwgdHJhbnNsb2NvIH19PC90aD5cbiAgICAgICAgICAgICAgPHRoIHNjb3BlPVwidHJ1ZVwiPiB7eyAnQ3JtLkFjY291bnRNZXNzYWdlLk1vbnRoJyB8IHRyYW5zbG9jbyB9fTwvdGg+XG5cbiAgICAgICAgICAgICAgPHRoIHNjb3BlPVwidHJ1ZVwiPnt7ICdDcm0uQWNjb3VudE1lc3NhZ2UuU2lnblVwQXQnIHwgdHJhbnNsb2NvIH19PC90aD5cbiAgICAgICAgICAgICAgPHRoIHNjb3BlPVwidHJ1ZVwiPnt7ICdDcm0uQWNjb3VudE1lc3NhZ2UuQ0NFeHBBdCcgfCB0cmFuc2xvY28gfX08L3RoPlxuICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgIDxuZy10ZW1wbGF0ZSBwVGVtcGxhdGU9XCJib2R5XCJcbiAgICAgICAgICAgIGxldC1hY2NvdW50PlxuICAgICAgICAgICAgPHRyPlxuICAgICAgICAgICAgICA8dGQgZGF0YS1oZWFkPVwiQWNjb3VudFwiPlxuICAgICAgICAgICAgICAgIDxhIFtyb3V0ZXJMaW5rXT1cIlsnLycgKyBzdWJzY3JpcHRpb24/LnNsdWcgKyByb3V0ZXJzLmFjY291bnRJbmZvLCBhY2NvdW50LmNybV9hY2NvdW50X2lkXVwiIGNsYXNzPVwibmFtZS1saW5rXCI+XG4gICAgICAgICAgICAgICAgICA8c3BhbiBbbmdiVG9vbHRpcF09XCJhY2NvdW50LmNybV9hY2NvdW50X25hbWVcIj57eyBhY2NvdW50LmNybV9hY2NvdW50X25hbWUgfCB0ZXh0VHJ1bmNhdGU6MjAgfX08L3NwYW4+XG4gICAgICAgICAgICAgICAgPC9hPlxuICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICA8dGQgZGF0YS1oZWFkPVwiTVJSXCIgY2xhc3M9XCJleHBlY3RlZC1tcnJcIj5cbiAgICAgICAgICAgICAgICB7eyBhY2NvdW50LmV4cGVjdGVkX21yciAvIDEwMCB8IGN1cnJlbmN5OiBhY2NvdW50LmN1cnJlbmN5IH19XG4gICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICAgIDx0ZCBkYXRhLWhlYWQ9XCJRdWFydGVyXCI+e3sgYWNjb3VudC5zZXNzaW9uc19sYXN0X3F1YXJ0ZXIgfX08L3RkPlxuICAgICAgICAgICAgICA8dGQgZGF0YS1oZWFkPVwiTW9udGhcIj57eyBhY2NvdW50LnNlc3Npb25zX2xhc3RfbW9udGggfX08L3RkPlxuICAgICAgICAgICAgICA8dGQgZGF0YS1oZWFkPVwiU2lnblVwQXRcIj5cbiAgICAgICAgICAgICAgICB7eyBhY2NvdW50LnNpZ25lZF91cF9hdCB8IGRhdGVGb3JtYXQgfX1cbiAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgICAgPHRkIGRhdGEtaGVhZD1cIkV4cEF0XCI+XG4gICAgICAgICAgICAgICAge3sgYWNjb3VudC5jY19leHBpcmluZ19hdCB8IGRhdGVGb3JtYXQgfX1cbiAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgPC9wLXRhYmxlPlxuICAgICAgICA8c3BhbiBjbGFzcz1cInRvdGFsLXJlY29yZHMtY291bnRcIiAqbmdJZj1cIkNvbnRyYWN0UmVuZXdhbC5sZW5ndGggIT09IDBcIj57eyAnTGFiZWwuVG90YWwnIHwgdHJhbnNsb2NvIH19OiB7eyBDb250cmFjdFJlbmV3YWwubGVuZ3RoIH19PC9zcGFuPlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2ICpuZ0lmPVwiQ29udHJhY3RSZW5ld2FsPy5sZW5ndGggPT09IDBcIj5cbiAgICAgICAgPHB3LW5vLWRhdGEgW3dpdGhJbWFnZV09XCJ0cnVlXCIgW21lc3NhZ2VdPVwiJ0NybS5TdW1tYXJ5Lk5vSW5zaWdodE1lc3NhZ2UnIHwgdHJhbnNsb2NvXCI+IDwvcHctbm8tZGF0YT5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuXG5cbiAgICAgPCEtLSBBY2NvdW50IEluc2lnaHRzIC0tPlxuICAgICA8ZGl2IGNsYXNzPVwiY29sLTEyIGNvbC1tZC02IG1iLTMgYW5hbHl0aWNzXCI+XG4gICAgICA8aDUgY2xhc3M9XCJhY2NvcmRpb24taGVhZGluZ1wiPkFjY291bnQgSW5zaWdodHM8L2g1PlxuICAgICAgPGRpdiBjbGFzcz1cInctMTAwIHRleHQtY2VudGVyIG10LTNcIj5cbiAgICAgICAgPG5nLXRlbXBsYXRlIFtuZ0lmXT1cIiFhY2NvdW50SW5zaWdodExvYWRlZFwiPlxuICAgICAgICAgIDxwLXByb2dyZXNzU3Bpbm5lciBzdHJva2VXaWR0aD1cIjJcIj4gPC9wLXByb2dyZXNzU3Bpbm5lcj5cbiAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cInByaW1lbmctZGF0YXRhYmxlLWNvbnRhaW5lciB0YWJsZS1yZXNwb25zaXZlXCJcbiAgICAgICAgKm5nSWY9XCJhY2NvdW50SW5zaWdodD8ubGVuZ3RoXCI+XG4gICAgICAgIDxwLXRhYmxlIGNsYXNzPVwidGFibGVcIlxuICAgICAgICAgICNkdFxuICAgICAgICAgIFt2YWx1ZV09XCJhY2NvdW50SW5zaWdodFwiXG4gICAgICAgICAgW3BhZ2luYXRvcl09XCJ0cnVlXCJcbiAgICAgICAgICBbcm93c109XCIyMFwiXG5cbiAgICAgICAgICBbdG90YWxSZWNvcmRzXT1cIjEyXCJcbj5cbiAgICAgICAgICA8bmctdGVtcGxhdGUgcFRlbXBsYXRlPVwiaGVhZGVyXCI+XG4gICAgICAgICAgICA8dHI+XG4gICAgICAgICAgICAgIDx0aCBzY29wZT1cInRydWVcIj57eyAnVmFsdWUnIH19PC90aD5cbiAgICAgICAgICAgICAgPHRoIHNjb3BlPVwidHJ1ZVwiPnt7ICdDcm0uU3VtbWFyeS5UaXRsZScgfCB0cmFuc2xvY28gfX08L3RoPlxuICAgICAgICAgICAgICA8dGggc2NvcGU9XCJ0cnVlXCI+IHt7ICdDcm0uQ29udGFjdE1lc3NhZ2UuUmVhc29uJyB8IHRyYW5zbG9jbyB9fSA8L3RoPlxuICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgIDxuZy10ZW1wbGF0ZSBwVGVtcGxhdGU9XCJib2R5XCJcbiAgICAgICAgICAgIGxldC1hY2NvdW50PlxuICAgICAgICAgICAgPHRyPlxuICAgICAgICAgICAgICA8dGQgZGF0YS1oZWFkPVwidmFsdWVcIj57eyBhY2NvdW50LnZhbHVlIH19PC90ZD5cbiAgICAgICAgICAgICAgPHRkIGRhdGEtaGVhZD1cInRpdGxlXCI+e3sgYWNjb3VudC50aXRsZSB9fTwvdGQ+XG4gICAgICAgICAgICAgIDx0ZCBkYXRhLWhlYWQ9XCJyZWFzb25cIj5cbiAgICAgICAgICAgICAgICB7eyBhY2NvdW50LnJlYXNvbiB9fVxuICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICA8L3AtdGFibGU+XG4gICAgICA8L2Rpdj5cbiAgICAgICA8ZGl2ICpuZ0lmPVwiIWFjY291bnRJbnNpZ2h0Py5sZW5ndGggJiYgYWNjb3VudEluc2lnaHRMb2FkZWRcIj5cbiAgICAgICAgPHB3LW5vLWRhdGEgW3dpdGhJbWFnZV09XCJ0cnVlXCIgW21lc3NhZ2VdPVwiJ0NybS5TdW1tYXJ5Lk5vSW5zaWdodE1lc3NhZ2UnIHwgdHJhbnNsb2NvXCI+IDwvcHctbm8tZGF0YT5cbiAgICAgIDwvZGl2PlxuICAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiY29sLTEyIGNvbC1tZC02IG1iLTMgYW5hbHl0aWNzXCI+XG4gICAgICA8aDUgY2xhc3M9XCJhY2NvcmRpb24taGVhZGluZ1wiPkdlb2dyYXBoeTwvaDU+XG4gICAgICA8ZGl2PlxuICAgICAgICA8bmctdGVtcGxhdGUgW25nSWZdPVwiYWNjb3VudEdlb2dyYXBoeVwiPlxuICAgICAgICAgIDxwbG90bHktcGxvdCBbZGF0YV09XCJhY2NvdW50R2VvZ3JhcGh5Py5kYXRhXCJcbiAgICAgICAgICAgIFtsYXlvdXRdPVwiYWNjb3VudEdlb2dyYXBoeT8ubGF5b3V0XCIgW3VzZVJlc2l6ZUhhbmRsZXJdPVwidHJ1ZVwiPlxuICAgICAgICAgIDwvcGxvdGx5LXBsb3Q+XG4gICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXYgKm5nSWY9XCIhYWNjb3VudEdlb2dyYXBoeVwiPlxuICAgICAgICA8cHctbm8tZGF0YSBbd2l0aEltYWdlXT1cInRydWVcIiBbbWVzc2FnZV09XCInQ3JtLkNvbnRhY3RNZXNzYWdlLk5vSW5zaWdodE1lc3NhZ2UnIHwgdHJhbnNsb2NvXCI+XG4gICAgICAgIDwvcHctbm8tZGF0YT5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICA8L25nLWNvbnRhaW5lcj5cbjwvZGl2PlxuIl19