@tuki-io/tuki-widgets 0.0.126 → 0.0.127

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 (37) hide show
  1. package/contact-center/cc-readiness/cc-readiness.module.d.ts +19 -0
  2. package/contact-center/cc-readiness/cc-readiness.service.d.ts +12 -0
  3. package/contact-center/cc-readiness/components/card/card.component.d.ts +6 -0
  4. package/contact-center/cc-readiness/types/cc-readiness.d.ts +20 -0
  5. package/contact-center/cc-readiness/widgets/licences-requirement/licences-requirement.component.d.ts +52 -0
  6. package/contact-center/cc-readiness/widgets/summary-grid/summary-grid.component.d.ts +26 -0
  7. package/contact-center/index.d.ts +5 -0
  8. package/contact-center/public-api.d.ts +3 -0
  9. package/contact-center/shared/api.endpoints.d.ts +6 -0
  10. package/contact-center/shared/api.service.d.ts +20 -0
  11. package/contact-center/shared/material.module.d.ts +15 -0
  12. package/contact-center/shared/shared.module.d.ts +10 -0
  13. package/esm2020/contact-center/cc-readiness/cc-readiness.module.mjs +71 -0
  14. package/esm2020/contact-center/cc-readiness/cc-readiness.service.mjs +35 -0
  15. package/esm2020/contact-center/cc-readiness/components/card/card.component.mjs +13 -0
  16. package/esm2020/contact-center/cc-readiness/types/cc-readiness.mjs +5 -0
  17. package/esm2020/contact-center/cc-readiness/widgets/licences-requirement/licences-requirement.component.mjs +187 -0
  18. package/esm2020/contact-center/cc-readiness/widgets/summary-grid/summary-grid.component.mjs +47 -0
  19. package/esm2020/contact-center/public-api.mjs +4 -0
  20. package/esm2020/contact-center/shared/api.endpoints.mjs +7 -0
  21. package/esm2020/contact-center/shared/api.service.mjs +86 -0
  22. package/esm2020/contact-center/shared/material.module.mjs +76 -0
  23. package/esm2020/contact-center/shared/shared.module.mjs +33 -0
  24. package/esm2020/contact-center/tuki-io-tuki-widgets-contact-center.mjs +5 -0
  25. package/esm2020/di2mt/shared/services/api.service.mjs +1 -1
  26. package/esm2020/users-list/src/users-list.component.mjs +3 -3
  27. package/fesm2015/tuki-io-tuki-widgets-contact-center.mjs +433 -0
  28. package/fesm2015/tuki-io-tuki-widgets-contact-center.mjs.map +1 -0
  29. package/fesm2015/tuki-io-tuki-widgets-di2mt.mjs.map +1 -1
  30. package/fesm2015/tuki-io-tuki-widgets-users-list.mjs +2 -2
  31. package/fesm2015/tuki-io-tuki-widgets-users-list.mjs.map +1 -1
  32. package/fesm2020/tuki-io-tuki-widgets-contact-center.mjs +430 -0
  33. package/fesm2020/tuki-io-tuki-widgets-contact-center.mjs.map +1 -0
  34. package/fesm2020/tuki-io-tuki-widgets-di2mt.mjs.map +1 -1
  35. package/fesm2020/tuki-io-tuki-widgets-users-list.mjs +2 -2
  36. package/fesm2020/tuki-io-tuki-widgets-users-list.mjs.map +1 -1
  37. package/package.json +9 -1
@@ -0,0 +1,430 @@
1
+ import * as i0 from '@angular/core';
2
+ import { Injectable, inject, Component, Input, NgModule } from '@angular/core';
3
+ import * as i1$1 from '@angular/common';
4
+ import { CommonModule } from '@angular/common';
5
+ import * as i1 from '@angular/common/http';
6
+ import { HttpHeaders, HttpClientModule } from '@angular/common/http';
7
+ import { map, catchError, of, finalize } from 'rxjs';
8
+ import * as i2 from 'ng-apexcharts';
9
+ import { NgApexchartsModule } from 'ng-apexcharts';
10
+ import * as i3 from '@angular/material/select';
11
+ import { MatSelectModule } from '@angular/material/select';
12
+ import * as i4 from '@angular/material/core';
13
+ import { MatOptionModule } from '@angular/material/core';
14
+ import { MatButtonModule } from '@angular/material/button';
15
+ import { MatCheckboxModule } from '@angular/material/checkbox';
16
+ import { MatPaginatorModule } from '@angular/material/paginator';
17
+ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
18
+ import { MatTableModule } from '@angular/material/table';
19
+
20
+ class APIService {
21
+ constructor(httpClient) {
22
+ this.httpClient = httpClient;
23
+ this.apiUrl = window.location.protocol + '//' + window.location.hostname + '/dcp';
24
+ this.token = 'eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbkBjb3JyZW5ldC5jb20iLCJyb2xlcyI6IlNVUEVSX1VTRVIiLCJpYXQiOjE3NTUwODUyMzgsImV4cCI6MTc1NTEwMzIzOH0.X1CKx-OBZvSs7Bzr_4SWW2ulBgHNkYZrmVuv6V7FZyo';
25
+ // this.apiUrl = window.location.protocol + '//' + window.location.host + '/dcp';
26
+ this.apiUrl = 'https://dev.tuki.io/webex';
27
+ // this.apiUrl = 'http://localhost:8088/dcp';
28
+ }
29
+ fetch(url, params, cache) {
30
+ const headers = this.getHeaders(cache);
31
+ params = params || {};
32
+ return this.httpClient.get(this.apiUrl + url, { params: this.prepareEncodedParams(params), headers });
33
+ }
34
+ post(url, body, params = {}) {
35
+ body = body || null;
36
+ const headers = this.getHeaders();
37
+ return this.httpClient.post(this.apiUrl + url, body, { params: this.prepareEncodedParams(params), headers });
38
+ }
39
+ // use when response extended data is necessary:
40
+ postExtended(url, body = null, params = {}, headers = {}) {
41
+ headers = headers || this.getHeaders();
42
+ return this.httpClient.post(this.apiUrl + url, body, {
43
+ headers,
44
+ observe: 'response',
45
+ params: this.prepareEncodedParams(params)
46
+ });
47
+ }
48
+ put(url, body = null, params = {}) {
49
+ const headers = this.getHeaders();
50
+ return this.httpClient.put(this.apiUrl + url, body, { headers, params: this.prepareEncodedParams(params) });
51
+ }
52
+ delete(url, params = {}) {
53
+ const headers = this.getHeaders();
54
+ return this.httpClient.delete(this.apiUrl + url, { headers, params: this.prepareEncodedParams(params) });
55
+ }
56
+ fetchPagination(url, pageSize, pageNumber, additionalParams = {}, cache) {
57
+ const copyAdditionalParams = JSON.parse(JSON.stringify(additionalParams));
58
+ const params = Object.assign(copyAdditionalParams, { size: pageSize.toString(), page: pageNumber.toString() });
59
+ return this.fetch(url, params, cache);
60
+ }
61
+ prepareEncodedParams(params) {
62
+ const result = {};
63
+ if (!params) {
64
+ return {};
65
+ }
66
+ for (const key of Object.keys(params)) {
67
+ if (params[key]) {
68
+ const stringParam = params[key].toString();
69
+ result[key] = stringParam.includes('+') ? encodeURIComponent(stringParam) : stringParam;
70
+ }
71
+ }
72
+ return result;
73
+ }
74
+ getHeaders(cache) {
75
+ let headers = new HttpHeaders();
76
+ if (cache) {
77
+ headers = headers.append('_Cache', 'true ');
78
+ }
79
+ const token = this.token || this.getParameterByName('token');
80
+ headers = headers.append('Authorization', 'Bearer ' + token);
81
+ return headers;
82
+ }
83
+ getParameterByName(name, url = window.location.href) {
84
+ name = name.replace(/[\[\]]/g, '\\$&');
85
+ var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'), results = regex.exec(url);
86
+ if (!results)
87
+ return null;
88
+ if (!results[2])
89
+ return '';
90
+ return decodeURIComponent(results[2].replace(/\+/g, ' '));
91
+ }
92
+ }
93
+ APIService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: APIService, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable });
94
+ APIService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: APIService, providedIn: 'root' });
95
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: APIService, decorators: [{
96
+ type: Injectable,
97
+ args: [{
98
+ providedIn: 'root'
99
+ }]
100
+ }], ctorParameters: function () { return [{ type: i1.HttpClient }]; } });
101
+
102
+ const API = {
103
+ READINESS: {
104
+ UCCX_SERVER_ENTITY_STATS: (customerId) => `/api/uccx/migration/customer/${customerId}/entity-counts`,
105
+ LICENSE_USAGE_SUMMARY: (customerId) => `/api/webexreadiness/customers/${customerId}/callinglicesnsecountperfeature`,
106
+ }
107
+ };
108
+
109
+ class CcReadinessService {
110
+ constructor() {
111
+ this.api = inject(APIService);
112
+ }
113
+ fetchUccxServerEntityStats(customerId) {
114
+ return this.api.fetch(API.READINESS.UCCX_SERVER_ENTITY_STATS(customerId))
115
+ .pipe(map((stats) => {
116
+ stats.forEach(stat => {
117
+ // @ts-ignore
118
+ delete stat.counts.reasonCodes;
119
+ });
120
+ return stats;
121
+ }));
122
+ }
123
+ fetchWebexLicenseUsageSummary(customerId) {
124
+ return this.api.fetch(API.READINESS.LICENSE_USAGE_SUMMARY(customerId));
125
+ }
126
+ setToken(token) {
127
+ this.api.token = token;
128
+ }
129
+ }
130
+ CcReadinessService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: CcReadinessService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
131
+ CcReadinessService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: CcReadinessService, providedIn: 'root' });
132
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: CcReadinessService, decorators: [{
133
+ type: Injectable,
134
+ args: [{
135
+ providedIn: 'root'
136
+ }]
137
+ }], ctorParameters: function () { return []; } });
138
+
139
+ class CardComponent {
140
+ }
141
+ CardComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: CardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
142
+ CardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: CardComponent, selector: "tk-card", inputs: { title: "title" }, ngImport: i0, template: "<article class=\"card\">\r\n <header class=\"card__header\">\r\n <h2>{{ title }}</h2>\r\n <!--<div class=\"card__menu-button\">\r\n <img width=\"18\" src=\"assets/icons/menu_icon.png\" alt=\"Menu Icon\">\r\n </div>-->\r\n </header>\r\n <div class=\"card__content\">\r\n <ng-content select=\"card-content\"></ng-content>\r\n </div>\r\n</article>\r\n", styles: ["@import\"https://fonts.googleapis.com/css?family=Poppins:400,100,200,300,500,600,800,700,900\";@import\"https://fonts.googleapis.com/css2?family=Inter:wght@300;400&display=swap\";:host{display:block;height:100%;box-sizing:border-box}.card{font-family:Inter,Inter,sans-serif;background-color:#fff;border-radius:1rem;padding:2rem;border:1px solid hsla(0,0%,0%,.2);min-width:300px;max-width:100%;height:100%;display:flex;flex-direction:column;box-sizing:border-box;gap:2.5rem}.card__header{position:relative;display:flex;align-items:center;justify-content:space-between}.card__header h2{font-size:16px;margin:0}.card__header .card__menu-button{position:relative;display:flex;align-items:center}.card__content{display:flex;flex-direction:column;gap:2.5rem;flex-grow:1}\n"] });
143
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: CardComponent, decorators: [{
144
+ type: Component,
145
+ args: [{ selector: 'tk-card', template: "<article class=\"card\">\r\n <header class=\"card__header\">\r\n <h2>{{ title }}</h2>\r\n <!--<div class=\"card__menu-button\">\r\n <img width=\"18\" src=\"assets/icons/menu_icon.png\" alt=\"Menu Icon\">\r\n </div>-->\r\n </header>\r\n <div class=\"card__content\">\r\n <ng-content select=\"card-content\"></ng-content>\r\n </div>\r\n</article>\r\n", styles: ["@import\"https://fonts.googleapis.com/css?family=Poppins:400,100,200,300,500,600,800,700,900\";@import\"https://fonts.googleapis.com/css2?family=Inter:wght@300;400&display=swap\";:host{display:block;height:100%;box-sizing:border-box}.card{font-family:Inter,Inter,sans-serif;background-color:#fff;border-radius:1rem;padding:2rem;border:1px solid hsla(0,0%,0%,.2);min-width:300px;max-width:100%;height:100%;display:flex;flex-direction:column;box-sizing:border-box;gap:2.5rem}.card__header{position:relative;display:flex;align-items:center;justify-content:space-between}.card__header h2{font-size:16px;margin:0}.card__header .card__menu-button{position:relative;display:flex;align-items:center}.card__content{display:flex;flex-direction:column;gap:2.5rem;flex-grow:1}\n"] }]
146
+ }], propDecorators: { title: [{
147
+ type: Input
148
+ }] } });
149
+
150
+ const LEGEND_COLORS = {
151
+ existing: '#16A693',
152
+ missing: '#808080'
153
+ };
154
+ class LicencesRequirementComponent {
155
+ constructor() {
156
+ this.ccReadinessService = inject(CcReadinessService);
157
+ this.viewModel = null;
158
+ this.loading = false;
159
+ this.error = false;
160
+ this.filters = ['All', 'Professional licenses', 'Workspace licenses'];
161
+ this.selectedSummaryIndex = 0;
162
+ this.summary = null;
163
+ }
164
+ ngOnInit() {
165
+ this.loadSummaries();
166
+ }
167
+ ngOnDestroy() {
168
+ this.subscription?.unsubscribe();
169
+ }
170
+ ngOnChanges(changes) {
171
+ if ((changes['customerId'] && !changes['customerId'].firstChange) ||
172
+ (changes['token'] && !changes['token'].firstChange)) {
173
+ this.loadSummaries();
174
+ }
175
+ }
176
+ onFilterChange(index) {
177
+ if (!isNaN(index) && index >= 0 && index < this.filters.length) {
178
+ this.selectFilter(index);
179
+ }
180
+ }
181
+ loadSummaries() {
182
+ const numericCustomerId = Number(this.customerId);
183
+ if (!numericCustomerId || !this.token) {
184
+ return;
185
+ }
186
+ this.subscription?.unsubscribe();
187
+ this.loading = true;
188
+ this.error = false;
189
+ this.viewModel = null;
190
+ this.selectedSummaryIndex = 0;
191
+ this.ccReadinessService.setToken(this.token);
192
+ this.subscription = this.ccReadinessService.fetchWebexLicenseUsageSummary(numericCustomerId)
193
+ .pipe(catchError(error => {
194
+ console.error('Unable to load Webex license usage summary', error);
195
+ this.error = true;
196
+ return of([]);
197
+ }), finalize(() => this.loading = false))
198
+ .subscribe(items => {
199
+ console.log('Raw API response:', items);
200
+ // Handle both array and single object responses
201
+ if (Array.isArray(items) && items.length > 0) {
202
+ this.summary = items[0];
203
+ }
204
+ else if (items && typeof items === 'object' && !Array.isArray(items)) {
205
+ // If single object returned, use it directly
206
+ this.summary = items;
207
+ }
208
+ else {
209
+ this.summary = null;
210
+ }
211
+ console.log('Processed summary:', this.summary);
212
+ this.selectFilter(0);
213
+ });
214
+ }
215
+ selectFilter(index) {
216
+ this.selectedSummaryIndex = index;
217
+ if (!this.summary) {
218
+ this.viewModel = null;
219
+ return;
220
+ }
221
+ this.viewModel = this.mapSummaryToViewModel(this.summary, index);
222
+ console.log('Created viewModel for filter index', index, ':', this.viewModel);
223
+ }
224
+ mapSummaryToViewModel(summary, filterIndex) {
225
+ console.log('Mapping summary to viewModel:', summary, 'filterIndex:', filterIndex);
226
+ // Extract data from webexReadinessLicenseStats and license counts
227
+ const personStat = summary.webexReadinessLicenseStats?.find(stat => stat.feature === 'PERSON');
228
+ const deviceStat = summary.webexReadinessLicenseStats?.find(stat => stat.feature === 'ORPHANED_DEVICE');
229
+ const professionalNeeded = personStat?.totalCount ?? 0;
230
+ const workspaceNeeded = deviceStat?.totalCount ?? 0;
231
+ const professionalOwned = Number(summary.totalProfessionalLicenseCount ?? 0);
232
+ const workspaceOwned = Number(summary.totalWorkspaceProfessionalLicenseCount ?? 0);
233
+ // Filter data based on selection
234
+ let existingCount;
235
+ let missingCount;
236
+ let rows;
237
+ if (filterIndex === 0) {
238
+ // All - show both
239
+ existingCount = professionalOwned + workspaceOwned;
240
+ const totalNeeded = professionalNeeded + workspaceNeeded;
241
+ missingCount = Math.max(0, totalNeeded - existingCount);
242
+ rows = [
243
+ { label: 'Professional licenses', value: professionalNeeded },
244
+ { label: 'Workspace licenses', value: workspaceNeeded }
245
+ ];
246
+ }
247
+ else if (filterIndex === 1) {
248
+ // Professional licenses only
249
+ existingCount = professionalOwned;
250
+ missingCount = Math.max(0, professionalNeeded - professionalOwned);
251
+ rows = [{ label: 'Professional licenses', value: professionalNeeded }];
252
+ }
253
+ else {
254
+ // Workspace licenses only
255
+ existingCount = workspaceOwned;
256
+ missingCount = Math.max(0, workspaceNeeded - workspaceOwned);
257
+ rows = [{ label: 'Workspace licenses', value: workspaceNeeded }];
258
+ }
259
+ const totalLicenses = existingCount + missingCount;
260
+ const legendItems = [
261
+ {
262
+ label: 'Existing licenses',
263
+ count: existingCount,
264
+ percentage: totalLicenses > 0 ? (existingCount / totalLicenses) * 100 : 0,
265
+ color: LEGEND_COLORS.existing
266
+ },
267
+ {
268
+ label: 'Missing licenses',
269
+ count: missingCount,
270
+ percentage: totalLicenses > 0 ? (missingCount / totalLicenses) * 100 : 0,
271
+ color: LEGEND_COLORS.missing
272
+ }
273
+ ];
274
+ console.log('Legend items:', legendItems);
275
+ console.log('Table rows:', rows);
276
+ const totalRequired = rows.reduce((acc, row) => acc + row.value, 0);
277
+ return {
278
+ chartOptions: this.buildChartOptions(legendItems),
279
+ legendItems,
280
+ rows,
281
+ totalRequired
282
+ };
283
+ }
284
+ buildChartOptions(legendItems) {
285
+ return {
286
+ series: legendItems.map(item => item.count),
287
+ chart: {
288
+ type: 'donut',
289
+ height: 220
290
+ },
291
+ labels: legendItems.map(item => item.label),
292
+ colors: legendItems.map(item => item.color),
293
+ legend: {
294
+ show: false
295
+ },
296
+ plotOptions: {
297
+ pie: {
298
+ donut: {
299
+ size: '75%'
300
+ }
301
+ }
302
+ },
303
+ dataLabels: {
304
+ enabled: false
305
+ }
306
+ };
307
+ }
308
+ normalizePercentage(value) {
309
+ if (!isFinite(value)) {
310
+ return 0;
311
+ }
312
+ // Convert decimal to percentage (0.9487 → 94.9)
313
+ const percentage = value * 100;
314
+ return Math.round(percentage * 10) / 10;
315
+ }
316
+ }
317
+ LicencesRequirementComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: LicencesRequirementComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
318
+ LicencesRequirementComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: LicencesRequirementComponent, selector: "cc-licenses-requirement", inputs: { customerId: "customerId", token: "token" }, usesOnChanges: true, ngImport: i0, template: "<tk-card title=\"Licenses requirement\">\n <ng-container ngProjectAs=\"card-content\">\n <div\n class=\"widget-body\"\n *ngIf=\"!loading && !error && viewModel; else widgetState\"\n >\n <div class=\"left-section\">\n <mat-select\n [(value)]=\"selectedSummaryIndex\"\n (selectionChange)=\"onFilterChange($event.value)\"\n class=\"filter-select\"\n >\n <mat-option *ngFor=\"let option of filters; index as i\" [value]=\"i\">\n {{ option }}\n </mat-option>\n </mat-select>\n\n <div class=\"chart-section\">\n <div class=\"chart-wrapper\">\n <apx-chart\n [series]=\"viewModel.chartOptions.series\"\n [chart]=\"viewModel.chartOptions.chart\"\n [labels]=\"viewModel.chartOptions.labels\"\n [colors]=\"viewModel.chartOptions.colors\"\n [legend]=\"viewModel.chartOptions.legend\"\n [plotOptions]=\"viewModel.chartOptions.plotOptions\"\n [dataLabels]=\"viewModel.chartOptions.dataLabels\"\n >\n </apx-chart>\n </div>\n <div class=\"legend\">\n <div class=\"legend-item\" *ngFor=\"let item of viewModel.legendItems\">\n <span\n class=\"legend-marker\"\n [style.backgroundColor]=\"item.color\"\n ></span>\n <span class=\"legend-label\">{{ item.label }}</span>\n <span class=\"legend-value\">{{ item.count | number }}</span>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"divider\" aria-hidden=\"true\"></div>\n\n <div class=\"table-section\">\n <div class=\"table-header\">\n <span>License</span>\n <span>Required</span>\n </div>\n <div class=\"table-row\" *ngFor=\"let row of viewModel.rows\">\n <span>{{ row.label }}</span>\n <span>{{ row.value | number }}</span>\n </div>\n <div class=\"table-row total-row\">\n <span>Total</span>\n <span>{{ viewModel.totalRequired | number }}</span>\n </div>\n </div>\n </div>\n\n <ng-template #widgetState>\n <div class=\"state-message\" *ngIf=\"loading\">\n Loading license requirements\u2026\n </div>\n <div class=\"state-message error\" *ngIf=\"!loading && error\">\n Unable to load license requirements.\n </div>\n <div class=\"state-message\" *ngIf=\"!loading && !error && !viewModel\">\n No license data available.\n </div>\n </ng-template>\n </ng-container>\n</tk-card>\n", styles: ["@import\"https://fonts.googleapis.com/css?family=Poppins:400,100,200,300,500,600,800,700,900\";@import\"https://fonts.googleapis.com/css2?family=Inter:wght@300;400&display=swap\";:host{display:block;width:100%;box-sizing:border-box}.filter-select{font-family:Inter,Inter,sans-serif;font-size:14px;min-width:140px;border:1px solid #e5e7eb;border-radius:.5rem;padding:.5rem .75rem;background-color:#fff}.filter-select:hover{border-color:#d1d5db}:host ::ng-deep .filter-select.mat-mdc-select{border:1px solid #e5e7eb;border-radius:.5rem;background-color:#fff}:host ::ng-deep .filter-select.mat-mdc-select:hover{border-color:#d1d5db}:host ::ng-deep .filter-select.mat-mdc-select.mat-focused{border-color:#16a693}:host ::ng-deep .filter-select .mat-mdc-select-trigger{font-size:14px;padding:.5rem .75rem}:host ::ng-deep .filter-select .mat-mdc-select-value{color:#111827}:host ::ng-deep .filter-select .mat-mdc-select-arrow-wrapper{padding-left:.5rem}.widget-body{display:flex;gap:2.5rem;align-items:flex-start}.left-section{flex:2;display:flex;flex-direction:column;gap:1rem}.chart-section{display:flex;gap:1.5rem;align-items:center}.chart-wrapper{width:220px;min-height:220px;flex-shrink:0}.chart-wrapper apx-chart{width:220px!important;height:220px!important}.legend{display:flex;flex-direction:column;gap:.75rem}.legend-item{display:flex;align-items:center;gap:.5rem;font-family:Inter,Inter,sans-serif;font-size:14px}.legend-marker{width:14px;height:14px;border-radius:50%;display:inline-flex}.legend-label{color:#4b5563}.legend-value{margin-left:auto;font-weight:600;color:#111827}.divider{width:1px;min-height:200px;align-self:stretch;background:#e5e7eb}.table-section{flex:3;display:flex;flex-direction:column;gap:.75rem;font-family:Inter,Inter,sans-serif}.table-header,.table-row{display:flex;justify-content:space-between;font-size:14px}.table-header{font-weight:600;color:#6b7280;padding-bottom:.5rem;border-bottom:1px solid #e5e7eb}.table-row{color:#111827}.total-row{font-weight:700;margin-top:.5rem;padding-top:.5rem;border-top:1px solid #e5e7eb}.state-message{font-family:Inter,Inter,sans-serif;font-size:14px;color:#6b7280}.state-message.error{color:#b91c1c}@media (max-width: 960px){.widget-body{flex-direction:column}.divider{display:none}.chart-section{justify-content:space-between}}:host ::ng-deep .apexcharts-legend{display:none!important}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.ChartComponent, selector: "apx-chart", inputs: ["chart", "annotations", "colors", "dataLabels", "series", "stroke", "labels", "legend", "markers", "noData", "fill", "tooltip", "plotOptions", "responsive", "xaxis", "yaxis", "forecastDataPoints", "grid", "states", "title", "subtitle", "theme", "autoUpdateSeries"] }, { kind: "component", type: i3.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex"], exportAs: ["matSelect"] }, { kind: "component", type: i4.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { kind: "component", type: CardComponent, selector: "tk-card", inputs: ["title"] }, { kind: "pipe", type: i1$1.DecimalPipe, name: "number" }] });
319
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: LicencesRequirementComponent, decorators: [{
320
+ type: Component,
321
+ args: [{ selector: 'cc-licenses-requirement', template: "<tk-card title=\"Licenses requirement\">\n <ng-container ngProjectAs=\"card-content\">\n <div\n class=\"widget-body\"\n *ngIf=\"!loading && !error && viewModel; else widgetState\"\n >\n <div class=\"left-section\">\n <mat-select\n [(value)]=\"selectedSummaryIndex\"\n (selectionChange)=\"onFilterChange($event.value)\"\n class=\"filter-select\"\n >\n <mat-option *ngFor=\"let option of filters; index as i\" [value]=\"i\">\n {{ option }}\n </mat-option>\n </mat-select>\n\n <div class=\"chart-section\">\n <div class=\"chart-wrapper\">\n <apx-chart\n [series]=\"viewModel.chartOptions.series\"\n [chart]=\"viewModel.chartOptions.chart\"\n [labels]=\"viewModel.chartOptions.labels\"\n [colors]=\"viewModel.chartOptions.colors\"\n [legend]=\"viewModel.chartOptions.legend\"\n [plotOptions]=\"viewModel.chartOptions.plotOptions\"\n [dataLabels]=\"viewModel.chartOptions.dataLabels\"\n >\n </apx-chart>\n </div>\n <div class=\"legend\">\n <div class=\"legend-item\" *ngFor=\"let item of viewModel.legendItems\">\n <span\n class=\"legend-marker\"\n [style.backgroundColor]=\"item.color\"\n ></span>\n <span class=\"legend-label\">{{ item.label }}</span>\n <span class=\"legend-value\">{{ item.count | number }}</span>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"divider\" aria-hidden=\"true\"></div>\n\n <div class=\"table-section\">\n <div class=\"table-header\">\n <span>License</span>\n <span>Required</span>\n </div>\n <div class=\"table-row\" *ngFor=\"let row of viewModel.rows\">\n <span>{{ row.label }}</span>\n <span>{{ row.value | number }}</span>\n </div>\n <div class=\"table-row total-row\">\n <span>Total</span>\n <span>{{ viewModel.totalRequired | number }}</span>\n </div>\n </div>\n </div>\n\n <ng-template #widgetState>\n <div class=\"state-message\" *ngIf=\"loading\">\n Loading license requirements\u2026\n </div>\n <div class=\"state-message error\" *ngIf=\"!loading && error\">\n Unable to load license requirements.\n </div>\n <div class=\"state-message\" *ngIf=\"!loading && !error && !viewModel\">\n No license data available.\n </div>\n </ng-template>\n </ng-container>\n</tk-card>\n", styles: ["@import\"https://fonts.googleapis.com/css?family=Poppins:400,100,200,300,500,600,800,700,900\";@import\"https://fonts.googleapis.com/css2?family=Inter:wght@300;400&display=swap\";:host{display:block;width:100%;box-sizing:border-box}.filter-select{font-family:Inter,Inter,sans-serif;font-size:14px;min-width:140px;border:1px solid #e5e7eb;border-radius:.5rem;padding:.5rem .75rem;background-color:#fff}.filter-select:hover{border-color:#d1d5db}:host ::ng-deep .filter-select.mat-mdc-select{border:1px solid #e5e7eb;border-radius:.5rem;background-color:#fff}:host ::ng-deep .filter-select.mat-mdc-select:hover{border-color:#d1d5db}:host ::ng-deep .filter-select.mat-mdc-select.mat-focused{border-color:#16a693}:host ::ng-deep .filter-select .mat-mdc-select-trigger{font-size:14px;padding:.5rem .75rem}:host ::ng-deep .filter-select .mat-mdc-select-value{color:#111827}:host ::ng-deep .filter-select .mat-mdc-select-arrow-wrapper{padding-left:.5rem}.widget-body{display:flex;gap:2.5rem;align-items:flex-start}.left-section{flex:2;display:flex;flex-direction:column;gap:1rem}.chart-section{display:flex;gap:1.5rem;align-items:center}.chart-wrapper{width:220px;min-height:220px;flex-shrink:0}.chart-wrapper apx-chart{width:220px!important;height:220px!important}.legend{display:flex;flex-direction:column;gap:.75rem}.legend-item{display:flex;align-items:center;gap:.5rem;font-family:Inter,Inter,sans-serif;font-size:14px}.legend-marker{width:14px;height:14px;border-radius:50%;display:inline-flex}.legend-label{color:#4b5563}.legend-value{margin-left:auto;font-weight:600;color:#111827}.divider{width:1px;min-height:200px;align-self:stretch;background:#e5e7eb}.table-section{flex:3;display:flex;flex-direction:column;gap:.75rem;font-family:Inter,Inter,sans-serif}.table-header,.table-row{display:flex;justify-content:space-between;font-size:14px}.table-header{font-weight:600;color:#6b7280;padding-bottom:.5rem;border-bottom:1px solid #e5e7eb}.table-row{color:#111827}.total-row{font-weight:700;margin-top:.5rem;padding-top:.5rem;border-top:1px solid #e5e7eb}.state-message{font-family:Inter,Inter,sans-serif;font-size:14px;color:#6b7280}.state-message.error{color:#b91c1c}@media (max-width: 960px){.widget-body{flex-direction:column}.divider{display:none}.chart-section{justify-content:space-between}}:host ::ng-deep .apexcharts-legend{display:none!important}\n"] }]
322
+ }], propDecorators: { customerId: [{
323
+ type: Input
324
+ }], token: [{
325
+ type: Input
326
+ }] } });
327
+
328
+ const ENTITY_CONFIG = {
329
+ applications: { label: 'Applications' },
330
+ triggers: { label: 'Triggers' },
331
+ contactServiceQueues: { label: 'CSQs' },
332
+ resources: { label: 'Resources' },
333
+ resourceGroups: { label: 'Resource Groups' },
334
+ skills: { label: 'Skills' },
335
+ xml: { label: 'XML' },
336
+ scripts: { label: 'Scripts' },
337
+ audioPrompts: { label: 'Audio Prompts' },
338
+ teams: { label: 'Teams' },
339
+ wrapUpCodes: { label: 'Wrap-Up Codes' },
340
+ phonebooks: { label: 'Phonebooks' }
341
+ };
342
+ class SummaryGridComponent {
343
+ constructor() {
344
+ this.ccReadinessService = inject(CcReadinessService);
345
+ this.ENTITY_CONFIG = ENTITY_CONFIG;
346
+ }
347
+ ngOnInit() {
348
+ this.ccReadinessService.setToken(this.token);
349
+ this.data$ = this.ccReadinessService.fetchUccxServerEntityStats(this.customerId)
350
+ .pipe(map(items => {
351
+ return items.map(item => ({
352
+ uccxIp: item.uccxIp,
353
+ counts: Object.entries(item.counts).map(([name, value]) => ({ name, value }))
354
+ }));
355
+ }));
356
+ }
357
+ }
358
+ SummaryGridComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SummaryGridComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
359
+ SummaryGridComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: SummaryGridComponent, selector: "cc-summary-grid", inputs: { customerId: "customerId", token: "token" }, ngImport: i0, template: "<ng-container *ngIf=\"data$ | async as data\">\r\n <div *ngFor=\"let stats of data\">\r\n <tk-card [title]=\"stats.uccxIp\">\r\n <ng-container ngProjectAs=\"card-content\">\r\n <div class=\"grid-wrapper\">\r\n <div class=\"grid-item\" *ngFor=\"let item of stats.counts\">\r\n <div class=\"item-top\">\r\n <span class=\"item-icon\">\r\n <img width=\"24\" height=\"24\" src=\"assets/icons/{{ item.name }}.svg\" alt=\"{{ item.name }} Icon\">\r\n </span>\r\n <span class=\"item-count\">{{ item.value }}</span>\r\n </div>\r\n <span class=\"item-label\">{{ ENTITY_CONFIG[item.name].label }}</span>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </tk-card>\r\n </div>\r\n</ng-container>", styles: [".grid-wrapper{display:grid;grid-template-columns:repeat(6,1fr);gap:2rem;row-gap:2rem}.grid-item{display:flex;flex-direction:column;gap:.5rem}.item-top{display:flex;align-items:center;gap:inherit}.item-icon{display:flex;align-items:center}.item-count{font-size:20px}.item-label{font-size:14px}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: CardComponent, selector: "tk-card", inputs: ["title"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }] });
360
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SummaryGridComponent, decorators: [{
361
+ type: Component,
362
+ args: [{ selector: 'cc-summary-grid', template: "<ng-container *ngIf=\"data$ | async as data\">\r\n <div *ngFor=\"let stats of data\">\r\n <tk-card [title]=\"stats.uccxIp\">\r\n <ng-container ngProjectAs=\"card-content\">\r\n <div class=\"grid-wrapper\">\r\n <div class=\"grid-item\" *ngFor=\"let item of stats.counts\">\r\n <div class=\"item-top\">\r\n <span class=\"item-icon\">\r\n <img width=\"24\" height=\"24\" src=\"assets/icons/{{ item.name }}.svg\" alt=\"{{ item.name }} Icon\">\r\n </span>\r\n <span class=\"item-count\">{{ item.value }}</span>\r\n </div>\r\n <span class=\"item-label\">{{ ENTITY_CONFIG[item.name].label }}</span>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </tk-card>\r\n </div>\r\n</ng-container>", styles: [".grid-wrapper{display:grid;grid-template-columns:repeat(6,1fr);gap:2rem;row-gap:2rem}.grid-item{display:flex;flex-direction:column;gap:.5rem}.item-top{display:flex;align-items:center;gap:inherit}.item-icon{display:flex;align-items:center}.item-count{font-size:20px}.item-label{font-size:14px}\n"] }]
363
+ }], propDecorators: { customerId: [{
364
+ type: Input
365
+ }], token: [{
366
+ type: Input
367
+ }] } });
368
+
369
+ class CcReadinessModule {
370
+ }
371
+ CcReadinessModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: CcReadinessModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
372
+ CcReadinessModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: CcReadinessModule, declarations: [LicencesRequirementComponent,
373
+ SummaryGridComponent,
374
+ CardComponent], imports: [CommonModule,
375
+ HttpClientModule,
376
+ NgApexchartsModule,
377
+ MatTableModule,
378
+ MatButtonModule,
379
+ MatCheckboxModule,
380
+ MatSelectModule,
381
+ MatProgressSpinnerModule,
382
+ MatOptionModule,
383
+ MatPaginatorModule,
384
+ MatSelectModule], exports: [LicencesRequirementComponent,
385
+ SummaryGridComponent] });
386
+ CcReadinessModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: CcReadinessModule, imports: [CommonModule,
387
+ HttpClientModule,
388
+ NgApexchartsModule,
389
+ MatTableModule,
390
+ MatButtonModule,
391
+ MatCheckboxModule,
392
+ MatSelectModule,
393
+ MatProgressSpinnerModule,
394
+ MatOptionModule,
395
+ MatPaginatorModule,
396
+ MatSelectModule] });
397
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: CcReadinessModule, decorators: [{
398
+ type: NgModule,
399
+ args: [{
400
+ declarations: [
401
+ LicencesRequirementComponent,
402
+ SummaryGridComponent,
403
+ CardComponent
404
+ ],
405
+ imports: [
406
+ CommonModule,
407
+ HttpClientModule,
408
+ NgApexchartsModule,
409
+ MatTableModule,
410
+ MatButtonModule,
411
+ MatCheckboxModule,
412
+ MatSelectModule,
413
+ MatProgressSpinnerModule,
414
+ MatOptionModule,
415
+ MatPaginatorModule,
416
+ MatSelectModule
417
+ ],
418
+ exports: [
419
+ LicencesRequirementComponent,
420
+ SummaryGridComponent
421
+ ]
422
+ }]
423
+ }] });
424
+
425
+ /**
426
+ * Generated bundle index. Do not edit.
427
+ */
428
+
429
+ export { CcReadinessModule, LicencesRequirementComponent, SummaryGridComponent };
430
+ //# sourceMappingURL=tuki-io-tuki-widgets-contact-center.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tuki-io-tuki-widgets-contact-center.mjs","sources":["../../../../projects/tuki/widgets/contact-center/shared/api.service.ts","../../../../projects/tuki/widgets/contact-center/shared/api.endpoints.ts","../../../../projects/tuki/widgets/contact-center/cc-readiness/cc-readiness.service.ts","../../../../projects/tuki/widgets/contact-center/cc-readiness/components/card/card.component.ts","../../../../projects/tuki/widgets/contact-center/cc-readiness/components/card/card.component.html","../../../../projects/tuki/widgets/contact-center/cc-readiness/widgets/licences-requirement/licences-requirement.component.ts","../../../../projects/tuki/widgets/contact-center/cc-readiness/widgets/licences-requirement/licences-requirement.component.html","../../../../projects/tuki/widgets/contact-center/cc-readiness/widgets/summary-grid/summary-grid.component.ts","../../../../projects/tuki/widgets/contact-center/cc-readiness/widgets/summary-grid/summary-grid.component.html","../../../../projects/tuki/widgets/contact-center/cc-readiness/cc-readiness.module.ts","../../../../projects/tuki/widgets/contact-center/tuki-io-tuki-widgets-contact-center.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\r\nimport { HttpClient, HttpHeaders } from '@angular/common/http';\r\nimport { Observable } from 'rxjs';\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class APIService {\r\n public token: any;\r\n apiUrl = window.location.protocol + '//' + window.location.hostname + '/dcp';\r\n constructor(\r\n private httpClient: HttpClient\r\n ) {\r\n this.token = 'eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbkBjb3JyZW5ldC5jb20iLCJyb2xlcyI6IlNVUEVSX1VTRVIiLCJpYXQiOjE3NTUwODUyMzgsImV4cCI6MTc1NTEwMzIzOH0.X1CKx-OBZvSs7Bzr_4SWW2ulBgHNkYZrmVuv6V7FZyo'\r\n // this.apiUrl = window.location.protocol + '//' + window.location.host + '/dcp';\r\n this.apiUrl = 'https://dev.tuki.io/webex';\r\n // this.apiUrl = 'http://localhost:8088/dcp';\r\n }\r\n\r\n fetch(url: string, params?: any, cache?: boolean): Observable<any> {\r\n const headers = this.getHeaders(cache);\r\n params = params || {};\r\n return this.httpClient.get(this.apiUrl + url, {params: this.prepareEncodedParams(params), headers});\r\n }\r\n\r\n post(url: string, body: any, params = {}): Observable<any> {\r\n body = body || null;\r\n const headers = this.getHeaders();\r\n return this.httpClient.post(this.apiUrl + url, body, {params: this.prepareEncodedParams(params), headers});\r\n }\r\n\r\n // use when response extended data is necessary:\r\n postExtended(url: string, body = null, params = {}, headers = {}) {\r\n headers = headers || this.getHeaders();\r\n return this.httpClient.post(this.apiUrl + url, body, {\r\n headers,\r\n observe: 'response',\r\n params: this.prepareEncodedParams(params)\r\n });\r\n }\r\n\r\n put(url: string, body = null, params = {}) {\r\n const headers = this.getHeaders();\r\n return this.httpClient.put(this.apiUrl + url, body, {headers, params: this.prepareEncodedParams(params)});\r\n }\r\n\r\n delete(url: string, params = {}) {\r\n const headers = this.getHeaders();\r\n return this.httpClient.delete(this.apiUrl + url, {headers, params: this.prepareEncodedParams(params)});\r\n }\r\n\r\n fetchPagination(url: string, pageSize: number, pageNumber: number, additionalParams = {}, cache?: boolean): Observable<any> {\r\n const copyAdditionalParams = JSON.parse(JSON.stringify(additionalParams));\r\n const params = Object.assign(copyAdditionalParams, {size: pageSize.toString(), page: pageNumber.toString()});\r\n return this.fetch(url, params, cache) as Observable<any>;\r\n }\r\n\r\n private prepareEncodedParams(params: any) {\r\n const result: any = {};\r\n\r\n if (!params) {\r\n return {};\r\n }\r\n for (const key of Object.keys(params)) {\r\n if (params[key]) {\r\n const stringParam = params[key].toString();\r\n result[key] = stringParam.includes('+') ? encodeURIComponent(stringParam) : stringParam;\r\n }\r\n }\r\n return result;\r\n }\r\n\r\n private getHeaders(cache?: boolean): HttpHeaders {\r\n let headers = new HttpHeaders();\r\n if (cache) {\r\n headers = headers.append('_Cache', 'true ');\r\n }\r\n const token = this.token || this.getParameterByName('token');\r\n headers = headers.append('Authorization', 'Bearer '+ token);\r\n return headers;\r\n }\r\n\r\n private getParameterByName(name: any, url = window.location.href) {\r\n name = name.replace(/[\\[\\]]/g, '\\\\$&');\r\n var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),\r\n results = regex.exec(url);\r\n if (!results) return null;\r\n if (!results[2]) return '';\r\n return decodeURIComponent(results[2].replace(/\\+/g, ' '));\r\n }\r\n}","export const API = {\r\n READINESS: {\r\n UCCX_SERVER_ENTITY_STATS: (customerId: number) => `/api/uccx/migration/customer/${customerId}/entity-counts`,\r\n LICENSE_USAGE_SUMMARY: (customerId: number) => `/api/webexreadiness/customers/${customerId}/callinglicesnsecountperfeature`,\r\n }\r\n}","import { inject, Inject, Injectable } from '@angular/core';\nimport { APIService } from '../shared/api.service';\nimport { UccxServerEntityStats, WebexLicenseUsageSummary } from './types/cc-readiness';\nimport { API } from '../shared/api.endpoints';\nimport { catchError, map, Observable, throwError } from 'rxjs';\n\n@Injectable({\n providedIn: 'root'\n})\nexport class CcReadinessService {\n private readonly api = inject(APIService);\n\n constructor() { }\n\n fetchUccxServerEntityStats(customerId: number): Observable<UccxServerEntityStats[]> {\n return this.api.fetch(API.READINESS.UCCX_SERVER_ENTITY_STATS(customerId))\n .pipe(map((stats: UccxServerEntityStats[]) => {\n stats.forEach(stat => {\n // @ts-ignore\n delete stat.counts.reasonCodes;\n });\n return stats;\n }));\n }\n\n fetchWebexLicenseUsageSummary(customerId: number): Observable<WebexLicenseUsageSummary[]> {\n return this.api.fetch(API.READINESS.LICENSE_USAGE_SUMMARY(customerId));\n }\n\n setToken(token: string): void {\n this.api.token = token;\n }\n}","import { Component, Input } from \"@angular/core\";\r\n\r\n@Component({\r\n selector: 'tk-card',\r\n templateUrl: './card.component.html',\r\n styleUrls: ['./card.component.scss']\r\n})\r\nexport class CardComponent {\r\n @Input() title!: string;\r\n}","<article class=\"card\">\r\n <header class=\"card__header\">\r\n <h2>{{ title }}</h2>\r\n <!--<div class=\"card__menu-button\">\r\n <img width=\"18\" src=\"assets/icons/menu_icon.png\" alt=\"Menu Icon\">\r\n </div>-->\r\n </header>\r\n <div class=\"card__content\">\r\n <ng-content select=\"card-content\"></ng-content>\r\n </div>\r\n</article>\r\n","import { Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges, inject } from '@angular/core';\nimport { ApexChart, ApexDataLabels, ApexLegend, ApexNonAxisChartSeries, ApexPlotOptions } from 'ng-apexcharts';\nimport { catchError, finalize, of, Subscription } from 'rxjs';\nimport { CcReadinessService } from '../../cc-readiness.service';\nimport { WebexLicenseUsageSummary } from '../../types/cc-readiness';\n\ninterface LicenseLegendItem {\n label: string;\n count: number;\n percentage: number;\n color: string;\n}\n\ninterface LicenseTableRow {\n label: string;\n value: number;\n}\n\ninterface LicenseChartOptions {\n series: ApexNonAxisChartSeries;\n chart: ApexChart;\n labels: string[];\n colors: string[];\n legend: ApexLegend;\n plotOptions: ApexPlotOptions;\n dataLabels: ApexDataLabels;\n}\n\ninterface LicenseRequirementViewModel {\n chartOptions: LicenseChartOptions;\n legendItems: LicenseLegendItem[];\n rows: LicenseTableRow[];\n totalRequired: number;\n}\n\nconst LEGEND_COLORS = {\n existing: '#16A693',\n missing: '#808080'\n};\n\n@Component({\n selector: 'cc-licenses-requirement',\n templateUrl: './licences-requirement.component.html',\n styleUrls: ['./licences-requirement.component.scss']\n})\nexport class LicencesRequirementComponent implements OnInit, OnDestroy, OnChanges {\n @Input() customerId!: number;\n @Input() token!: string;\n\n private readonly ccReadinessService = inject(CcReadinessService);\n private subscription?: Subscription;\n\n viewModel: LicenseRequirementViewModel | null = null;\n loading = false;\n error = false;\n\n filters: string[] = ['All', 'Professional licenses', 'Workspace licenses'];\n selectedSummaryIndex = 0;\n\n private summary: WebexLicenseUsageSummary | null = null;\n\n ngOnInit(): void {\n this.loadSummaries();\n }\n\n ngOnDestroy(): void {\n this.subscription?.unsubscribe();\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if ((changes['customerId'] && !changes['customerId'].firstChange) ||\n (changes['token'] && !changes['token'].firstChange)) {\n this.loadSummaries();\n }\n }\n\n onFilterChange(index: number): void {\n if (!isNaN(index) && index >= 0 && index < this.filters.length) {\n this.selectFilter(index);\n }\n }\n\n private loadSummaries(): void {\n const numericCustomerId = Number(this.customerId);\n if (!numericCustomerId || !this.token) {\n return;\n }\n\n this.subscription?.unsubscribe();\n this.loading = true;\n this.error = false;\n this.viewModel = null;\n this.selectedSummaryIndex = 0;\n\n this.ccReadinessService.setToken(this.token);\n this.subscription = this.ccReadinessService.fetchWebexLicenseUsageSummary(numericCustomerId)\n .pipe(\n catchError(error => {\n console.error('Unable to load Webex license usage summary', error);\n this.error = true;\n return of<WebexLicenseUsageSummary[]>([]);\n }),\n finalize(() => this.loading = false)\n )\n .subscribe(items => {\n console.log('Raw API response:', items);\n // Handle both array and single object responses\n if (Array.isArray(items) && items.length > 0) {\n this.summary = items[0];\n } else if (items && typeof items === 'object' && !Array.isArray(items)) {\n // If single object returned, use it directly\n this.summary = items as unknown as WebexLicenseUsageSummary;\n } else {\n this.summary = null;\n }\n\n console.log('Processed summary:', this.summary);\n this.selectFilter(0);\n });\n }\n\n private selectFilter(index: number): void {\n this.selectedSummaryIndex = index;\n if (!this.summary) {\n this.viewModel = null;\n return;\n }\n this.viewModel = this.mapSummaryToViewModel(this.summary, index);\n console.log('Created viewModel for filter index', index, ':', this.viewModel);\n }\n\n private mapSummaryToViewModel(summary: WebexLicenseUsageSummary, filterIndex: number): LicenseRequirementViewModel {\n console.log('Mapping summary to viewModel:', summary, 'filterIndex:', filterIndex);\n\n // Extract data from webexReadinessLicenseStats and license counts\n const personStat = summary.webexReadinessLicenseStats?.find(stat => stat.feature === 'PERSON');\n const deviceStat = summary.webexReadinessLicenseStats?.find(stat => stat.feature === 'ORPHANED_DEVICE');\n\n const professionalNeeded = personStat?.totalCount ?? 0;\n const workspaceNeeded = deviceStat?.totalCount ?? 0;\n\n const professionalOwned = Number(summary.totalProfessionalLicenseCount ?? 0);\n const workspaceOwned = Number(summary.totalWorkspaceProfessionalLicenseCount ?? 0);\n\n // Filter data based on selection\n let existingCount: number;\n let missingCount: number;\n let rows: LicenseTableRow[];\n\n if (filterIndex === 0) {\n // All - show both\n existingCount = professionalOwned + workspaceOwned;\n const totalNeeded = professionalNeeded + workspaceNeeded;\n missingCount = Math.max(0, totalNeeded - existingCount);\n\n rows = [\n { label: 'Professional licenses', value: professionalNeeded },\n { label: 'Workspace licenses', value: workspaceNeeded }\n ];\n } else if (filterIndex === 1) {\n // Professional licenses only\n existingCount = professionalOwned;\n missingCount = Math.max(0, professionalNeeded - professionalOwned);\n\n rows = [{ label: 'Professional licenses', value: professionalNeeded }];\n } else {\n // Workspace licenses only\n existingCount = workspaceOwned;\n missingCount = Math.max(0, workspaceNeeded - workspaceOwned);\n\n rows = [{ label: 'Workspace licenses', value: workspaceNeeded }];\n }\n\n const totalLicenses = existingCount + missingCount;\n\n const legendItems: LicenseLegendItem[] = [\n {\n label: 'Existing licenses',\n count: existingCount,\n percentage: totalLicenses > 0 ? (existingCount / totalLicenses) * 100 : 0,\n color: LEGEND_COLORS.existing\n },\n {\n label: 'Missing licenses',\n count: missingCount,\n percentage: totalLicenses > 0 ? (missingCount / totalLicenses) * 100 : 0,\n color: LEGEND_COLORS.missing\n }\n ];\n\n console.log('Legend items:', legendItems);\n console.log('Table rows:', rows);\n\n const totalRequired = rows.reduce((acc, row) => acc + row.value, 0);\n\n return {\n chartOptions: this.buildChartOptions(legendItems),\n legendItems,\n rows,\n totalRequired\n };\n }\n\n private buildChartOptions(legendItems: LicenseLegendItem[]): LicenseChartOptions {\n return {\n series: legendItems.map(item => item.count),\n chart: {\n type: 'donut',\n height: 220\n },\n labels: legendItems.map(item => item.label),\n colors: legendItems.map(item => item.color),\n legend: {\n show: false\n },\n plotOptions: {\n pie: {\n donut: {\n size: '75%'\n }\n }\n },\n dataLabels: {\n enabled: false\n }\n };\n }\n\n private normalizePercentage(value: number): number {\n if (!isFinite(value)) {\n return 0;\n }\n // Convert decimal to percentage (0.9487 → 94.9)\n const percentage = value * 100;\n return Math.round(percentage * 10) / 10;\n }\n}\n","<tk-card title=\"Licenses requirement\">\n <ng-container ngProjectAs=\"card-content\">\n <div\n class=\"widget-body\"\n *ngIf=\"!loading && !error && viewModel; else widgetState\"\n >\n <div class=\"left-section\">\n <mat-select\n [(value)]=\"selectedSummaryIndex\"\n (selectionChange)=\"onFilterChange($event.value)\"\n class=\"filter-select\"\n >\n <mat-option *ngFor=\"let option of filters; index as i\" [value]=\"i\">\n {{ option }}\n </mat-option>\n </mat-select>\n\n <div class=\"chart-section\">\n <div class=\"chart-wrapper\">\n <apx-chart\n [series]=\"viewModel.chartOptions.series\"\n [chart]=\"viewModel.chartOptions.chart\"\n [labels]=\"viewModel.chartOptions.labels\"\n [colors]=\"viewModel.chartOptions.colors\"\n [legend]=\"viewModel.chartOptions.legend\"\n [plotOptions]=\"viewModel.chartOptions.plotOptions\"\n [dataLabels]=\"viewModel.chartOptions.dataLabels\"\n >\n </apx-chart>\n </div>\n <div class=\"legend\">\n <div class=\"legend-item\" *ngFor=\"let item of viewModel.legendItems\">\n <span\n class=\"legend-marker\"\n [style.backgroundColor]=\"item.color\"\n ></span>\n <span class=\"legend-label\">{{ item.label }}</span>\n <span class=\"legend-value\">{{ item.count | number }}</span>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"divider\" aria-hidden=\"true\"></div>\n\n <div class=\"table-section\">\n <div class=\"table-header\">\n <span>License</span>\n <span>Required</span>\n </div>\n <div class=\"table-row\" *ngFor=\"let row of viewModel.rows\">\n <span>{{ row.label }}</span>\n <span>{{ row.value | number }}</span>\n </div>\n <div class=\"table-row total-row\">\n <span>Total</span>\n <span>{{ viewModel.totalRequired | number }}</span>\n </div>\n </div>\n </div>\n\n <ng-template #widgetState>\n <div class=\"state-message\" *ngIf=\"loading\">\n Loading license requirements…\n </div>\n <div class=\"state-message error\" *ngIf=\"!loading && error\">\n Unable to load license requirements.\n </div>\n <div class=\"state-message\" *ngIf=\"!loading && !error && !viewModel\">\n No license data available.\n </div>\n </ng-template>\n </ng-container>\n</tk-card>\n","import { Component, inject, Input, OnInit } from \"@angular/core\";\r\nimport { CcReadinessService } from \"../../cc-readiness.service\";\r\nimport { map, Observable } from \"rxjs\";\r\nimport { EntityType, UccxServerEntityStats } from \"../../types/cc-readiness\";\r\n\r\ninterface SummaryGridCount {\r\n name: string;\r\n value: number;\r\n}\r\n\r\ninterface SummaryGridItem {\r\n uccxIp: string;\r\n counts: SummaryGridCount[];\r\n}\r\n\r\nconst ENTITY_CONFIG: { [key: string]: { label: string } } = {\r\n applications: { label: 'Applications' },\r\n triggers: { label: 'Triggers' },\r\n contactServiceQueues: { label: 'CSQs' },\r\n resources: { label: 'Resources' },\r\n resourceGroups: { label: 'Resource Groups' },\r\n skills: { label: 'Skills' },\r\n xml: { label: 'XML' },\r\n scripts: { label: 'Scripts' },\r\n audioPrompts: { label: 'Audio Prompts' },\r\n teams: { label: 'Teams' },\r\n wrapUpCodes: { label: 'Wrap-Up Codes' },\r\n phonebooks: { label: 'Phonebooks' }\r\n};\r\n\r\n@Component({\r\n selector: 'cc-summary-grid',\r\n templateUrl: 'summary-grid.component.html',\r\n styleUrls: ['summary-grid.component.scss']\r\n})\r\nexport class SummaryGridComponent implements OnInit {\r\n @Input() customerId!: number;\r\n @Input() token!: string;\r\n\r\n private readonly ccReadinessService = inject(CcReadinessService);\r\n\r\n readonly ENTITY_CONFIG = ENTITY_CONFIG;\r\n\r\n data$!: Observable<SummaryGridItem[]>;\r\n\r\n ngOnInit(): void {\r\n this.ccReadinessService.setToken(this.token);\r\n\r\n this.data$ = this.ccReadinessService.fetchUccxServerEntityStats(this.customerId)\r\n .pipe(map(items => {\r\n return items.map(item => ({\r\n uccxIp: item.uccxIp,\r\n counts: Object.entries(item.counts).map(([name, value]) => ({ name, value }))\r\n }));\r\n }));\r\n }\r\n}","<ng-container *ngIf=\"data$ | async as data\">\r\n <div *ngFor=\"let stats of data\">\r\n <tk-card [title]=\"stats.uccxIp\">\r\n <ng-container ngProjectAs=\"card-content\">\r\n <div class=\"grid-wrapper\">\r\n <div class=\"grid-item\" *ngFor=\"let item of stats.counts\">\r\n <div class=\"item-top\">\r\n <span class=\"item-icon\">\r\n <img width=\"24\" height=\"24\" src=\"assets/icons/{{ item.name }}.svg\" alt=\"{{ item.name }} Icon\">\r\n </span>\r\n <span class=\"item-count\">{{ item.value }}</span>\r\n </div>\r\n <span class=\"item-label\">{{ ENTITY_CONFIG[item.name].label }}</span>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </tk-card>\r\n </div>\r\n</ng-container>","import { NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { HttpClientModule } from '@angular/common/http';\nimport { LicencesRequirementComponent } from './widgets/licences-requirement/licences-requirement.component';\nimport { SummaryGridComponent } from './widgets/summary-grid/summary-grid.component';\nimport { CardComponent } from './components/card/card.component';\nimport { NgApexchartsModule } from 'ng-apexcharts';\nimport { MaterialModule } from '../shared/material.module';\nimport { SharedModule } from '../shared/shared.module';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatCheckboxModule } from '@angular/material/checkbox';\nimport { MatOptionModule } from '@angular/material/core';\nimport { MatPaginatorModule } from '@angular/material/paginator';\nimport { MatProgressSpinnerModule } from '@angular/material/progress-spinner';\nimport { MatSelectModule } from '@angular/material/select';\nimport { MatTableModule } from '@angular/material/table';\n\n\n\n@NgModule({\n declarations: [\n LicencesRequirementComponent,\n SummaryGridComponent,\n CardComponent\n ],\n imports: [\n CommonModule,\n HttpClientModule,\n NgApexchartsModule,\n MatTableModule,\n MatButtonModule,\n MatCheckboxModule,\n MatSelectModule,\n MatProgressSpinnerModule,\n MatOptionModule,\n MatPaginatorModule,\n MatSelectModule\n ],\n exports: [\n LicencesRequirementComponent,\n SummaryGridComponent\n ]\n})\nexport class CcReadinessModule { }\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1","i5.CardComponent","i2.CardComponent"],"mappings":"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"}