@cqa-lib/cqa-ui 0.1.2 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2020/lib/action-menu/action-menu.component.mjs +42 -0
- package/esm2020/lib/assets/images/image-assets.constants.mjs +28 -0
- package/esm2020/lib/badge/badge.component.mjs +141 -0
- package/esm2020/lib/button/button.component.mjs +42 -67
- package/esm2020/lib/column-visibility/column-visibility.component.mjs +69 -0
- package/esm2020/lib/dashboards/chart-card/chart-card.component.mjs +22 -0
- package/esm2020/lib/dashboards/coverage-module-card/coverage-module-card.component.mjs +105 -0
- package/esm2020/lib/dashboards/dashboard-header/dashboard-header.component.mjs +82 -0
- package/esm2020/lib/dashboards/failed-test-cases-card/failed-test-cases-card.component.mjs +59 -0
- package/esm2020/lib/dashboards/heat-error-map-cell/heat-error-map-cell.component.mjs +45 -0
- package/esm2020/lib/dashboards/insight-card/insight-card.component.mjs +201 -0
- package/esm2020/lib/dashboards/metrics-card/metrics-block.component.mjs +41 -0
- package/esm2020/lib/dashboards/metrics-card/metrics-card-item.interface.mjs +2 -0
- package/esm2020/lib/dashboards/metrics-card/metrics-card.component.mjs +62 -0
- package/esm2020/lib/dashboards/progress-text-card/progress-text-card.component.mjs +46 -0
- package/esm2020/lib/dashboards/test-distribution-card/test-distribution-card.component.mjs +35 -0
- package/esm2020/lib/dialog/dialog.component.mjs +4 -4
- package/esm2020/lib/dropdown-button/dropdown-button.component.mjs +189 -0
- package/esm2020/lib/dynamic-select/dynamic-select-field.component.mjs +160 -0
- package/esm2020/lib/empty-state/empty-state.component.mjs +37 -0
- package/esm2020/lib/filters/dynamic-filter/dynamic-filter.component.mjs +239 -0
- package/esm2020/lib/full-table-loader/full-table-loader.component.mjs +16 -0
- package/esm2020/lib/inline-sort/inline-sort.component.mjs +58 -0
- package/esm2020/lib/other-button/other-button.component.mjs +76 -0
- package/esm2020/lib/pagination/pagination.component.mjs +102 -0
- package/esm2020/lib/search-bar/search-bar.component.mjs +3 -3
- package/esm2020/lib/segment-control/segment-control.component.mjs +3 -3
- package/esm2020/lib/selected-filters/selected-filters.component.mjs +27 -0
- package/esm2020/lib/table/dynamic-table/dynamic-cell.directive.mjs +35 -0
- package/esm2020/lib/table/dynamic-table/dynamic-table.component.mjs +258 -0
- package/esm2020/lib/table-action-toolbar/table-action-toolbar.component.mjs +52 -0
- package/esm2020/lib/table-data-loader/table-data-loader.component.mjs +19 -0
- package/esm2020/lib/templates/table-template.component.mjs +365 -0
- package/esm2020/lib/ui-kit.module.mjs +196 -17
- package/esm2020/lib/utils/metadata-colors.util.mjs +100 -0
- package/esm2020/lib/utils/tw-overlay-container.mjs +22 -0
- package/esm2020/public-api.mjs +29 -1
- package/fesm2015/cqa-lib-cqa-ui.mjs +2899 -133
- package/fesm2015/cqa-lib-cqa-ui.mjs.map +1 -1
- package/fesm2020/cqa-lib-cqa-ui.mjs +2867 -133
- package/fesm2020/cqa-lib-cqa-ui.mjs.map +1 -1
- package/lib/action-menu/action-menu.component.d.ts +17 -0
- package/lib/assets/images/image-assets.constants.d.ts +20 -0
- package/lib/badge/badge.component.d.ts +25 -0
- package/lib/button/button.component.d.ts +6 -5
- package/lib/column-visibility/column-visibility.component.d.ts +33 -0
- package/lib/dashboards/chart-card/chart-card.component.d.ts +8 -0
- package/lib/dashboards/coverage-module-card/coverage-module-card.component.d.ts +44 -0
- package/lib/dashboards/dashboard-header/dashboard-header.component.d.ts +30 -0
- package/lib/dashboards/failed-test-cases-card/failed-test-cases-card.component.d.ts +28 -0
- package/lib/dashboards/heat-error-map-cell/heat-error-map-cell.component.d.ts +14 -0
- package/lib/dashboards/insight-card/insight-card.component.d.ts +73 -0
- package/lib/dashboards/metrics-card/metrics-block.component.d.ts +12 -0
- package/lib/dashboards/metrics-card/metrics-card-item.interface.d.ts +12 -0
- package/lib/dashboards/metrics-card/metrics-card.component.d.ts +17 -0
- package/lib/dashboards/progress-text-card/progress-text-card.component.d.ts +13 -0
- package/lib/dashboards/test-distribution-card/test-distribution-card.component.d.ts +29 -0
- package/lib/dropdown-button/dropdown-button.component.d.ts +32 -0
- package/lib/dynamic-select/dynamic-select-field.component.d.ts +43 -0
- package/lib/empty-state/empty-state.component.d.ts +20 -0
- package/lib/filters/dynamic-filter/dynamic-filter.component.d.ts +56 -0
- package/lib/full-table-loader/full-table-loader.component.d.ts +6 -0
- package/lib/inline-sort/inline-sort.component.d.ts +12 -0
- package/lib/other-button/other-button.component.d.ts +37 -0
- package/lib/pagination/pagination.component.d.ts +37 -0
- package/lib/selected-filters/selected-filters.component.d.ts +17 -0
- package/lib/table/dynamic-table/dynamic-cell.directive.d.ts +16 -0
- package/lib/table/dynamic-table/dynamic-table.component.d.ts +72 -0
- package/lib/table-action-toolbar/table-action-toolbar.component.d.ts +34 -0
- package/lib/table-data-loader/table-data-loader.component.d.ts +7 -0
- package/lib/templates/table-template.component.d.ts +90 -0
- package/lib/ui-kit.module.d.ts +43 -6
- package/lib/utils/metadata-colors.util.d.ts +50 -0
- package/lib/utils/tw-overlay-container.d.ts +12 -0
- package/package.json +1 -1
- package/public-api.d.ts +28 -0
- package/src/assets/fonts/SFUIText-Bold/SF-UI-Text-Bold.eot +0 -0
- package/src/assets/fonts/SFUIText-Bold/SF-UI-Text-Bold.otf +0 -0
- package/src/assets/fonts/SFUIText-Bold/SF-UI-Text-Bold.svg +14730 -0
- package/src/assets/fonts/SFUIText-Bold/SF-UI-Text-Bold.ttf +0 -0
- package/src/assets/fonts/SFUIText-Bold/SF-UI-Text-Bold.woff +0 -0
- package/src/assets/fonts/SFUIText-Bold/SF-UI-Text-Bold.woff2 +0 -0
- package/src/assets/fonts/SFUIText-Light/SF-UI-Text-Light.eot +0 -0
- package/src/assets/fonts/SFUIText-Light/SF-UI-Text-Light.otf +0 -0
- package/src/assets/fonts/SFUIText-Light/SF-UI-Text-Light.svg +21333 -0
- package/src/assets/fonts/SFUIText-Light/SF-UI-Text-Light.ttf +0 -0
- package/src/assets/fonts/SFUIText-Light/SF-UI-Text-Light.woff +0 -0
- package/src/assets/fonts/SFUIText-Light/SF-UI-Text-Light.woff2 +0 -0
- package/src/assets/fonts/SFUIText-Medium/SF-UI-Text-Medium.eot +0 -0
- package/src/assets/fonts/SFUIText-Medium/SF-UI-Text-Medium.otf +0 -0
- package/src/assets/fonts/SFUIText-Medium/SF-UI-Text-Medium.svg +14584 -0
- package/src/assets/fonts/SFUIText-Medium/SF-UI-Text-Medium.ttf +0 -0
- package/src/assets/fonts/SFUIText-Medium/SF-UI-Text-Medium.woff +0 -0
- package/src/assets/fonts/SFUIText-Medium/SF-UI-Text-Medium.woff2 +0 -0
- package/src/assets/fonts/SFUIText-Regular/SF-UI-Text-Regular.eot +0 -0
- package/src/assets/fonts/SFUIText-Regular/SF-UI-Text-Regular.otf +0 -0
- package/src/assets/fonts/SFUIText-Regular/SF-UI-Text-Regular.svg +17870 -0
- package/src/assets/fonts/SFUIText-Regular/SF-UI-Text-Regular.ttf +0 -0
- package/src/assets/fonts/SFUIText-Regular/SF-UI-Text-Regular.woff +0 -0
- package/src/assets/fonts/SFUIText-Regular/SF-UI-Text-Regular.woff2 +0 -0
- package/src/assets/fonts/SFUIText-Semibold/SF-UI-Text-Semibold.eot +0 -0
- package/src/assets/fonts/SFUIText-Semibold/SF-UI-Text-Semibold.otf +0 -0
- package/src/assets/fonts/SFUIText-Semibold/SF-UI-Text-Semibold.svg +14732 -0
- package/src/assets/fonts/SFUIText-Semibold/SF-UI-Text-Semibold.ttf +0 -0
- package/src/assets/fonts/SFUIText-Semibold/SF-UI-Text-Semibold.woff +0 -0
- package/src/assets/fonts/SFUIText-Semibold/SF-UI-Text-Semibold.woff2 +0 -0
- package/src/lib/assets/images/.gitkeep +0 -0
- package/src/lib/assets/images/DashboardIcon.png +0 -0
- package/src/lib/assets/images/FilesIcon.png +0 -0
- package/src/lib/assets/images/README.md +66 -0
- package/src/lib/assets/images/ReportsIcon.png +0 -0
- package/src/lib/assets/images/SearchIcon.png +0 -0
- package/src/lib/assets/images/StepsIcon.png +0 -0
- package/src/lib/assets/images/TestCaseIcon.png +0 -0
- package/src/lib/assets/images/analytics-chart-icon.svg +11 -0
- package/src/lib/assets/images/checklist-add-icon.svg +10 -0
- package/src/lib/assets/images/document-gear-icon.svg +9 -0
- package/src/lib/assets/images/empty-state-default-icon.svg +8 -0
- package/src/lib/assets/images/image-assets.constants.ts +38 -0
- package/src/lib/assets/images/search-debug-icon.svg +8 -0
- package/src/lib/assets/images/test-case-icon.svg +9 -0
- package/src/lib/assets/images/upload-folder-icon.svg +7 -0
- package/src/lib/utils/metadata-colors.constants.js +33 -0
- package/storybook-static/assets/images/README.md +66 -0
- package/styles.css +1 -1
|
@@ -1,13 +1,32 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { EventEmitter, Component, Input, Output, HostListener, ViewChildren, ViewChild, ChangeDetectionStrategy, NgModule, InjectionToken, Injector
|
|
2
|
+
import { EventEmitter, Component, Input, Output, HostListener, ViewChildren, ViewChild, ChangeDetectionStrategy, Directive, TemplateRef, ContentChildren, ContentChild, ElementRef, Injectable, NgModule, InjectionToken, Injector } from '@angular/core';
|
|
3
3
|
import * as i2 from '@angular/common';
|
|
4
4
|
import { CommonModule } from '@angular/common';
|
|
5
|
-
import * as
|
|
6
|
-
import { FormsModule } from '@angular/forms';
|
|
5
|
+
import * as i1$1 from '@angular/forms';
|
|
6
|
+
import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|
7
7
|
import * as i1 from '@angular/material/icon';
|
|
8
8
|
import { MatIconModule } from '@angular/material/icon';
|
|
9
|
-
import * as i1$
|
|
10
|
-
import {
|
|
9
|
+
import * as i1$2 from '@angular/material/tooltip';
|
|
10
|
+
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
11
|
+
import * as i3$1 from '@angular/material/menu';
|
|
12
|
+
import { MatMenuModule } from '@angular/material/menu';
|
|
13
|
+
import * as i1$3 from '@angular/material/button';
|
|
14
|
+
import { MatButtonModule } from '@angular/material/button';
|
|
15
|
+
import * as i3$2 from '@angular/material/form-field';
|
|
16
|
+
import { MatFormFieldModule } from '@angular/material/form-field';
|
|
17
|
+
import * as i2$1 from '@angular/material/select';
|
|
18
|
+
import { MatSelectModule } from '@angular/material/select';
|
|
19
|
+
import * as i3$3 from '@angular/material/core';
|
|
20
|
+
import { MatOptionModule, MatNativeDateModule } from '@angular/material/core';
|
|
21
|
+
import * as i3$4 from '@angular/material/checkbox';
|
|
22
|
+
import { MatCheckboxModule } from '@angular/material/checkbox';
|
|
23
|
+
import * as i4$1 from '@angular/material/radio';
|
|
24
|
+
import { MatRadioModule } from '@angular/material/radio';
|
|
25
|
+
import * as i4 from '@angular/material/datepicker';
|
|
26
|
+
import { MatDatepickerModule } from '@angular/material/datepicker';
|
|
27
|
+
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
|
28
|
+
import * as i1$4 from '@angular/cdk/overlay';
|
|
29
|
+
import { OverlayContainer, OverlayModule, OverlayConfig } from '@angular/cdk/overlay';
|
|
11
30
|
import * as i3 from '@angular/cdk/portal';
|
|
12
31
|
import { TemplatePortal, CdkPortalOutlet, PortalModule, ComponentPortal } from '@angular/cdk/portal';
|
|
13
32
|
import { filter } from 'rxjs/operators';
|
|
@@ -18,6 +37,7 @@ class ButtonComponent {
|
|
|
18
37
|
this.variant = 'filled';
|
|
19
38
|
this.disabled = false;
|
|
20
39
|
this.iconPosition = 'start';
|
|
40
|
+
this.fullWidth = false;
|
|
21
41
|
this.type = 'button';
|
|
22
42
|
this.clicked = new EventEmitter();
|
|
23
43
|
// Internal state tracking
|
|
@@ -30,74 +50,26 @@ class ButtonComponent {
|
|
|
30
50
|
}
|
|
31
51
|
get buttonClasses() {
|
|
32
52
|
const baseClasses = [
|
|
33
|
-
'cqa-flex',
|
|
34
|
-
'cqa-flex-col',
|
|
35
|
-
'cqa-justify-center',
|
|
53
|
+
'cqa-inline-flex',
|
|
36
54
|
'cqa-items-center',
|
|
37
|
-
'cqa-p-0',
|
|
38
|
-
'cqa-gap-2',
|
|
39
|
-
'cqa-rounded-lg',
|
|
40
|
-
'cqa-cursor-pointer',
|
|
41
|
-
'cqa-font-inter',
|
|
42
|
-
'cqa-font-semibold',
|
|
43
|
-
'cqa-text-sm',
|
|
44
|
-
'cqa-leading-[14px]',
|
|
45
|
-
'cqa-transition-all',
|
|
46
|
-
'cqa-duration-200',
|
|
47
|
-
'cqa-outline-none'
|
|
48
|
-
];
|
|
49
|
-
if (this.disabled) {
|
|
50
|
-
baseClasses.push('cqa-cursor-not-allowed');
|
|
51
|
-
}
|
|
52
|
-
// Add variant and state specific classes
|
|
53
|
-
const variantClasses = this.getVariantClasses();
|
|
54
|
-
return [...baseClasses, ...variantClasses].join(' ');
|
|
55
|
-
}
|
|
56
|
-
get stateLayerClasses() {
|
|
57
|
-
const classes = [
|
|
58
|
-
'cqa-flex',
|
|
59
|
-
'cqa-flex-row',
|
|
60
55
|
'cqa-justify-center',
|
|
61
|
-
'cqa-items-center',
|
|
62
56
|
'cqa-gap-2',
|
|
63
|
-
'cqa-w-full',
|
|
64
|
-
'cqa-h-full',
|
|
65
57
|
'cqa-py-[10px]',
|
|
66
|
-
'cqa-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const classes = [
|
|
72
|
-
'cqa-flex',
|
|
73
|
-
'cqa-items-center',
|
|
74
|
-
'cqa-text-center',
|
|
75
|
-
'cqa-font-inter',
|
|
76
|
-
'cqa-font-semibold',
|
|
77
|
-
'cqa-text-sm',
|
|
78
|
-
'cqa-leading-[14px]',
|
|
79
|
-
'cqa-flex-none',
|
|
80
|
-
this.textClass,
|
|
58
|
+
'cqa-rounded-[8px]',
|
|
59
|
+
'cqa-text-[12.3px]',
|
|
60
|
+
'cqa-leading-[17.5px]',
|
|
61
|
+
'cqa-font-medium',
|
|
62
|
+
'cqa-border',
|
|
81
63
|
];
|
|
82
64
|
if (this.disabled) {
|
|
83
|
-
|
|
65
|
+
baseClasses.push('cqa-cursor-not-allowed');
|
|
84
66
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
get iconClasses() {
|
|
88
|
-
const classes = [
|
|
89
|
-
'cqa-flex',
|
|
90
|
-
'cqa-items-center',
|
|
91
|
-
'cqa-justify-center',
|
|
92
|
-
'cqa-w-[14px]',
|
|
93
|
-
'cqa-h-[14px]',
|
|
94
|
-
'cqa-shrink-0',
|
|
95
|
-
'cqa-flex-none'
|
|
96
|
-
];
|
|
97
|
-
if (this.disabled) {
|
|
98
|
-
classes.push('cqa-opacity-[0.38]');
|
|
67
|
+
if (this.fullWidth) {
|
|
68
|
+
baseClasses.push('cqa-w-full');
|
|
99
69
|
}
|
|
100
|
-
|
|
70
|
+
// Add variant and state specific classes
|
|
71
|
+
const variantClasses = this.getVariantClasses();
|
|
72
|
+
return [...baseClasses, ...variantClasses, ...(this.customClass ? [this.customClass] : [])].join(' ');
|
|
101
73
|
}
|
|
102
74
|
getVariantClasses() {
|
|
103
75
|
const classes = [];
|
|
@@ -106,9 +78,21 @@ class ButtonComponent {
|
|
|
106
78
|
classes.push('cqa-bg-primary-muted');
|
|
107
79
|
}
|
|
108
80
|
else {
|
|
109
|
-
classes.push('cqa-bg-primary');
|
|
81
|
+
classes.push('cqa-bg-primary cqa-text-white');
|
|
82
|
+
if (this.isHovered) {
|
|
83
|
+
classes.push('cqa-bg-primary-hover');
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
else if (this.variant === 'grey-solid') {
|
|
88
|
+
// Neutral grey solid style
|
|
89
|
+
if (this.disabled) {
|
|
90
|
+
classes.push('cqa-bg-grey-400', 'cqa-border', 'cqa-border-primary-muted');
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
classes.push('cqa-bg-grey-400', 'cqa-border', 'cqa-border-primary-muted');
|
|
110
94
|
if (this.isHovered) {
|
|
111
|
-
classes.push('cqa-
|
|
95
|
+
classes.push('cqa-bg-grey-200');
|
|
112
96
|
}
|
|
113
97
|
}
|
|
114
98
|
}
|
|
@@ -130,10 +114,10 @@ class ButtonComponent {
|
|
|
130
114
|
}
|
|
131
115
|
else if (this.variant === 'text') {
|
|
132
116
|
if (this.disabled) {
|
|
133
|
-
classes.push('cqa-bg-transparent');
|
|
117
|
+
classes.push('cqa-bg-transparent', 'cqa-border-none');
|
|
134
118
|
}
|
|
135
119
|
else {
|
|
136
|
-
classes.push('cqa-bg-transparent');
|
|
120
|
+
classes.push('cqa-bg-transparent', 'cqa-border-none');
|
|
137
121
|
if (this.isHovered || this.isFocused || this.isPressed) {
|
|
138
122
|
classes.push('cqa-bg-primary-surface');
|
|
139
123
|
}
|
|
@@ -183,6 +167,8 @@ class ButtonComponent {
|
|
|
183
167
|
switch (this.variant) {
|
|
184
168
|
case 'filled':
|
|
185
169
|
return 'cqa-text-surface-default';
|
|
170
|
+
case 'grey-solid':
|
|
171
|
+
return 'cqa-text-black-100';
|
|
186
172
|
case 'outlined':
|
|
187
173
|
if (this.isFocused || this.isHovered || this.isPressed) {
|
|
188
174
|
return 'cqa-text-primary-hover';
|
|
@@ -230,10 +216,10 @@ class ButtonComponent {
|
|
|
230
216
|
}
|
|
231
217
|
}
|
|
232
218
|
ButtonComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: ButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
233
|
-
ButtonComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: ButtonComponent, selector: "cqa-button", inputs: { variant: "variant", disabled: "disabled", icon: "icon", iconPosition: "iconPosition", type: "type" }, outputs: { clicked: "clicked" }, host: { listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()", "mousedown": "onMouseDown()", "mouseup": "onMouseUp()", "focus": "onFocus()", "blur": "onBlur()" } }, ngImport: i0, template: "<div id=\"cqa-ui-root\"
|
|
219
|
+
ButtonComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: ButtonComponent, selector: "cqa-button", inputs: { variant: "variant", disabled: "disabled", icon: "icon", iconPosition: "iconPosition", fullWidth: "fullWidth", iconColor: "iconColor", type: "type", text: "text", customClass: "customClass" }, outputs: { clicked: "clicked" }, host: { listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()", "mousedown": "onMouseDown()", "mouseup": "onMouseUp()", "focus": "onFocus()", "blur": "onBlur()" } }, ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <button\n [ngClass]=\"\n text && icon && iconPosition === 'start' ? 'cqa-pr-[24px] cqa-pl-[16px]' :\n text && icon && iconPosition === 'end' ? 'cqa-pl-[24px] cqa-pr-[16px]' :\n text && !icon ? 'cqa-px-[24px]' : !text && icon ? 'cqa-px-[12px]' : 'cqa-px-[24px]'\"\n [type]=\"type\"\n [disabled]=\"disabled\"\n [attr.aria-disabled]=\"disabled\"\n [class]=\"buttonClasses\"\n (click)=\"onClick($event)\"\n >\n\n <mat-icon *ngIf=\"icon && iconPosition === 'start'\" class=\"!cqa-w-[18px] !cqa-h-[18px] !cqa-text-[18px]\" [style.color]=\"iconColor\">\n {{ icon }}\n </mat-icon>\n\n <!-- Dynamic text support -->\n <span *ngIf=\"text\">{{text}}</span>\n\n <ng-content *ngIf=\"!text\" ></ng-content>\n\n <mat-icon *ngIf=\"icon && iconPosition === 'end'\" class=\"!cqa-w-[18px] !cqa-h-[18px] !cqa-text-[18px]\" [style.color]=\"iconColor\">\n {{ icon }}\n </mat-icon>\n\n </button>\n</div>", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
|
|
234
220
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: ButtonComponent, decorators: [{
|
|
235
221
|
type: Component,
|
|
236
|
-
args: [{ selector: 'cqa-button', template: "<div id=\"cqa-ui-root\"
|
|
222
|
+
args: [{ selector: 'cqa-button', template: "<div id=\"cqa-ui-root\">\n <button\n [ngClass]=\"\n text && icon && iconPosition === 'start' ? 'cqa-pr-[24px] cqa-pl-[16px]' :\n text && icon && iconPosition === 'end' ? 'cqa-pl-[24px] cqa-pr-[16px]' :\n text && !icon ? 'cqa-px-[24px]' : !text && icon ? 'cqa-px-[12px]' : 'cqa-px-[24px]'\"\n [type]=\"type\"\n [disabled]=\"disabled\"\n [attr.aria-disabled]=\"disabled\"\n [class]=\"buttonClasses\"\n (click)=\"onClick($event)\"\n >\n\n <mat-icon *ngIf=\"icon && iconPosition === 'start'\" class=\"!cqa-w-[18px] !cqa-h-[18px] !cqa-text-[18px]\" [style.color]=\"iconColor\">\n {{ icon }}\n </mat-icon>\n\n <!-- Dynamic text support -->\n <span *ngIf=\"text\">{{text}}</span>\n\n <ng-content *ngIf=\"!text\" ></ng-content>\n\n <mat-icon *ngIf=\"icon && iconPosition === 'end'\" class=\"!cqa-w-[18px] !cqa-h-[18px] !cqa-text-[18px]\" [style.color]=\"iconColor\">\n {{ icon }}\n </mat-icon>\n\n </button>\n</div>", styles: [] }]
|
|
237
223
|
}], propDecorators: { variant: [{
|
|
238
224
|
type: Input
|
|
239
225
|
}], disabled: [{
|
|
@@ -242,8 +228,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
|
|
|
242
228
|
type: Input
|
|
243
229
|
}], iconPosition: [{
|
|
244
230
|
type: Input
|
|
231
|
+
}], fullWidth: [{
|
|
232
|
+
type: Input
|
|
233
|
+
}], iconColor: [{
|
|
234
|
+
type: Input
|
|
245
235
|
}], type: [{
|
|
246
236
|
type: Input
|
|
237
|
+
}], text: [{
|
|
238
|
+
type: Input
|
|
239
|
+
}], customClass: [{
|
|
240
|
+
type: Input
|
|
247
241
|
}], clicked: [{
|
|
248
242
|
type: Output
|
|
249
243
|
}], onMouseEnter: [{
|
|
@@ -328,10 +322,10 @@ class SearchBarComponent {
|
|
|
328
322
|
}
|
|
329
323
|
}
|
|
330
324
|
SearchBarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: SearchBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
331
|
-
SearchBarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: SearchBarComponent, selector: "cqa-search-bar", inputs: { placeholder: "placeholder", value: "value", disabled: "disabled", showClear: "showClear", ariaLabel: "ariaLabel", autoFocus: "autoFocus", size: "size", fullWidth: "fullWidth" }, outputs: { valueChange: "valueChange", search: "search", cleared: "cleared" }, usesOnChanges: true, ngImport: i0, template: "<div id=\"cqa-ui-root\" [style.display]=\"fullWidth ? 'block' : 'inline-block'\"
|
|
325
|
+
SearchBarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: SearchBarComponent, selector: "cqa-search-bar", inputs: { placeholder: "placeholder", value: "value", disabled: "disabled", showClear: "showClear", ariaLabel: "ariaLabel", autoFocus: "autoFocus", size: "size", fullWidth: "fullWidth" }, outputs: { valueChange: "valueChange", search: "search", cleared: "cleared" }, usesOnChanges: true, ngImport: i0, template: "<div id=\"cqa-ui-root\" [style.display]=\"fullWidth ? 'block' : 'inline-block'\"\n [style.width]=\"fullWidth ? '100%' : 'auto'\">\n <form\n class=\"cqa-inline-flex cqa-items-center cqa-gap-2 cqa-px-6 cqa-py-3 cqa-text-[14px] cqa-border cqa-border-gray-200 cqa-rounded-md cqa-bg-white cqa-shadow-sm cqa-transition-colors\"\n [ngClass]=\"fullWidth ? 'cqa-w-full' : widthClasses[size]\" (submit)=\"onSubmit($event)\">\n <span class=\"cqa-flex-none cqa-flex cqa-items-center cqa-justify-center cqa-text-gray-400 cqa-w-4 cqa-h-4\"\n [ngClass]=\"{ 'cqa-opacity-[0.38]': disabled }\">\n <mat-icon class=\"cqa-flex cqa-items-center cqa-justify-center cqa-leading-none cqa-p-0\" [style.width.px]=\"16\"\n [style.height.px]=\"16\" [style.fontSize.px]=\"16\">\n search\n </mat-icon>\n </span>\n\n <input\n type=\"text\"\n class=\"cqa-flex-1 cqa-min-w-[180px] cqa-border-none cqa-outline-none cqa-bg-transparent placeholder:cqa-text-gray-400 disabled:cqa-text-gray-400 disabled:cqa-cursor-not-allowed cqa-font-['SF_Pro_Text'] cqa-font-normal cqa-text-[12.3px] cqa-leading-none cqa-tracking-normal cqa-align-middle cqa-text-muted\"\n [placeholder]=\"placeholder\"\n [value]=\"inputValue\"\n (input)=\"onInput($event)\"\n [disabled]=\"disabled\"\n [attr.aria-label]=\"ariaLabel\"\n autocomplete=\"off\"\n autocapitalize=\"none\"\n spellcheck=\"false\"\n [attr.autofocus]=\"autoFocus ? '' : null\"\n />\n\n <button *ngIf=\"showClear && inputValue\" type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-p-0 cqa-w-4 cqa-h-4 cqa-border-0 cqa-bg-transparent cqa-cursor-pointer cqa-text-gray-500 cqa-hover:cqa-text-gray-700 disabled:cqa-text-gray-300 cqa-transition-colors cqa-leading-none\"\n (click)=\"clear()\" [disabled]=\"disabled\" aria-label=\"Clear search\">\n <mat-icon class=\"cqa-flex cqa-items-center cqa-justify-center cqa-leading-none cqa-p-0\" [style.width.px]=\"16\"\n [style.height.px]=\"16\" [style.fontSize.px]=\"16\" [ngClass]=\"{ 'cqa-opacity-[0.38]': disabled }\">\n close\n </mat-icon>\n </button>\n </form>\n</div>", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i1$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
|
|
332
326
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: SearchBarComponent, decorators: [{
|
|
333
327
|
type: Component,
|
|
334
|
-
args: [{ selector: 'cqa-search-bar', template: "<div id=\"cqa-ui-root\" [style.display]=\"fullWidth ? 'block' : 'inline-block'\"
|
|
328
|
+
args: [{ selector: 'cqa-search-bar', template: "<div id=\"cqa-ui-root\" [style.display]=\"fullWidth ? 'block' : 'inline-block'\"\n [style.width]=\"fullWidth ? '100%' : 'auto'\">\n <form\n class=\"cqa-inline-flex cqa-items-center cqa-gap-2 cqa-px-6 cqa-py-3 cqa-text-[14px] cqa-border cqa-border-gray-200 cqa-rounded-md cqa-bg-white cqa-shadow-sm cqa-transition-colors\"\n [ngClass]=\"fullWidth ? 'cqa-w-full' : widthClasses[size]\" (submit)=\"onSubmit($event)\">\n <span class=\"cqa-flex-none cqa-flex cqa-items-center cqa-justify-center cqa-text-gray-400 cqa-w-4 cqa-h-4\"\n [ngClass]=\"{ 'cqa-opacity-[0.38]': disabled }\">\n <mat-icon class=\"cqa-flex cqa-items-center cqa-justify-center cqa-leading-none cqa-p-0\" [style.width.px]=\"16\"\n [style.height.px]=\"16\" [style.fontSize.px]=\"16\">\n search\n </mat-icon>\n </span>\n\n <input\n type=\"text\"\n class=\"cqa-flex-1 cqa-min-w-[180px] cqa-border-none cqa-outline-none cqa-bg-transparent placeholder:cqa-text-gray-400 disabled:cqa-text-gray-400 disabled:cqa-cursor-not-allowed cqa-font-['SF_Pro_Text'] cqa-font-normal cqa-text-[12.3px] cqa-leading-none cqa-tracking-normal cqa-align-middle cqa-text-muted\"\n [placeholder]=\"placeholder\"\n [value]=\"inputValue\"\n (input)=\"onInput($event)\"\n [disabled]=\"disabled\"\n [attr.aria-label]=\"ariaLabel\"\n autocomplete=\"off\"\n autocapitalize=\"none\"\n spellcheck=\"false\"\n [attr.autofocus]=\"autoFocus ? '' : null\"\n />\n\n <button *ngIf=\"showClear && inputValue\" type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-p-0 cqa-w-4 cqa-h-4 cqa-border-0 cqa-bg-transparent cqa-cursor-pointer cqa-text-gray-500 cqa-hover:cqa-text-gray-700 disabled:cqa-text-gray-300 cqa-transition-colors cqa-leading-none\"\n (click)=\"clear()\" [disabled]=\"disabled\" aria-label=\"Clear search\">\n <mat-icon class=\"cqa-flex cqa-items-center cqa-justify-center cqa-leading-none cqa-p-0\" [style.width.px]=\"16\"\n [style.height.px]=\"16\" [style.fontSize.px]=\"16\" [ngClass]=\"{ 'cqa-opacity-[0.38]': disabled }\">\n close\n </mat-icon>\n </button>\n </form>\n</div>", styles: [] }]
|
|
335
329
|
}], propDecorators: { placeholder: [{
|
|
336
330
|
type: Input
|
|
337
331
|
}], value: [{
|
|
@@ -544,10 +538,10 @@ class SegmentControlComponent {
|
|
|
544
538
|
}
|
|
545
539
|
}
|
|
546
540
|
SegmentControlComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: SegmentControlComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
547
|
-
SegmentControlComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: SegmentControlComponent, selector: "cqa-segment-control", inputs: { segments: "segments", value: "value", disabled: "disabled" }, outputs: { valueChange: "valueChange" }, viewQueries: [{ propertyName: "segmentContainer", first: true, predicate: ["segmentContainer"], descendants: true }, { propertyName: "segmentButtons", predicate: ["segmentButton"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div id=\"cqa-ui-root\" style=\"display: inline-block;\">\n <div\n #segmentContainer\n class=\"cqa-relative cqa-inline-flex cqa-flex-row cqa-items-start cqa-p-[3.5px] cqa-h-[31.5px] cqa-bg-
|
|
541
|
+
SegmentControlComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: SegmentControlComponent, selector: "cqa-segment-control", inputs: { segments: "segments", value: "value", disabled: "disabled" }, outputs: { valueChange: "valueChange" }, viewQueries: [{ propertyName: "segmentContainer", first: true, predicate: ["segmentContainer"], descendants: true }, { propertyName: "segmentButtons", predicate: ["segmentButton"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div id=\"cqa-ui-root\" style=\"display: inline-block;\">\n <div\n #segmentContainer\n class=\"cqa-relative cqa-inline-flex cqa-flex-row cqa-items-start cqa-p-[3.5px] cqa-h-[31.5px] cqa-bg-surface-light cqa-rounded-[8px]\"\n role=\"tablist\"\n [attr.aria-disabled]=\"disabled || null\"\n >\n <div\n class=\"cqa-absolute cqa-rounded-[8px] cqa-transition-all cqa-duration-200 cqa-ease-in-out cqa-pointer-events-none\"\n [class.cqa-opacity-0]=\"!isIndicatorVisible\" [ngStyle]=\"indicatorStyle\" aria-hidden=\"true\"></div>\n\n <button *ngFor=\"let segment of segments; index as index; trackBy: trackByValue\" #segmentButton type=\"button\"\n role=\"tab\"\n class=\"cqa-relative cqa-z-10 cqa-flex cqa-flex-col cqa-justify-center cqa-items-center cqa-px-[14px] cqa-py-[3.5px] cqa-h-[25px] cqa-rounded-[8px] cqa-transition-all cqa-duration-200 cqa-ease-in-out cqa-whitespace-nowrap cqa-text-center focus:cqa-outline-none focus-visible:cqa-outline-none focus-visible:cqa-ring-0 focus-visible:cqa-ring-offset-0 cqa-flex-none\"\n [ngClass]=\"{\n 'cqa-text-white cqa-font-medium': isSelected(segment),\n 'cqa-text-muted': !isSelected(segment) && !(disabled || segment.disabled),\n 'cqa-cursor-not-allowed': disabled || segment.disabled,\n 'cqa-text-disabled': (disabled || segment.disabled) && !isSelected(segment),\n 'cqa-hover:cqa-text-black': !isSelected(segment) && !disabled && !segment.disabled\n }\" [disabled]=\"disabled || segment.disabled\" [attr.aria-selected]=\"isSelected(segment)\"\n [attr.tabindex]=\"!disabled && !segment.disabled ? (isSelected(segment) ? 0 : -1) : -1\"\n (click)=\"select(segment, index)\" (keydown)=\"onKeyDown($event, index)\">\n <span\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-h-[18px] cqa-font-['Inter'] cqa-font-normal cqa-text-[12px] cqa-leading-[12px] cqa-text-center cqa-align-middle\">\n {{ segment.label }}\n </span>\n </button>\n </div>\n</div>", directives: [{ type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
|
|
548
542
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: SegmentControlComponent, decorators: [{
|
|
549
543
|
type: Component,
|
|
550
|
-
args: [{ selector: 'cqa-segment-control', template: "<div id=\"cqa-ui-root\" style=\"display: inline-block;\">\n <div\n #segmentContainer\n class=\"cqa-relative cqa-inline-flex cqa-flex-row cqa-items-start cqa-p-[3.5px] cqa-h-[31.5px] cqa-bg-
|
|
544
|
+
args: [{ selector: 'cqa-segment-control', template: "<div id=\"cqa-ui-root\" style=\"display: inline-block;\">\n <div\n #segmentContainer\n class=\"cqa-relative cqa-inline-flex cqa-flex-row cqa-items-start cqa-p-[3.5px] cqa-h-[31.5px] cqa-bg-surface-light cqa-rounded-[8px]\"\n role=\"tablist\"\n [attr.aria-disabled]=\"disabled || null\"\n >\n <div\n class=\"cqa-absolute cqa-rounded-[8px] cqa-transition-all cqa-duration-200 cqa-ease-in-out cqa-pointer-events-none\"\n [class.cqa-opacity-0]=\"!isIndicatorVisible\" [ngStyle]=\"indicatorStyle\" aria-hidden=\"true\"></div>\n\n <button *ngFor=\"let segment of segments; index as index; trackBy: trackByValue\" #segmentButton type=\"button\"\n role=\"tab\"\n class=\"cqa-relative cqa-z-10 cqa-flex cqa-flex-col cqa-justify-center cqa-items-center cqa-px-[14px] cqa-py-[3.5px] cqa-h-[25px] cqa-rounded-[8px] cqa-transition-all cqa-duration-200 cqa-ease-in-out cqa-whitespace-nowrap cqa-text-center focus:cqa-outline-none focus-visible:cqa-outline-none focus-visible:cqa-ring-0 focus-visible:cqa-ring-offset-0 cqa-flex-none\"\n [ngClass]=\"{\n 'cqa-text-white cqa-font-medium': isSelected(segment),\n 'cqa-text-muted': !isSelected(segment) && !(disabled || segment.disabled),\n 'cqa-cursor-not-allowed': disabled || segment.disabled,\n 'cqa-text-disabled': (disabled || segment.disabled) && !isSelected(segment),\n 'cqa-hover:cqa-text-black': !isSelected(segment) && !disabled && !segment.disabled\n }\" [disabled]=\"disabled || segment.disabled\" [attr.aria-selected]=\"isSelected(segment)\"\n [attr.tabindex]=\"!disabled && !segment.disabled ? (isSelected(segment) ? 0 : -1) : -1\"\n (click)=\"select(segment, index)\" (keydown)=\"onKeyDown($event, index)\">\n <span\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-h-[18px] cqa-font-['Inter'] cqa-font-normal cqa-text-[12px] cqa-leading-[12px] cqa-text-center cqa-align-middle\">\n {{ segment.label }}\n </span>\n </button>\n </div>\n</div>", styles: [] }]
|
|
551
545
|
}], propDecorators: { segments: [{
|
|
552
546
|
type: Input
|
|
553
547
|
}], value: [{
|
|
@@ -615,7 +609,7 @@ class DialogComponent {
|
|
|
615
609
|
'cqa-rounded-2xl',
|
|
616
610
|
'cqa-shadow-md',
|
|
617
611
|
'cqa-border',
|
|
618
|
-
'cqa-border-
|
|
612
|
+
'cqa-border-border-default',
|
|
619
613
|
'cqa-p-6',
|
|
620
614
|
'cqa-text-left',
|
|
621
615
|
];
|
|
@@ -676,69 +670,2809 @@ class DialogComponent {
|
|
|
676
670
|
}
|
|
677
671
|
}
|
|
678
672
|
DialogComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DialogComponent, deps: [{ token: i0.ViewContainerRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
679
|
-
DialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: DialogComponent, selector: "cqa-dialog", viewQueries: [{ propertyName: "portalOutlet", first: true, predicate: CdkPortalOutlet, descendants: true, static: true }], ngImport: i0, template: "<div id=\"cqa-ui-root\"
|
|
673
|
+
DialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: DialogComponent, selector: "cqa-dialog", viewQueries: [{ propertyName: "portalOutlet", first: true, predicate: CdkPortalOutlet, descendants: true, static: true }], ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <div class=\"cqa-flex cqa-w-full cqa-justify-center cqa-px-4 sm:cqa-px-6\">\n <div [ngClass]=\"panelClassList\" [ngStyle]=\"panelStyles\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-5\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <h2 class=\"cqa-text-lg cqa-font-semibold cqa-text-dialog\">\n {{ config.title }}\n </h2>\n\n <p *ngIf=\"config.description\" class=\"cqa-text-sm cqa-leading-6 cqa-text-dialog-secondary\">\n {{ config.description }}\n </p>\n\n <div *ngIf=\"config.warning\"\n class=\"cqa-rounded-xl cqa-border cqa-border-red-200 cqa-bg-red-50 cqa-px-4 cqa-py-3 cqa-text-sm cqa-leading-5 cqa-text-red-700\">\n {{ config.warning }}\n </div>\n </div>\n\n <div class=\"cqa-text-sm cqa-text-dialog\" [class.hidden]=\"!contentAttached\">\n <ng-template cdkPortalOutlet></ng-template>\n </div>\n\n <div class=\"cqa-mt-4 cqa-flex cqa-flex-wrap cqa-gap-3\" [ngClass]=\"buttonAlignmentClass\">\n <cqa-button *ngFor=\"let button of config.buttons\" type=\"button\" [variant]=\"buttonVariant(button)\"\n [ngClass]=\"buttonHostClasses(button)\" (clicked)=\"onButtonClick(button)\">\n {{ button.label }}\n </cqa-button>\n </div>\n </div>\n </div>\n </div>\n</div>", components: [{ type: ButtonComponent, selector: "cqa-button", inputs: ["variant", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass"], outputs: ["clicked"] }], directives: [{ type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.CdkPortalOutlet, selector: "[cdkPortalOutlet]", inputs: ["cdkPortalOutlet"], outputs: ["attached"], exportAs: ["cdkPortalOutlet"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
680
674
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DialogComponent, decorators: [{
|
|
681
675
|
type: Component,
|
|
682
|
-
args: [{ selector: 'cqa-dialog', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div id=\"cqa-ui-root\"
|
|
676
|
+
args: [{ selector: 'cqa-dialog', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div id=\"cqa-ui-root\">\n <div class=\"cqa-flex cqa-w-full cqa-justify-center cqa-px-4 sm:cqa-px-6\">\n <div [ngClass]=\"panelClassList\" [ngStyle]=\"panelStyles\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-5\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <h2 class=\"cqa-text-lg cqa-font-semibold cqa-text-dialog\">\n {{ config.title }}\n </h2>\n\n <p *ngIf=\"config.description\" class=\"cqa-text-sm cqa-leading-6 cqa-text-dialog-secondary\">\n {{ config.description }}\n </p>\n\n <div *ngIf=\"config.warning\"\n class=\"cqa-rounded-xl cqa-border cqa-border-red-200 cqa-bg-red-50 cqa-px-4 cqa-py-3 cqa-text-sm cqa-leading-5 cqa-text-red-700\">\n {{ config.warning }}\n </div>\n </div>\n\n <div class=\"cqa-text-sm cqa-text-dialog\" [class.hidden]=\"!contentAttached\">\n <ng-template cdkPortalOutlet></ng-template>\n </div>\n\n <div class=\"cqa-mt-4 cqa-flex cqa-flex-wrap cqa-gap-3\" [ngClass]=\"buttonAlignmentClass\">\n <cqa-button *ngFor=\"let button of config.buttons\" type=\"button\" [variant]=\"buttonVariant(button)\"\n [ngClass]=\"buttonHostClasses(button)\" (clicked)=\"onButtonClick(button)\">\n {{ button.label }}\n </cqa-button>\n </div>\n </div>\n </div>\n </div>\n</div>", styles: [] }]
|
|
683
677
|
}], ctorParameters: function () { return [{ type: i0.ViewContainerRef }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { portalOutlet: [{
|
|
684
678
|
type: ViewChild,
|
|
685
679
|
args: [CdkPortalOutlet, { static: true }]
|
|
686
680
|
}] } });
|
|
687
681
|
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
class UiKitModule {
|
|
682
|
+
class DynamicCellTemplateDirective {
|
|
683
|
+
constructor(template) {
|
|
684
|
+
this.template = template;
|
|
685
|
+
}
|
|
693
686
|
}
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
DialogComponent], imports: [CommonModule,
|
|
699
|
-
FormsModule,
|
|
700
|
-
MatIconModule,
|
|
701
|
-
OverlayModule,
|
|
702
|
-
PortalModule], exports: [ButtonComponent,
|
|
703
|
-
SearchBarComponent,
|
|
704
|
-
SegmentControlComponent,
|
|
705
|
-
DialogComponent] });
|
|
706
|
-
UiKitModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: UiKitModule, imports: [[
|
|
707
|
-
CommonModule,
|
|
708
|
-
FormsModule,
|
|
709
|
-
MatIconModule,
|
|
710
|
-
OverlayModule,
|
|
711
|
-
PortalModule
|
|
712
|
-
]] });
|
|
713
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: UiKitModule, decorators: [{
|
|
714
|
-
type: NgModule,
|
|
687
|
+
DynamicCellTemplateDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DynamicCellTemplateDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
|
|
688
|
+
DynamicCellTemplateDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.4.0", type: DynamicCellTemplateDirective, selector: "ng-template[dynamicCell]", inputs: { name: ["dynamicCell", "name"] }, ngImport: i0 });
|
|
689
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DynamicCellTemplateDirective, decorators: [{
|
|
690
|
+
type: Directive,
|
|
715
691
|
args: [{
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
]
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
692
|
+
selector: "ng-template[dynamicCell]"
|
|
693
|
+
}]
|
|
694
|
+
}], ctorParameters: function () { return [{ type: i0.TemplateRef }]; }, propDecorators: { name: [{
|
|
695
|
+
type: Input,
|
|
696
|
+
args: ["dynamicCell"]
|
|
697
|
+
}] } });
|
|
698
|
+
class DynamicHeaderTemplateDirective {
|
|
699
|
+
constructor(template) {
|
|
700
|
+
this.template = template;
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
DynamicHeaderTemplateDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DynamicHeaderTemplateDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
|
|
704
|
+
DynamicHeaderTemplateDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.4.0", type: DynamicHeaderTemplateDirective, selector: "ng-template[dynamicHeader]", inputs: { name: ["dynamicHeader", "name"] }, ngImport: i0 });
|
|
705
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DynamicHeaderTemplateDirective, decorators: [{
|
|
706
|
+
type: Directive,
|
|
707
|
+
args: [{
|
|
708
|
+
selector: "ng-template[dynamicHeader]"
|
|
709
|
+
}]
|
|
710
|
+
}], ctorParameters: function () { return [{ type: i0.TemplateRef }]; }, propDecorators: { name: [{
|
|
711
|
+
type: Input,
|
|
712
|
+
args: ["dynamicHeader"]
|
|
713
|
+
}] } });
|
|
714
|
+
|
|
715
|
+
class FullTableLoaderComponent {
|
|
716
|
+
constructor() {
|
|
717
|
+
this.label = 'Loading...';
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
FullTableLoaderComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: FullTableLoaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
721
|
+
FullTableLoaderComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: FullTableLoaderComponent, selector: "cqa-full-table-loader", inputs: { label: "label" }, ngImport: i0, template: "<div\n class=\"table-loading-overlay cqa-absolute cqa-top-0 cqa-bottom-0 cqa-left-0 cqa-right-0 cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-justify-center cqa-z-[1000]\">\n <div\n class=\"blur-backdrop cqa-absolute cqa-top-0 cqa-bottom-0 cqa-left-0 cqa-right-0 cqa-bg-white/70 cqa-backdrop-blur-[4px] cqa-z-[1]\">\n </div>\n <div\n class=\"loading-spinner cqa-flex cqa-flex-row cqa-items-center cqa-justify-center cqa-gap-3 cqa-text-center cqa-relative cqa-z-20 cqa-bg-white cqa-py-4 cqa-px-6 cqa-rounded-xl cqa-shadow-lg\">\n <svg class=\"cqa-animate-spin cqa-text-primary\" width=\"32\" height=\"32\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\"\n viewBox=\"0 0 24 24\">\n <circle class=\"cqa-opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"cqa-opacity-75\" fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\">\n </path>\n </svg>\n <span class=\"cqa-text-primary\">{{ label }}</span>\n </div>\n</div>\n\n\n" });
|
|
722
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: FullTableLoaderComponent, decorators: [{
|
|
723
|
+
type: Component,
|
|
724
|
+
args: [{ selector: 'cqa-full-table-loader', template: "<div\n class=\"table-loading-overlay cqa-absolute cqa-top-0 cqa-bottom-0 cqa-left-0 cqa-right-0 cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-justify-center cqa-z-[1000]\">\n <div\n class=\"blur-backdrop cqa-absolute cqa-top-0 cqa-bottom-0 cqa-left-0 cqa-right-0 cqa-bg-white/70 cqa-backdrop-blur-[4px] cqa-z-[1]\">\n </div>\n <div\n class=\"loading-spinner cqa-flex cqa-flex-row cqa-items-center cqa-justify-center cqa-gap-3 cqa-text-center cqa-relative cqa-z-20 cqa-bg-white cqa-py-4 cqa-px-6 cqa-rounded-xl cqa-shadow-lg\">\n <svg class=\"cqa-animate-spin cqa-text-primary\" width=\"32\" height=\"32\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\"\n viewBox=\"0 0 24 24\">\n <circle class=\"cqa-opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"cqa-opacity-75\" fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\">\n </path>\n </svg>\n <span class=\"cqa-text-primary\">{{ label }}</span>\n </div>\n</div>\n\n\n", styles: [] }]
|
|
725
|
+
}], propDecorators: { label: [{
|
|
726
|
+
type: Input
|
|
727
|
+
}] } });
|
|
728
|
+
|
|
729
|
+
class TableDataLoaderComponent {
|
|
730
|
+
constructor() {
|
|
731
|
+
this.label = 'Loading...';
|
|
732
|
+
this.size = 24;
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
TableDataLoaderComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TableDataLoaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
736
|
+
TableDataLoaderComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TableDataLoaderComponent, selector: "cqa-table-data-loader", inputs: { label: "label", size: "size" }, ngImport: i0, template: "<div class=\"loading-spinner-simple cqa-py-2 cqa-flex cqa-flex-row cqa-items-center cqa-justify-center cqa-gap-3 cqa-text-center\">\n <svg class=\"cqa-animate-spin cqa-text-primary\" [attr.width]=\"size\" [attr.height]=\"size\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"cqa-opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"cqa-opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n <span class=\"cqa-text-primary\">{{ label }}</span>\n </div>\n\n\n" });
|
|
737
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TableDataLoaderComponent, decorators: [{
|
|
738
|
+
type: Component,
|
|
739
|
+
args: [{ selector: 'cqa-table-data-loader', template: "<div class=\"loading-spinner-simple cqa-py-2 cqa-flex cqa-flex-row cqa-items-center cqa-justify-center cqa-gap-3 cqa-text-center\">\n <svg class=\"cqa-animate-spin cqa-text-primary\" [attr.width]=\"size\" [attr.height]=\"size\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"cqa-opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"cqa-opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n <span class=\"cqa-text-primary\">{{ label }}</span>\n </div>\n\n\n", styles: [] }]
|
|
740
|
+
}], propDecorators: { label: [{
|
|
741
|
+
type: Input
|
|
742
|
+
}], size: [{
|
|
743
|
+
type: Input
|
|
744
|
+
}] } });
|
|
745
|
+
|
|
746
|
+
class DynamicTableComponent {
|
|
747
|
+
constructor() {
|
|
748
|
+
this.data = [];
|
|
749
|
+
this.columns = [];
|
|
750
|
+
// Enable built-in select-all behavior for a 'checkbox' column
|
|
751
|
+
this.enableSelectAll = true;
|
|
752
|
+
// Enable simple client-side sorting when clicking sortable headers (no custom header)
|
|
753
|
+
this.enableLocalSort = true;
|
|
754
|
+
// Emit sort changes so parent can perform server-side sort if desired
|
|
755
|
+
this.sortChange = new EventEmitter();
|
|
756
|
+
this._sortDirection = null;
|
|
757
|
+
}
|
|
758
|
+
get isXs() {
|
|
759
|
+
const w = this.screenWidth || window.innerWidth;
|
|
760
|
+
return w <= 480;
|
|
761
|
+
}
|
|
762
|
+
get isSm() {
|
|
763
|
+
const w = this.screenWidth || window.innerWidth;
|
|
764
|
+
return w <= 768;
|
|
765
|
+
}
|
|
766
|
+
get isMd() {
|
|
767
|
+
const w = this.screenWidth || window.innerWidth;
|
|
768
|
+
return w <= 992;
|
|
769
|
+
}
|
|
770
|
+
get visibleColumns() {
|
|
771
|
+
const responsiveFilter = (c) => {
|
|
772
|
+
const r = c?.responsive || {};
|
|
773
|
+
if (r.xs && this.isXs)
|
|
774
|
+
return false;
|
|
775
|
+
if (r.sm && this.isSm)
|
|
776
|
+
return false;
|
|
777
|
+
if (r.md && this.isMd)
|
|
778
|
+
return false;
|
|
779
|
+
return true;
|
|
780
|
+
};
|
|
781
|
+
return (this.columns || []).filter(c => c.isShow !== false).filter(responsiveFilter);
|
|
782
|
+
}
|
|
783
|
+
getHeaderTemplate(colId) {
|
|
784
|
+
const tpl = this.headerTemplates?.find(t => t.name === colId);
|
|
785
|
+
return tpl ? tpl.template : null;
|
|
786
|
+
}
|
|
787
|
+
getCellTemplate(colId) {
|
|
788
|
+
const tpl = this.cellTemplates?.find(t => t.name === colId);
|
|
789
|
+
return tpl ? tpl.template : null;
|
|
790
|
+
}
|
|
791
|
+
getCellValue(row, path) {
|
|
792
|
+
if (!row || !path)
|
|
793
|
+
return "";
|
|
794
|
+
const parts = path.split(".");
|
|
795
|
+
let current = row;
|
|
796
|
+
for (const part of parts) {
|
|
797
|
+
if (current == null)
|
|
798
|
+
return "";
|
|
799
|
+
current = current[part];
|
|
800
|
+
}
|
|
801
|
+
return current ?? "";
|
|
802
|
+
}
|
|
803
|
+
trackByIndex(index) {
|
|
804
|
+
return index;
|
|
805
|
+
}
|
|
806
|
+
// Compute grid-template-columns string from column config
|
|
807
|
+
get computedGridTemplate() {
|
|
808
|
+
if (this.gridTemplateColumns) {
|
|
809
|
+
return this.gridTemplateColumns;
|
|
810
|
+
}
|
|
811
|
+
const cols = this.visibleColumns;
|
|
812
|
+
if (!cols?.length)
|
|
813
|
+
return '';
|
|
814
|
+
const fixedPx = cols.reduce((sum, c) => sum + (c.fixedPx || 0), 0);
|
|
815
|
+
const dynamicCols = cols.filter(c => !c.fixedPx);
|
|
816
|
+
const totalWeight = dynamicCols.reduce((sum, c) => sum + (c.weight || 1), 0) || 1;
|
|
817
|
+
const parts = cols.map(c => {
|
|
818
|
+
if (c.fixedPx && c.fixedPx > 0) {
|
|
819
|
+
return `${c.fixedPx}px`;
|
|
820
|
+
}
|
|
821
|
+
const share = (c.weight || 1) / totalWeight;
|
|
822
|
+
return `calc((100% - ${fixedPx}px) * ${share.toFixed(4)})`;
|
|
823
|
+
});
|
|
824
|
+
return parts.join(' ');
|
|
825
|
+
}
|
|
826
|
+
// Compute per-column widths for use with <colgroup>
|
|
827
|
+
get computedColumnWidths() {
|
|
828
|
+
const cols = this.visibleColumns;
|
|
829
|
+
if (!cols?.length)
|
|
830
|
+
return [];
|
|
831
|
+
const fixedPx = cols.reduce((sum, c) => sum + (c.fixedPx || 0), 0);
|
|
832
|
+
const dynamicCols = cols.filter(c => !c.fixedPx);
|
|
833
|
+
const totalWeight = dynamicCols.reduce((sum, c) => sum + (c.weight || 1), 0) || 1;
|
|
834
|
+
return cols.map(c => {
|
|
835
|
+
if (c.fixedPx && c.fixedPx > 0) {
|
|
836
|
+
return `${c.fixedPx}px`;
|
|
837
|
+
}
|
|
838
|
+
const share = (c.weight || 1) / totalWeight;
|
|
839
|
+
return `calc((100% - ${fixedPx}px) * ${share.toFixed(4)})`;
|
|
840
|
+
});
|
|
841
|
+
}
|
|
842
|
+
// Selection helpers
|
|
843
|
+
get allSelected() {
|
|
844
|
+
const rows = this.data || [];
|
|
845
|
+
if (!rows.length)
|
|
846
|
+
return false;
|
|
847
|
+
return rows.every(r => !!r?.isSelected);
|
|
848
|
+
}
|
|
849
|
+
get someSelected() {
|
|
850
|
+
const rows = this.data || [];
|
|
851
|
+
if (!rows.length)
|
|
852
|
+
return false;
|
|
853
|
+
const anySelected = rows.some(r => !!r?.isSelected);
|
|
854
|
+
return anySelected && !this.allSelected;
|
|
855
|
+
}
|
|
856
|
+
onSelectAllChange(event) {
|
|
857
|
+
const target = event.target;
|
|
858
|
+
this.toggleSelectAll(target.checked);
|
|
859
|
+
}
|
|
860
|
+
onRowSelectChange(event, row) {
|
|
861
|
+
const target = event.target;
|
|
862
|
+
row.isSelected = target.checked;
|
|
863
|
+
}
|
|
864
|
+
toggleSelectAll(checked) {
|
|
865
|
+
const rows = this.data || [];
|
|
866
|
+
for (const row of rows) {
|
|
867
|
+
if (row) {
|
|
868
|
+
row.isSelected = checked;
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
get computedData() {
|
|
873
|
+
const source = this.data || [];
|
|
874
|
+
if (!this.enableLocalSort || !this._sortActive || !this._sortDirection) {
|
|
875
|
+
return source;
|
|
876
|
+
}
|
|
877
|
+
const col = this.visibleColumns.find(c => c.fieldId === this._sortActive);
|
|
878
|
+
if (!col || !col.fieldValue) {
|
|
879
|
+
return source;
|
|
880
|
+
}
|
|
881
|
+
const dir = this._sortDirection === 'asc' ? 1 : -1;
|
|
882
|
+
const fieldPath = col.fieldValue;
|
|
883
|
+
const out = [...source];
|
|
884
|
+
out.sort((a, b) => dir * this.compareValues(this.getCellValue(a, fieldPath), this.getCellValue(b, fieldPath)));
|
|
885
|
+
return out;
|
|
886
|
+
}
|
|
887
|
+
// Computed loading flags to support backward compatibility
|
|
888
|
+
get showTableLoading() {
|
|
889
|
+
return this.isTableLoading ?? false;
|
|
890
|
+
}
|
|
891
|
+
get showTableDataLoading() {
|
|
892
|
+
return this.isTableDataLoading ?? false;
|
|
893
|
+
}
|
|
894
|
+
// True when table has no data and is not currently loading — used to show an empty state
|
|
895
|
+
get isEmpty() {
|
|
896
|
+
const anyLoading = this.showTableLoading || this.showTableDataLoading;
|
|
897
|
+
return !anyLoading && (!(this.data && this.data.length) || this.data.length === 0);
|
|
898
|
+
}
|
|
899
|
+
isSortedAsc(colId) {
|
|
900
|
+
return this._sortActive === colId && this._sortDirection === 'asc';
|
|
901
|
+
}
|
|
902
|
+
isSortedDesc(colId) {
|
|
903
|
+
return this._sortActive === colId && this._sortDirection === 'desc';
|
|
904
|
+
}
|
|
905
|
+
toggleSort(col) {
|
|
906
|
+
if (!col?.sortable)
|
|
907
|
+
return;
|
|
908
|
+
const colId = col.fieldId;
|
|
909
|
+
if (this._sortActive !== colId) {
|
|
910
|
+
this._sortActive = colId;
|
|
911
|
+
this._sortDirection = 'asc';
|
|
912
|
+
}
|
|
913
|
+
else {
|
|
914
|
+
// cycle asc -> desc -> null -> asc
|
|
915
|
+
if (this._sortDirection === 'asc')
|
|
916
|
+
this._sortDirection = 'desc';
|
|
917
|
+
else if (this._sortDirection === 'desc')
|
|
918
|
+
this._sortDirection = null;
|
|
919
|
+
else
|
|
920
|
+
this._sortDirection = 'asc';
|
|
921
|
+
}
|
|
922
|
+
this.sortChange.emit({ fieldId: this._sortActive, fieldValue: col.fieldValue, direction: this._sortDirection });
|
|
923
|
+
}
|
|
924
|
+
compareValues(a, b) {
|
|
925
|
+
if (a == null && b == null)
|
|
926
|
+
return 0;
|
|
927
|
+
if (a == null)
|
|
928
|
+
return 1; // nulls last in asc (handled by dir multiplier)
|
|
929
|
+
if (b == null)
|
|
930
|
+
return -1;
|
|
931
|
+
const numA = typeof a === 'number' ? a : Number(a);
|
|
932
|
+
const numB = typeof b === 'number' ? b : Number(b);
|
|
933
|
+
const aIsNum = !isNaN(numA) && a !== '' && a !== null && a !== false;
|
|
934
|
+
const bIsNum = !isNaN(numB) && b !== '' && b !== null && b !== false;
|
|
935
|
+
if (aIsNum && bIsNum) {
|
|
936
|
+
if (numA < numB)
|
|
937
|
+
return -1;
|
|
938
|
+
if (numA > numB)
|
|
939
|
+
return 1;
|
|
940
|
+
return 0;
|
|
941
|
+
}
|
|
942
|
+
// Date detection: attempt parse when both values are strings and parseable
|
|
943
|
+
if (typeof a === 'string' && typeof b === 'string') {
|
|
944
|
+
const tsA = Date.parse(a);
|
|
945
|
+
const tsB = Date.parse(b);
|
|
946
|
+
if (!isNaN(tsA) && !isNaN(tsB)) {
|
|
947
|
+
if (tsA < tsB)
|
|
948
|
+
return -1;
|
|
949
|
+
if (tsA > tsB)
|
|
950
|
+
return 1;
|
|
951
|
+
return 0;
|
|
952
|
+
}
|
|
953
|
+
// localeCompare, case-insensitive
|
|
954
|
+
return a.localeCompare(b, undefined, { sensitivity: 'base', numeric: true });
|
|
955
|
+
}
|
|
956
|
+
// Fallback to string comparison
|
|
957
|
+
const sa = String(a);
|
|
958
|
+
const sb = String(b);
|
|
959
|
+
return sa.localeCompare(sb, undefined, { sensitivity: 'base', numeric: true });
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
DynamicTableComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DynamicTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
963
|
+
DynamicTableComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: DynamicTableComponent, selector: "app-dynamic-table", inputs: { data: "data", columns: "columns", emptyState: "emptyState", gridTemplateColumns: "gridTemplateColumns", screenWidth: "screenWidth", enableSelectAll: "enableSelectAll", enableLocalSort: "enableLocalSort", isTableLoading: "isTableLoading", isTableDataLoading: "isTableDataLoading" }, outputs: { sortChange: "sortChange" }, queries: [{ propertyName: "emptyTableTpl", first: true, predicate: ["emptyTableTpl"], descendants: true, read: TemplateRef }, { propertyName: "cellTemplates", predicate: DynamicCellTemplateDirective }, { propertyName: "headerTemplates", predicate: DynamicHeaderTemplateDirective }], ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <div class=\"cqa-relative\">\n <cqa-full-table-loader *ngIf=\"showTableLoading\"></cqa-full-table-loader>\n <cqa-table-data-loader *ngIf=\"showTableDataLoading\"></cqa-table-data-loader>\n <table class=\"table-inner cqa-w-full\" [class.is-loading]=\"true\">\n <colgroup>\n <ng-container *ngFor=\"let width of computedColumnWidths; trackBy: trackByIndex\">\n <col [style.width]=\"width\" />\n </ng-container>\n </colgroup>\n\n <thead *ngIf=\"data?.length\">\n <tr class=\"table-header cqa-items-center\">\n <ng-container *ngFor=\"let col of visibleColumns; trackBy: trackByIndex\">\n <th\n class=\"header-cell cqa-py-[13.25px] cqa-px-[10.5px] cqa-text-xs cqa-font-semibold cqa-text-left cqa-text-[#374151] cqa-bg-[#eff0f7]\"\n [ngClass]=\"col.fieldId + '-cell'\">\n <!-- Built-in select-all for checkbox column when enabled and no custom header template -->\n <ng-container\n *ngIf=\"col.fieldId === 'checkbox' && enableSelectAll && !getHeaderTemplate(col.fieldId); else headerTplOrDefault\">\n <div class=\"custom-checkbox\">\n <input type=\"checkbox\" id=\"checkbox\" aria-label=\"Select all rows\" [checked]=\"allSelected\"\n [indeterminate]=\"someSelected\" (change)=\"onSelectAllChange($event)\" class=\"hidden-checkbox\" />\n <label for=\"checkbox\" class=\"custom-checkbox-label\"></label>\n </div>\n </ng-container>\n <ng-template #headerTplOrDefault>\n <ng-container *ngIf=\"getHeaderTemplate(col.fieldId) as headerTpl; else defaultHeader\">\n <ng-container *ngTemplateOutlet=\"headerTpl\"></ng-container>\n </ng-container>\n <ng-template #defaultHeader>\n <ng-container *ngIf=\"col.sortable; else plainHeader\">\n <button type=\"button\" class=\"header-text cqa-inline-flex cqa-items-center cqa-gap-1\"\n (click)=\"toggleSort(col)\" [attr.aria-label]=\"'Sort by ' + (col.fieldName || col.fieldId)\">\n <span class=\"cqa-text-[12.3px] cqa-leading-[17.5px] cqa-text-[#0A0A0A] cqa-font-medium\">{{\n col.fieldName }}</span>\n <span *ngIf=\"isSortedAsc(col.fieldId)\">\u25B2</span>\n <span *ngIf=\"isSortedDesc(col.fieldId)\">\u25BC</span>\n </button>\n </ng-container>\n <ng-template #plainHeader>\n <span class=\"header-text\">{{ col.fieldName }}</span>\n </ng-template>\n </ng-template>\n </ng-template>\n </th>\n </ng-container>\n </tr>\n </thead>\n\n <tbody class=\"table-body cqa-w-full\">\n <tr class=\"table-row cqa-bg-surface-default hover:cqa-bg-surface-hover\" *ngFor=\"let row of computedData; let rowIndex = index; trackBy: trackByIndex\"\n [class.selected]=\"row?.isSelected\">\n <ng-container *ngFor=\"let col of visibleColumns; trackBy: trackByIndex\">\n <td class=\"cell cqa-px-[10.5px] cqa-py-[11px]\" [ngClass]=\"col.fieldId + '-cell'\">\n <!-- Built-in checkbox cell when no custom template is provided -->\n <ng-container *ngIf=\"col.fieldId === 'checkbox' && !getCellTemplate(col.fieldId); else regularCell\">\n <div class=\"custom-checkbox\">\n <input\n type=\"checkbox\"\n class=\"hidden-checkbox\"\n [attr.id]=\"'row-checkbox-' + rowIndex\"\n aria-label=\"Select row\"\n [checked]=\"row?.isSelected\"\n (change)=\"onRowSelectChange($event, row)\" />\n <label\n class=\"custom-checkbox-label\"\n [attr.for]=\"'row-checkbox-' + rowIndex\">\n </label>\n </div>\n </ng-container>\n <ng-template #regularCell>\n <ng-container *ngIf=\"getCellTemplate(col.fieldId) as cellTpl; else defaultCell\">\n <ng-container\n *ngTemplateOutlet=\"cellTpl; context: {$implicit: row, row: row, value: getCellValue(row, col.fieldValue)}\"></ng-container>\n </ng-container>\n <ng-template #defaultCell>\n <span class=\"cqa-text-xs cqa-text-[#374151]\">{{ getCellValue(row, col.fieldValue) }}</span>\n </ng-template>\n </ng-template>\n </td>\n </ng-container>\n </tr>\n </tbody>\n </table>\n </div>\n</div>", components: [{ type: FullTableLoaderComponent, selector: "cqa-full-table-loader", inputs: ["label"] }, { type: TableDataLoaderComponent, selector: "cqa-table-data-loader", inputs: ["label", "size"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }] });
|
|
964
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DynamicTableComponent, decorators: [{
|
|
965
|
+
type: Component,
|
|
966
|
+
args: [{ selector: "app-dynamic-table", template: "<div id=\"cqa-ui-root\">\n <div class=\"cqa-relative\">\n <cqa-full-table-loader *ngIf=\"showTableLoading\"></cqa-full-table-loader>\n <cqa-table-data-loader *ngIf=\"showTableDataLoading\"></cqa-table-data-loader>\n <table class=\"table-inner cqa-w-full\" [class.is-loading]=\"true\">\n <colgroup>\n <ng-container *ngFor=\"let width of computedColumnWidths; trackBy: trackByIndex\">\n <col [style.width]=\"width\" />\n </ng-container>\n </colgroup>\n\n <thead *ngIf=\"data?.length\">\n <tr class=\"table-header cqa-items-center\">\n <ng-container *ngFor=\"let col of visibleColumns; trackBy: trackByIndex\">\n <th\n class=\"header-cell cqa-py-[13.25px] cqa-px-[10.5px] cqa-text-xs cqa-font-semibold cqa-text-left cqa-text-[#374151] cqa-bg-[#eff0f7]\"\n [ngClass]=\"col.fieldId + '-cell'\">\n <!-- Built-in select-all for checkbox column when enabled and no custom header template -->\n <ng-container\n *ngIf=\"col.fieldId === 'checkbox' && enableSelectAll && !getHeaderTemplate(col.fieldId); else headerTplOrDefault\">\n <div class=\"custom-checkbox\">\n <input type=\"checkbox\" id=\"checkbox\" aria-label=\"Select all rows\" [checked]=\"allSelected\"\n [indeterminate]=\"someSelected\" (change)=\"onSelectAllChange($event)\" class=\"hidden-checkbox\" />\n <label for=\"checkbox\" class=\"custom-checkbox-label\"></label>\n </div>\n </ng-container>\n <ng-template #headerTplOrDefault>\n <ng-container *ngIf=\"getHeaderTemplate(col.fieldId) as headerTpl; else defaultHeader\">\n <ng-container *ngTemplateOutlet=\"headerTpl\"></ng-container>\n </ng-container>\n <ng-template #defaultHeader>\n <ng-container *ngIf=\"col.sortable; else plainHeader\">\n <button type=\"button\" class=\"header-text cqa-inline-flex cqa-items-center cqa-gap-1\"\n (click)=\"toggleSort(col)\" [attr.aria-label]=\"'Sort by ' + (col.fieldName || col.fieldId)\">\n <span class=\"cqa-text-[12.3px] cqa-leading-[17.5px] cqa-text-[#0A0A0A] cqa-font-medium\">{{\n col.fieldName }}</span>\n <span *ngIf=\"isSortedAsc(col.fieldId)\">\u25B2</span>\n <span *ngIf=\"isSortedDesc(col.fieldId)\">\u25BC</span>\n </button>\n </ng-container>\n <ng-template #plainHeader>\n <span class=\"header-text\">{{ col.fieldName }}</span>\n </ng-template>\n </ng-template>\n </ng-template>\n </th>\n </ng-container>\n </tr>\n </thead>\n\n <tbody class=\"table-body cqa-w-full\">\n <tr class=\"table-row cqa-bg-surface-default hover:cqa-bg-surface-hover\" *ngFor=\"let row of computedData; let rowIndex = index; trackBy: trackByIndex\"\n [class.selected]=\"row?.isSelected\">\n <ng-container *ngFor=\"let col of visibleColumns; trackBy: trackByIndex\">\n <td class=\"cell cqa-px-[10.5px] cqa-py-[11px]\" [ngClass]=\"col.fieldId + '-cell'\">\n <!-- Built-in checkbox cell when no custom template is provided -->\n <ng-container *ngIf=\"col.fieldId === 'checkbox' && !getCellTemplate(col.fieldId); else regularCell\">\n <div class=\"custom-checkbox\">\n <input\n type=\"checkbox\"\n class=\"hidden-checkbox\"\n [attr.id]=\"'row-checkbox-' + rowIndex\"\n aria-label=\"Select row\"\n [checked]=\"row?.isSelected\"\n (change)=\"onRowSelectChange($event, row)\" />\n <label\n class=\"custom-checkbox-label\"\n [attr.for]=\"'row-checkbox-' + rowIndex\">\n </label>\n </div>\n </ng-container>\n <ng-template #regularCell>\n <ng-container *ngIf=\"getCellTemplate(col.fieldId) as cellTpl; else defaultCell\">\n <ng-container\n *ngTemplateOutlet=\"cellTpl; context: {$implicit: row, row: row, value: getCellValue(row, col.fieldValue)}\"></ng-container>\n </ng-container>\n <ng-template #defaultCell>\n <span class=\"cqa-text-xs cqa-text-[#374151]\">{{ getCellValue(row, col.fieldValue) }}</span>\n </ng-template>\n </ng-template>\n </td>\n </ng-container>\n </tr>\n </tbody>\n </table>\n </div>\n</div>", styles: [] }]
|
|
967
|
+
}], propDecorators: { data: [{
|
|
968
|
+
type: Input
|
|
969
|
+
}], columns: [{
|
|
970
|
+
type: Input
|
|
971
|
+
}], emptyState: [{
|
|
972
|
+
type: Input
|
|
973
|
+
}], gridTemplateColumns: [{
|
|
974
|
+
type: Input
|
|
975
|
+
}], screenWidth: [{
|
|
976
|
+
type: Input
|
|
977
|
+
}], enableSelectAll: [{
|
|
978
|
+
type: Input
|
|
979
|
+
}], enableLocalSort: [{
|
|
980
|
+
type: Input
|
|
981
|
+
}], isTableLoading: [{
|
|
982
|
+
type: Input
|
|
983
|
+
}], isTableDataLoading: [{
|
|
984
|
+
type: Input
|
|
985
|
+
}], sortChange: [{
|
|
986
|
+
type: Output
|
|
987
|
+
}], cellTemplates: [{
|
|
988
|
+
type: ContentChildren,
|
|
989
|
+
args: [DynamicCellTemplateDirective]
|
|
990
|
+
}], headerTemplates: [{
|
|
991
|
+
type: ContentChildren,
|
|
992
|
+
args: [DynamicHeaderTemplateDirective]
|
|
993
|
+
}], emptyTableTpl: [{
|
|
994
|
+
type: ContentChild,
|
|
995
|
+
args: ['emptyTableTpl', { read: TemplateRef }]
|
|
996
|
+
}] } });
|
|
997
|
+
|
|
998
|
+
class InlineSortComponent {
|
|
999
|
+
get getToolTip() {
|
|
1000
|
+
if (this.ascending == true)
|
|
1001
|
+
return this.heading?.includes('created_at') ? 'message.common.sort_by.old' : 'message.common.sort_by.ascending';
|
|
1002
|
+
else if (this.ascending == false)
|
|
1003
|
+
return this.heading?.includes('created_at') ? 'message.common.sort_by.new' : 'message.common.sort_by.descending';
|
|
1004
|
+
else
|
|
1005
|
+
return 'message.common.sort';
|
|
1006
|
+
}
|
|
1007
|
+
ngOnChanges() {
|
|
1008
|
+
if (this.ascending != undefined) {
|
|
1009
|
+
this.tooltipDiv?.hide();
|
|
1010
|
+
this.tooltipDiv?.show(200);
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
InlineSortComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: InlineSortComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1015
|
+
InlineSortComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: InlineSortComponent, selector: "app-inline-sort, cqa-inline-sort", inputs: { ascending: "ascending", heading: "heading" }, viewQueries: [{ propertyName: "tooltipDiv", first: true, predicate: ["tooltipDiv"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
|
|
1016
|
+
<div #tooltipDiv="matTooltip"
|
|
1017
|
+
class="w-fit-content sort-header"
|
|
1018
|
+
[matTooltip]="getToolTip"
|
|
1019
|
+
[matTooltipPosition]="'after'">
|
|
1020
|
+
<span>{{ heading }}</span>
|
|
1021
|
+
<span *ngIf="ascending" class='fa-down-sort'></span>
|
|
1022
|
+
<span *ngIf="ascending==false" class='fa-up-sort'></span>
|
|
1023
|
+
<span *ngIf="ascending==undefined" class='fa-down-sort opaque-50'></span>
|
|
1024
|
+
</div>
|
|
1025
|
+
`, isInline: true, directives: [{ type: i1$2.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
|
|
1026
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: InlineSortComponent, decorators: [{
|
|
1027
|
+
type: Component,
|
|
1028
|
+
args: [{
|
|
1029
|
+
selector: 'app-inline-sort, cqa-inline-sort',
|
|
1030
|
+
template: `
|
|
1031
|
+
<div #tooltipDiv="matTooltip"
|
|
1032
|
+
class="w-fit-content sort-header"
|
|
1033
|
+
[matTooltip]="getToolTip"
|
|
1034
|
+
[matTooltipPosition]="'after'">
|
|
1035
|
+
<span>{{ heading }}</span>
|
|
1036
|
+
<span *ngIf="ascending" class='fa-down-sort'></span>
|
|
1037
|
+
<span *ngIf="ascending==false" class='fa-up-sort'></span>
|
|
1038
|
+
<span *ngIf="ascending==undefined" class='fa-down-sort opaque-50'></span>
|
|
1039
|
+
</div>
|
|
1040
|
+
`,
|
|
1041
|
+
styles: []
|
|
1042
|
+
}]
|
|
1043
|
+
}], propDecorators: { ascending: [{
|
|
1044
|
+
type: Input
|
|
1045
|
+
}], heading: [{
|
|
1046
|
+
type: Input
|
|
1047
|
+
}], tooltipDiv: [{
|
|
1048
|
+
type: ViewChild,
|
|
1049
|
+
args: ['tooltipDiv']
|
|
1050
|
+
}] } });
|
|
1051
|
+
|
|
1052
|
+
class PaginationComponent {
|
|
1053
|
+
constructor() {
|
|
1054
|
+
this.totalElements = 0;
|
|
1055
|
+
this.pageIndex = 0; // 0-based
|
|
1056
|
+
this.pageSize = 10;
|
|
1057
|
+
this.pageItemCount = 0; // number of items currently rendered on this page
|
|
1058
|
+
this.pageSizeOptions = [10, 20, 40, 60, 80];
|
|
1059
|
+
this.pageIndexChange = new EventEmitter();
|
|
1060
|
+
this.pageSizeChange = new EventEmitter();
|
|
1061
|
+
this.paginate = new EventEmitter();
|
|
1062
|
+
// Local UI state for custom page-size dropdown
|
|
1063
|
+
this.pageSizeOpen = false;
|
|
1064
|
+
this.pagesOption = {
|
|
1065
|
+
placeholder: 'Choose page',
|
|
1066
|
+
disabled: false,
|
|
1067
|
+
multiple: false,
|
|
1068
|
+
searchable: false,
|
|
1069
|
+
options: [
|
|
1070
|
+
{ id: 1, name: '10' },
|
|
1071
|
+
{ id: 2, name: '20' },
|
|
1072
|
+
{ id: 3, name: '30' },
|
|
1073
|
+
{ id: 4, name: '40' },
|
|
1074
|
+
],
|
|
1075
|
+
};
|
|
1076
|
+
}
|
|
1077
|
+
get computedTotalPages() {
|
|
1078
|
+
if (this.totalPages != null && this.totalPages > 0) {
|
|
1079
|
+
return this.totalPages;
|
|
1080
|
+
}
|
|
1081
|
+
if (this.pageSize > 0 && this.totalElements >= 0) {
|
|
1082
|
+
return Math.max(1, Math.ceil(this.totalElements / this.pageSize));
|
|
1083
|
+
}
|
|
1084
|
+
return 0;
|
|
1085
|
+
}
|
|
1086
|
+
getStartItem() {
|
|
1087
|
+
if (!this.totalElements) {
|
|
1088
|
+
return 0;
|
|
1089
|
+
}
|
|
1090
|
+
return this.pageIndex * this.pageSize + 1;
|
|
1091
|
+
}
|
|
1092
|
+
getEndItem() {
|
|
1093
|
+
const end = this.getStartItem() + this.pageItemCount - 1;
|
|
1094
|
+
if (end < 0) {
|
|
1095
|
+
return 0;
|
|
1096
|
+
}
|
|
1097
|
+
return Math.min(end, this.totalElements);
|
|
1098
|
+
}
|
|
1099
|
+
togglePageSizeMenu() {
|
|
1100
|
+
this.pageSizeOpen = !this.pageSizeOpen;
|
|
1101
|
+
}
|
|
1102
|
+
selectPageSize(size) {
|
|
1103
|
+
if (this.pageSize !== size) {
|
|
1104
|
+
this.pageSize = size;
|
|
1105
|
+
this.onPageSizeChange();
|
|
1106
|
+
}
|
|
1107
|
+
this.pageSizeOpen = false;
|
|
1108
|
+
}
|
|
1109
|
+
onPageSizeChange() {
|
|
1110
|
+
this.pageIndex = 0;
|
|
1111
|
+
this.pageSizeChange.emit(this.pageSize);
|
|
1112
|
+
this.pageIndexChange.emit(this.pageIndex);
|
|
1113
|
+
this.paginate.emit({ pageIndex: this.pageIndex, pageSize: this.pageSize });
|
|
1114
|
+
}
|
|
1115
|
+
goToPage(index) {
|
|
1116
|
+
const lastIndex = Math.max(0, this.computedTotalPages - 1);
|
|
1117
|
+
const next = Math.max(0, Math.min(index, lastIndex));
|
|
1118
|
+
if (next === this.pageIndex) {
|
|
1119
|
+
return;
|
|
1120
|
+
}
|
|
1121
|
+
this.pageIndex = next;
|
|
1122
|
+
this.pageIndexChange.emit(this.pageIndex);
|
|
1123
|
+
this.paginate.emit({ pageIndex: this.pageIndex, pageSize: this.pageSize });
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
PaginationComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: PaginationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1127
|
+
PaginationComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: PaginationComponent, selector: "cqa-pagination", inputs: { totalElements: "totalElements", totalPages: "totalPages", pageIndex: "pageIndex", pageSize: "pageSize", pageItemCount: "pageItemCount", pageSizeOptions: "pageSizeOptions" }, outputs: { pageIndexChange: "pageIndexChange", pageSizeChange: "pageSizeChange", paginate: "paginate" }, ngImport: i0, template: "<!-- Bottom Pagination -->\n<div id=\"cqa-ui-root\" >\n <div class=\"table-footer-pagination cqa-text-grey-300 cqa-text-[12.3px] cqa-leading-[17.5px] cqa-flex cqa-items-center cqa-justify-between cqa-gap-2 cqa-flex-wrap cqa-bg-surface-default cqa-px-[21px] cqa-py-[15px]\" *ngIf=\"pageItemCount && totalElements\">\n <div class=\"pagination-info cqa-flex cqa-items-center cqa-gap-[7px] cqa-relative\">\n <span class=\"rows-label\">Rows per page</span>\n <div class=\"cqa-relative\">\n <!-- Custom Select Trigger -->\n <button\n type=\"button\"\n class=\"cqa-inline-flex cqa-items-center cqa-gap-[19px] cqa-bg-white cqa-text-black-100 cqa-rounded-[5px] cqa-px-[11.5px] cqa-py-[6.75px]\"\n (click)=\"togglePageSizeMenu()\"\n [attr.aria-expanded]=\"pageSizeOpen\"\n aria-haspopup=\"listbox\"\n >\n {{ pageSize }}\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><g opacity=\"0.5\"><path d=\"M3.5 5.25L7 8.75L10.5 5.25\" stroke=\"#717182\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></g></svg>\n </button>\n <!-- Dropdown Menu -->\n <div\n *ngIf=\"pageSizeOpen\"\n class=\"cqa-absolute cqa-z-[100] cqa-bottom-[calc(100%+8px)] cqa-left-0 cqa-w-[75px] cqa-max-h-[170px] cqa-overflow-auto cqa-rounded-lg cqa-border cqa-border-[#E5E7EB] cqa-bg-white cqa-shadow-[0px_4px_6px_-1px_rgba(0,0,0,0.1)] cqa-p-[5px]\"\n role=\"listbox\"\n [attr.aria-activedescendant]=\"'pagesize-' + pageSize\"\n >\n <button\n *ngFor=\"let size of pageSizeOptions\"\n type=\"button\"\n class=\"cqa-w-full cqa-px-2 cqa-py-[6px] hover:cqa-bg-[#F7F8FA] cqa-text-left cqa-rounded-md cqa-text-black-100\"\n [attr.id]=\"'pagesize-' + size\"\n role=\"option\"\n [attr.aria-selected]=\"pageSize === size\"\n (click)=\"selectPageSize(size)\"\n >\n {{ size }}\n </button>\n </div>\n </div>\n </div>\n\n <div class=\"pagination-right cqa-flex cqa-items-center cqa-gap-[21px]\">\n <div class=\"pagination-range\">\n {{ getStartItem() }}–{{ getEndItem() }} of {{ totalElements }}\n </div>\n <div class=\"pagination-controls cqa-flex cqa-items-stretch cqa-gap-[3.5px]\">\n <button class=\"pagination-btn cqa-w-[28px] cqa-h-[28px] cqa-min-w-[28px] cqa-rounded-[5px] cqa-border cqa-border-[#E5E7EB] cqa-bg-[#F7F8FA] cqa-flex cqa-items-center cqa-justify-center\" [disabled]=\"pageIndex === 0\" (click)=\"goToPage(pageIndex - 1)\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M8.75 10.5L5.25 7L8.75 3.5\" stroke=\"#838384\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </button>\n <button class=\"pagination-btn cqa-w-[28px] cqa-h-[28px] cqa-min-w-[28px] cqa-rounded-[5px] cqa-border cqa-border-[#E5E7EB] cqa-bg-[#F7F8FA] cqa-flex cqa-items-center cqa-justify-center\" [disabled]=\"pageIndex >= computedTotalPages - 1\" (click)=\"goToPage(pageIndex + 1)\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M5.25 10.5L8.75 7L5.25 3.5\" stroke=\"#838384\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </button>\n </div>\n </div>\n </div>\n</div>", directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
|
|
1128
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: PaginationComponent, decorators: [{
|
|
1129
|
+
type: Component,
|
|
1130
|
+
args: [{ selector: 'cqa-pagination', template: "<!-- Bottom Pagination -->\n<div id=\"cqa-ui-root\" >\n <div class=\"table-footer-pagination cqa-text-grey-300 cqa-text-[12.3px] cqa-leading-[17.5px] cqa-flex cqa-items-center cqa-justify-between cqa-gap-2 cqa-flex-wrap cqa-bg-surface-default cqa-px-[21px] cqa-py-[15px]\" *ngIf=\"pageItemCount && totalElements\">\n <div class=\"pagination-info cqa-flex cqa-items-center cqa-gap-[7px] cqa-relative\">\n <span class=\"rows-label\">Rows per page</span>\n <div class=\"cqa-relative\">\n <!-- Custom Select Trigger -->\n <button\n type=\"button\"\n class=\"cqa-inline-flex cqa-items-center cqa-gap-[19px] cqa-bg-white cqa-text-black-100 cqa-rounded-[5px] cqa-px-[11.5px] cqa-py-[6.75px]\"\n (click)=\"togglePageSizeMenu()\"\n [attr.aria-expanded]=\"pageSizeOpen\"\n aria-haspopup=\"listbox\"\n >\n {{ pageSize }}\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><g opacity=\"0.5\"><path d=\"M3.5 5.25L7 8.75L10.5 5.25\" stroke=\"#717182\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></g></svg>\n </button>\n <!-- Dropdown Menu -->\n <div\n *ngIf=\"pageSizeOpen\"\n class=\"cqa-absolute cqa-z-[100] cqa-bottom-[calc(100%+8px)] cqa-left-0 cqa-w-[75px] cqa-max-h-[170px] cqa-overflow-auto cqa-rounded-lg cqa-border cqa-border-[#E5E7EB] cqa-bg-white cqa-shadow-[0px_4px_6px_-1px_rgba(0,0,0,0.1)] cqa-p-[5px]\"\n role=\"listbox\"\n [attr.aria-activedescendant]=\"'pagesize-' + pageSize\"\n >\n <button\n *ngFor=\"let size of pageSizeOptions\"\n type=\"button\"\n class=\"cqa-w-full cqa-px-2 cqa-py-[6px] hover:cqa-bg-[#F7F8FA] cqa-text-left cqa-rounded-md cqa-text-black-100\"\n [attr.id]=\"'pagesize-' + size\"\n role=\"option\"\n [attr.aria-selected]=\"pageSize === size\"\n (click)=\"selectPageSize(size)\"\n >\n {{ size }}\n </button>\n </div>\n </div>\n </div>\n\n <div class=\"pagination-right cqa-flex cqa-items-center cqa-gap-[21px]\">\n <div class=\"pagination-range\">\n {{ getStartItem() }}–{{ getEndItem() }} of {{ totalElements }}\n </div>\n <div class=\"pagination-controls cqa-flex cqa-items-stretch cqa-gap-[3.5px]\">\n <button class=\"pagination-btn cqa-w-[28px] cqa-h-[28px] cqa-min-w-[28px] cqa-rounded-[5px] cqa-border cqa-border-[#E5E7EB] cqa-bg-[#F7F8FA] cqa-flex cqa-items-center cqa-justify-center\" [disabled]=\"pageIndex === 0\" (click)=\"goToPage(pageIndex - 1)\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M8.75 10.5L5.25 7L8.75 3.5\" stroke=\"#838384\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </button>\n <button class=\"pagination-btn cqa-w-[28px] cqa-h-[28px] cqa-min-w-[28px] cqa-rounded-[5px] cqa-border cqa-border-[#E5E7EB] cqa-bg-[#F7F8FA] cqa-flex cqa-items-center cqa-justify-center\" [disabled]=\"pageIndex >= computedTotalPages - 1\" (click)=\"goToPage(pageIndex + 1)\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M5.25 10.5L8.75 7L5.25 3.5\" stroke=\"#838384\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </button>\n </div>\n </div>\n </div>\n</div>", styles: [] }]
|
|
1131
|
+
}], propDecorators: { totalElements: [{
|
|
1132
|
+
type: Input
|
|
1133
|
+
}], totalPages: [{
|
|
1134
|
+
type: Input
|
|
1135
|
+
}], pageIndex: [{
|
|
1136
|
+
type: Input
|
|
1137
|
+
}], pageSize: [{
|
|
1138
|
+
type: Input
|
|
1139
|
+
}], pageItemCount: [{
|
|
1140
|
+
type: Input
|
|
1141
|
+
}], pageSizeOptions: [{
|
|
1142
|
+
type: Input
|
|
1143
|
+
}], pageIndexChange: [{
|
|
1144
|
+
type: Output
|
|
1145
|
+
}], pageSizeChange: [{
|
|
1146
|
+
type: Output
|
|
1147
|
+
}], paginate: [{
|
|
1148
|
+
type: Output
|
|
1149
|
+
}] } });
|
|
1150
|
+
|
|
1151
|
+
class ActionMenuButtonComponent {
|
|
1152
|
+
constructor() {
|
|
1153
|
+
this.view = new EventEmitter();
|
|
1154
|
+
this.edit = new EventEmitter();
|
|
1155
|
+
this.delete = new EventEmitter();
|
|
1156
|
+
}
|
|
1157
|
+
navigateToTestCase(id) {
|
|
1158
|
+
if (id === undefined || id === null)
|
|
1159
|
+
return;
|
|
1160
|
+
this.view.emit(id);
|
|
1161
|
+
}
|
|
1162
|
+
editTestCase(row) {
|
|
1163
|
+
if (!row)
|
|
1164
|
+
return;
|
|
1165
|
+
this.edit.emit(row);
|
|
1166
|
+
}
|
|
1167
|
+
deleteTestCase(row) {
|
|
1168
|
+
if (!row)
|
|
1169
|
+
return;
|
|
1170
|
+
this.delete.emit(row);
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
ActionMenuButtonComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: ActionMenuButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1174
|
+
ActionMenuButtonComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: ActionMenuButtonComponent, selector: "cqa-action-menu-button", inputs: { row: "row" }, outputs: { view: "view", edit: "edit", delete: "delete" }, ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <button class=\"action-menu-btn\" [matMenuTriggerFor]=\"actionMenu\" (click)=\"$event.stopPropagation()\" mat-icon-button\n type=\"button\" aria-label=\"More actions\">\n <mat-icon>more_horiz</mat-icon>\n </button>\n\n <mat-menu #actionMenu=\"matMenu\" class=\"action-menu\" xPosition=\"after\" yPosition=\"below\" hasBackdrop=\"true\">\n <button mat-menu-item (click)=\"navigateToTestCase(row?.id)\">\n <mat-icon>visibility</mat-icon>\n <span>View</span>\n </button>\n <button mat-menu-item (click)=\"editTestCase(row)\">\n <mat-icon>edit_square</mat-icon>\n <span>Edit</span>\n </button>\n <button mat-menu-item (click)=\"deleteTestCase(row)\" class=\"delete-menu-item\">\n <mat-icon>delete</mat-icon>\n <span>Delete</span>\n </button>\n </mat-menu>\n</div>", components: [{ type: i1$3.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { type: i3$1.MatMenu, selector: "mat-menu", exportAs: ["matMenu"] }, { type: i3$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["disabled", "disableRipple", "role"], exportAs: ["matMenuItem"] }], directives: [{ type: i3$1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", exportAs: ["matMenuTrigger"] }] });
|
|
1175
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: ActionMenuButtonComponent, decorators: [{
|
|
1176
|
+
type: Component,
|
|
1177
|
+
args: [{ selector: 'cqa-action-menu-button', template: "<div id=\"cqa-ui-root\">\n <button class=\"action-menu-btn\" [matMenuTriggerFor]=\"actionMenu\" (click)=\"$event.stopPropagation()\" mat-icon-button\n type=\"button\" aria-label=\"More actions\">\n <mat-icon>more_horiz</mat-icon>\n </button>\n\n <mat-menu #actionMenu=\"matMenu\" class=\"action-menu\" xPosition=\"after\" yPosition=\"below\" hasBackdrop=\"true\">\n <button mat-menu-item (click)=\"navigateToTestCase(row?.id)\">\n <mat-icon>visibility</mat-icon>\n <span>View</span>\n </button>\n <button mat-menu-item (click)=\"editTestCase(row)\">\n <mat-icon>edit_square</mat-icon>\n <span>Edit</span>\n </button>\n <button mat-menu-item (click)=\"deleteTestCase(row)\" class=\"delete-menu-item\">\n <mat-icon>delete</mat-icon>\n <span>Delete</span>\n </button>\n </mat-menu>\n</div>", styles: [] }]
|
|
1178
|
+
}], propDecorators: { row: [{
|
|
1179
|
+
type: Input
|
|
1180
|
+
}], view: [{
|
|
1181
|
+
type: Output
|
|
1182
|
+
}], edit: [{
|
|
1183
|
+
type: Output
|
|
1184
|
+
}], delete: [{
|
|
1185
|
+
type: Output
|
|
1186
|
+
}] } });
|
|
1187
|
+
|
|
1188
|
+
class OtherButtonComponent {
|
|
1189
|
+
constructor() {
|
|
1190
|
+
// Single button API (backwards compatible)
|
|
1191
|
+
this.icon = '';
|
|
1192
|
+
this.label = '';
|
|
1193
|
+
this.classes = '';
|
|
1194
|
+
this.colorClass = '';
|
|
1195
|
+
this.buttonClass = '';
|
|
1196
|
+
this.disabled = false;
|
|
1197
|
+
this.type = 'button';
|
|
1198
|
+
// Group buttons API (new)
|
|
1199
|
+
this.buttons = null;
|
|
1200
|
+
/** Extra classes for the button group container */
|
|
1201
|
+
this.groupClass = '';
|
|
1202
|
+
/** Gap utility class; defaults to Tailwind spacing applied in template */
|
|
1203
|
+
this.gapClass = 'cqa-gap-2';
|
|
1204
|
+
/** When true, allows wrapping to next line on smaller screens */
|
|
1205
|
+
this.wrap = true;
|
|
1206
|
+
this.clicked = new EventEmitter();
|
|
1207
|
+
/** Emits the config of the clicked button in a group, along with the event */
|
|
1208
|
+
this.buttonClick = new EventEmitter();
|
|
1209
|
+
}
|
|
1210
|
+
onClick(event) {
|
|
1211
|
+
if (this.disabled) {
|
|
1212
|
+
event.preventDefault();
|
|
1213
|
+
event.stopPropagation();
|
|
1214
|
+
return;
|
|
1215
|
+
}
|
|
1216
|
+
this.clicked.emit(event);
|
|
1217
|
+
}
|
|
1218
|
+
onItemClick(event, item) {
|
|
1219
|
+
if (item?.disabled) {
|
|
1220
|
+
event.preventDefault();
|
|
1221
|
+
event.stopPropagation();
|
|
1222
|
+
return;
|
|
1223
|
+
}
|
|
1224
|
+
this.buttonClick.emit({ event, item });
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
OtherButtonComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: OtherButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1228
|
+
OtherButtonComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: OtherButtonComponent, selector: "cqa-other-button", inputs: { icon: "icon", label: "label", classes: "classes", colorClass: "colorClass", buttonClass: "buttonClass", disabled: "disabled", type: "type", buttons: "buttons", groupClass: "groupClass", gapClass: "gapClass", wrap: "wrap" }, outputs: { clicked: "clicked", buttonClick: "buttonClick" }, ngImport: i0, template: "<div id=\"cqa-ui-root\" >\n <!-- Group rendering if buttons are provided -->\n <ng-container *ngIf=\"buttons?.length; else singleButton\">\n <div class=\"cqa-inline-flex cqa-items-center\" [ngClass]=\"[wrap ? 'cqa-flex-wrap' : '', gapClass, groupClass]\">\n <button *ngFor=\"let b of buttons\"\n [type]=\"b.type || 'button'\"\n class=\"cqa-inline-flex cqa-items-center cqa-gap-1 cqa-py-[5.75px] cqa-px-[11.5px] cqa-rounded-[5px] cqa-text-[12.3px] cqa-leading-[17.5px] cqa-font-medium cqa-border\"\n [ngClass]=\"[b.classes || classes, buttonClass, b.colorClass || colorClass]\"\n [disabled]=\"b.disabled\"\n (click)=\"onItemClick($event, b)\">\n <mat-icon *ngIf=\"b.icon || icon\" class=\"!cqa-w-[16px] !cqa-h-[16px] !cqa-text-[16px]\">{{ b.icon || icon }}</mat-icon>\n <span>{{ b.label }}</span>\n </button>\n </div>\n </ng-container>\n\n <!-- Single button (backwards compatible) -->\n <ng-template #singleButton>\n <button [type]=\"type\"\n class=\"cqa-inline-flex cqa-items-center cqa-gap-1 cqa-py-[5.75px] cqa-px-[11.5px] cqa-rounded-[5px] cqa-text-[12.3px] cqa-leading-[17.5px] cqa-font-medium cqa-border\"\n [ngClass]=\"[classes, buttonClass, colorClass]\" [disabled]=\"disabled\" (click)=\"onClick($event)\">\n <mat-icon *ngIf=\"icon\" class=\"!cqa-w-[16px] !cqa-h-[16px] !cqa-text-[16px]\">{{ icon }}</mat-icon>\n <span>{{ label }}</span>\n </button>\n </ng-template>\n</div>", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1229
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: OtherButtonComponent, decorators: [{
|
|
1230
|
+
type: Component,
|
|
1231
|
+
args: [{ selector: 'cqa-other-button', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div id=\"cqa-ui-root\" >\n <!-- Group rendering if buttons are provided -->\n <ng-container *ngIf=\"buttons?.length; else singleButton\">\n <div class=\"cqa-inline-flex cqa-items-center\" [ngClass]=\"[wrap ? 'cqa-flex-wrap' : '', gapClass, groupClass]\">\n <button *ngFor=\"let b of buttons\"\n [type]=\"b.type || 'button'\"\n class=\"cqa-inline-flex cqa-items-center cqa-gap-1 cqa-py-[5.75px] cqa-px-[11.5px] cqa-rounded-[5px] cqa-text-[12.3px] cqa-leading-[17.5px] cqa-font-medium cqa-border\"\n [ngClass]=\"[b.classes || classes, buttonClass, b.colorClass || colorClass]\"\n [disabled]=\"b.disabled\"\n (click)=\"onItemClick($event, b)\">\n <mat-icon *ngIf=\"b.icon || icon\" class=\"!cqa-w-[16px] !cqa-h-[16px] !cqa-text-[16px]\">{{ b.icon || icon }}</mat-icon>\n <span>{{ b.label }}</span>\n </button>\n </div>\n </ng-container>\n\n <!-- Single button (backwards compatible) -->\n <ng-template #singleButton>\n <button [type]=\"type\"\n class=\"cqa-inline-flex cqa-items-center cqa-gap-1 cqa-py-[5.75px] cqa-px-[11.5px] cqa-rounded-[5px] cqa-text-[12.3px] cqa-leading-[17.5px] cqa-font-medium cqa-border\"\n [ngClass]=\"[classes, buttonClass, colorClass]\" [disabled]=\"disabled\" (click)=\"onClick($event)\">\n <mat-icon *ngIf=\"icon\" class=\"!cqa-w-[16px] !cqa-h-[16px] !cqa-text-[16px]\">{{ icon }}</mat-icon>\n <span>{{ label }}</span>\n </button>\n </ng-template>\n</div>", styles: [] }]
|
|
1232
|
+
}], propDecorators: { icon: [{
|
|
1233
|
+
type: Input
|
|
1234
|
+
}], label: [{
|
|
1235
|
+
type: Input
|
|
1236
|
+
}], classes: [{
|
|
1237
|
+
type: Input
|
|
1238
|
+
}], colorClass: [{
|
|
1239
|
+
type: Input
|
|
1240
|
+
}], buttonClass: [{
|
|
1241
|
+
type: Input
|
|
1242
|
+
}], disabled: [{
|
|
1243
|
+
type: Input
|
|
1244
|
+
}], type: [{
|
|
1245
|
+
type: Input
|
|
1246
|
+
}], buttons: [{
|
|
1247
|
+
type: Input
|
|
1248
|
+
}], groupClass: [{
|
|
1249
|
+
type: Input
|
|
1250
|
+
}], gapClass: [{
|
|
1251
|
+
type: Input
|
|
1252
|
+
}], wrap: [{
|
|
1253
|
+
type: Input
|
|
1254
|
+
}], clicked: [{
|
|
1255
|
+
type: Output
|
|
1256
|
+
}], buttonClick: [{
|
|
1257
|
+
type: Output
|
|
1258
|
+
}] } });
|
|
1259
|
+
|
|
1260
|
+
class DynamicSelectFieldComponent {
|
|
1261
|
+
constructor() {
|
|
1262
|
+
// Must be public for template access in Angular's strict template checking mode
|
|
1263
|
+
this.searchTextByKey = {};
|
|
1264
|
+
}
|
|
1265
|
+
ngOnInit() {
|
|
1266
|
+
if (!this.config || !this.config.key) {
|
|
1267
|
+
throw new Error('cqa-dynamic-select: input "config.key" is required.');
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
ngOnChanges(changes) {
|
|
1271
|
+
if ('config' in changes) {
|
|
1272
|
+
// When config changes (including toggling multiple), ensure control value shape matches
|
|
1273
|
+
this.syncControlValueForMultipleMode();
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
get panelClass() {
|
|
1277
|
+
return `ctc-select-panel ${this.isMultiple ? 'multiple' : ''}`.trim();
|
|
1278
|
+
}
|
|
1279
|
+
get isMultiple() {
|
|
1280
|
+
return this.toBoolean(this.config?.multiple);
|
|
1281
|
+
}
|
|
1282
|
+
get isDisabled() {
|
|
1283
|
+
return this.toBoolean(this.config?.disabled);
|
|
1284
|
+
}
|
|
1285
|
+
toBoolean(value) {
|
|
1286
|
+
if (typeof value === 'string') {
|
|
1287
|
+
const v = value.trim().toLowerCase();
|
|
1288
|
+
if (v === 'true' || v === '1')
|
|
1289
|
+
return true;
|
|
1290
|
+
if (v === 'false' || v === '0' || v === '')
|
|
1291
|
+
return false;
|
|
1292
|
+
return true; // any other non-empty string treated as truthy
|
|
1293
|
+
}
|
|
1294
|
+
if (typeof value === 'number') {
|
|
1295
|
+
return value !== 0;
|
|
1296
|
+
}
|
|
1297
|
+
return !!value;
|
|
1298
|
+
}
|
|
1299
|
+
syncControlValueForMultipleMode() {
|
|
1300
|
+
const key = this.config?.key;
|
|
1301
|
+
if (!key || !this.form)
|
|
1302
|
+
return;
|
|
1303
|
+
const control = this.form.get(key);
|
|
1304
|
+
if (!control)
|
|
1305
|
+
return;
|
|
1306
|
+
const currentValue = control.value;
|
|
1307
|
+
if (this.isMultiple) {
|
|
1308
|
+
if (currentValue == null)
|
|
1309
|
+
return;
|
|
1310
|
+
if (Array.isArray(currentValue))
|
|
1311
|
+
return;
|
|
1312
|
+
control.setValue([currentValue], { emitEvent: false });
|
|
1313
|
+
}
|
|
1314
|
+
else {
|
|
1315
|
+
if (!Array.isArray(currentValue))
|
|
1316
|
+
return;
|
|
1317
|
+
control.setValue(currentValue.length ? currentValue[0] : null, { emitEvent: false });
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
onSelectOpenedChange(opened, _select) {
|
|
1321
|
+
if (!opened) {
|
|
1322
|
+
// Reset search text on close so the next open shows full list
|
|
1323
|
+
if (this.config?.key) {
|
|
1324
|
+
this.searchTextByKey[this.config.key] = '';
|
|
1325
|
+
}
|
|
1326
|
+
// Ensure any previous custom listeners are cleared (legacy compatibility)
|
|
1327
|
+
if (this.outsideCleanup) {
|
|
1328
|
+
this.outsideCleanup();
|
|
1329
|
+
this.outsideCleanup = undefined;
|
|
1330
|
+
}
|
|
1331
|
+
return;
|
|
1332
|
+
}
|
|
1333
|
+
// Focus the search box if enabled
|
|
1334
|
+
if (this.config?.searchable) {
|
|
1335
|
+
setTimeout(() => {
|
|
1336
|
+
const input = document.querySelector('.ts-select-search-input');
|
|
1337
|
+
input?.focus();
|
|
1338
|
+
}, 0);
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
onSearch(key, value) {
|
|
1342
|
+
this.searchTextByKey[key] = value ?? '';
|
|
1343
|
+
}
|
|
1344
|
+
filteredOptions(c) {
|
|
1345
|
+
const t = (this.searchTextByKey[c.key] || '').toLowerCase().trim();
|
|
1346
|
+
if (!t)
|
|
1347
|
+
return c.options || [];
|
|
1348
|
+
return (c.options || []).filter((opt) => {
|
|
1349
|
+
const text = String(opt.name ?? opt.label ?? opt.value ?? '').toLowerCase();
|
|
1350
|
+
return text.includes(t);
|
|
1351
|
+
});
|
|
1352
|
+
}
|
|
1353
|
+
// Close when an option is selected if requested. Always close for single-select.
|
|
1354
|
+
onOptionSelected(select) {
|
|
1355
|
+
// Let Angular Material auto-close for single-select.
|
|
1356
|
+
// For multi-select, close only if explicitly requested.
|
|
1357
|
+
const shouldClose = this.isMultiple ? !!this.config?.closeOnSelect : false;
|
|
1358
|
+
if (shouldClose) {
|
|
1359
|
+
try {
|
|
1360
|
+
select.close();
|
|
1361
|
+
}
|
|
1362
|
+
catch { }
|
|
1363
|
+
}
|
|
1364
|
+
// If searchable, clear the search after selection so reopening works predictably
|
|
1365
|
+
if (this.config?.searchable && this.config?.key) {
|
|
1366
|
+
this.searchTextByKey[this.config.key] = '';
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
handleDocumentClick(event) {
|
|
1370
|
+
// Close when clicking outside of the trigger and outside of the open panel
|
|
1371
|
+
if (!this.selectRef?.panelOpen) {
|
|
1372
|
+
return;
|
|
1373
|
+
}
|
|
1374
|
+
const target = event.target;
|
|
1375
|
+
if (!target)
|
|
1376
|
+
return;
|
|
1377
|
+
// If click is inside the component host, ignore
|
|
1378
|
+
if (this.hostEl?.nativeElement && this.hostEl.nativeElement.contains(target)) {
|
|
1379
|
+
return;
|
|
1380
|
+
}
|
|
1381
|
+
// If click is inside any open mat-select panel, ignore
|
|
1382
|
+
const panelEls = Array.from(document.querySelectorAll('.mat-select-panel'));
|
|
1383
|
+
const clickInsidePanel = panelEls.some((el) => el.contains(target));
|
|
1384
|
+
if (clickInsidePanel) {
|
|
1385
|
+
return;
|
|
1386
|
+
}
|
|
1387
|
+
try {
|
|
1388
|
+
this.selectRef.close();
|
|
1389
|
+
}
|
|
1390
|
+
catch { }
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
DynamicSelectFieldComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DynamicSelectFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1394
|
+
DynamicSelectFieldComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: DynamicSelectFieldComponent, selector: "cqa-dynamic-select", inputs: { form: "form", config: "config" }, host: { listeners: { "document:click": "handleDocumentClick($event)" } }, viewQueries: [{ propertyName: "selectRef", first: true, predicate: ["selectRef"], descendants: true }, { propertyName: "hostEl", first: true, predicate: ["host"], descendants: true, read: ElementRef }], usesOnChanges: true, ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <ng-container [formGroup]=\"form\">\n <label *ngIf=\"config.label\"\n class=\"form-label cqa-text-[#374151] cqa-text-[14px] cqa-font-medium cqa-block cqa-leading-[1.4] cqa-mb-2\">{{\n config.label }}</label>\n <mat-form-field #host class=\"mat-select-custom cqa-w-full\" appearance=\"fill\">\n <mat-select #selectRef=\"matSelect\" [placeholder]=\"config.placeholder\" [disabled]=\"isDisabled\" [multiple]=\"isMultiple\"\n disableOptionCentering [panelClass]=\"panelClass\" [formControlName]=\"config.key\"\n (openedChange)=\"onSelectOpenedChange($event, selectRef)\" (selectionChange)=\"onOptionSelected(selectRef)\">\n\n <mat-option *ngIf=\"config.searchable\" class=\"ts-select-search\" disabled>\n <input class=\"ts-select-search-input\" type=\"text\" [value]=\"searchTextByKey[config.key] || ''\"\n (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\" (input)=\"onSearch(config.key, $any($event.target).value)\"\n placeholder=\"Search...\" />\n </mat-option>\n\n <mat-option *ngFor=\"let opt of filteredOptions(config)\" [value]=\"opt.id ?? opt.value\"\n [textContent]=\"opt.name ?? opt.label ?? opt.value\">\n {{ opt.name ?? opt.label ?? opt.value }}\n </mat-option>\n </mat-select>\n\n <div>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4 6L8 10L12 6\" stroke=\"#0A0A0A\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </div>\n </mat-form-field>\n </ng-container>\n</div>", components: [{ type: i3$2.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: i2$1.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex"], exportAs: ["matSelect"] }, { type: i3$3.MatOption, selector: "mat-option", exportAs: ["matOption"] }], directives: [{ type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1395
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DynamicSelectFieldComponent, decorators: [{
|
|
1396
|
+
type: Component,
|
|
1397
|
+
args: [{ selector: 'cqa-dynamic-select', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div id=\"cqa-ui-root\">\n <ng-container [formGroup]=\"form\">\n <label *ngIf=\"config.label\"\n class=\"form-label cqa-text-[#374151] cqa-text-[14px] cqa-font-medium cqa-block cqa-leading-[1.4] cqa-mb-2\">{{\n config.label }}</label>\n <mat-form-field #host class=\"mat-select-custom cqa-w-full\" appearance=\"fill\">\n <mat-select #selectRef=\"matSelect\" [placeholder]=\"config.placeholder\" [disabled]=\"isDisabled\" [multiple]=\"isMultiple\"\n disableOptionCentering [panelClass]=\"panelClass\" [formControlName]=\"config.key\"\n (openedChange)=\"onSelectOpenedChange($event, selectRef)\" (selectionChange)=\"onOptionSelected(selectRef)\">\n\n <mat-option *ngIf=\"config.searchable\" class=\"ts-select-search\" disabled>\n <input class=\"ts-select-search-input\" type=\"text\" [value]=\"searchTextByKey[config.key] || ''\"\n (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\" (input)=\"onSearch(config.key, $any($event.target).value)\"\n placeholder=\"Search...\" />\n </mat-option>\n\n <mat-option *ngFor=\"let opt of filteredOptions(config)\" [value]=\"opt.id ?? opt.value\"\n [textContent]=\"opt.name ?? opt.label ?? opt.value\">\n {{ opt.name ?? opt.label ?? opt.value }}\n </mat-option>\n </mat-select>\n\n <div>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4 6L8 10L12 6\" stroke=\"#0A0A0A\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </div>\n </mat-form-field>\n </ng-container>\n</div>", styles: [] }]
|
|
1398
|
+
}], propDecorators: { form: [{
|
|
1399
|
+
type: Input
|
|
1400
|
+
}], config: [{
|
|
1401
|
+
type: Input
|
|
1402
|
+
}], selectRef: [{
|
|
1403
|
+
type: ViewChild,
|
|
1404
|
+
args: ['selectRef', { static: false }]
|
|
1405
|
+
}], hostEl: [{
|
|
1406
|
+
type: ViewChild,
|
|
1407
|
+
args: ['host', { static: false, read: ElementRef }]
|
|
1408
|
+
}], handleDocumentClick: [{
|
|
1409
|
+
type: HostListener,
|
|
1410
|
+
args: ['document:click', ['$event']]
|
|
1411
|
+
}] } });
|
|
1412
|
+
|
|
1413
|
+
class DynamicFilterComponent {
|
|
1414
|
+
constructor(fb) {
|
|
1415
|
+
this.fb = fb;
|
|
1416
|
+
this.config = [];
|
|
1417
|
+
this.model = {};
|
|
1418
|
+
this.showFilterPanel = true;
|
|
1419
|
+
this.filtersApplied = new EventEmitter();
|
|
1420
|
+
this.filtersChanged = new EventEmitter();
|
|
1421
|
+
this.resetAction = new EventEmitter();
|
|
1422
|
+
this.form = this.fb.group({});
|
|
1423
|
+
this.maxDate = new Date();
|
|
1424
|
+
this.searchTextByKey = {};
|
|
1425
|
+
this.selectOutsideCleanup = new Map();
|
|
1426
|
+
}
|
|
1427
|
+
ngOnChanges(changes) {
|
|
1428
|
+
if (changes['config'] || changes['model']) {
|
|
1429
|
+
this.buildForm();
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
onDateChange(event, key) {
|
|
1433
|
+
const formGroup = this.getDateGroup(key);
|
|
1434
|
+
const start = formGroup.get('start')?.value;
|
|
1435
|
+
const end = formGroup.get('end')?.value;
|
|
1436
|
+
// When both dates are selected, auto-apply
|
|
1437
|
+
// if (start && end) {
|
|
1438
|
+
// this.applyDateRange(key, { start, end });
|
|
1439
|
+
// }
|
|
1440
|
+
}
|
|
1441
|
+
buildForm() {
|
|
1442
|
+
const ctrls = {};
|
|
1443
|
+
(this.config || []).forEach(c => {
|
|
1444
|
+
if (c.hidden)
|
|
1445
|
+
return;
|
|
1446
|
+
if (c.type === 'date-range') {
|
|
1447
|
+
ctrls[c.key] = this.fb.group({ start: new FormControl(), end: new FormControl() });
|
|
1448
|
+
}
|
|
1449
|
+
else {
|
|
1450
|
+
const initial = this.model?.[c.key];
|
|
1451
|
+
if (c.multiple) {
|
|
1452
|
+
const value = Array.isArray(initial) ? initial : (initial != null ? [initial] : []);
|
|
1453
|
+
ctrls[c.key] = new FormControl(value);
|
|
1454
|
+
}
|
|
1455
|
+
else {
|
|
1456
|
+
ctrls[c.key] = new FormControl(Array.isArray(initial) ? (initial.length ? initial[0] : undefined) : initial);
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
});
|
|
1460
|
+
this.form = this.fb.group(ctrls);
|
|
1461
|
+
this.form.valueChanges.subscribe(() => this.filtersChanged.emit(this.serialize()));
|
|
1462
|
+
}
|
|
1463
|
+
onSelectOpenedChange(opened, select) {
|
|
1464
|
+
if (opened) {
|
|
1465
|
+
setTimeout(() => {
|
|
1466
|
+
const onDocDown = (e) => {
|
|
1467
|
+
const panel = document.querySelector('.cdk-overlay-pane .mat-select-panel');
|
|
1468
|
+
const target = e.target;
|
|
1469
|
+
const originEl = select?._elementRef?.nativeElement || null;
|
|
1470
|
+
const insidePanel = !!(panel && target && panel.contains(target));
|
|
1471
|
+
const insideOrigin = !!(originEl && target && originEl.contains(target));
|
|
1472
|
+
if (!insidePanel && !insideOrigin) {
|
|
1473
|
+
select.close();
|
|
1474
|
+
}
|
|
1475
|
+
};
|
|
1476
|
+
document.addEventListener('mousedown', onDocDown, true);
|
|
1477
|
+
this.selectOutsideCleanup.set(select, () => document.removeEventListener('mousedown', onDocDown, true));
|
|
1478
|
+
}, 0);
|
|
1479
|
+
}
|
|
1480
|
+
else {
|
|
1481
|
+
const cleanup = this.selectOutsideCleanup.get(select);
|
|
1482
|
+
if (cleanup)
|
|
1483
|
+
cleanup();
|
|
1484
|
+
this.selectOutsideCleanup.delete(select);
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
onSearch(key, text) {
|
|
1488
|
+
this.searchTextByKey[key] = (text || '').toLowerCase();
|
|
1489
|
+
}
|
|
1490
|
+
filteredOptions(item) {
|
|
1491
|
+
const options = item?.options || [];
|
|
1492
|
+
const q = (this.searchTextByKey[item.key] || '').trim();
|
|
1493
|
+
if (!q)
|
|
1494
|
+
return options;
|
|
1495
|
+
return options.filter(opt => {
|
|
1496
|
+
const name = (opt.name ?? opt.label ?? String(opt.value ?? '')).toLowerCase();
|
|
1497
|
+
return name.includes(q);
|
|
1498
|
+
});
|
|
1499
|
+
}
|
|
1500
|
+
getDateGroup(key) {
|
|
1501
|
+
return this.form.get(key);
|
|
1502
|
+
}
|
|
1503
|
+
getSelectConfig(item) {
|
|
1504
|
+
return {
|
|
1505
|
+
key: item.key,
|
|
1506
|
+
label: item.label,
|
|
1507
|
+
placeholder: item.placeholder,
|
|
1508
|
+
disabled: item.disabled,
|
|
1509
|
+
multiple: item.multiple,
|
|
1510
|
+
searchable: item.searchable,
|
|
1511
|
+
options: item.options || []
|
|
1512
|
+
};
|
|
1513
|
+
}
|
|
1514
|
+
apply() {
|
|
1515
|
+
this.filtersApplied.emit(this.serialize());
|
|
1516
|
+
}
|
|
1517
|
+
reset() {
|
|
1518
|
+
Object.keys(this.form.controls).forEach(key => {
|
|
1519
|
+
const ctrl = this.form.get(key);
|
|
1520
|
+
if (ctrl instanceof FormGroup) {
|
|
1521
|
+
ctrl.get('start')?.setValue(undefined);
|
|
1522
|
+
ctrl.get('end')?.setValue(undefined);
|
|
1523
|
+
}
|
|
1524
|
+
else {
|
|
1525
|
+
ctrl?.setValue(undefined);
|
|
1526
|
+
}
|
|
1527
|
+
});
|
|
1528
|
+
this.resetAction.emit();
|
|
1529
|
+
this.filtersChanged.emit(this.serialize());
|
|
1530
|
+
}
|
|
1531
|
+
serialize() {
|
|
1532
|
+
const result = {};
|
|
1533
|
+
(this.config || []).forEach(c => {
|
|
1534
|
+
const ctrl = this.form.get(c.key);
|
|
1535
|
+
if (!ctrl)
|
|
1536
|
+
return;
|
|
1537
|
+
let val = ctrl instanceof FormGroup ? ctrl.getRawValue() : ctrl.value;
|
|
1538
|
+
if (c.type === 'date-range') {
|
|
1539
|
+
const start = val?.start;
|
|
1540
|
+
const end = val?.end;
|
|
1541
|
+
if (start || end)
|
|
1542
|
+
result[c.key] = { start, end };
|
|
1543
|
+
}
|
|
1544
|
+
else {
|
|
1545
|
+
if (val !== undefined && val !== null && (Array.isArray(val) ? val.length > 0 : val !== '')) {
|
|
1546
|
+
result[c.key] = val;
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
});
|
|
1550
|
+
return result;
|
|
1551
|
+
}
|
|
1552
|
+
// Mat date range picker overlay preset helpers
|
|
1553
|
+
applyPresetToGroup(key, presetKey) {
|
|
1554
|
+
const dateGroup = this.getDateGroup(key);
|
|
1555
|
+
if (!dateGroup)
|
|
1556
|
+
return;
|
|
1557
|
+
const { start, end } = this.getPresetDates(presetKey);
|
|
1558
|
+
dateGroup.patchValue({ start, end });
|
|
1559
|
+
this.filtersChanged.emit(this.serialize());
|
|
1560
|
+
}
|
|
1561
|
+
getPresetDates(presetKey) {
|
|
1562
|
+
const today = new Date();
|
|
1563
|
+
const clampToEndOfToday = (d) => { const nd = new Date(d); nd.setHours(23, 59, 59, 999); return nd; };
|
|
1564
|
+
switch (presetKey) {
|
|
1565
|
+
case 'today':
|
|
1566
|
+
return { start: today, end: today };
|
|
1567
|
+
case 'last7days': {
|
|
1568
|
+
const start = new Date();
|
|
1569
|
+
start.setDate(start.getDate() - 6);
|
|
1570
|
+
return { start, end: today };
|
|
1571
|
+
}
|
|
1572
|
+
case 'last30days': {
|
|
1573
|
+
const start = new Date();
|
|
1574
|
+
start.setDate(start.getDate() - 29);
|
|
1575
|
+
return { start, end: today };
|
|
1576
|
+
}
|
|
1577
|
+
case 'last90days': {
|
|
1578
|
+
const start = new Date();
|
|
1579
|
+
start.setDate(start.getDate() - 89);
|
|
1580
|
+
return { start, end: today };
|
|
1581
|
+
}
|
|
1582
|
+
case 'thismonth': {
|
|
1583
|
+
const start = new Date(today.getFullYear(), today.getMonth(), 1);
|
|
1584
|
+
return { start, end: today };
|
|
1585
|
+
}
|
|
1586
|
+
case 'lastmonth': {
|
|
1587
|
+
const start = new Date(today.getFullYear(), today.getMonth() - 1, 1);
|
|
1588
|
+
const end = new Date(today.getFullYear(), today.getMonth(), 0);
|
|
1589
|
+
return { start, end: clampToEndOfToday(end) };
|
|
1590
|
+
}
|
|
1591
|
+
}
|
|
1592
|
+
}
|
|
1593
|
+
getDateValidationError(key) {
|
|
1594
|
+
const dateGroup = this.getDateGroup(key);
|
|
1595
|
+
if (!dateGroup)
|
|
1596
|
+
return null;
|
|
1597
|
+
const startCtrl = dateGroup.controls['start'];
|
|
1598
|
+
const endCtrl = dateGroup.controls['end'];
|
|
1599
|
+
const startVal = startCtrl?.value;
|
|
1600
|
+
const endVal = endCtrl?.value;
|
|
1601
|
+
const startParseErr = startCtrl?.errors?.['matDatepickerParse']?.text;
|
|
1602
|
+
const endParseErr = endCtrl?.errors?.['matDatepickerParse']?.text;
|
|
1603
|
+
if (!startVal && !endVal && !startParseErr && !endParseErr)
|
|
1604
|
+
return null;
|
|
1605
|
+
if (startParseErr)
|
|
1606
|
+
return `Invalid start date format`;
|
|
1607
|
+
if (endParseErr)
|
|
1608
|
+
return `Invalid end date format`;
|
|
1609
|
+
if (startVal && !endVal)
|
|
1610
|
+
return `Please select an end date`;
|
|
1611
|
+
if (!startVal && endVal)
|
|
1612
|
+
return `Please select a start date`;
|
|
1613
|
+
if (dateGroup.hasError('matStartDateInvalid'))
|
|
1614
|
+
return `Start date must be before end date`;
|
|
1615
|
+
if (dateGroup.hasError('matEndDateInvalid'))
|
|
1616
|
+
return `End date must be after start date`;
|
|
1617
|
+
if (dateGroup.invalid) {
|
|
1618
|
+
const config = this.config?.find(c => c.key === key);
|
|
1619
|
+
return config ? `${config.label} is invalid` : 'Date range is invalid';
|
|
1620
|
+
}
|
|
1621
|
+
return null;
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1624
|
+
DynamicFilterComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DynamicFilterComponent, deps: [{ token: i1$1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
|
|
1625
|
+
DynamicFilterComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: DynamicFilterComponent, selector: "cqa-dynamic-filter", inputs: { config: "config", model: "model", showFilterPanel: "showFilterPanel" }, outputs: { filtersApplied: "filtersApplied", filtersChanged: "filtersChanged", resetAction: "resetAction" }, usesOnChanges: true, ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <div class=\"cqa-filter cqa-mb-[28px]\" *ngIf=\"showFilterPanel\">\n <form class=\"ts-form cqa-grid lg:cqa-grid-cols-4 md:cqa-grid-cols-2 cqa-gap-4\" [formGroup]=\"form\"\n (keydown.enter)=\"(false)\" novalidate=\"novalidate\">\n <ng-container *ngFor=\"let c of config\">\n <ng-container *ngIf=\"!c.hidden\">\n <div class=\"form-group cqa-flex cqa-flex-col cqa-gap-2\">\n <!-- Select -->\n <ng-container *ngIf=\"c.type === 'select'\">\n <cqa-dynamic-select [form]=\"form\" [config]=\"getSelectConfig(c)\"></cqa-dynamic-select>\n </ng-container>\n\n <!-- Date Range --> \n <ng-container *ngIf=\"c.type === 'date-range'\">\n <label\n class=\"form-label cqa-text-[#374151] cqa-text-[14px] cqa-font-medium cqa-block cqa-leading-[1.4]\">{{\n c.label }}</label>\n <mat-form-field class=\"mat-date-custom\" appearance=\"fill\">\n <mat-date-range-input [rangePicker]=\"picker\" [formGroup]=\"getDateGroup(c.key)\" [max]=\"maxDate\">\n <input matStartDate formControlName=\"start\" placeholder=\"Start date\" [max]=\"maxDate\" required\n [readonly]=\"true\" (focus)=\"picker.open()\" (click)=\"picker.open()\" />\n <input matEndDate formControlName=\"end\" placeholder=\"End date\" [max]=\"maxDate\" required\n [readonly]=\"true\" (focus)=\"picker.open()\" (click)=\"picker.open()\" />\n </mat-date-range-input>\n <mat-date-range-picker #picker (dateChange)=\"onDateChange($event, c.key)\"\n [panelClass]=\"'ctc-date-range-panel'\">\n <mat-datepicker-actions>\n <div class=\"ctc-date-presets\">\n <div class=\"cqa-mb-2 cqa-font-medium\">Quick Presets</div>\n <div class=\"btn-group\">\n <button type=\"button\" class=\"preset-btn today\"\n (click)=\"applyPresetToGroup(c.key, 'today'); picker.close()\">Today</button>\n <button type=\"button\" class=\"preset-btn last7days\"\n (click)=\"applyPresetToGroup(c.key, 'last7days'); picker.close()\">Last 7 days</button>\n <button type=\"button\" class=\"preset-btn last30days\"\n (click)=\"applyPresetToGroup(c.key, 'last30days'); picker.close()\">Last 30 days</button>\n <button type=\"button\" class=\"preset-btn last90days\"\n (click)=\"applyPresetToGroup(c.key, 'last90days'); picker.close()\">Last 90 days</button>\n <button type=\"button\" class=\"preset-btn thismonth\"\n (click)=\"applyPresetToGroup(c.key, 'thismonth'); picker.close()\">This month</button>\n <button type=\"button\" class=\"preset-btn lastmonth\"\n (click)=\"applyPresetToGroup(c.key, 'lastmonth'); picker.close()\">Last month</button>\n </div>\n </div>\n <div class=\"cqa-font-medium cqa-mb-2 cqa-mt-[10px] cqa-w-full\">Custom Range</div>\n <button\n class=\"cqa-font-medium !cqa-mb-2 !cqa-mt-[10px] cqa-w-[calc(100%-32px)] !cqa-absolute cqa-bottom-[2px]\"\n mat-flat-button color=\"primary\" matDatepickerApply>Apply</button>\n </mat-datepicker-actions>\n </mat-date-range-picker>\n <div (click)=\"picker.open()\" class=\"cqa-cursor-pointer\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M5.33398 1.33203V3.9987\" stroke=\"#0A0A0A\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M10.666 1.33203V3.9987\" stroke=\"#0A0A0A\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path\n d=\"M12.6667 2.66797H3.33333C2.59695 2.66797 2 3.26492 2 4.0013V13.3346C2 14.071 2.59695 14.668 3.33333 14.668H12.6667C13.403 14.668 14 14.071 14 13.3346V4.0013C14 3.26492 13.403 2.66797 12.6667 2.66797Z\"\n stroke=\"#0A0A0A\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M2 6.66797H14\" stroke=\"#0A0A0A\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </div>\n </mat-form-field>\n <!-- Specific validation messages -->\n <mat-error *ngIf=\"getDateValidationError(c.key) && !picker.opened\">\n {{ getDateValidationError(c.key) }}\n </mat-error>\n\n </ng-container>\n </div>\n </ng-container>\n </ng-container>\n </form>\n\n <div class=\"cqa-flex cqa-justify-end cqa-items-stretch cqa-gap-2 cqa-mt-4\">\n <button type=\"button\"\n class=\"cqa-text-[13.33px] cqa-leading-[1] cqa-flex cqa-flex-row cqa-justify-center cqa-items-center cqa-px-[11px] cqa-py-[1px] cqa-gap-[14px] cqa-h-8 cqa-border cqa-border-[#0B0B0C] cqa-shadow-[0_1px_2px_rgba(0,0,0,0.05)] cqa-rounded-lg cqa-text-[#0B0B0C]\"\n (click)=\"reset()\">Reset</button>\n <button type=\"button\"\n class=\"cqa-text-[13.33px] cqa-leading-[1] cqa-flex cqa-flex-row cqa-justify-center cqa-items-center cqa-px-[11px] cqa-py-[1px] cqa-gap-[14px] cqa-h-8 cqa-bg-[#0B0B0C] cqa-border cqa-border-[#E5E5E5] cqa-shadow-[0_1px_2px_rgba(0,0,0,0.05)] cqa-rounded-lg cqa-text-white\"\n (click)=\"apply()\">Apply Filter</button>\n </div>\n </div>\n</div>", components: [{ type: DynamicSelectFieldComponent, selector: "cqa-dynamic-select", inputs: ["form", "config"] }, { type: i3$2.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: i4.MatDateRangeInput, selector: "mat-date-range-input", inputs: ["rangePicker", "required", "dateFilter", "min", "max", "disabled", "separator", "comparisonStart", "comparisonEnd"], exportAs: ["matDateRangeInput"] }, { type: i4.MatDateRangePicker, selector: "mat-date-range-picker", exportAs: ["matDateRangePicker"] }, { type: i4.MatDatepickerActions, selector: "mat-datepicker-actions, mat-date-range-picker-actions" }, { type: i1$3.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i4.MatStartDate, selector: "input[matStartDate]", inputs: ["errorStateMatcher"], outputs: ["dateChange", "dateInput"] }, { type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i4.MatEndDate, selector: "input[matEndDate]", inputs: ["errorStateMatcher"], outputs: ["dateChange", "dateInput"] }, { type: i4.MatDatepickerApply, selector: "[matDatepickerApply], [matDateRangePickerApply]" }, { type: i3$2.MatError, selector: "mat-error", inputs: ["id"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1626
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DynamicFilterComponent, decorators: [{
|
|
1627
|
+
type: Component,
|
|
1628
|
+
args: [{ selector: 'cqa-dynamic-filter', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div id=\"cqa-ui-root\">\n <div class=\"cqa-filter cqa-mb-[28px]\" *ngIf=\"showFilterPanel\">\n <form class=\"ts-form cqa-grid lg:cqa-grid-cols-4 md:cqa-grid-cols-2 cqa-gap-4\" [formGroup]=\"form\"\n (keydown.enter)=\"(false)\" novalidate=\"novalidate\">\n <ng-container *ngFor=\"let c of config\">\n <ng-container *ngIf=\"!c.hidden\">\n <div class=\"form-group cqa-flex cqa-flex-col cqa-gap-2\">\n <!-- Select -->\n <ng-container *ngIf=\"c.type === 'select'\">\n <cqa-dynamic-select [form]=\"form\" [config]=\"getSelectConfig(c)\"></cqa-dynamic-select>\n </ng-container>\n\n <!-- Date Range --> \n <ng-container *ngIf=\"c.type === 'date-range'\">\n <label\n class=\"form-label cqa-text-[#374151] cqa-text-[14px] cqa-font-medium cqa-block cqa-leading-[1.4]\">{{\n c.label }}</label>\n <mat-form-field class=\"mat-date-custom\" appearance=\"fill\">\n <mat-date-range-input [rangePicker]=\"picker\" [formGroup]=\"getDateGroup(c.key)\" [max]=\"maxDate\">\n <input matStartDate formControlName=\"start\" placeholder=\"Start date\" [max]=\"maxDate\" required\n [readonly]=\"true\" (focus)=\"picker.open()\" (click)=\"picker.open()\" />\n <input matEndDate formControlName=\"end\" placeholder=\"End date\" [max]=\"maxDate\" required\n [readonly]=\"true\" (focus)=\"picker.open()\" (click)=\"picker.open()\" />\n </mat-date-range-input>\n <mat-date-range-picker #picker (dateChange)=\"onDateChange($event, c.key)\"\n [panelClass]=\"'ctc-date-range-panel'\">\n <mat-datepicker-actions>\n <div class=\"ctc-date-presets\">\n <div class=\"cqa-mb-2 cqa-font-medium\">Quick Presets</div>\n <div class=\"btn-group\">\n <button type=\"button\" class=\"preset-btn today\"\n (click)=\"applyPresetToGroup(c.key, 'today'); picker.close()\">Today</button>\n <button type=\"button\" class=\"preset-btn last7days\"\n (click)=\"applyPresetToGroup(c.key, 'last7days'); picker.close()\">Last 7 days</button>\n <button type=\"button\" class=\"preset-btn last30days\"\n (click)=\"applyPresetToGroup(c.key, 'last30days'); picker.close()\">Last 30 days</button>\n <button type=\"button\" class=\"preset-btn last90days\"\n (click)=\"applyPresetToGroup(c.key, 'last90days'); picker.close()\">Last 90 days</button>\n <button type=\"button\" class=\"preset-btn thismonth\"\n (click)=\"applyPresetToGroup(c.key, 'thismonth'); picker.close()\">This month</button>\n <button type=\"button\" class=\"preset-btn lastmonth\"\n (click)=\"applyPresetToGroup(c.key, 'lastmonth'); picker.close()\">Last month</button>\n </div>\n </div>\n <div class=\"cqa-font-medium cqa-mb-2 cqa-mt-[10px] cqa-w-full\">Custom Range</div>\n <button\n class=\"cqa-font-medium !cqa-mb-2 !cqa-mt-[10px] cqa-w-[calc(100%-32px)] !cqa-absolute cqa-bottom-[2px]\"\n mat-flat-button color=\"primary\" matDatepickerApply>Apply</button>\n </mat-datepicker-actions>\n </mat-date-range-picker>\n <div (click)=\"picker.open()\" class=\"cqa-cursor-pointer\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M5.33398 1.33203V3.9987\" stroke=\"#0A0A0A\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M10.666 1.33203V3.9987\" stroke=\"#0A0A0A\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path\n d=\"M12.6667 2.66797H3.33333C2.59695 2.66797 2 3.26492 2 4.0013V13.3346C2 14.071 2.59695 14.668 3.33333 14.668H12.6667C13.403 14.668 14 14.071 14 13.3346V4.0013C14 3.26492 13.403 2.66797 12.6667 2.66797Z\"\n stroke=\"#0A0A0A\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M2 6.66797H14\" stroke=\"#0A0A0A\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </div>\n </mat-form-field>\n <!-- Specific validation messages -->\n <mat-error *ngIf=\"getDateValidationError(c.key) && !picker.opened\">\n {{ getDateValidationError(c.key) }}\n </mat-error>\n\n </ng-container>\n </div>\n </ng-container>\n </ng-container>\n </form>\n\n <div class=\"cqa-flex cqa-justify-end cqa-items-stretch cqa-gap-2 cqa-mt-4\">\n <button type=\"button\"\n class=\"cqa-text-[13.33px] cqa-leading-[1] cqa-flex cqa-flex-row cqa-justify-center cqa-items-center cqa-px-[11px] cqa-py-[1px] cqa-gap-[14px] cqa-h-8 cqa-border cqa-border-[#0B0B0C] cqa-shadow-[0_1px_2px_rgba(0,0,0,0.05)] cqa-rounded-lg cqa-text-[#0B0B0C]\"\n (click)=\"reset()\">Reset</button>\n <button type=\"button\"\n class=\"cqa-text-[13.33px] cqa-leading-[1] cqa-flex cqa-flex-row cqa-justify-center cqa-items-center cqa-px-[11px] cqa-py-[1px] cqa-gap-[14px] cqa-h-8 cqa-bg-[#0B0B0C] cqa-border cqa-border-[#E5E5E5] cqa-shadow-[0_1px_2px_rgba(0,0,0,0.05)] cqa-rounded-lg cqa-text-white\"\n (click)=\"apply()\">Apply Filter</button>\n </div>\n </div>\n</div>", styles: [] }]
|
|
1629
|
+
}], ctorParameters: function () { return [{ type: i1$1.FormBuilder }]; }, propDecorators: { config: [{
|
|
1630
|
+
type: Input
|
|
1631
|
+
}], model: [{
|
|
1632
|
+
type: Input
|
|
1633
|
+
}], showFilterPanel: [{
|
|
1634
|
+
type: Input
|
|
1635
|
+
}], filtersApplied: [{
|
|
1636
|
+
type: Output
|
|
1637
|
+
}], filtersChanged: [{
|
|
1638
|
+
type: Output
|
|
1639
|
+
}], resetAction: [{
|
|
1640
|
+
type: Output
|
|
1641
|
+
}] } });
|
|
1642
|
+
|
|
1643
|
+
class ColumnVisibilityComponent {
|
|
1644
|
+
constructor() {
|
|
1645
|
+
this.isStepGroup = false;
|
|
1646
|
+
// Dynamic columns (preferred). Each item defines the id used as key and the label to render.
|
|
1647
|
+
this.columns = [];
|
|
1648
|
+
// Start with an empty visibility map; keys will be added from 'columns'
|
|
1649
|
+
this.columnVisibility = {};
|
|
1650
|
+
this.selectedAutoRefreshInterval = 0; // 0 = Off
|
|
1651
|
+
this.columnVisibilityChange = new EventEmitter();
|
|
1652
|
+
this.autoRefreshChange = new EventEmitter();
|
|
1653
|
+
}
|
|
1654
|
+
ngOnChanges(changes) {
|
|
1655
|
+
// When dynamic columns change, ensure we have keys in the visibility map
|
|
1656
|
+
if (changes['columns'] && Array.isArray(this.columns) && this.columns.length) {
|
|
1657
|
+
for (const col of this.columns) {
|
|
1658
|
+
if (this.columnVisibility[col.id] === undefined) {
|
|
1659
|
+
this.columnVisibility[col.id] = true;
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
get areAllColumnsSelected() {
|
|
1665
|
+
const keys = this.getTogglableKeys();
|
|
1666
|
+
return keys.every(k => !!this.columnVisibility[k]);
|
|
1667
|
+
}
|
|
1668
|
+
toggleAllColumns(checked) {
|
|
1669
|
+
const keys = this.getTogglableKeys();
|
|
1670
|
+
for (const k of keys) {
|
|
1671
|
+
this.columnVisibility[k] = checked;
|
|
1672
|
+
}
|
|
1673
|
+
this.saveColumnPreferences();
|
|
1674
|
+
}
|
|
1675
|
+
saveColumnPreferences() {
|
|
1676
|
+
this.columnVisibilityChange.emit({ ...this.columnVisibility });
|
|
1677
|
+
}
|
|
1678
|
+
onAutoRefreshChange() {
|
|
1679
|
+
this.autoRefreshChange.emit(this.selectedAutoRefreshInterval);
|
|
1680
|
+
}
|
|
1681
|
+
getTogglableKeys() {
|
|
1682
|
+
return Array.isArray(this.columns) ? this.columns.map(c => c.id) : [];
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
ColumnVisibilityComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: ColumnVisibilityComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1686
|
+
ColumnVisibilityComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: ColumnVisibilityComponent, selector: "cqa-column-visibility", inputs: { isStepGroup: "isStepGroup", columns: "columns", columnVisibility: "columnVisibility", selectedAutoRefreshInterval: "selectedAutoRefreshInterval" }, outputs: { columnVisibilityChange: "columnVisibilityChange", autoRefreshChange: "autoRefreshChange" }, usesOnChanges: true, ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <cqa-button variant=\"grey-solid\" icon=\"settings\" [matMenuTriggerFor]=\"settingsMenu\" aria-label=\"Settings\">\n </cqa-button>\n\n <mat-menu #settingsMenu=\"matMenu\" class=\"table-settings-menu\">\n <div class=\"settings-menu-content cqa-p-[17px]\" (click)=\"$event.stopPropagation()\">\n <div class=\"settings-section cqa-mb-3\">\n <h4 class=\"settings-title cqa-font-bold cqa-text-[14px] cqa-leading-[20px] cqa-mb-2\">Show Columns</h4>\n <div class=\"settings-options cqa-flex cqa-flex-col cqa-gap-2 cqa-text-[14px] cqa-leading-[20px]\">\n <mat-checkbox [checked]=\"areAllColumnsSelected\" (change)=\"toggleAllColumns($event.checked)\"\n class=\"select-all-checkbox\">\n {{ areAllColumnsSelected ? 'Unselect All' : 'Select All' }}\n </mat-checkbox>\n <!-- Dynamic column list -->\n <ng-container *ngIf=\"columns?.length\">\n <mat-checkbox *ngFor=\"let col of columns\" [(ngModel)]=\"columnVisibility[col.id]\"\n (change)=\"saveColumnPreferences()\">\n {{ col.label }}\n </mat-checkbox>\n </ng-container>\n </div>\n </div>\n\n <div class=\"settings-section\">\n <h4 class=\"settings-title cqa-font-bold cqa-text-[14px] cqa-leading-[20px] cqa-mb-2\">Auto refresh every</h4>\n <div class=\"refresh-options\">\n <mat-radio-group [(ngModel)]=\"selectedAutoRefreshInterval\" (change)=\"onAutoRefreshChange()\"\n class=\"cqa-flex cqa-flex-col cqa-gap-2 cqa-text-[14px] cqa-leading-[20px]\">\n <label><mat-radio-button [value]=\"10000\">10 Seconds</mat-radio-button></label>\n <label><mat-radio-button [value]=\"20000\">20 Seconds</mat-radio-button></label>\n <label><mat-radio-button [value]=\"30000\">30 Seconds</mat-radio-button></label>\n <label><mat-radio-button [value]=\"0\">Off</mat-radio-button></label>\n </mat-radio-group>\n </div>\n </div>\n </div>\n </mat-menu>", components: [{ type: ButtonComponent, selector: "cqa-button", inputs: ["variant", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass"], outputs: ["clicked"] }, { type: i3$1.MatMenu, selector: "mat-menu", exportAs: ["matMenu"] }, { type: i3$4.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex", "aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { type: i4$1.MatRadioButton, selector: "mat-radio-button", inputs: ["disableRipple", "tabIndex"], exportAs: ["matRadioButton"] }], directives: [{ type: i3$1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", exportAs: ["matMenuTrigger"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i4$1.MatRadioGroup, selector: "mat-radio-group", exportAs: ["matRadioGroup"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1687
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: ColumnVisibilityComponent, decorators: [{
|
|
1688
|
+
type: Component,
|
|
1689
|
+
args: [{ selector: 'cqa-column-visibility', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div id=\"cqa-ui-root\">\n <cqa-button variant=\"grey-solid\" icon=\"settings\" [matMenuTriggerFor]=\"settingsMenu\" aria-label=\"Settings\">\n </cqa-button>\n\n <mat-menu #settingsMenu=\"matMenu\" class=\"table-settings-menu\">\n <div class=\"settings-menu-content cqa-p-[17px]\" (click)=\"$event.stopPropagation()\">\n <div class=\"settings-section cqa-mb-3\">\n <h4 class=\"settings-title cqa-font-bold cqa-text-[14px] cqa-leading-[20px] cqa-mb-2\">Show Columns</h4>\n <div class=\"settings-options cqa-flex cqa-flex-col cqa-gap-2 cqa-text-[14px] cqa-leading-[20px]\">\n <mat-checkbox [checked]=\"areAllColumnsSelected\" (change)=\"toggleAllColumns($event.checked)\"\n class=\"select-all-checkbox\">\n {{ areAllColumnsSelected ? 'Unselect All' : 'Select All' }}\n </mat-checkbox>\n <!-- Dynamic column list -->\n <ng-container *ngIf=\"columns?.length\">\n <mat-checkbox *ngFor=\"let col of columns\" [(ngModel)]=\"columnVisibility[col.id]\"\n (change)=\"saveColumnPreferences()\">\n {{ col.label }}\n </mat-checkbox>\n </ng-container>\n </div>\n </div>\n\n <div class=\"settings-section\">\n <h4 class=\"settings-title cqa-font-bold cqa-text-[14px] cqa-leading-[20px] cqa-mb-2\">Auto refresh every</h4>\n <div class=\"refresh-options\">\n <mat-radio-group [(ngModel)]=\"selectedAutoRefreshInterval\" (change)=\"onAutoRefreshChange()\"\n class=\"cqa-flex cqa-flex-col cqa-gap-2 cqa-text-[14px] cqa-leading-[20px]\">\n <label><mat-radio-button [value]=\"10000\">10 Seconds</mat-radio-button></label>\n <label><mat-radio-button [value]=\"20000\">20 Seconds</mat-radio-button></label>\n <label><mat-radio-button [value]=\"30000\">30 Seconds</mat-radio-button></label>\n <label><mat-radio-button [value]=\"0\">Off</mat-radio-button></label>\n </mat-radio-group>\n </div>\n </div>\n </div>\n </mat-menu>", styles: [] }]
|
|
1690
|
+
}], propDecorators: { isStepGroup: [{
|
|
1691
|
+
type: Input
|
|
1692
|
+
}], columns: [{
|
|
1693
|
+
type: Input
|
|
1694
|
+
}], columnVisibility: [{
|
|
1695
|
+
type: Input
|
|
1696
|
+
}], selectedAutoRefreshInterval: [{
|
|
1697
|
+
type: Input
|
|
1698
|
+
}], columnVisibilityChange: [{
|
|
1699
|
+
type: Output
|
|
1700
|
+
}], autoRefreshChange: [{
|
|
1701
|
+
type: Output
|
|
1702
|
+
}] } });
|
|
1703
|
+
|
|
1704
|
+
class TableActionToolbarComponent {
|
|
1705
|
+
constructor() {
|
|
1706
|
+
this.selectedItems = [];
|
|
1707
|
+
this.actions = [];
|
|
1708
|
+
this.actionClick = new EventEmitter();
|
|
1709
|
+
}
|
|
1710
|
+
get hasSelection() {
|
|
1711
|
+
return (this.selectedItems?.length || 0) > 0;
|
|
1712
|
+
}
|
|
1713
|
+
get isSingleSelection() {
|
|
1714
|
+
return this.selectedItems?.length === 1;
|
|
1715
|
+
}
|
|
1716
|
+
get selectionLabel() {
|
|
1717
|
+
const n = this.selectedItems?.length || 0;
|
|
1718
|
+
return n === 1 ? '1 selected' : `${n} selected`;
|
|
1719
|
+
}
|
|
1720
|
+
visibleActions() {
|
|
1721
|
+
const ctx = { selected: this.selectedItems || [] };
|
|
1722
|
+
return (this.actions || []).filter(a => (a.show ? a.show(ctx) : true));
|
|
1723
|
+
}
|
|
1724
|
+
isDisabled(action) {
|
|
1725
|
+
const ctx = { selected: this.selectedItems || [] };
|
|
1726
|
+
return action.disabled ? !!action.disabled(ctx) : false;
|
|
1727
|
+
}
|
|
1728
|
+
onAction(action) {
|
|
1729
|
+
if (this.isDisabled(action)) {
|
|
1730
|
+
return;
|
|
1731
|
+
}
|
|
1732
|
+
const context = { id: action.id, selected: this.selectedItems || [] };
|
|
1733
|
+
if (action.onClick) {
|
|
1734
|
+
action.onClick(context);
|
|
1735
|
+
}
|
|
1736
|
+
this.actionClick.emit(context);
|
|
1737
|
+
}
|
|
1738
|
+
}
|
|
1739
|
+
TableActionToolbarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TableActionToolbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1740
|
+
TableActionToolbarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TableActionToolbarComponent, selector: "cqa-table-action-toolbar", inputs: { selectedItems: "selectedItems", actions: "actions" }, outputs: { actionClick: "actionClick" }, ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <div\n class=\"action-toolbar cqa-flex cqa-items-center cqa-justify-between cqa-gap-2 cqa-flex-wrap cqa-py-[15.5px] sm:cqa-px-[34px] cqa-px-[20px] cqa-bg-primary cqa-text-white cqa-rounded-[7px]\"\n *ngIf=\"hasSelection\">\n <div class=\"action-toolbar-left cqa-text-[14px] cqa-leading-[21px] cqa-font-medium\">\n {{ selectionLabel }}\n </div>\n <div class=\"action-toolbar-right cqa-flex cqa-items-center cqa-gap-[7px]\">\n <ng-container *ngFor=\"let action of visibleActions()\">\n <div [attr.aria-disabled]=\"isDisabled(action)\" [class.cqa-opacity-50]=\"isDisabled(action)\" [class.cqa-cursor-not-allowed]=\"isDisabled(action)\" (click)=\"!isDisabled(action) && onAction(action)\"\n class=\"cqa-flex cqa-items-center cqa-gap-[8.75px] cqa-py-[5px] cqa-px-[8.75px] cqa-cursor-pointer cqa-text-[12.3px] cqa-leading-[17.5px] cqa-font-medium\">\n <mat-icon class=\"!cqa-w-[16px] !cqa-h-[16px] !cqa-text-[16px]\">{{ action.icon }}</mat-icon>\n <span class=\"md:cqa-flex cqa-hidden\">{{ action.label }}</span>\n </div>\n </ng-container>\n </div>\n <!-- Forwards clicks inside toolbar without affecting outer selections -->\n </div>\n</div>", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1741
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TableActionToolbarComponent, decorators: [{
|
|
1742
|
+
type: Component,
|
|
1743
|
+
args: [{ selector: 'cqa-table-action-toolbar', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div id=\"cqa-ui-root\">\n <div\n class=\"action-toolbar cqa-flex cqa-items-center cqa-justify-between cqa-gap-2 cqa-flex-wrap cqa-py-[15.5px] sm:cqa-px-[34px] cqa-px-[20px] cqa-bg-primary cqa-text-white cqa-rounded-[7px]\"\n *ngIf=\"hasSelection\">\n <div class=\"action-toolbar-left cqa-text-[14px] cqa-leading-[21px] cqa-font-medium\">\n {{ selectionLabel }}\n </div>\n <div class=\"action-toolbar-right cqa-flex cqa-items-center cqa-gap-[7px]\">\n <ng-container *ngFor=\"let action of visibleActions()\">\n <div [attr.aria-disabled]=\"isDisabled(action)\" [class.cqa-opacity-50]=\"isDisabled(action)\" [class.cqa-cursor-not-allowed]=\"isDisabled(action)\" (click)=\"!isDisabled(action) && onAction(action)\"\n class=\"cqa-flex cqa-items-center cqa-gap-[8.75px] cqa-py-[5px] cqa-px-[8.75px] cqa-cursor-pointer cqa-text-[12.3px] cqa-leading-[17.5px] cqa-font-medium\">\n <mat-icon class=\"!cqa-w-[16px] !cqa-h-[16px] !cqa-text-[16px]\">{{ action.icon }}</mat-icon>\n <span class=\"md:cqa-flex cqa-hidden\">{{ action.label }}</span>\n </div>\n </ng-container>\n </div>\n <!-- Forwards clicks inside toolbar without affecting outer selections -->\n </div>\n</div>", styles: [] }]
|
|
1744
|
+
}], propDecorators: { selectedItems: [{
|
|
1745
|
+
type: Input
|
|
1746
|
+
}], actions: [{
|
|
1747
|
+
type: Input
|
|
1748
|
+
}], actionClick: [{
|
|
1749
|
+
type: Output
|
|
1750
|
+
}] } });
|
|
1751
|
+
|
|
1752
|
+
class MetricsBlockComponent {
|
|
1753
|
+
constructor() {
|
|
1754
|
+
this.progress = '0%';
|
|
1755
|
+
this.layout = '1';
|
|
1756
|
+
this.itemslength = '0';
|
|
1757
|
+
}
|
|
1758
|
+
formatPercent(value) {
|
|
1759
|
+
if (value === undefined || value === null || Number.isNaN(value))
|
|
1760
|
+
return '';
|
|
1761
|
+
const sign = value > 0 ? '+' : value < 0 ? '' : '';
|
|
1762
|
+
return `${sign}${value}%`;
|
|
1763
|
+
}
|
|
1764
|
+
percentClass(value) {
|
|
1765
|
+
if (value === undefined || value === null || Number.isNaN(value))
|
|
1766
|
+
return 'cqa-text-[#6B7280]';
|
|
1767
|
+
if (value > 0)
|
|
1768
|
+
return 'cqa-text-[#10B981]';
|
|
1769
|
+
if (value < 0)
|
|
1770
|
+
return 'cqa-text-[#EF4444]';
|
|
1771
|
+
return 'cqa-text-[#6B7280]';
|
|
1772
|
+
}
|
|
1773
|
+
}
|
|
1774
|
+
MetricsBlockComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: MetricsBlockComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1775
|
+
MetricsBlockComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: MetricsBlockComponent, selector: "cqa-metrics-block", inputs: { item: "item", progress: "progress", layout: "layout", itemslength: "itemslength" }, ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <div\n [ngClass]=\"[layout === '1'\n ? 'cqa-flex cqa-justify-center cqa-items-center cqa-py-3 md:cqa-pt-1 md:cqa-pb-0.5 cqa-px-5 cqa-gap-3 cqa-w-full md:cqa-h-[62px] cqa-border-b-0 cqa-border-[#E5E7EB]'\n : 'cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-py-3 md:cqa-py-1 lg:cqa-px-5 cqa-px-2 cqa-w-full md:cqa-h-[53px]', itemslength == item.id ? 'cqa-border-l md:cqa-border-l-0 md:cqa-border-l' : '' , item.id == '1' && layout === '1' ? 'cqa-border-l md:cqa-border-r' : '']\">\n <ng-container *ngIf=\"layout === '1'; else layout2\">\n <!-- [ngClass]=\"{ 'border-l md:border-l-0': itemslength == item.id }\" -->\n <div class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-10 cqa-h-10 cqa-min-w-[40px] cqa-rounded-[10px]\"\n [ngClass]=\"item.accentBgClass || 'cqa-bg-[#EEF2FF]'\">\n <mat-icon class=\"!cqa-w-5 !cqa-h-5 !cqa-text-[20px]\" [ngClass]=\"item.iconColorClass || 'cqa-text-[#3F43EE]'\"\n *ngIf=\"item.icon\">{{ item.icon }}</mat-icon>\n </div>\n <div class=\"cqa-flex cqa-flex-col cqa-items-start cqa-gap-0.5 cqa-w-full cqa-h-auto cqa-flex-1 cqa-truncate\">\n <div class=\"cqa-w-full cqa-h-4 cqa-text-[12px] cqa-leading-4 cqa-font-medium cqa-text-[#6A7282]\">{{ item.label\n }}</div>\n <div class=\"cqa-w-full cqa-h-7 cqa-gap-2 cqa-flex\"\n [ngClass]=\"item.subtext ? 'cqa-justify-between cqa-items-center' : 'cqa-justify-start cqa-items-center'\">\n <div\n class=\"cqa-text-[20px] cqa-leading-[28px] cqa-font-semibold cqa-tracking-[-0.449219px] cqa-text-[#101828]\">\n {{ item.value | number }}</div>\n <div *ngIf=\"item.subtext\"\n class=\"cqa-text-[12px] cqa-leading-4 cqa-text-[#6A7282] cqa-truncate cqa-hidden sm:cqa-block\">{{\n item.subtext }}</div>\n </div>\n <div class=\"cqa-w-full cqa-h-1 cqa-rounded-full cqa-bg-[#F3F4F6] cqa-overflow-hidden\">\n <div class=\"cqa-h-full cqa-rounded-full\" [ngClass]=\"item.colorClass || 'cqa-bg-[#3F43EE]'\"\n [style.width]=\"progress\"></div>\n </div>\n </div>\n </ng-container>\n <ng-template #layout2>\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\">\n <mat-icon class=\"!cqa-w-5 !cqa-h-5 !cqa-text-[16px]\" [ngClass]=\"item.iconColorClass || 'cqa-text-[#3F43EE]'\"\n *ngIf=\"item.icon\">{{ item.icon }}</mat-icon>\n <span class=\"cqa-text-[12px] cqa-leading-4 cqa-text-[#6B7280]\">{{ item.label }}</span>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-1.5 cqa-w-full cqa-justify-between\">\n <h6 class=\"cqa-text-[16px] cqa-leading-7 cqa-tracking-[-0.45px] cqa-text-[#111827]\">{{ item.value | number }}\n </h6>\n <span *ngIf=\"item.percent !== undefined\" class=\"cqa-text-[10px] cqa-leading-4\"\n [ngClass]=\"percentClass(item.percent)\">{{ formatPercent(item.percent) }}</span>\n </div>\n </ng-template>\n </div>\n</div>", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], pipes: { "number": i2.DecimalPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1776
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: MetricsBlockComponent, decorators: [{
|
|
1777
|
+
type: Component,
|
|
1778
|
+
args: [{ selector: 'cqa-metrics-block', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div id=\"cqa-ui-root\">\n <div\n [ngClass]=\"[layout === '1'\n ? 'cqa-flex cqa-justify-center cqa-items-center cqa-py-3 md:cqa-pt-1 md:cqa-pb-0.5 cqa-px-5 cqa-gap-3 cqa-w-full md:cqa-h-[62px] cqa-border-b-0 cqa-border-[#E5E7EB]'\n : 'cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-py-3 md:cqa-py-1 lg:cqa-px-5 cqa-px-2 cqa-w-full md:cqa-h-[53px]', itemslength == item.id ? 'cqa-border-l md:cqa-border-l-0 md:cqa-border-l' : '' , item.id == '1' && layout === '1' ? 'cqa-border-l md:cqa-border-r' : '']\">\n <ng-container *ngIf=\"layout === '1'; else layout2\">\n <!-- [ngClass]=\"{ 'border-l md:border-l-0': itemslength == item.id }\" -->\n <div class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-10 cqa-h-10 cqa-min-w-[40px] cqa-rounded-[10px]\"\n [ngClass]=\"item.accentBgClass || 'cqa-bg-[#EEF2FF]'\">\n <mat-icon class=\"!cqa-w-5 !cqa-h-5 !cqa-text-[20px]\" [ngClass]=\"item.iconColorClass || 'cqa-text-[#3F43EE]'\"\n *ngIf=\"item.icon\">{{ item.icon }}</mat-icon>\n </div>\n <div class=\"cqa-flex cqa-flex-col cqa-items-start cqa-gap-0.5 cqa-w-full cqa-h-auto cqa-flex-1 cqa-truncate\">\n <div class=\"cqa-w-full cqa-h-4 cqa-text-[12px] cqa-leading-4 cqa-font-medium cqa-text-[#6A7282]\">{{ item.label\n }}</div>\n <div class=\"cqa-w-full cqa-h-7 cqa-gap-2 cqa-flex\"\n [ngClass]=\"item.subtext ? 'cqa-justify-between cqa-items-center' : 'cqa-justify-start cqa-items-center'\">\n <div\n class=\"cqa-text-[20px] cqa-leading-[28px] cqa-font-semibold cqa-tracking-[-0.449219px] cqa-text-[#101828]\">\n {{ item.value | number }}</div>\n <div *ngIf=\"item.subtext\"\n class=\"cqa-text-[12px] cqa-leading-4 cqa-text-[#6A7282] cqa-truncate cqa-hidden sm:cqa-block\">{{\n item.subtext }}</div>\n </div>\n <div class=\"cqa-w-full cqa-h-1 cqa-rounded-full cqa-bg-[#F3F4F6] cqa-overflow-hidden\">\n <div class=\"cqa-h-full cqa-rounded-full\" [ngClass]=\"item.colorClass || 'cqa-bg-[#3F43EE]'\"\n [style.width]=\"progress\"></div>\n </div>\n </div>\n </ng-container>\n <ng-template #layout2>\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\">\n <mat-icon class=\"!cqa-w-5 !cqa-h-5 !cqa-text-[16px]\" [ngClass]=\"item.iconColorClass || 'cqa-text-[#3F43EE]'\"\n *ngIf=\"item.icon\">{{ item.icon }}</mat-icon>\n <span class=\"cqa-text-[12px] cqa-leading-4 cqa-text-[#6B7280]\">{{ item.label }}</span>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-1.5 cqa-w-full cqa-justify-between\">\n <h6 class=\"cqa-text-[16px] cqa-leading-7 cqa-tracking-[-0.45px] cqa-text-[#111827]\">{{ item.value | number }}\n </h6>\n <span *ngIf=\"item.percent !== undefined\" class=\"cqa-text-[10px] cqa-leading-4\"\n [ngClass]=\"percentClass(item.percent)\">{{ formatPercent(item.percent) }}</span>\n </div>\n </ng-template>\n </div>\n</div>", styles: [] }]
|
|
1779
|
+
}], propDecorators: { item: [{
|
|
1780
|
+
type: Input
|
|
1781
|
+
}], progress: [{
|
|
1782
|
+
type: Input
|
|
1783
|
+
}], layout: [{
|
|
1784
|
+
type: Input
|
|
1785
|
+
}], itemslength: [{
|
|
1786
|
+
type: Input
|
|
1787
|
+
}] } });
|
|
1788
|
+
|
|
1789
|
+
class MetricsCardComponent {
|
|
1790
|
+
constructor() {
|
|
1791
|
+
this.icon = 'text_snippet';
|
|
1792
|
+
this.title = 'Total Test Cases';
|
|
1793
|
+
this.total = 0;
|
|
1794
|
+
this.items = [];
|
|
1795
|
+
this.cardClass = '';
|
|
1796
|
+
this.layout = '1';
|
|
1797
|
+
}
|
|
1798
|
+
progressWidth(item) {
|
|
1799
|
+
const max = item.max ?? this.inferMax();
|
|
1800
|
+
if (!max || max <= 0)
|
|
1801
|
+
return '0%';
|
|
1802
|
+
const pct = Math.max(0, Math.min(100, (item.value / max) * 100));
|
|
1803
|
+
return pct.toFixed(1) + '%';
|
|
1804
|
+
}
|
|
1805
|
+
inferMax() {
|
|
1806
|
+
const maxFromItems = this.items.reduce((m, it) => Math.max(m, it.value), 0);
|
|
1807
|
+
return maxFromItems || 1;
|
|
1808
|
+
}
|
|
1809
|
+
formatPercent(value) {
|
|
1810
|
+
if (value === undefined || value === null || Number.isNaN(value))
|
|
1811
|
+
return '';
|
|
1812
|
+
const sign = value > 0 ? '+' : value < 0 ? '' : '';
|
|
1813
|
+
return `${sign}${value}%`;
|
|
1814
|
+
}
|
|
1815
|
+
percentClass(value) {
|
|
1816
|
+
if (value === undefined || value === null || Number.isNaN(value))
|
|
1817
|
+
return 'cqa-text-[#6B7280]';
|
|
1818
|
+
if (value > 0)
|
|
1819
|
+
return 'cqa-text-[#10B981]'; // green
|
|
1820
|
+
if (value < 0)
|
|
1821
|
+
return 'cqa-text-[#EF4444]'; // red
|
|
1822
|
+
return 'cqa-text-[#6B7280]'; // neutral
|
|
1823
|
+
}
|
|
1824
|
+
}
|
|
1825
|
+
MetricsCardComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: MetricsCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1826
|
+
MetricsCardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: MetricsCardComponent, selector: "cqa-metrics-card", inputs: { icon: "icon", title: "title", total: "total", items: "items", cardClass: "cardClass", layout: "layout", totalPercent: "totalPercent" }, ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <div *ngIf=\"layout === '1'\"\n class=\"cqa-w-full cqa-box-border cqa-flex cqa-flex-col cqa-items-start cqa-px-px cqa-pb-px md:cqa-h-[63px] cqa-bg-white cqa-border-t-2 cqa-border-r cqa-border-b-0 cqa-border-l cqa-border-solid cqa-border-[#3F43EE] cqa-rounded-[10px] cqa-flex-none cqa-order-0 cqa-self-stretch cqa-grow-0\"\n [ngClass]=\"cardClass\">\n <!-- Metric blocks -->\n <div\n class=\"cqa-flex-1 cqa-w-full cqa-grid cqa-grid-cols-2 md:cqa-gap-0 cqa-gap-y-2 cqa-py-1 md:cqa-p-0 sm:cqa-grid-cols-2 md:cqa-grid-cols-4 sm:cqa-border-r cqa-border-[#E5E7EB]\">\n <!-- Left total block -->\n <div\n class=\"cqa-flex cqa-flex-col cqa-justify-center cqa-items-start cqa-py-3 md:cqa-pt-1 md:cqa-pb-0.5 cqa-px-6 cqa-gap-1 cqa-w-full sm:cqa-w-[100%] md:cqa-w-[180px] lg:cqa-w-[290px] md:cqa-h-[61px] cqa-border-b-1 sm:cqa-border-b-0 md:cqa-border-b-0 cqa-border-[#E5E7EB]\">\n <span class=\"cqa-text-[12px] cqa-leading-[16px] cqa-font-medium cqa-text-[#6A7282]\"> {{ title }} </span>\n <h3 class=\"cqa-text-[30px] cqa-leading-[36px] cqa-font-bold cqa-tracking-[0.395508px] cqa-text-[#101828]\"> {{\n total | number }} </h3>\n </div>\n <cqa-metrics-block *ngFor=\"let it of items;\" [item]=\"it\" [itemslength]=\"items.length.toString()\"\n [progress]=\"progressWidth(it)\">\n </cqa-metrics-block>\n </div>\n </div>\n\n <div *ngIf=\"layout === '2'\"\n class=\"cqa-w-full cqa-box-border cqa-flex cqa-flex-col cqa-items-start cqa-px-px cqa-pb-px md:cqa-h-[63px] cqa-bg-white cqa-flex-none cqa-order-0 cqa-self-stretch cqa-grow-0\"\n [ngClass]=\"cardClass\">\n <div\n class=\"cqa-flex cqa-flex-col md:cqa-flex-row cqa-flex-wrap cqa-items-stretch cqa-w-full cqa-min-h-[53px] cqa-rounded-none cqa-flex-none cqa-order-0 cqa-self-stretch cqa-grow-0 cqa-gap-4\">\n <!-- Left total block -->\n <div\n class=\"cqa-flex cqa-flex-col cqa-justify-center cqa-items-start cqa-py-3 md:cqa-py-1 cqa-px-4 sm:cqa-px-6 cqa-gap-1 cqa-w-full sm:cqa-w-[100%] md:cqa-w-[240px] lg:cqa-w-[290px] md:cqa-h-[61px] cqa-rounded-[10px] cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-relative cqa-overflow-hidden before:cqa-content-[''] before:cqa-bg-[#4C4C51] before:cqa-h-[2px] before:cqa-w-full before:cqa-absolute before:cqa-top-0 before:cqa-left-0\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-justify-between cqa-w-full\">\n <mat-icon class=\"!cqa-w-4 !cqa-h-4 !cqa-text-[16px] cqa-text-[#6B7280]\">{{ icon }}</mat-icon>\n <span class=\"cqa-text-[#6B7280] cqa-text-[14px] cqa-leading-4\">{{ title }}</span>\n <div class=\"cqa-flex cqa-items-end cqa-gap-2 cqa-ml-auto\">\n <h4 class=\"cqa-text-[28px] cqa-leading-7 cqa-tracking-[-0.45px] cqa-text-[#111827]\">{{ total | number }}\n </h4>\n <span *ngIf=\"totalPercent !== undefined\" class=\"cqa-text-[10px] cqa-leading-4\"\n [ngClass]=\"percentClass(totalPercent)\">{{ formatPercent(totalPercent) }}</span>\n </div>\n </div>\n\n </div>\n <!-- Metric blocks -->\n <div\n class=\"cqa-flex-1 cqa-w-full cqa-grid cqa-grid-cols-2 md:cqa-grid-cols-3 cqa-items-center cqa-rounded-[10px] cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-relative cqa-overflow-hidden\">\n <span class=\"cqa-h-[2px] cqa-w-full cqa-absolute cqa-top-0 cqa-left-0\"\n [style.background]=\"'linear-gradient(90deg, #3B82F6 0%, rgba(0, 0, 0, 0) 100%)'\"></span>\n <cqa-metrics-block *ngFor=\"let it of items; let i = index\" [item]=\"it\" [layout]=\"layout\">\n </cqa-metrics-block>\n </div>\n </div>\n </div>\n</div>", components: [{ type: MetricsBlockComponent, selector: "cqa-metrics-block", inputs: ["item", "progress", "layout", "itemslength"] }, { type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], pipes: { "number": i2.DecimalPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1827
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: MetricsCardComponent, decorators: [{
|
|
1828
|
+
type: Component,
|
|
1829
|
+
args: [{ selector: 'cqa-metrics-card', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div id=\"cqa-ui-root\">\n <div *ngIf=\"layout === '1'\"\n class=\"cqa-w-full cqa-box-border cqa-flex cqa-flex-col cqa-items-start cqa-px-px cqa-pb-px md:cqa-h-[63px] cqa-bg-white cqa-border-t-2 cqa-border-r cqa-border-b-0 cqa-border-l cqa-border-solid cqa-border-[#3F43EE] cqa-rounded-[10px] cqa-flex-none cqa-order-0 cqa-self-stretch cqa-grow-0\"\n [ngClass]=\"cardClass\">\n <!-- Metric blocks -->\n <div\n class=\"cqa-flex-1 cqa-w-full cqa-grid cqa-grid-cols-2 md:cqa-gap-0 cqa-gap-y-2 cqa-py-1 md:cqa-p-0 sm:cqa-grid-cols-2 md:cqa-grid-cols-4 sm:cqa-border-r cqa-border-[#E5E7EB]\">\n <!-- Left total block -->\n <div\n class=\"cqa-flex cqa-flex-col cqa-justify-center cqa-items-start cqa-py-3 md:cqa-pt-1 md:cqa-pb-0.5 cqa-px-6 cqa-gap-1 cqa-w-full sm:cqa-w-[100%] md:cqa-w-[180px] lg:cqa-w-[290px] md:cqa-h-[61px] cqa-border-b-1 sm:cqa-border-b-0 md:cqa-border-b-0 cqa-border-[#E5E7EB]\">\n <span class=\"cqa-text-[12px] cqa-leading-[16px] cqa-font-medium cqa-text-[#6A7282]\"> {{ title }} </span>\n <h3 class=\"cqa-text-[30px] cqa-leading-[36px] cqa-font-bold cqa-tracking-[0.395508px] cqa-text-[#101828]\"> {{\n total | number }} </h3>\n </div>\n <cqa-metrics-block *ngFor=\"let it of items;\" [item]=\"it\" [itemslength]=\"items.length.toString()\"\n [progress]=\"progressWidth(it)\">\n </cqa-metrics-block>\n </div>\n </div>\n\n <div *ngIf=\"layout === '2'\"\n class=\"cqa-w-full cqa-box-border cqa-flex cqa-flex-col cqa-items-start cqa-px-px cqa-pb-px md:cqa-h-[63px] cqa-bg-white cqa-flex-none cqa-order-0 cqa-self-stretch cqa-grow-0\"\n [ngClass]=\"cardClass\">\n <div\n class=\"cqa-flex cqa-flex-col md:cqa-flex-row cqa-flex-wrap cqa-items-stretch cqa-w-full cqa-min-h-[53px] cqa-rounded-none cqa-flex-none cqa-order-0 cqa-self-stretch cqa-grow-0 cqa-gap-4\">\n <!-- Left total block -->\n <div\n class=\"cqa-flex cqa-flex-col cqa-justify-center cqa-items-start cqa-py-3 md:cqa-py-1 cqa-px-4 sm:cqa-px-6 cqa-gap-1 cqa-w-full sm:cqa-w-[100%] md:cqa-w-[240px] lg:cqa-w-[290px] md:cqa-h-[61px] cqa-rounded-[10px] cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-relative cqa-overflow-hidden before:cqa-content-[''] before:cqa-bg-[#4C4C51] before:cqa-h-[2px] before:cqa-w-full before:cqa-absolute before:cqa-top-0 before:cqa-left-0\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-justify-between cqa-w-full\">\n <mat-icon class=\"!cqa-w-4 !cqa-h-4 !cqa-text-[16px] cqa-text-[#6B7280]\">{{ icon }}</mat-icon>\n <span class=\"cqa-text-[#6B7280] cqa-text-[14px] cqa-leading-4\">{{ title }}</span>\n <div class=\"cqa-flex cqa-items-end cqa-gap-2 cqa-ml-auto\">\n <h4 class=\"cqa-text-[28px] cqa-leading-7 cqa-tracking-[-0.45px] cqa-text-[#111827]\">{{ total | number }}\n </h4>\n <span *ngIf=\"totalPercent !== undefined\" class=\"cqa-text-[10px] cqa-leading-4\"\n [ngClass]=\"percentClass(totalPercent)\">{{ formatPercent(totalPercent) }}</span>\n </div>\n </div>\n\n </div>\n <!-- Metric blocks -->\n <div\n class=\"cqa-flex-1 cqa-w-full cqa-grid cqa-grid-cols-2 md:cqa-grid-cols-3 cqa-items-center cqa-rounded-[10px] cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-relative cqa-overflow-hidden\">\n <span class=\"cqa-h-[2px] cqa-w-full cqa-absolute cqa-top-0 cqa-left-0\"\n [style.background]=\"'linear-gradient(90deg, #3B82F6 0%, rgba(0, 0, 0, 0) 100%)'\"></span>\n <cqa-metrics-block *ngFor=\"let it of items; let i = index\" [item]=\"it\" [layout]=\"layout\">\n </cqa-metrics-block>\n </div>\n </div>\n </div>\n</div>", styles: [] }]
|
|
1830
|
+
}], propDecorators: { icon: [{
|
|
1831
|
+
type: Input
|
|
1832
|
+
}], title: [{
|
|
1833
|
+
type: Input
|
|
1834
|
+
}], total: [{
|
|
1835
|
+
type: Input
|
|
1836
|
+
}], items: [{
|
|
1837
|
+
type: Input
|
|
1838
|
+
}], cardClass: [{
|
|
1839
|
+
type: Input
|
|
1840
|
+
}], layout: [{
|
|
1841
|
+
type: Input
|
|
1842
|
+
}], totalPercent: [{
|
|
1843
|
+
type: Input
|
|
1844
|
+
}] } });
|
|
1845
|
+
|
|
1846
|
+
class ChartCardComponent {
|
|
1847
|
+
constructor() {
|
|
1848
|
+
this.title = 'Chart';
|
|
1849
|
+
this.cardClass = '';
|
|
1850
|
+
}
|
|
1851
|
+
}
|
|
1852
|
+
ChartCardComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: ChartCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1853
|
+
ChartCardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: ChartCardComponent, selector: "cqa-chart-card", inputs: { title: "title", subtitle: "subtitle", cardClass: "cardClass" }, ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <div\n class=\"cqa-w-full cqa-box-border cqa-flex cqa-flex-col cqa-bg-white cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-rounded-[10px]\"\n [ngClass]=\"cardClass\">\n <!-- Header -->\n <div\n class=\"cqa-flex cqa-items-center cqa-justify-between cqa-px-4 sm:cqa-px-6 cqa-py-3 cqa-border-b cqa-border-[#E5E7EB]\">\n <div class=\"cqa-flex cqa-flex-col\">\n <div class=\"cqa-text-[14px] cqa-leading-5 cqa-font-semibold cqa-text-[#101828]\">{{ title }}</div>\n <div *ngIf=\"subtitle\" class=\"cqa-text-[12px] cqa-leading-4 cqa-text-[#6A7282] cqa-mt-0.5\">{{ subtitle }}</div>\n </div>\n <!-- Right-side actions slot -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <ng-content select=\"[chart-actions]\"></ng-content>\n </div>\n </div>\n\n <!-- Chart/content area -->\n <div class=\"cqa-p-3 sm:cqa-p-4\">\n <div class=\"cqa-w-full cqa-min-h-[220px]\">\n <ng-content></ng-content>\n </div>\n </div>\n </div>\n</div>", directives: [{ type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1854
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: ChartCardComponent, decorators: [{
|
|
1855
|
+
type: Component,
|
|
1856
|
+
args: [{ selector: 'cqa-chart-card', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div id=\"cqa-ui-root\">\n <div\n class=\"cqa-w-full cqa-box-border cqa-flex cqa-flex-col cqa-bg-white cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-rounded-[10px]\"\n [ngClass]=\"cardClass\">\n <!-- Header -->\n <div\n class=\"cqa-flex cqa-items-center cqa-justify-between cqa-px-4 sm:cqa-px-6 cqa-py-3 cqa-border-b cqa-border-[#E5E7EB]\">\n <div class=\"cqa-flex cqa-flex-col\">\n <div class=\"cqa-text-[14px] cqa-leading-5 cqa-font-semibold cqa-text-[#101828]\">{{ title }}</div>\n <div *ngIf=\"subtitle\" class=\"cqa-text-[12px] cqa-leading-4 cqa-text-[#6A7282] cqa-mt-0.5\">{{ subtitle }}</div>\n </div>\n <!-- Right-side actions slot -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <ng-content select=\"[chart-actions]\"></ng-content>\n </div>\n </div>\n\n <!-- Chart/content area -->\n <div class=\"cqa-p-3 sm:cqa-p-4\">\n <div class=\"cqa-w-full cqa-min-h-[220px]\">\n <ng-content></ng-content>\n </div>\n </div>\n </div>\n</div>", styles: [] }]
|
|
1857
|
+
}], propDecorators: { title: [{
|
|
1858
|
+
type: Input
|
|
1859
|
+
}], subtitle: [{
|
|
1860
|
+
type: Input
|
|
1861
|
+
}], cardClass: [{
|
|
1862
|
+
type: Input
|
|
1863
|
+
}] } });
|
|
1864
|
+
|
|
1865
|
+
class ProgressTextCardComponent {
|
|
1866
|
+
constructor() {
|
|
1867
|
+
this.value = 0; // 0 - 100
|
|
1868
|
+
this.label = 'Test Success Rate';
|
|
1869
|
+
this.deltaSuffix = 'since last run';
|
|
1870
|
+
this.cardClass = '';
|
|
1871
|
+
}
|
|
1872
|
+
get percentText() {
|
|
1873
|
+
const v = Math.max(0, Math.min(100, Number(this.value) || 0));
|
|
1874
|
+
return `${v}%`;
|
|
1875
|
+
}
|
|
1876
|
+
get fillWidth() {
|
|
1877
|
+
const v = Math.max(0, Math.min(100, Number(this.value) || 0));
|
|
1878
|
+
return v + '%';
|
|
1879
|
+
}
|
|
1880
|
+
deltaClass() {
|
|
1881
|
+
if (this.deltaPercent === undefined || this.deltaPercent === null || Number.isNaN(this.deltaPercent)) {
|
|
1882
|
+
return 'text-[#6B7280]';
|
|
1883
|
+
}
|
|
1884
|
+
if (this.deltaPercent > 0)
|
|
1885
|
+
return 'text-[#10B981]';
|
|
1886
|
+
if (this.deltaPercent < 0)
|
|
1887
|
+
return 'text-[#EF4444]';
|
|
1888
|
+
return 'text-[#6B7280]';
|
|
1889
|
+
}
|
|
1890
|
+
}
|
|
1891
|
+
ProgressTextCardComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: ProgressTextCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1892
|
+
ProgressTextCardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: ProgressTextCardComponent, selector: "cqa-progress-text-card", inputs: { value: "value", label: "label", deltaPercent: "deltaPercent", deltaSuffix: "deltaSuffix", cardClass: "cardClass" }, ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <div\n class=\"cqa-w-full cqa-box-border cqa-flex cqa-flex-col cqa-bg-white cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-rounded-[10px] cqa-p-4 sm:cqa-p-5\"\n [ngClass]=\"cardClass\">\n <div class=\"cqa-flex cqa-items-baseline cqa-gap-2\">\n <div\n class=\"cqa-text-[28px] sm:cqa-text-[32px] cqa-leading-[36px] cqa-font-bold cqa-tracking-[-0.3px] cqa-text-[#111827]\">\n {{ percentText }}</div>\n <div class=\"cqa-text-[18px] sm:cqa-text-[20px] cqa-leading-[28px] cqa-text-[#111827]\">{{ label }}</div>\n </div>\n <div class=\"cqa-mt-4 cqa-w-full cqa-h-[14px] cqa-bg-[#E5E7EB] cqa-rounded-full cqa-overflow-hidden\">\n <div class=\"cqa-h-full cqa-rounded-full\" [style.width]=\"fillWidth\"\n [style.background]=\"'linear-gradient(90deg, #DD5A38 0%, #F59E0B 40%, #10B981 100%)'\">\n </div>\n </div>\n <div class=\"cqa-mt-2 cqa-text-[14px] cqa-leading-5\" [ngClass]=\"deltaClass()\" *ngIf=\"deltaPercent !== undefined\">\n {{ deltaPercent > 0 ? '+' : ''}}{{ deltaPercent }}% {{ deltaSuffix }}\n </div>\n </div>\n</div>", directives: [{ type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1893
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: ProgressTextCardComponent, decorators: [{
|
|
1894
|
+
type: Component,
|
|
1895
|
+
args: [{ selector: 'cqa-progress-text-card', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div id=\"cqa-ui-root\">\n <div\n class=\"cqa-w-full cqa-box-border cqa-flex cqa-flex-col cqa-bg-white cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-rounded-[10px] cqa-p-4 sm:cqa-p-5\"\n [ngClass]=\"cardClass\">\n <div class=\"cqa-flex cqa-items-baseline cqa-gap-2\">\n <div\n class=\"cqa-text-[28px] sm:cqa-text-[32px] cqa-leading-[36px] cqa-font-bold cqa-tracking-[-0.3px] cqa-text-[#111827]\">\n {{ percentText }}</div>\n <div class=\"cqa-text-[18px] sm:cqa-text-[20px] cqa-leading-[28px] cqa-text-[#111827]\">{{ label }}</div>\n </div>\n <div class=\"cqa-mt-4 cqa-w-full cqa-h-[14px] cqa-bg-[#E5E7EB] cqa-rounded-full cqa-overflow-hidden\">\n <div class=\"cqa-h-full cqa-rounded-full\" [style.width]=\"fillWidth\"\n [style.background]=\"'linear-gradient(90deg, #DD5A38 0%, #F59E0B 40%, #10B981 100%)'\">\n </div>\n </div>\n <div class=\"cqa-mt-2 cqa-text-[14px] cqa-leading-5\" [ngClass]=\"deltaClass()\" *ngIf=\"deltaPercent !== undefined\">\n {{ deltaPercent > 0 ? '+' : ''}}{{ deltaPercent }}% {{ deltaSuffix }}\n </div>\n </div>\n</div>", styles: [] }]
|
|
1896
|
+
}], propDecorators: { value: [{
|
|
1897
|
+
type: Input
|
|
1898
|
+
}], label: [{
|
|
1899
|
+
type: Input
|
|
1900
|
+
}], deltaPercent: [{
|
|
1901
|
+
type: Input
|
|
1902
|
+
}], deltaSuffix: [{
|
|
1903
|
+
type: Input
|
|
1904
|
+
}], cardClass: [{
|
|
1905
|
+
type: Input
|
|
1906
|
+
}] } });
|
|
1907
|
+
|
|
1908
|
+
class DashboardHeaderComponent {
|
|
1909
|
+
constructor() {
|
|
1910
|
+
this.title = '';
|
|
1911
|
+
this.badgeClass = 'bg-[#D1FAE5] text-[#065F46]';
|
|
1912
|
+
this.headerClass = '';
|
|
1913
|
+
// Optional workspace select on the right
|
|
1914
|
+
this.workspaceOptions = [];
|
|
1915
|
+
this.workspacePlaceholder = 'Workspace';
|
|
1916
|
+
this.workspaceDisabled = false;
|
|
1917
|
+
this.workspaceMultiple = true;
|
|
1918
|
+
this.workspaceSearchable = false;
|
|
1919
|
+
this.workspaceValueChange = new EventEmitter();
|
|
1920
|
+
this.workspaceForm = new FormGroup({
|
|
1921
|
+
workspace: new FormControl(),
|
|
1922
|
+
});
|
|
1923
|
+
}
|
|
1924
|
+
ngOnInit() {
|
|
1925
|
+
this.syncFormFromInput();
|
|
1926
|
+
this.workspaceForm.get('workspace')?.valueChanges.subscribe((v) => {
|
|
1927
|
+
this.workspaceValue = v;
|
|
1928
|
+
this.workspaceValueChange.emit(v);
|
|
1929
|
+
});
|
|
1930
|
+
}
|
|
1931
|
+
ngOnChanges(_changes) {
|
|
1932
|
+
this.syncFormFromInput();
|
|
1933
|
+
}
|
|
1934
|
+
get workspaceConfig() {
|
|
1935
|
+
return {
|
|
1936
|
+
key: 'workspace',
|
|
1937
|
+
placeholder: this.workspacePlaceholder,
|
|
1938
|
+
disabled: this.workspaceDisabled,
|
|
1939
|
+
multiple: this.workspaceMultiple,
|
|
1940
|
+
searchable: this.workspaceSearchable,
|
|
1941
|
+
options: this.workspaceOptions,
|
|
1942
|
+
};
|
|
1943
|
+
}
|
|
1944
|
+
syncFormFromInput() {
|
|
1945
|
+
const ctrl = this.workspaceForm.get('workspace');
|
|
1946
|
+
if (!ctrl)
|
|
1947
|
+
return;
|
|
1948
|
+
const val = this.workspaceValue;
|
|
1949
|
+
const normalized = this.workspaceMultiple
|
|
1950
|
+
? Array.isArray(val) ? val : (val != null ? [val] : [])
|
|
1951
|
+
: (Array.isArray(val) ? (val.length ? val[0] : undefined) : val);
|
|
1952
|
+
ctrl.setValue(normalized, { emitEvent: false });
|
|
1953
|
+
}
|
|
1954
|
+
}
|
|
1955
|
+
DashboardHeaderComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DashboardHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1956
|
+
DashboardHeaderComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: DashboardHeaderComponent, selector: "cqa-dashboard-header", inputs: { title: "title", badgeText: "badgeText", badgeClass: "badgeClass", headerClass: "headerClass", workspaceOptions: "workspaceOptions", workspacePlaceholder: "workspacePlaceholder", workspaceDisabled: "workspaceDisabled", workspaceValue: "workspaceValue", workspaceMultiple: "workspaceMultiple", workspaceSearchable: "workspaceSearchable" }, outputs: { workspaceValueChange: "workspaceValueChange" }, usesOnChanges: true, ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <div\n class=\"cqa-w-full cqa-flex cqa-items-end cqa-justify-between cqa-bg-white cqa-pr-6 cqa-pl-2 lg:cqa-px-6 lg:cqa-py-[6px] cqa-py-2 cqa-border-b cqa-border-default cqa-shadow-header\"\n [ngClass]=\"headerClass\">\n <!-- Left branding block -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-min-w-0\">\n <div class=\"cqa-pr-4 lg:cqa-hidden cqa-gap-2 md:cqa-flex\">\n <cqa-button variant=\"filled\" icon=\"\" [customClass]=\"'!cqa-rounded-[10px] !cqa-p-[7px] !cqa-min-w-[47px]'\">\n <svg width=\"31\" height=\"22\" viewBox=\"0 0 31 22\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M5.16675 11H25.8334\" stroke=\"white\" stroke-width=\"1.83333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M5.16675 16.5H25.8334\" stroke=\"white\" stroke-width=\"1.83333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M5.16675 5.5H25.8334\" stroke=\"white\" stroke-width=\"1.83333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </cqa-button>\n <span class=\"cqa-border-l cqa-border-primary-surface cqa-hidden md:cqa-flex\"></span>\n <cqa-button variant=\"filled\" icon=\"\" class=\"cqa-hidden md:cqa-flex\" [customClass]=\"'!cqa-rounded-[10px] !cqa-p-[7px] !cqa-min-w-[47px]'\">\n <svg width=\"22\" height=\"22\" viewBox=\"0 0 22 22\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4.58337 11H17.4167\" stroke=\"white\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M11 4.58301V17.4163\" stroke=\"white\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </cqa-button>\n </div>\n <!-- Optional projected logo -->\n <svg width=\"32\" height=\"32\" viewBox=\"0 0 32 32\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n <rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"15.5\" fill=\"url(#pattern0_6303_22035)\" />\n <rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"15.5\" stroke=\"#D8D9FC\" />\n <defs>\n <pattern id=\"pattern0_6303_22035\" patternContentUnits=\"objectBoundingBox\" width=\"1\" height=\"1\">\n <use xlink:href=\"#image0_6303_22035\" transform=\"scale(0.005)\" />\n </pattern>\n <image id=\"image0_6303_22035\" width=\"200\" height=\"200\" preserveAspectRatio=\"none\"\n xlink:href=\"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBw8SEBMQEBASEBAQEBYRFRUXFRARERASGRkWGxYXGBUYHigsGBomGxUYITEhJSkrLjouGSAzODMsNygtLjcBCgoKDg0OGxAQGy4dICUrNy0rKysrMDctLisvLS0tKy0tLTcuLS0tMDctNi0tLSstLS0rLS0rLTEtLS0tLS0tLf/AABEIAMgAyAMBIgACEQEDEQH/xAAcAAEAAgIDAQAAAAAAAAAAAAAABQYCBwEDBAj/xABBEAABAwICAwsKBQUAAwEAAAABAAIDBBEFIQYSQQciMVFSYXGBkaHRExQWIzJUkqKxwRdCYnKyU4LC4fAkNPEV/8QAGwEBAAIDAQEAAAAAAAAAAAAAAAIDAQQFBgf/xAAuEQACAQIEAwYGAwAAAAAAAAAAAQIDEQQSIVETMUEFUmGBkbEUIjJCccEVodH/2gAMAwEAAhEDEQA/AN4oiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiA81XK5jdcDWDc3DaW8Y5xwrkyFzNeIg3F2n8ruZd6r/AJbzSo1DlTzm7eKN+3qz71KKuRbsS1JViVhLbtIJa4H2mOHCCF1UNfrPdC+zZo7awzs5p4HtvsPdwKMxwuppRVxi7HEMmbyh+V3SuNI4TJEytpT66Aa7CPzxn2mnjy2KagvJ+5jMyS8/1JxBLl5S5hdsfbNzDxOHeOtcYjiBgc18n/rvIa539F/5Sf0k5X2G3Go9zosSorsOo/hBz1oZm8Gf/ZFdOjOLCshkpapvr4wY5mG2/GY1gmTq+nMZiD08bidNeopqqV1OTvm70mHrtm1Uf00xP3uT5PBbI0br3QzvwmrOvqj1DnWPlYiCdU9X3CoWnui5optaME08pJZw7w7WH7LcoON8kkvB7lM780eT00xP3uT5PBPTTE/e5Pk8FAItvhQ2RVne5P8AppifvcnyeCemmJ+9yfJ4KAROFDZDO9yz0GnmIxyNe6YytBzY4N1XDaLgZHnW4cAxqGrhE0JyOTm/mY7aCvndTeiekMlFOJG3MbspGctvHzEcK16+GUleK1J06jT1PoBVTTKmrmtM9JO8Bou6MWOXG247lY6KqZLG2WN2sx7Q5p4wu9cqUbqx0KFXhTU7J+DNLeleIe8v+XwT0rxD3l/y+Cm9P9GvJONTC31TzvwOBjuPoJVKXOm5wdmz2uFjhcRTU4wXoia9K8Q95f8AL4J6V4h7y/5fBQqKGeW5sfCUO4vRE16V4h7y/wCXwWUel1eCD5w42PAQ0g9OSg0Wc8tw8HQ7i9Ebo0X0hjq49Yb2Vvts4uccYU4tD4ViMlPK2aI2c09ThtBW6MExSOphbLHwEZja120FbtGrnVnzPJ9qdnPDSzR+l/14EiiIrzknCjseofLQOaPaG+b0j/rKSXCynZ3MNXViuYBVNqad1PLmWt1ect2HpC8OiVa6KV9FKeBx1P3bR0EZrpmd5rXEjJhdf+x3D3/RYabQmKojqGZF4vf9bbfay21FN5ej18ym7tfY80U3/wCbiTozlTTkHmAPAf7XXHQsdNo30VbFiEIykNnjYSALg/ub/FerTyJs9HDVtHs2vzNdYEdTgEa7z7B3tOcsDevWZmO1uXWVJdJv8MxuvNGG6DTCelhxGnO+hs4OHDqEjva77qUopIsWw4tfYOcNV3HHK3gcO49ahNzesE1PNQy5t1SWj9Drhw6jn/covc7rXUte+kkOUrjGeLyjL2PWLjrCw4NRcesdV+DKlqnuUSupHwyPikFnxuLXDnH1C6FsTdewgNljq2jKUaj/AN7RvT1t/itdrepTzwUiicbOwREVhEIiIDYu5PpCWyGikO9ku6L9L8y5vQRn1c62svmmmndG9sjDZ7HBwPEQvoXB8WingjnDmjyjA61xkdo7brmYulaWZdTZoyurM9dXTMkY6N4u14LSOMLSWPYW6mqHwuz1Tdp5TTwFbv8AOGctvaFSd0uhZJC2oYWl0R1XWIuWOsO427VzMRTco32O92Ni+FXyN6S9+hrVERc89mEREAVn0Exw09QGPNoZiGu4mu/K77KsLlShJxd0U4ihGtTcJdT6DuigtDcUNRSMc43e0ajukbesWPWuV1Iu6uj5/VpunNwlzROoiLJWVDTeHfRv4wW9lrfVYY563DY5dsZF+0sPfZe7TZvqmHik+oK8EG+wuYckn6tK24P5YvZlEvqaOnBfXYbUwHPUDiP5N+YKO3Mqq00sJ4JI9a3O3/Tu5SGgJuZ2bHMb3aw+6rmgj9XEIhx67fkd4K5rSovMhfWLOjRmTzXFWsvZomfCecG4HfZYadtNPirpWZG8c7emwv3tKx0kPk8VkI/LUNd/Er37rbLVcR44P8nKa1nF7oj9r8GXLTumbUYZK5udmNnb1WP8b9q0Wt+YR6zCmA569Jq/JZaDWMJpmjsyVbowiItwpCIiAIiIAso3WIPEViijKKasydObjJSXRkui4jOQ6AuV42Ss2j6pTlmgnugiIokwiIgL5uV1lpJoScnNDx0jI/UdiKK3OpCK9g5THjuv9lyujh3eB4vtuChim91f9G3URFcckrWmz/VRjjeT2A+K8EO9wuY8o/5NCz02mvJGzktJ7f8A4sdIfU4fFDteRcdrj3kLbgvlit2US+ps6NAsjO88DWD/ACP2Vc0DYXYhEeIPcfgd9yrJhfqMLqJjkZAQP4DvJUfuZ03rJp3ZNjYG36bk9zVc5aVH5EEtYor2kI8pisgGetUtZ3tH2Xv3W5L1cbeTAO9zl59EojU4o2QjLyj53cwFyPmIXVpmTVYs6Jme/ZA3sAPzXVi0mlsjH2vxZsjC/VYUwnLUo9b5LrQa3lugVbafDZGtyL2tgYOmwPygrRqjhNVKW7M1uiCIi3CkIiIAiKUotHa2Zgkip5JI3Xs4DI2JH1Cw5Jcxa/Ii0U36I4j7pL8Kwn0Zro2l8lNIyNvtOIsAFCVWCTdyynTlKSilzZjGMh0LlEXjpO8mz6pTjlilsgiIsEgiIgLRucx3r2nksee633RS+5XR76acjIARt7y77IujhlaB4vtqanin4K37NjLhFFaSV3koTb25N437nsV8Vd2OQ3ZXK9GzzuuJ4WB1zxajbfX7rq0vkdPVsp2Zllm/3OzPdZTeG07aOldLJ7ZGs7/Fv/ca8eiVAbvrZvafctvsGes5bSkk822iKbPluR26DO2Gnho2bcz+1vB2k9yyrGeYYOWnKacWPHrP4R1M+i68IpjiFe+reP8Ax4XAMB4HW9kD+R6QurSVrsRxBlHGfU0+cjhwAm2t15BvSpq2kH01Zjd+SMtAKVtLRzV8o9ppLf2Nv9T9FF7meHOnq5K2QXEZJB45X3+gJ7QpjdBqCWwYXSt38pbdo2MbbVHRcX/tUnWTw4RhwaLOeBZo2yzHhPRfPoCw5tptc5exlJabIpu61jIknZSsO9p8388jgPo36lUFdlRM57nPeS5z3FxO0krrW9ShkiolEnd3CIisIhERAeigpHzSshjF3yODQOc/ZfROF0LYIY4WezGwNHPbb2qgblOjZaPPpW5uBbCOJvA5/Xwdq2SuXi6uaWVdDaoxsrhUPdPxWzGUrTm867+Zo9kdv0VxxSvZBE6aQ2awX5zxAc91pHFa99RM+Z/tPde3ENg7FzMRUyxtueg7Fwbq1eI+Ufc8iIi0D2AREQBcgXyGZ4FwrjueYCZZfOJB6qI73ifJ/r6qUIuTsa+KxEaFJ1JF70UwvzaljjPt21nfuOZ7ODqRTCLqJWVkeAqTdSbm+bOHEAXPAFC0lOZ5vOXj1bMoWnb+sqVqIdcap9n8w5XN0LKVhLbNOrsvxdCmnbkVtXITEITVzCLgp4XXkP8AUfyR0LHSIvl1aGn3rpB6xw4IYfE8AHSpuGFrGajAAAMhn3rGkpGsueF7zrPceF5+w2WUlO3lyI5SJr3CjpmwUzLzP9XC3K7n7XG+wcJK68LoYcOpHySHWf7cr/zSSHIAceZsOlTEVIPKGV2+kI1QdjGclv1J/wBLiajD5GPfm2M3Y3Zr8o8ZGxM/T1M5SuYPRCnE2J15DZ5RrG+fkGcDWDjNrDuWrtLdIpK2cyOu2Nu9jZyG7TzklbA0y0cxOuksHxMp2HeM1nZnlONsz9FW/wAL6/lw/E7wW5QlTXzSevsUTUnoloUdFePwvr+XD8TvBPwvr+XD8TvBbPxFPvFfDlsUdFePwvr+XD8TvBPwvr+XD8TvBPiKfeHDlsUdWvQTRN1ZLryAimjO+P8AUPIB+qlsO3LqkyN8vJG2K++1CS4jiFx3raNBRxwxtiiaGRsFgBsVFfFJK0GWQpO92d0cYaA1oAaBYAZAAJLIGgucQABck8ACzKqul2F11V6qFzGQbbuOtIeew4OZcuTaV1qb1CnGc1GTyrdlL000kNVJqRm0EZ3v6zyj9lWVb/w9reVF8TvBPw9reVF8TvBaEqdSTu0exoYzBUKahCasioIrf+Htbyovid4J+Htbyovid4KPBnsXfyeF76Kgit/4e1vKi+J3gsotzyrJGs+MNvmQXEgdFlngz2MPtPC99EJo5gclXKGNyYM3u2Nb4rctBRxwxtijbqsYLALpwbCoqaIRRCwHCdrjxkr3rcpUsi8Ty3aOPlip6aRXL/TlERXHNCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiA/9k=\" />\n </defs>\n </svg>\n\n <!-- Title + optional badge -->\n <div class=\"cqa-items-end cqa-gap-3 cqa-min-w-0 cqa-hidden md:cqa-flex\">\n <div\n class=\"cqa-truncate cqa-text-[#22223B] cqa-font-extrabold cqa-text-[32px] cqa-font-nunito-sans cqa-leading-[1]\">\n {{ title }}</div>\n <span *ngIf=\"badgeText\"\n class=\"cqa-px-2 cqa-py-[2px] cqa-rounded-lg cqa-text-[12px] cqa-font-medium cqa-leading-4 cqa-whitespace-nowrap cqa-text-[#007A55] cqa-bg-[#D0FAE5] cqa-border cqa-border-[#A4F4CF]\"\n [ngClass]=\"badgeClass\">{{ badgeText }}</span>\n </div>\n </div>\n\n <!-- Right controls/actions -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-3 cqa-flex-1\">\n <!-- Optional workspace select -->\n <div *ngIf=\"workspaceOptions?.length\" class=\"cqa-w-full cqa-max-w-[199px] cqa-ml-auto header-dropdown\">\n <cqa-dynamic-select [form]=\"workspaceForm\" [config]=\"workspaceConfig\">\n </cqa-dynamic-select>\n </div>\n\n <ng-content></ng-content>\n </div>\n </div>\n</div>", components: [{ type: ButtonComponent, selector: "cqa-button", inputs: ["variant", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass"], outputs: ["clicked"] }, { type: DynamicSelectFieldComponent, selector: "cqa-dynamic-select", inputs: ["form", "config"] }], directives: [{ type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1957
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DashboardHeaderComponent, decorators: [{
|
|
1958
|
+
type: Component,
|
|
1959
|
+
args: [{ selector: 'cqa-dashboard-header', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div id=\"cqa-ui-root\">\n <div\n class=\"cqa-w-full cqa-flex cqa-items-end cqa-justify-between cqa-bg-white cqa-pr-6 cqa-pl-2 lg:cqa-px-6 lg:cqa-py-[6px] cqa-py-2 cqa-border-b cqa-border-default cqa-shadow-header\"\n [ngClass]=\"headerClass\">\n <!-- Left branding block -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-min-w-0\">\n <div class=\"cqa-pr-4 lg:cqa-hidden cqa-gap-2 md:cqa-flex\">\n <cqa-button variant=\"filled\" icon=\"\" [customClass]=\"'!cqa-rounded-[10px] !cqa-p-[7px] !cqa-min-w-[47px]'\">\n <svg width=\"31\" height=\"22\" viewBox=\"0 0 31 22\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M5.16675 11H25.8334\" stroke=\"white\" stroke-width=\"1.83333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M5.16675 16.5H25.8334\" stroke=\"white\" stroke-width=\"1.83333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M5.16675 5.5H25.8334\" stroke=\"white\" stroke-width=\"1.83333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </cqa-button>\n <span class=\"cqa-border-l cqa-border-primary-surface cqa-hidden md:cqa-flex\"></span>\n <cqa-button variant=\"filled\" icon=\"\" class=\"cqa-hidden md:cqa-flex\" [customClass]=\"'!cqa-rounded-[10px] !cqa-p-[7px] !cqa-min-w-[47px]'\">\n <svg width=\"22\" height=\"22\" viewBox=\"0 0 22 22\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4.58337 11H17.4167\" stroke=\"white\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M11 4.58301V17.4163\" stroke=\"white\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </cqa-button>\n </div>\n <!-- Optional projected logo -->\n <svg width=\"32\" height=\"32\" viewBox=\"0 0 32 32\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n <rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"15.5\" fill=\"url(#pattern0_6303_22035)\" />\n <rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"15.5\" stroke=\"#D8D9FC\" />\n <defs>\n <pattern id=\"pattern0_6303_22035\" patternContentUnits=\"objectBoundingBox\" width=\"1\" height=\"1\">\n <use xlink:href=\"#image0_6303_22035\" transform=\"scale(0.005)\" />\n </pattern>\n <image id=\"image0_6303_22035\" width=\"200\" height=\"200\" preserveAspectRatio=\"none\"\n xlink:href=\"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBw8SEBMQEBASEBAQEBYRFRUXFRARERASGRkWGxYXGBUYHigsGBomGxUYITEhJSkrLjouGSAzODMsNygtLjcBCgoKDg0OGxAQGy4dICUrNy0rKysrMDctLisvLS0tKy0tLTcuLS0tMDctNi0tLSstLS0rLS0rLTEtLS0tLS0tLf/AABEIAMgAyAMBIgACEQEDEQH/xAAcAAEAAgIDAQAAAAAAAAAAAAAABQYCBwEDBAj/xABBEAABAwICAwsKBQUAAwEAAAABAAIDBBEFIQYSQQciMVFSYXGBkaHRExQWIzJUkqKxwRdCYnKyU4LC4fAkNPEV/8QAGwEBAAIDAQEAAAAAAAAAAAAAAAIDAQQFBgf/xAAuEQACAQIEAwYGAwAAAAAAAAAAAQIDEQQSIVETMUEFUmGBkbEUIjJCccEVodH/2gAMAwEAAhEDEQA/AN4oiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiA81XK5jdcDWDc3DaW8Y5xwrkyFzNeIg3F2n8ruZd6r/AJbzSo1DlTzm7eKN+3qz71KKuRbsS1JViVhLbtIJa4H2mOHCCF1UNfrPdC+zZo7awzs5p4HtvsPdwKMxwuppRVxi7HEMmbyh+V3SuNI4TJEytpT66Aa7CPzxn2mnjy2KagvJ+5jMyS8/1JxBLl5S5hdsfbNzDxOHeOtcYjiBgc18n/rvIa539F/5Sf0k5X2G3Go9zosSorsOo/hBz1oZm8Gf/ZFdOjOLCshkpapvr4wY5mG2/GY1gmTq+nMZiD08bidNeopqqV1OTvm70mHrtm1Uf00xP3uT5PBbI0br3QzvwmrOvqj1DnWPlYiCdU9X3CoWnui5optaME08pJZw7w7WH7LcoON8kkvB7lM780eT00xP3uT5PBPTTE/e5Pk8FAItvhQ2RVne5P8AppifvcnyeCemmJ+9yfJ4KAROFDZDO9yz0GnmIxyNe6YytBzY4N1XDaLgZHnW4cAxqGrhE0JyOTm/mY7aCvndTeiekMlFOJG3MbspGctvHzEcK16+GUleK1J06jT1PoBVTTKmrmtM9JO8Bou6MWOXG247lY6KqZLG2WN2sx7Q5p4wu9cqUbqx0KFXhTU7J+DNLeleIe8v+XwT0rxD3l/y+Cm9P9GvJONTC31TzvwOBjuPoJVKXOm5wdmz2uFjhcRTU4wXoia9K8Q95f8AL4J6V4h7y/5fBQqKGeW5sfCUO4vRE16V4h7y/wCXwWUel1eCD5w42PAQ0g9OSg0Wc8tw8HQ7i9Ebo0X0hjq49Yb2Vvts4uccYU4tD4ViMlPK2aI2c09ThtBW6MExSOphbLHwEZja120FbtGrnVnzPJ9qdnPDSzR+l/14EiiIrzknCjseofLQOaPaG+b0j/rKSXCynZ3MNXViuYBVNqad1PLmWt1ect2HpC8OiVa6KV9FKeBx1P3bR0EZrpmd5rXEjJhdf+x3D3/RYabQmKojqGZF4vf9bbfay21FN5ej18ym7tfY80U3/wCbiTozlTTkHmAPAf7XXHQsdNo30VbFiEIykNnjYSALg/ub/FerTyJs9HDVtHs2vzNdYEdTgEa7z7B3tOcsDevWZmO1uXWVJdJv8MxuvNGG6DTCelhxGnO+hs4OHDqEjva77qUopIsWw4tfYOcNV3HHK3gcO49ahNzesE1PNQy5t1SWj9Drhw6jn/covc7rXUte+kkOUrjGeLyjL2PWLjrCw4NRcesdV+DKlqnuUSupHwyPikFnxuLXDnH1C6FsTdewgNljq2jKUaj/AN7RvT1t/itdrepTzwUiicbOwREVhEIiIDYu5PpCWyGikO9ku6L9L8y5vQRn1c62svmmmndG9sjDZ7HBwPEQvoXB8WingjnDmjyjA61xkdo7brmYulaWZdTZoyurM9dXTMkY6N4u14LSOMLSWPYW6mqHwuz1Tdp5TTwFbv8AOGctvaFSd0uhZJC2oYWl0R1XWIuWOsO427VzMRTco32O92Ni+FXyN6S9+hrVERc89mEREAVn0Exw09QGPNoZiGu4mu/K77KsLlShJxd0U4ihGtTcJdT6DuigtDcUNRSMc43e0ajukbesWPWuV1Iu6uj5/VpunNwlzROoiLJWVDTeHfRv4wW9lrfVYY563DY5dsZF+0sPfZe7TZvqmHik+oK8EG+wuYckn6tK24P5YvZlEvqaOnBfXYbUwHPUDiP5N+YKO3Mqq00sJ4JI9a3O3/Tu5SGgJuZ2bHMb3aw+6rmgj9XEIhx67fkd4K5rSovMhfWLOjRmTzXFWsvZomfCecG4HfZYadtNPirpWZG8c7emwv3tKx0kPk8VkI/LUNd/Er37rbLVcR44P8nKa1nF7oj9r8GXLTumbUYZK5udmNnb1WP8b9q0Wt+YR6zCmA569Jq/JZaDWMJpmjsyVbowiItwpCIiAIiIAso3WIPEViijKKasydObjJSXRkui4jOQ6AuV42Ss2j6pTlmgnugiIokwiIgL5uV1lpJoScnNDx0jI/UdiKK3OpCK9g5THjuv9lyujh3eB4vtuChim91f9G3URFcckrWmz/VRjjeT2A+K8EO9wuY8o/5NCz02mvJGzktJ7f8A4sdIfU4fFDteRcdrj3kLbgvlit2US+ps6NAsjO88DWD/ACP2Vc0DYXYhEeIPcfgd9yrJhfqMLqJjkZAQP4DvJUfuZ03rJp3ZNjYG36bk9zVc5aVH5EEtYor2kI8pisgGetUtZ3tH2Xv3W5L1cbeTAO9zl59EojU4o2QjLyj53cwFyPmIXVpmTVYs6Jme/ZA3sAPzXVi0mlsjH2vxZsjC/VYUwnLUo9b5LrQa3lugVbafDZGtyL2tgYOmwPygrRqjhNVKW7M1uiCIi3CkIiIAiKUotHa2Zgkip5JI3Xs4DI2JH1Cw5Jcxa/Ii0U36I4j7pL8Kwn0Zro2l8lNIyNvtOIsAFCVWCTdyynTlKSilzZjGMh0LlEXjpO8mz6pTjlilsgiIsEgiIgLRucx3r2nksee633RS+5XR76acjIARt7y77IujhlaB4vtqanin4K37NjLhFFaSV3koTb25N437nsV8Vd2OQ3ZXK9GzzuuJ4WB1zxajbfX7rq0vkdPVsp2Zllm/3OzPdZTeG07aOldLJ7ZGs7/Fv/ca8eiVAbvrZvafctvsGes5bSkk822iKbPluR26DO2Gnho2bcz+1vB2k9yyrGeYYOWnKacWPHrP4R1M+i68IpjiFe+reP8Ax4XAMB4HW9kD+R6QurSVrsRxBlHGfU0+cjhwAm2t15BvSpq2kH01Zjd+SMtAKVtLRzV8o9ppLf2Nv9T9FF7meHOnq5K2QXEZJB45X3+gJ7QpjdBqCWwYXSt38pbdo2MbbVHRcX/tUnWTw4RhwaLOeBZo2yzHhPRfPoCw5tptc5exlJabIpu61jIknZSsO9p8388jgPo36lUFdlRM57nPeS5z3FxO0krrW9ShkiolEnd3CIisIhERAeigpHzSshjF3yODQOc/ZfROF0LYIY4WezGwNHPbb2qgblOjZaPPpW5uBbCOJvA5/Xwdq2SuXi6uaWVdDaoxsrhUPdPxWzGUrTm867+Zo9kdv0VxxSvZBE6aQ2awX5zxAc91pHFa99RM+Z/tPde3ENg7FzMRUyxtueg7Fwbq1eI+Ufc8iIi0D2AREQBcgXyGZ4FwrjueYCZZfOJB6qI73ifJ/r6qUIuTsa+KxEaFJ1JF70UwvzaljjPt21nfuOZ7ODqRTCLqJWVkeAqTdSbm+bOHEAXPAFC0lOZ5vOXj1bMoWnb+sqVqIdcap9n8w5XN0LKVhLbNOrsvxdCmnbkVtXITEITVzCLgp4XXkP8AUfyR0LHSIvl1aGn3rpB6xw4IYfE8AHSpuGFrGajAAAMhn3rGkpGsueF7zrPceF5+w2WUlO3lyI5SJr3CjpmwUzLzP9XC3K7n7XG+wcJK68LoYcOpHySHWf7cr/zSSHIAceZsOlTEVIPKGV2+kI1QdjGclv1J/wBLiajD5GPfm2M3Y3Zr8o8ZGxM/T1M5SuYPRCnE2J15DZ5RrG+fkGcDWDjNrDuWrtLdIpK2cyOu2Nu9jZyG7TzklbA0y0cxOuksHxMp2HeM1nZnlONsz9FW/wAL6/lw/E7wW5QlTXzSevsUTUnoloUdFePwvr+XD8TvBPwvr+XD8TvBbPxFPvFfDlsUdFePwvr+XD8TvBPwvr+XD8TvBPiKfeHDlsUdWvQTRN1ZLryAimjO+P8AUPIB+qlsO3LqkyN8vJG2K++1CS4jiFx3raNBRxwxtiiaGRsFgBsVFfFJK0GWQpO92d0cYaA1oAaBYAZAAJLIGgucQABck8ACzKqul2F11V6qFzGQbbuOtIeew4OZcuTaV1qb1CnGc1GTyrdlL000kNVJqRm0EZ3v6zyj9lWVb/w9reVF8TvBPw9reVF8TvBaEqdSTu0exoYzBUKahCasioIrf+Htbyovid4J+Htbyovid4KPBnsXfyeF76Kgit/4e1vKi+J3gsotzyrJGs+MNvmQXEgdFlngz2MPtPC99EJo5gclXKGNyYM3u2Nb4rctBRxwxtijbqsYLALpwbCoqaIRRCwHCdrjxkr3rcpUsi8Ty3aOPlip6aRXL/TlERXHNCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiA/9k=\" />\n </defs>\n </svg>\n\n <!-- Title + optional badge -->\n <div class=\"cqa-items-end cqa-gap-3 cqa-min-w-0 cqa-hidden md:cqa-flex\">\n <div\n class=\"cqa-truncate cqa-text-[#22223B] cqa-font-extrabold cqa-text-[32px] cqa-font-nunito-sans cqa-leading-[1]\">\n {{ title }}</div>\n <span *ngIf=\"badgeText\"\n class=\"cqa-px-2 cqa-py-[2px] cqa-rounded-lg cqa-text-[12px] cqa-font-medium cqa-leading-4 cqa-whitespace-nowrap cqa-text-[#007A55] cqa-bg-[#D0FAE5] cqa-border cqa-border-[#A4F4CF]\"\n [ngClass]=\"badgeClass\">{{ badgeText }}</span>\n </div>\n </div>\n\n <!-- Right controls/actions -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-3 cqa-flex-1\">\n <!-- Optional workspace select -->\n <div *ngIf=\"workspaceOptions?.length\" class=\"cqa-w-full cqa-max-w-[199px] cqa-ml-auto header-dropdown\">\n <cqa-dynamic-select [form]=\"workspaceForm\" [config]=\"workspaceConfig\">\n </cqa-dynamic-select>\n </div>\n\n <ng-content></ng-content>\n </div>\n </div>\n</div>", styles: [] }]
|
|
1960
|
+
}], propDecorators: { title: [{
|
|
1961
|
+
type: Input
|
|
1962
|
+
}], badgeText: [{
|
|
1963
|
+
type: Input
|
|
1964
|
+
}], badgeClass: [{
|
|
1965
|
+
type: Input
|
|
1966
|
+
}], headerClass: [{
|
|
1967
|
+
type: Input
|
|
1968
|
+
}], workspaceOptions: [{
|
|
1969
|
+
type: Input
|
|
1970
|
+
}], workspacePlaceholder: [{
|
|
1971
|
+
type: Input
|
|
1972
|
+
}], workspaceDisabled: [{
|
|
1973
|
+
type: Input
|
|
1974
|
+
}], workspaceValue: [{
|
|
1975
|
+
type: Input
|
|
1976
|
+
}], workspaceMultiple: [{
|
|
1977
|
+
type: Input
|
|
1978
|
+
}], workspaceSearchable: [{
|
|
1979
|
+
type: Input
|
|
1980
|
+
}], workspaceValueChange: [{
|
|
1981
|
+
type: Output
|
|
1982
|
+
}] } });
|
|
1983
|
+
|
|
1984
|
+
class CoverageModuleCardComponent {
|
|
1985
|
+
constructor() {
|
|
1986
|
+
/** Card title, e.g. "AI Ask" */
|
|
1987
|
+
this.title = 'Coverage';
|
|
1988
|
+
/** Number of issues to display next to title */
|
|
1989
|
+
this.issues = 0;
|
|
1990
|
+
/** Optional "View" action visibility */
|
|
1991
|
+
this.showViewAction = true;
|
|
1992
|
+
/** Middle metrics: left group */
|
|
1993
|
+
this.positiveCount = 0;
|
|
1994
|
+
this.negativeCount = 0;
|
|
1995
|
+
this.edgeCaseCount = 0;
|
|
1996
|
+
this.positiveLabel = 'Positive';
|
|
1997
|
+
this.negativeLabel = 'Negative';
|
|
1998
|
+
this.edgeCaseLabel = 'Edge Case';
|
|
1999
|
+
/** Middle metrics: right group */
|
|
2000
|
+
this.aiCount = 0;
|
|
2001
|
+
this.humanCount = 0;
|
|
2002
|
+
this.aiLabel = 'AI';
|
|
2003
|
+
this.humanLabel = 'Human';
|
|
2004
|
+
/** Rows of coverage with percentage bars */
|
|
2005
|
+
this.items = [];
|
|
2006
|
+
/** CTA button label */
|
|
2007
|
+
this.ctaText = 'AI Coverage';
|
|
2008
|
+
/** Disable CTA */
|
|
2009
|
+
this.ctaDisabled = false;
|
|
2010
|
+
this.view = new EventEmitter();
|
|
2011
|
+
this.ctaClicked = new EventEmitter();
|
|
2012
|
+
}
|
|
2013
|
+
statusColorClass(item) {
|
|
2014
|
+
const status = item.status ?? 'neutral';
|
|
2015
|
+
switch (status) {
|
|
2016
|
+
case 'success':
|
|
2017
|
+
return 'cqa-bg-[#10B981]'; // green
|
|
2018
|
+
case 'error':
|
|
2019
|
+
return 'cqa-bg-[#EF4444]'; // red
|
|
2020
|
+
default:
|
|
2021
|
+
return 'cqa-bg-[#3B82F6]'; // blue
|
|
2022
|
+
}
|
|
2023
|
+
}
|
|
2024
|
+
textColorClass(item) {
|
|
2025
|
+
const status = item.status ?? 'neutral';
|
|
2026
|
+
switch (status) {
|
|
2027
|
+
case 'success':
|
|
2028
|
+
return 'cqa-text-[#10B981]';
|
|
2029
|
+
case 'error':
|
|
2030
|
+
return 'cqa-text-[#EF4444]';
|
|
2031
|
+
default:
|
|
2032
|
+
return 'cqa-text-[#374151]';
|
|
2033
|
+
}
|
|
2034
|
+
}
|
|
2035
|
+
formatPercent(pct) {
|
|
2036
|
+
if (pct === undefined || pct === null || Number.isNaN(pct))
|
|
2037
|
+
return '0%';
|
|
2038
|
+
const clamped = Math.max(0, Math.min(100, pct));
|
|
2039
|
+
return `${clamped}%`;
|
|
2040
|
+
}
|
|
2041
|
+
}
|
|
2042
|
+
CoverageModuleCardComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: CoverageModuleCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2043
|
+
CoverageModuleCardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: CoverageModuleCardComponent, selector: "cqa-coverage-module-card", inputs: { title: "title", issues: "issues", showViewAction: "showViewAction", positiveCount: "positiveCount", negativeCount: "negativeCount", edgeCaseCount: "edgeCaseCount", positiveLabel: "positiveLabel", negativeLabel: "negativeLabel", edgeCaseLabel: "edgeCaseLabel", aiCount: "aiCount", humanCount: "humanCount", aiLabel: "aiLabel", humanLabel: "humanLabel", items: "items", ctaText: "ctaText", ctaDisabled: "ctaDisabled" }, outputs: { view: "view", ctaClicked: "ctaClicked" }, ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <div\n class=\"cqa-w-full cqa-bg-white cqa-rounded-[8px] cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-py-[10px] md:cqa-px-[17px] cqa-px-3 cqa-shadow-card\">\n <!-- Header -->\n <div class=\"cqa-flex cqa-items-start cqa-justify-between cqa-mb-3\">\n <h3 class=\"cqa-text-[18px] cqa-leading-[28px] cqa-font-bold cqa-text-dialog\">{{ title }}</h3>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <span\n class=\"cqa-px-[10px] cqa-py-[4px] cqa-text-[12px] cqa-leading-[16px] cqa-flex cqa-items-center cqa-gap-1 cqa-rounded-full cqa-bg-warning-light cqa-text-danger\">\n {{ issues }} {{ issues === 1 ? 'issue' : 'issues' }}\n </span>\n <button type=\"button\"\n class=\"cqa-text-[14px] cqa-leading-[20px] cqa-text-primary cqa-flex cqa-items-center cqa-gap-1\"\n *ngIf=\"showViewAction\" (click)=\"view.emit()\">\n View\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6 12L10 8L6 4\" stroke=\"#4F46E5\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </button>\n </div>\n </div>\n\n <!-- Middle metrics row -->\n <div class=\"cqa-grid md:cqa-grid-cols-4 cqa-grid-cols-2 cqa-gap-3 cqa-mb-4 cqa-border-t cqa-border-b cqa-border-surface-[#F3F4F6] cqa-py-2\">\n <!-- Left: Positive / Negative / Edge Case -->\n <div class=\"cqa-text-center\">\n <div class=\"cqa-text-[18px] cqa-leading-[28px] cqa-font-bold cqa-text-[#059669]\">{{ positiveCount }}</div>\n <div class=\"cqa-text-[12px] cqa-leading-[16px] cqa-text-dialog-muted\">{{ positiveLabel }}</div>\n </div>\n <div class=\"cqa-text-center\">\n <div class=\"cqa-text-[18px] cqa-leading-[28px] cqa-font-bold cqa-text-[#EF4444]\">{{ negativeCount }}</div>\n <div class=\"cqa-text-[12px] cqa-leading-[16px] cqa-text-dialog-muted\">{{ negativeLabel }}</div>\n </div>\n <div class=\"cqa-text-center\">\n <div class=\"cqa-text-[18px] cqa-leading-[28px] cqa-font-bold cqa-text-[#F59E0B]\">{{ edgeCaseCount }}</div>\n <div class=\"cqa-text-[12px] cqa-leading-[16px] cqa-text-dialog-muted\">{{ edgeCaseLabel }}</div>\n </div>\n\n <!-- Right: AI / Human -->\n <div class=\"cqa-text-center cqa-flex cqa-items-center cqa-justify-center cqa-flex-col\">\n <div class=\"cqa-flex cqa-items-center cqa-justify-center\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-1 cqa-items-center cqa-justify-center cqa-w-[60px]\">\n <span class=\"cqa-text-[12px] cqa-leading-[16px] cqa-font-bold cqa-text-primary cqa-flex cqa-items-center cqa-gap-[2px]\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><g clip-path=\"url(#clip0_7415_11751)\"><path d=\"M4.9685 7.75012C4.92386 7.57709 4.83367 7.41918 4.70731 7.29282C4.58095 7.16646 4.42304 7.07626 4.25 7.03162L1.1825 6.24062C1.13017 6.22577 1.08411 6.19425 1.05131 6.15085C1.01851 6.10744 1.00076 6.05453 1.00076 6.00012C1.00076 5.94572 1.01851 5.89281 1.05131 5.8494C1.08411 5.806 1.13017 5.77448 1.1825 5.75962L4.25 4.96812C4.42298 4.92353 4.58085 4.83341 4.7072 4.70714C4.83356 4.58088 4.92378 4.42307 4.9685 4.25012L5.7595 1.18262C5.7742 1.13008 5.80569 1.0838 5.84916 1.05082C5.89263 1.01785 5.94569 1 6.00025 1C6.05481 1 6.10787 1.01785 6.15134 1.05082C6.19481 1.0838 6.2263 1.13008 6.241 1.18262L7.0315 4.25012C7.07614 4.42316 7.16633 4.58107 7.29269 4.70743C7.41905 4.83379 7.57696 4.92399 7.75 4.96862L10.8175 5.75912C10.8703 5.77367 10.9168 5.80513 10.9499 5.84866C10.9831 5.8922 11.001 5.94541 11.001 6.00012C11.001 6.05484 10.9831 6.10805 10.9499 6.15159C10.9168 6.19512 10.8703 6.22657 10.8175 6.24112L7.75 7.03162C7.57696 7.07626 7.41905 7.16646 7.29269 7.29282C7.16633 7.41918 7.07614 7.57709 7.0315 7.75012L6.2405 10.8176C6.2258 10.8702 6.19431 10.9165 6.15084 10.9494C6.10737 10.9824 6.05431 11.0002 5.99975 11.0002C5.94519 11.0002 5.89213 10.9824 5.84866 10.9494C5.80519 10.9165 5.7737 10.8702 5.759 10.8176L4.9685 7.75012Z\" stroke=\"#7C3AED\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M10 1.5V3.5\" stroke=\"#7C3AED\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M11 2.5H9\" stroke=\"#7C3AED\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M2 8.5V9.5\" stroke=\"#7C3AED\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M2.5 9H1.5\" stroke=\"#7C3AED\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></g><defs><clipPath id=\"clip0_7415_11751\"><rect width=\"12\" height=\"12\" fill=\"white\"/></clipPath></defs></svg>\n {{ aiLabel }}\n </span>\n <span class=\"cqa-text-[14px] cqa-leading-[20px] cqa-font-bold cqa-text-dialog\">{{ aiCount }}</span>\n </div>\n <div class=\"cqa-bg-primary-surface cqa-w-[2px] cqa-h-full cqa-mx-[3.5px]\"></div>\n <div class=\"cqa-flex cqa-flex-col cqa-gap-1 cqa-items-center cqa-justify-center cqa-w-[60px]\">\n <span class=\"cqa-text-[12px] cqa-leading-[16px] cqa-font-bold cqa-text-dialog-secondary cqa-flex cqa-items-center cqa-gap-[2px]\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M9.5 10.5V9.5C9.5 8.96957 9.28929 8.46086 8.91421 8.08579C8.53914 7.71071 8.03043 7.5 7.5 7.5H4.5C3.96957 7.5 3.46086 7.71071 3.08579 8.08579C2.71071 8.46086 2.5 8.96957 2.5 9.5V10.5\" stroke=\"#3F43EE\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M6 5.5C7.10457 5.5 8 4.60457 8 3.5C8 2.39543 7.10457 1.5 6 1.5C4.89543 1.5 4 2.39543 4 3.5C4 4.60457 4.89543 5.5 6 5.5Z\" stroke=\"#3F43EE\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n {{ humanLabel }}\n </span>\n <span class=\"cqa-text-[14px] cqa-leading-[20px] cqa-font-bold cqa-text-dialog\">{{ humanCount }}</span>\n </div>\n </div>\n <div class=\"cqa-text-[12px] cqa-leading-[16px] cqa-text-dialog-muted cqa-pt-[2px] cqa-pb-1\">Coverage</div>\n </div>\n </div>\n\n <!-- Body -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-2 cqa-mb-3\">\n <div *ngFor=\"let it of items\" class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <span class=\"md:cqa-w-full md:cqa-max-w-[216px] cqa-text-[12px] cqa-leading-[16px] cqa-text-dialog-secondary cqa-flex cqa-items-center cqa-gap-2\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M12.8333 6.46309V6.99976C12.8326 8.25767 12.4253 9.48165 11.6721 10.4892C10.9189 11.4967 9.86025 12.2337 8.65396 12.5904C7.44767 12.947 6.1584 12.9042 4.97844 12.4683C3.79848 12.0323 2.79105 11.2266 2.10639 10.1714C1.42174 9.11611 1.09654 7.8678 1.17931 6.61261C1.26208 5.35742 1.74837 4.16262 2.56566 3.20638C3.38295 2.25015 4.48746 1.58373 5.71444 1.30651C6.94143 1.02929 8.22515 1.15612 9.37417 1.66809\" stroke=\"#10B981\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M5.25 6.41634L7 8.16634L12.8333 2.33301\" stroke=\"#10B981\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n <!-- <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M7 12.8337C10.2217 12.8337 12.8333 10.222 12.8333 7.00033C12.8333 3.77866 10.2217 1.16699 7 1.16699C3.77834 1.16699 1.16666 3.77866 1.16666 7.00033C1.16666 10.222 3.77834 12.8337 7 12.8337Z\" stroke=\"#EF4444\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M7 4.66699V7.00033\" stroke=\"#EF4444\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M7 9.33301H7.00583\" stroke=\"#EF4444\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg> -->\n {{ it.label }}\n </span>\n <div class=\"cqa-flex-1 cqa-h-[6px] cqa-rounded-full cqa-bg-[#F3F4F6] cqa-overflow-hidden\">\n <div class=\"cqa-h-full cqa-rounded-full\" [ngClass]=\"statusColorClass(it)\"\n [style.width]=\"formatPercent(it.percent)\"></div>\n </div>\n <span class=\"cqa-min-w-[40px] cqa-text-[12px] cqa-leading-[16px] cqa-font-bold\" [ngClass]=\"textColorClass(it)\">{{\n formatPercent(it.percent) }}</span>\n </div>\n </div>\n\n <!-- Footer -->\n <cqa-button variant=\"filled\" [customClass]=\"'cqa-w-full cqa-text-[14px] cqa-leading-[20px] cqa-font-semibold'\">\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 18 18\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M9.01882 0C9.12979 0.0454767 9.17718 0.15653 9.22261 0.259691C9.24539 0.319799 9.26628 0.380234 9.28657 0.44115C9.29452 0.464493 9.30246 0.487836 9.31065 0.511886C9.41613 0.826009 9.51008 1.1435 9.60457 1.46076C9.62593 1.53238 9.64739 1.60397 9.66885 1.67557C9.7781 2.04007 9.88654 2.4048 9.99438 2.76969C10.0095 2.82093 10.0247 2.87218 10.0398 2.92342C10.0826 3.0679 10.1252 3.21239 10.1677 3.35694C10.2573 3.66239 10.3495 3.96695 10.4476 4.27002C10.4561 4.29653 10.4647 4.32305 10.4735 4.35036C10.7284 5.12999 11.0896 5.82875 11.6818 6.42393C11.6965 6.4394 11.7111 6.45488 11.7262 6.47083C11.979 6.72875 12.3034 6.93541 12.6276 7.10221C12.6441 7.11085 12.6606 7.11948 12.6776 7.12838C13.6317 7.61851 14.779 7.83407 15.8124 8.12101C16.2652 8.24681 16.7166 8.37658 17.1663 8.51206C17.1979 8.52157 17.2296 8.53107 17.2612 8.54055C17.3557 8.5689 17.45 8.59774 17.5442 8.62694C17.5662 8.63358 17.5882 8.64023 17.6108 8.64707C17.7406 8.68812 17.8648 8.73658 17.9713 8.82054C18.0038 8.88837 18.0038 8.88837 17.995 8.95619C17.8913 9.05472 17.7884 9.10092 17.6516 9.14599C17.632 9.15264 17.6124 9.1593 17.5923 9.16615C17.3612 9.24366 17.127 9.31149 16.8925 9.37871C16.8444 9.39261 16.7963 9.40651 16.7482 9.42042C16.4514 9.50603 16.1542 9.5898 15.8566 9.67263C15.4646 9.78175 15.0733 9.89268 14.6823 10.0049C14.6182 10.0232 14.5541 10.0416 14.49 10.0598C14.1534 10.1557 13.8185 10.2551 13.4863 10.3642C13.4587 10.3732 13.4312 10.3822 13.4028 10.3915C12.2902 10.7616 11.4422 11.4522 10.9114 12.462C10.6253 13.0295 10.4565 13.6432 10.2843 14.2489C10.2377 14.4124 10.1882 14.5749 10.1381 14.7374C10.0988 14.8652 10.0604 14.9933 10.023 15.1216C10.0185 15.1369 10.0141 15.1522 10.0095 15.1679C9.98788 15.2419 9.96638 15.3159 9.94503 15.3899C9.89039 15.5776 9.83156 15.7637 9.77111 15.9498C9.66383 16.2804 9.5662 16.6135 9.46917 16.947C9.32288 17.4491 9.32288 17.4491 9.23993 17.6905C9.23443 17.7067 9.22893 17.7229 9.22326 17.7396C9.19298 17.8256 9.16183 17.9047 9.10453 17.9774C9.01734 17.9958 9.01734 17.9958 8.93901 18C8.84946 17.8752 8.79016 17.7542 8.74265 17.6102C8.73574 17.5897 8.72882 17.5693 8.7217 17.5483C8.63368 17.285 8.55502 17.0189 8.47634 16.7529C8.45832 16.6921 8.44022 16.6313 8.42211 16.5705C8.2872 16.1173 8.15451 15.6635 8.02202 15.2096C7.47014 12.9645 7.47014 12.9645 6.078 11.1493C6.05569 11.1319 6.03338 11.1145 6.01039 11.0966C5.09826 10.398 3.89667 10.1394 2.7963 9.83627C2.52415 9.76124 2.2521 9.68587 1.98006 9.61046C1.95628 9.60386 1.95628 9.60386 1.93201 9.59714C1.53962 9.48834 1.14735 9.37925 0.756448 9.26566C0.739911 9.26089 0.723375 9.25612 0.706338 9.25121C0.105798 9.07767 0.105798 9.07767 0.00129307 8.95619C-0.00166252 8.90108 -0.00166252 8.90108 0.0249378 8.84315C0.134167 8.7408 0.240153 8.69696 0.38432 8.65238C0.405194 8.64567 0.426068 8.63897 0.447574 8.63206C0.511506 8.61164 0.575577 8.59169 0.639702 8.57183C0.658001 8.56609 0.676301 8.56035 0.695155 8.55443C0.82457 8.51385 0.95445 8.47479 1.08452 8.43618C1.11648 8.42665 1.11648 8.42665 1.14909 8.41693C1.70454 8.25174 2.26361 8.09801 2.82252 7.94392C3.23899 7.82909 3.65476 7.71236 4.06921 7.59097C4.08825 7.58542 4.1073 7.57987 4.12692 7.57415C5.087 7.29393 6.02557 6.89632 6.64547 6.1074C6.65475 6.09569 6.66403 6.08399 6.6736 6.07194C7.36395 5.1963 7.63315 4.13145 7.93391 3.09241C8.03285 2.75069 8.13298 2.40929 8.23345 2.06798C8.26127 1.97347 8.28906 1.87894 8.31673 1.78439C8.42788 1.40458 8.5407 1.02528 8.66 0.647727C8.67116 0.612372 8.68227 0.577001 8.69333 0.541614C8.86035 0.00797522 8.86035 0.00797522 9.01882 0Z\" fill=\"#FBFCFF\"/><path d=\"M14.4719 1.11069C14.5805 1.22817 14.6022 1.36624 14.636 1.51625C14.7487 1.98751 14.8786 2.42084 15.3293 2.6946C15.6074 2.84167 15.9389 2.90859 16.247 2.9718C16.3771 2.99902 16.4869 3.03515 16.5985 3.1074C16.6236 3.14555 16.6236 3.14555 16.6221 3.21197C16.5963 3.29273 16.5736 3.31878 16.5054 3.37165C16.4308 3.39549 16.4308 3.39549 16.3413 3.41404C16.3075 3.42147 16.2736 3.42898 16.2398 3.43656C16.2217 3.44058 16.2036 3.4446 16.1849 3.44874C15.6339 3.57062 15.6339 3.57062 15.1576 3.84645C15.1421 3.85837 15.1267 3.87029 15.1107 3.88257C14.7703 4.16959 14.6983 4.64703 14.5958 5.04699C14.59 5.06896 14.5841 5.09092 14.578 5.11355C14.573 5.133 14.5679 5.15244 14.5627 5.17248C14.5405 5.23185 14.5176 5.27057 14.4719 5.31607C14.3447 5.33152 14.3447 5.33152 14.2828 5.31607C14.1843 5.24309 14.1623 5.15997 14.1366 5.04828C14.1322 5.03099 14.1279 5.01369 14.1235 4.99587C14.1098 4.94064 14.0965 4.88531 14.0833 4.82996C13.9796 4.39891 13.8625 3.976 13.449 3.72333C13.1258 3.55101 12.7329 3.46951 12.3717 3.4037C12.2727 3.38399 12.216 3.3592 12.1547 3.28121C12.1414 3.20208 12.1414 3.20208 12.1547 3.12294C12.2489 3.02971 12.348 3.00696 12.4754 2.97881C12.5156 2.9693 12.5557 2.95973 12.5958 2.9501C12.6165 2.94516 12.6372 2.94022 12.6586 2.93512C12.7642 2.90911 12.8689 2.87995 12.9734 2.85021C12.9924 2.84494 13.0114 2.83967 13.031 2.83424C13.2436 2.77346 13.4271 2.69571 13.5971 2.5577C13.6129 2.54523 13.6288 2.53276 13.6451 2.5199C13.9096 2.29228 13.9995 1.95032 14.081 1.63124C14.0873 1.60702 14.0935 1.5828 14.0999 1.55784C14.1123 1.50918 14.1244 1.46046 14.1363 1.4117C14.1449 1.37776 14.1449 1.37776 14.1535 1.34315C14.1585 1.32288 14.1635 1.30261 14.1686 1.28172C14.1904 1.21719 14.219 1.16652 14.2591 1.11069C14.3362 1.07385 14.3903 1.0905 14.4719 1.11069Z\" fill=\"#FBFCFF\"/><path d=\"M3.59089 12.4942C3.61902 12.4944 3.61902 12.4944 3.64772 12.4946C3.84954 12.5004 3.98609 12.5623 4.13472 12.692C4.30767 12.8707 4.38753 13.0722 4.38299 13.313C4.36357 13.5082 4.24316 13.6787 4.09547 13.8107C3.92163 13.9448 3.74626 13.9892 3.52411 13.983C3.33681 13.9621 3.1606 13.877 3.02785 13.749C2.86276 13.5336 2.8145 13.3361 2.83869 13.0707C2.88867 12.8618 3.03274 12.6923 3.21701 12.5733C3.34502 12.5113 3.44798 12.493 3.59089 12.4942Z\" fill=\"#FBFCFF\"/></svg>\n {{ ctaText }}\n </cqa-button>\n </div>\n</div>", components: [{ type: ButtonComponent, selector: "cqa-button", inputs: ["variant", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass"], outputs: ["clicked"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2044
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: CoverageModuleCardComponent, decorators: [{
|
|
2045
|
+
type: Component,
|
|
2046
|
+
args: [{ selector: 'cqa-coverage-module-card', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div id=\"cqa-ui-root\">\n <div\n class=\"cqa-w-full cqa-bg-white cqa-rounded-[8px] cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-py-[10px] md:cqa-px-[17px] cqa-px-3 cqa-shadow-card\">\n <!-- Header -->\n <div class=\"cqa-flex cqa-items-start cqa-justify-between cqa-mb-3\">\n <h3 class=\"cqa-text-[18px] cqa-leading-[28px] cqa-font-bold cqa-text-dialog\">{{ title }}</h3>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <span\n class=\"cqa-px-[10px] cqa-py-[4px] cqa-text-[12px] cqa-leading-[16px] cqa-flex cqa-items-center cqa-gap-1 cqa-rounded-full cqa-bg-warning-light cqa-text-danger\">\n {{ issues }} {{ issues === 1 ? 'issue' : 'issues' }}\n </span>\n <button type=\"button\"\n class=\"cqa-text-[14px] cqa-leading-[20px] cqa-text-primary cqa-flex cqa-items-center cqa-gap-1\"\n *ngIf=\"showViewAction\" (click)=\"view.emit()\">\n View\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6 12L10 8L6 4\" stroke=\"#4F46E5\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </button>\n </div>\n </div>\n\n <!-- Middle metrics row -->\n <div class=\"cqa-grid md:cqa-grid-cols-4 cqa-grid-cols-2 cqa-gap-3 cqa-mb-4 cqa-border-t cqa-border-b cqa-border-surface-[#F3F4F6] cqa-py-2\">\n <!-- Left: Positive / Negative / Edge Case -->\n <div class=\"cqa-text-center\">\n <div class=\"cqa-text-[18px] cqa-leading-[28px] cqa-font-bold cqa-text-[#059669]\">{{ positiveCount }}</div>\n <div class=\"cqa-text-[12px] cqa-leading-[16px] cqa-text-dialog-muted\">{{ positiveLabel }}</div>\n </div>\n <div class=\"cqa-text-center\">\n <div class=\"cqa-text-[18px] cqa-leading-[28px] cqa-font-bold cqa-text-[#EF4444]\">{{ negativeCount }}</div>\n <div class=\"cqa-text-[12px] cqa-leading-[16px] cqa-text-dialog-muted\">{{ negativeLabel }}</div>\n </div>\n <div class=\"cqa-text-center\">\n <div class=\"cqa-text-[18px] cqa-leading-[28px] cqa-font-bold cqa-text-[#F59E0B]\">{{ edgeCaseCount }}</div>\n <div class=\"cqa-text-[12px] cqa-leading-[16px] cqa-text-dialog-muted\">{{ edgeCaseLabel }}</div>\n </div>\n\n <!-- Right: AI / Human -->\n <div class=\"cqa-text-center cqa-flex cqa-items-center cqa-justify-center cqa-flex-col\">\n <div class=\"cqa-flex cqa-items-center cqa-justify-center\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-1 cqa-items-center cqa-justify-center cqa-w-[60px]\">\n <span class=\"cqa-text-[12px] cqa-leading-[16px] cqa-font-bold cqa-text-primary cqa-flex cqa-items-center cqa-gap-[2px]\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><g clip-path=\"url(#clip0_7415_11751)\"><path d=\"M4.9685 7.75012C4.92386 7.57709 4.83367 7.41918 4.70731 7.29282C4.58095 7.16646 4.42304 7.07626 4.25 7.03162L1.1825 6.24062C1.13017 6.22577 1.08411 6.19425 1.05131 6.15085C1.01851 6.10744 1.00076 6.05453 1.00076 6.00012C1.00076 5.94572 1.01851 5.89281 1.05131 5.8494C1.08411 5.806 1.13017 5.77448 1.1825 5.75962L4.25 4.96812C4.42298 4.92353 4.58085 4.83341 4.7072 4.70714C4.83356 4.58088 4.92378 4.42307 4.9685 4.25012L5.7595 1.18262C5.7742 1.13008 5.80569 1.0838 5.84916 1.05082C5.89263 1.01785 5.94569 1 6.00025 1C6.05481 1 6.10787 1.01785 6.15134 1.05082C6.19481 1.0838 6.2263 1.13008 6.241 1.18262L7.0315 4.25012C7.07614 4.42316 7.16633 4.58107 7.29269 4.70743C7.41905 4.83379 7.57696 4.92399 7.75 4.96862L10.8175 5.75912C10.8703 5.77367 10.9168 5.80513 10.9499 5.84866C10.9831 5.8922 11.001 5.94541 11.001 6.00012C11.001 6.05484 10.9831 6.10805 10.9499 6.15159C10.9168 6.19512 10.8703 6.22657 10.8175 6.24112L7.75 7.03162C7.57696 7.07626 7.41905 7.16646 7.29269 7.29282C7.16633 7.41918 7.07614 7.57709 7.0315 7.75012L6.2405 10.8176C6.2258 10.8702 6.19431 10.9165 6.15084 10.9494C6.10737 10.9824 6.05431 11.0002 5.99975 11.0002C5.94519 11.0002 5.89213 10.9824 5.84866 10.9494C5.80519 10.9165 5.7737 10.8702 5.759 10.8176L4.9685 7.75012Z\" stroke=\"#7C3AED\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M10 1.5V3.5\" stroke=\"#7C3AED\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M11 2.5H9\" stroke=\"#7C3AED\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M2 8.5V9.5\" stroke=\"#7C3AED\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M2.5 9H1.5\" stroke=\"#7C3AED\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></g><defs><clipPath id=\"clip0_7415_11751\"><rect width=\"12\" height=\"12\" fill=\"white\"/></clipPath></defs></svg>\n {{ aiLabel }}\n </span>\n <span class=\"cqa-text-[14px] cqa-leading-[20px] cqa-font-bold cqa-text-dialog\">{{ aiCount }}</span>\n </div>\n <div class=\"cqa-bg-primary-surface cqa-w-[2px] cqa-h-full cqa-mx-[3.5px]\"></div>\n <div class=\"cqa-flex cqa-flex-col cqa-gap-1 cqa-items-center cqa-justify-center cqa-w-[60px]\">\n <span class=\"cqa-text-[12px] cqa-leading-[16px] cqa-font-bold cqa-text-dialog-secondary cqa-flex cqa-items-center cqa-gap-[2px]\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M9.5 10.5V9.5C9.5 8.96957 9.28929 8.46086 8.91421 8.08579C8.53914 7.71071 8.03043 7.5 7.5 7.5H4.5C3.96957 7.5 3.46086 7.71071 3.08579 8.08579C2.71071 8.46086 2.5 8.96957 2.5 9.5V10.5\" stroke=\"#3F43EE\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M6 5.5C7.10457 5.5 8 4.60457 8 3.5C8 2.39543 7.10457 1.5 6 1.5C4.89543 1.5 4 2.39543 4 3.5C4 4.60457 4.89543 5.5 6 5.5Z\" stroke=\"#3F43EE\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n {{ humanLabel }}\n </span>\n <span class=\"cqa-text-[14px] cqa-leading-[20px] cqa-font-bold cqa-text-dialog\">{{ humanCount }}</span>\n </div>\n </div>\n <div class=\"cqa-text-[12px] cqa-leading-[16px] cqa-text-dialog-muted cqa-pt-[2px] cqa-pb-1\">Coverage</div>\n </div>\n </div>\n\n <!-- Body -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-2 cqa-mb-3\">\n <div *ngFor=\"let it of items\" class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <span class=\"md:cqa-w-full md:cqa-max-w-[216px] cqa-text-[12px] cqa-leading-[16px] cqa-text-dialog-secondary cqa-flex cqa-items-center cqa-gap-2\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M12.8333 6.46309V6.99976C12.8326 8.25767 12.4253 9.48165 11.6721 10.4892C10.9189 11.4967 9.86025 12.2337 8.65396 12.5904C7.44767 12.947 6.1584 12.9042 4.97844 12.4683C3.79848 12.0323 2.79105 11.2266 2.10639 10.1714C1.42174 9.11611 1.09654 7.8678 1.17931 6.61261C1.26208 5.35742 1.74837 4.16262 2.56566 3.20638C3.38295 2.25015 4.48746 1.58373 5.71444 1.30651C6.94143 1.02929 8.22515 1.15612 9.37417 1.66809\" stroke=\"#10B981\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M5.25 6.41634L7 8.16634L12.8333 2.33301\" stroke=\"#10B981\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n <!-- <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M7 12.8337C10.2217 12.8337 12.8333 10.222 12.8333 7.00033C12.8333 3.77866 10.2217 1.16699 7 1.16699C3.77834 1.16699 1.16666 3.77866 1.16666 7.00033C1.16666 10.222 3.77834 12.8337 7 12.8337Z\" stroke=\"#EF4444\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M7 4.66699V7.00033\" stroke=\"#EF4444\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M7 9.33301H7.00583\" stroke=\"#EF4444\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg> -->\n {{ it.label }}\n </span>\n <div class=\"cqa-flex-1 cqa-h-[6px] cqa-rounded-full cqa-bg-[#F3F4F6] cqa-overflow-hidden\">\n <div class=\"cqa-h-full cqa-rounded-full\" [ngClass]=\"statusColorClass(it)\"\n [style.width]=\"formatPercent(it.percent)\"></div>\n </div>\n <span class=\"cqa-min-w-[40px] cqa-text-[12px] cqa-leading-[16px] cqa-font-bold\" [ngClass]=\"textColorClass(it)\">{{\n formatPercent(it.percent) }}</span>\n </div>\n </div>\n\n <!-- Footer -->\n <cqa-button variant=\"filled\" [customClass]=\"'cqa-w-full cqa-text-[14px] cqa-leading-[20px] cqa-font-semibold'\">\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 18 18\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M9.01882 0C9.12979 0.0454767 9.17718 0.15653 9.22261 0.259691C9.24539 0.319799 9.26628 0.380234 9.28657 0.44115C9.29452 0.464493 9.30246 0.487836 9.31065 0.511886C9.41613 0.826009 9.51008 1.1435 9.60457 1.46076C9.62593 1.53238 9.64739 1.60397 9.66885 1.67557C9.7781 2.04007 9.88654 2.4048 9.99438 2.76969C10.0095 2.82093 10.0247 2.87218 10.0398 2.92342C10.0826 3.0679 10.1252 3.21239 10.1677 3.35694C10.2573 3.66239 10.3495 3.96695 10.4476 4.27002C10.4561 4.29653 10.4647 4.32305 10.4735 4.35036C10.7284 5.12999 11.0896 5.82875 11.6818 6.42393C11.6965 6.4394 11.7111 6.45488 11.7262 6.47083C11.979 6.72875 12.3034 6.93541 12.6276 7.10221C12.6441 7.11085 12.6606 7.11948 12.6776 7.12838C13.6317 7.61851 14.779 7.83407 15.8124 8.12101C16.2652 8.24681 16.7166 8.37658 17.1663 8.51206C17.1979 8.52157 17.2296 8.53107 17.2612 8.54055C17.3557 8.5689 17.45 8.59774 17.5442 8.62694C17.5662 8.63358 17.5882 8.64023 17.6108 8.64707C17.7406 8.68812 17.8648 8.73658 17.9713 8.82054C18.0038 8.88837 18.0038 8.88837 17.995 8.95619C17.8913 9.05472 17.7884 9.10092 17.6516 9.14599C17.632 9.15264 17.6124 9.1593 17.5923 9.16615C17.3612 9.24366 17.127 9.31149 16.8925 9.37871C16.8444 9.39261 16.7963 9.40651 16.7482 9.42042C16.4514 9.50603 16.1542 9.5898 15.8566 9.67263C15.4646 9.78175 15.0733 9.89268 14.6823 10.0049C14.6182 10.0232 14.5541 10.0416 14.49 10.0598C14.1534 10.1557 13.8185 10.2551 13.4863 10.3642C13.4587 10.3732 13.4312 10.3822 13.4028 10.3915C12.2902 10.7616 11.4422 11.4522 10.9114 12.462C10.6253 13.0295 10.4565 13.6432 10.2843 14.2489C10.2377 14.4124 10.1882 14.5749 10.1381 14.7374C10.0988 14.8652 10.0604 14.9933 10.023 15.1216C10.0185 15.1369 10.0141 15.1522 10.0095 15.1679C9.98788 15.2419 9.96638 15.3159 9.94503 15.3899C9.89039 15.5776 9.83156 15.7637 9.77111 15.9498C9.66383 16.2804 9.5662 16.6135 9.46917 16.947C9.32288 17.4491 9.32288 17.4491 9.23993 17.6905C9.23443 17.7067 9.22893 17.7229 9.22326 17.7396C9.19298 17.8256 9.16183 17.9047 9.10453 17.9774C9.01734 17.9958 9.01734 17.9958 8.93901 18C8.84946 17.8752 8.79016 17.7542 8.74265 17.6102C8.73574 17.5897 8.72882 17.5693 8.7217 17.5483C8.63368 17.285 8.55502 17.0189 8.47634 16.7529C8.45832 16.6921 8.44022 16.6313 8.42211 16.5705C8.2872 16.1173 8.15451 15.6635 8.02202 15.2096C7.47014 12.9645 7.47014 12.9645 6.078 11.1493C6.05569 11.1319 6.03338 11.1145 6.01039 11.0966C5.09826 10.398 3.89667 10.1394 2.7963 9.83627C2.52415 9.76124 2.2521 9.68587 1.98006 9.61046C1.95628 9.60386 1.95628 9.60386 1.93201 9.59714C1.53962 9.48834 1.14735 9.37925 0.756448 9.26566C0.739911 9.26089 0.723375 9.25612 0.706338 9.25121C0.105798 9.07767 0.105798 9.07767 0.00129307 8.95619C-0.00166252 8.90108 -0.00166252 8.90108 0.0249378 8.84315C0.134167 8.7408 0.240153 8.69696 0.38432 8.65238C0.405194 8.64567 0.426068 8.63897 0.447574 8.63206C0.511506 8.61164 0.575577 8.59169 0.639702 8.57183C0.658001 8.56609 0.676301 8.56035 0.695155 8.55443C0.82457 8.51385 0.95445 8.47479 1.08452 8.43618C1.11648 8.42665 1.11648 8.42665 1.14909 8.41693C1.70454 8.25174 2.26361 8.09801 2.82252 7.94392C3.23899 7.82909 3.65476 7.71236 4.06921 7.59097C4.08825 7.58542 4.1073 7.57987 4.12692 7.57415C5.087 7.29393 6.02557 6.89632 6.64547 6.1074C6.65475 6.09569 6.66403 6.08399 6.6736 6.07194C7.36395 5.1963 7.63315 4.13145 7.93391 3.09241C8.03285 2.75069 8.13298 2.40929 8.23345 2.06798C8.26127 1.97347 8.28906 1.87894 8.31673 1.78439C8.42788 1.40458 8.5407 1.02528 8.66 0.647727C8.67116 0.612372 8.68227 0.577001 8.69333 0.541614C8.86035 0.00797522 8.86035 0.00797522 9.01882 0Z\" fill=\"#FBFCFF\"/><path d=\"M14.4719 1.11069C14.5805 1.22817 14.6022 1.36624 14.636 1.51625C14.7487 1.98751 14.8786 2.42084 15.3293 2.6946C15.6074 2.84167 15.9389 2.90859 16.247 2.9718C16.3771 2.99902 16.4869 3.03515 16.5985 3.1074C16.6236 3.14555 16.6236 3.14555 16.6221 3.21197C16.5963 3.29273 16.5736 3.31878 16.5054 3.37165C16.4308 3.39549 16.4308 3.39549 16.3413 3.41404C16.3075 3.42147 16.2736 3.42898 16.2398 3.43656C16.2217 3.44058 16.2036 3.4446 16.1849 3.44874C15.6339 3.57062 15.6339 3.57062 15.1576 3.84645C15.1421 3.85837 15.1267 3.87029 15.1107 3.88257C14.7703 4.16959 14.6983 4.64703 14.5958 5.04699C14.59 5.06896 14.5841 5.09092 14.578 5.11355C14.573 5.133 14.5679 5.15244 14.5627 5.17248C14.5405 5.23185 14.5176 5.27057 14.4719 5.31607C14.3447 5.33152 14.3447 5.33152 14.2828 5.31607C14.1843 5.24309 14.1623 5.15997 14.1366 5.04828C14.1322 5.03099 14.1279 5.01369 14.1235 4.99587C14.1098 4.94064 14.0965 4.88531 14.0833 4.82996C13.9796 4.39891 13.8625 3.976 13.449 3.72333C13.1258 3.55101 12.7329 3.46951 12.3717 3.4037C12.2727 3.38399 12.216 3.3592 12.1547 3.28121C12.1414 3.20208 12.1414 3.20208 12.1547 3.12294C12.2489 3.02971 12.348 3.00696 12.4754 2.97881C12.5156 2.9693 12.5557 2.95973 12.5958 2.9501C12.6165 2.94516 12.6372 2.94022 12.6586 2.93512C12.7642 2.90911 12.8689 2.87995 12.9734 2.85021C12.9924 2.84494 13.0114 2.83967 13.031 2.83424C13.2436 2.77346 13.4271 2.69571 13.5971 2.5577C13.6129 2.54523 13.6288 2.53276 13.6451 2.5199C13.9096 2.29228 13.9995 1.95032 14.081 1.63124C14.0873 1.60702 14.0935 1.5828 14.0999 1.55784C14.1123 1.50918 14.1244 1.46046 14.1363 1.4117C14.1449 1.37776 14.1449 1.37776 14.1535 1.34315C14.1585 1.32288 14.1635 1.30261 14.1686 1.28172C14.1904 1.21719 14.219 1.16652 14.2591 1.11069C14.3362 1.07385 14.3903 1.0905 14.4719 1.11069Z\" fill=\"#FBFCFF\"/><path d=\"M3.59089 12.4942C3.61902 12.4944 3.61902 12.4944 3.64772 12.4946C3.84954 12.5004 3.98609 12.5623 4.13472 12.692C4.30767 12.8707 4.38753 13.0722 4.38299 13.313C4.36357 13.5082 4.24316 13.6787 4.09547 13.8107C3.92163 13.9448 3.74626 13.9892 3.52411 13.983C3.33681 13.9621 3.1606 13.877 3.02785 13.749C2.86276 13.5336 2.8145 13.3361 2.83869 13.0707C2.88867 12.8618 3.03274 12.6923 3.21701 12.5733C3.34502 12.5113 3.44798 12.493 3.59089 12.4942Z\" fill=\"#FBFCFF\"/></svg>\n {{ ctaText }}\n </cqa-button>\n </div>\n</div>", styles: [] }]
|
|
2047
|
+
}], propDecorators: { title: [{
|
|
2048
|
+
type: Input
|
|
2049
|
+
}], issues: [{
|
|
2050
|
+
type: Input
|
|
2051
|
+
}], showViewAction: [{
|
|
2052
|
+
type: Input
|
|
2053
|
+
}], positiveCount: [{
|
|
2054
|
+
type: Input
|
|
2055
|
+
}], negativeCount: [{
|
|
2056
|
+
type: Input
|
|
2057
|
+
}], edgeCaseCount: [{
|
|
2058
|
+
type: Input
|
|
2059
|
+
}], positiveLabel: [{
|
|
2060
|
+
type: Input
|
|
2061
|
+
}], negativeLabel: [{
|
|
2062
|
+
type: Input
|
|
2063
|
+
}], edgeCaseLabel: [{
|
|
2064
|
+
type: Input
|
|
2065
|
+
}], aiCount: [{
|
|
2066
|
+
type: Input
|
|
2067
|
+
}], humanCount: [{
|
|
2068
|
+
type: Input
|
|
2069
|
+
}], aiLabel: [{
|
|
2070
|
+
type: Input
|
|
2071
|
+
}], humanLabel: [{
|
|
2072
|
+
type: Input
|
|
2073
|
+
}], items: [{
|
|
2074
|
+
type: Input
|
|
2075
|
+
}], ctaText: [{
|
|
2076
|
+
type: Input
|
|
2077
|
+
}], ctaDisabled: [{
|
|
2078
|
+
type: Input
|
|
2079
|
+
}], view: [{
|
|
2080
|
+
type: Output
|
|
2081
|
+
}], ctaClicked: [{
|
|
2082
|
+
type: Output
|
|
2083
|
+
}] } });
|
|
2084
|
+
|
|
2085
|
+
class TestDistributionCardComponent {
|
|
2086
|
+
constructor() {
|
|
2087
|
+
this.title = 'Test Distribution';
|
|
2088
|
+
this.segments = [];
|
|
2089
|
+
this.items = [];
|
|
2090
|
+
}
|
|
2091
|
+
totalSegments() {
|
|
2092
|
+
return this.segments.reduce((sum, s) => sum + (s.value || 0), 0) || 1;
|
|
2093
|
+
}
|
|
2094
|
+
segmentWidth(segment) {
|
|
2095
|
+
const total = this.totalSegments();
|
|
2096
|
+
const pct = Math.max(0, Math.min(100, (segment.value / total) * 100));
|
|
2097
|
+
return pct + '%';
|
|
2098
|
+
}
|
|
2099
|
+
segmentColor(segment, fallback) {
|
|
2100
|
+
return segment.colorClass || fallback;
|
|
2101
|
+
}
|
|
2102
|
+
}
|
|
2103
|
+
TestDistributionCardComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TestDistributionCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2104
|
+
TestDistributionCardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TestDistributionCardComponent, selector: "cqa-test-distribution-card", inputs: { title: "title", segments: "segments", items: "items" }, ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <div class=\"cqa-w-full cqa-bg-white cqa-rounded-[10px] cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-p-4\">\n <!-- Title -->\n <h3 class=\"cqa-text-[16px] cqa-leading-6 cqa-font-medium cqa-text-[#111827] cqa-mb-3\">{{ title }}</h3>\n\n <!-- Stacked segments pill -->\n <div class=\"cqa-w-full cqa-h-[28px] cqa-rounded-full cqa-bg-[#F3F4F6] cqa-overflow-hidden cqa-flex cqa-mb-3\">\n <ng-container *ngFor=\"let s of segments; let i = index; let last = last\">\n <div\n class=\"cqa-h-full cqa-flex cqa-items-center cqa-justify-center cqa-text-white cqa-text-[12px] cqa-leading-[12px]\"\n [ngClass]=\"[\n segmentColor(s, i === 0 ? 'cqa-bg-[#4F46E5]' : i === segments.length - 1 ? 'cqa-bg-[#10B981]' : 'cqa-bg-[#8B5CF6]'),\n i === 0 ? 'cqa-rounded-l-full' : '',\n last ? 'cqa-rounded-r-full' : ''\n ]\" [style.width]=\"segmentWidth(s)\">\n {{ s.label }}\n </div>\n </ng-container>\n </div>\n\n <!-- Items list -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-2\">\n <div *ngFor=\"let it of items\" class=\"cqa-flex cqa-flex-col\">\n <!-- Parent row -->\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-py-1\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <mat-icon class=\"cqa-text-[#6B7280]\" [style.width.px]=\"16\" [style.height.px]=\"16\" [style.fontSize.px]=\"16\"\n *ngIf=\"it.icon\">{{ it.icon }}</mat-icon>\n <span class=\"cqa-text-[14px] cqa-leading-5 cqa-text-[#111827]\">{{ it.label }}</span>\n </div>\n <div class=\"cqa-text-[14px] cqa-leading-5 cqa-font-semibold cqa-text-[#111827]\">{{ it.value | number }}</div>\n </div>\n\n <!-- Children rows -->\n <div *ngIf=\"it.children?.length\" class=\"cqa-flex cqa-flex-col cqa-gap-2\">\n <div *ngFor=\"let ch of it.children\"\n class=\"cqa-flex cqa-items-center cqa-justify-between cqa-px-2 cqa-py-1 cqa-rounded-md cqa-bg-[#F9FAFB] cqa-text-[#6B7280]\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <span class=\"cqa-w-[6px] cqa-h-[14px] cqa-rounded-full\"\n [ngClass]=\"ch.colorClass || 'cqa-bg-[#8B5CF6]'\"></span>\n <span class=\"cqa-text-[12px] cqa-leading-5\">\n {{ ch.label }}\n <span class=\"cqa-font-semibold cqa-text-[#111827]\">{{ ch.value }}</span>\n </span>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], pipes: { "number": i2.DecimalPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2105
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TestDistributionCardComponent, decorators: [{
|
|
2106
|
+
type: Component,
|
|
2107
|
+
args: [{ selector: 'cqa-test-distribution-card', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div id=\"cqa-ui-root\">\n <div class=\"cqa-w-full cqa-bg-white cqa-rounded-[10px] cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-p-4\">\n <!-- Title -->\n <h3 class=\"cqa-text-[16px] cqa-leading-6 cqa-font-medium cqa-text-[#111827] cqa-mb-3\">{{ title }}</h3>\n\n <!-- Stacked segments pill -->\n <div class=\"cqa-w-full cqa-h-[28px] cqa-rounded-full cqa-bg-[#F3F4F6] cqa-overflow-hidden cqa-flex cqa-mb-3\">\n <ng-container *ngFor=\"let s of segments; let i = index; let last = last\">\n <div\n class=\"cqa-h-full cqa-flex cqa-items-center cqa-justify-center cqa-text-white cqa-text-[12px] cqa-leading-[12px]\"\n [ngClass]=\"[\n segmentColor(s, i === 0 ? 'cqa-bg-[#4F46E5]' : i === segments.length - 1 ? 'cqa-bg-[#10B981]' : 'cqa-bg-[#8B5CF6]'),\n i === 0 ? 'cqa-rounded-l-full' : '',\n last ? 'cqa-rounded-r-full' : ''\n ]\" [style.width]=\"segmentWidth(s)\">\n {{ s.label }}\n </div>\n </ng-container>\n </div>\n\n <!-- Items list -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-2\">\n <div *ngFor=\"let it of items\" class=\"cqa-flex cqa-flex-col\">\n <!-- Parent row -->\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-py-1\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <mat-icon class=\"cqa-text-[#6B7280]\" [style.width.px]=\"16\" [style.height.px]=\"16\" [style.fontSize.px]=\"16\"\n *ngIf=\"it.icon\">{{ it.icon }}</mat-icon>\n <span class=\"cqa-text-[14px] cqa-leading-5 cqa-text-[#111827]\">{{ it.label }}</span>\n </div>\n <div class=\"cqa-text-[14px] cqa-leading-5 cqa-font-semibold cqa-text-[#111827]\">{{ it.value | number }}</div>\n </div>\n\n <!-- Children rows -->\n <div *ngIf=\"it.children?.length\" class=\"cqa-flex cqa-flex-col cqa-gap-2\">\n <div *ngFor=\"let ch of it.children\"\n class=\"cqa-flex cqa-items-center cqa-justify-between cqa-px-2 cqa-py-1 cqa-rounded-md cqa-bg-[#F9FAFB] cqa-text-[#6B7280]\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <span class=\"cqa-w-[6px] cqa-h-[14px] cqa-rounded-full\"\n [ngClass]=\"ch.colorClass || 'cqa-bg-[#8B5CF6]'\"></span>\n <span class=\"cqa-text-[12px] cqa-leading-5\">\n {{ ch.label }}\n <span class=\"cqa-font-semibold cqa-text-[#111827]\">{{ ch.value }}</span>\n </span>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>", styles: [] }]
|
|
2108
|
+
}], propDecorators: { title: [{
|
|
2109
|
+
type: Input
|
|
2110
|
+
}], segments: [{
|
|
2111
|
+
type: Input
|
|
2112
|
+
}], items: [{
|
|
2113
|
+
type: Input
|
|
2114
|
+
}] } });
|
|
2115
|
+
|
|
2116
|
+
class FailedTestCasesCardComponent {
|
|
2117
|
+
constructor() {
|
|
2118
|
+
/** E.g., "C-62: Upload Content" */
|
|
2119
|
+
this.title = 'Failed Test Case';
|
|
2120
|
+
/** Number of failures to display in the pill */
|
|
2121
|
+
this.failures = 0;
|
|
2122
|
+
/** Pill label (e.g., "failures") */
|
|
2123
|
+
this.failuresLabel = 'failures';
|
|
2124
|
+
/** Optional custom class for the pill background */
|
|
2125
|
+
this.pillClass = 'cqa-bg-[#F15F5F] cqa-text-[#FAFAFA]';
|
|
2126
|
+
/** Root cause label (left part, emphasized) */
|
|
2127
|
+
this.rootCauseLabel = 'Root cause';
|
|
2128
|
+
/** If false, hide the root cause row */
|
|
2129
|
+
this.showRootCause = true;
|
|
2130
|
+
/** Label for timestamp */
|
|
2131
|
+
this.lastFailedLabel = 'Last failed';
|
|
2132
|
+
/** Optional extra class for the outer card */
|
|
2133
|
+
this.cardClass = '';
|
|
2134
|
+
/** Left border accent class */
|
|
2135
|
+
this.leftAccentClass = 'cqa-border-l-[4px] cqa-border-[#EF4444]';
|
|
2136
|
+
}
|
|
2137
|
+
get rootCauseDisplay() {
|
|
2138
|
+
return this.rootCause && this.rootCause.trim().length
|
|
2139
|
+
? this.rootCause
|
|
2140
|
+
: 'No root cause available';
|
|
2141
|
+
}
|
|
2142
|
+
}
|
|
2143
|
+
FailedTestCasesCardComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: FailedTestCasesCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2144
|
+
FailedTestCasesCardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: FailedTestCasesCardComponent, selector: "cqa-failed-test-cases-card", inputs: { title: "title", failures: "failures", failuresLabel: "failuresLabel", pillClass: "pillClass", rootCause: "rootCause", rootCauseLabel: "rootCauseLabel", showRootCause: "showRootCause", lastFailed: "lastFailed", lastFailedLabel: "lastFailedLabel", cardClass: "cardClass", leftAccentClass: "leftAccentClass" }, ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <div class=\"cqa-w-full cqa-bg-[#FEF2F240] cqa-rounded-[10px] cqa-p-[10px] cqa-pl-[20px]\"\n [ngClass]=\"[leftAccentClass, cardClass]\">\n <div class=\"cqa-flex cqa-items-start cqa-justify-between cqa-gap-2 cqa-flex-wrap\">\n <!-- Title -->\n <h3 class=\"cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-text-[#1A1A1A]\">{{ title }}</h3>\n\n <!-- Failures pill -->\n <span class=\"cqa-px-[11px] cqa-py-[3px] cqa-rounded-full cqa-text-[12px] cqa-leading-[16px] cqa-font-medium cqa-tracking-[0.3px]\"\n [ngClass]=\"pillClass\">\n {{ failures | number }} {{ failuresLabel }}\n </span>\n </div>\n\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-flex-wrap cqa-mt-2\">\n <!-- Root cause -->\n <div *ngIf=\"showRootCause\" class=\"md:cqa-px-[11px] cqa-py-[3px] cqa-text-[12px] cqa-leading-[15px] cqa-text-[#F15F5F]\">\n <span class=\"cqa-font-semibold\">{{ rootCauseLabel }}: </span>{{ rootCauseDisplay }}\n </div>\n\n <!-- Timestamp -->\n <div *ngIf=\"lastFailed\"\n class=\"cqa-py-[3px] cqa-flex cqa-items-center cqa-gap-1 cqa-text-[10px] cqa-leading-[15px] cqa-font-medium cqa-text-dialog-muted\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M6 11C8.76142 11 11 8.76142 11 6C11 3.23858 8.76142 1 6 1C3.23858 1 1 3.23858 1 6C1 8.76142 3.23858 11 6 11Z\" stroke=\"#6B7280\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M6 3V6L8 7\" stroke=\"#6B7280\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n <span>{{ lastFailedLabel }}: {{ lastFailed }}</span>\n </div>\n </div>\n </div>\n</div>", directives: [{ type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], pipes: { "number": i2.DecimalPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2145
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: FailedTestCasesCardComponent, decorators: [{
|
|
2146
|
+
type: Component,
|
|
2147
|
+
args: [{ selector: 'cqa-failed-test-cases-card', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div id=\"cqa-ui-root\">\n <div class=\"cqa-w-full cqa-bg-[#FEF2F240] cqa-rounded-[10px] cqa-p-[10px] cqa-pl-[20px]\"\n [ngClass]=\"[leftAccentClass, cardClass]\">\n <div class=\"cqa-flex cqa-items-start cqa-justify-between cqa-gap-2 cqa-flex-wrap\">\n <!-- Title -->\n <h3 class=\"cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-text-[#1A1A1A]\">{{ title }}</h3>\n\n <!-- Failures pill -->\n <span class=\"cqa-px-[11px] cqa-py-[3px] cqa-rounded-full cqa-text-[12px] cqa-leading-[16px] cqa-font-medium cqa-tracking-[0.3px]\"\n [ngClass]=\"pillClass\">\n {{ failures | number }} {{ failuresLabel }}\n </span>\n </div>\n\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-flex-wrap cqa-mt-2\">\n <!-- Root cause -->\n <div *ngIf=\"showRootCause\" class=\"md:cqa-px-[11px] cqa-py-[3px] cqa-text-[12px] cqa-leading-[15px] cqa-text-[#F15F5F]\">\n <span class=\"cqa-font-semibold\">{{ rootCauseLabel }}: </span>{{ rootCauseDisplay }}\n </div>\n\n <!-- Timestamp -->\n <div *ngIf=\"lastFailed\"\n class=\"cqa-py-[3px] cqa-flex cqa-items-center cqa-gap-1 cqa-text-[10px] cqa-leading-[15px] cqa-font-medium cqa-text-dialog-muted\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M6 11C8.76142 11 11 8.76142 11 6C11 3.23858 8.76142 1 6 1C3.23858 1 1 3.23858 1 6C1 8.76142 3.23858 11 6 11Z\" stroke=\"#6B7280\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M6 3V6L8 7\" stroke=\"#6B7280\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n <span>{{ lastFailedLabel }}: {{ lastFailed }}</span>\n </div>\n </div>\n </div>\n</div>", styles: [] }]
|
|
2148
|
+
}], propDecorators: { title: [{
|
|
2149
|
+
type: Input
|
|
2150
|
+
}], failures: [{
|
|
2151
|
+
type: Input
|
|
2152
|
+
}], failuresLabel: [{
|
|
2153
|
+
type: Input
|
|
2154
|
+
}], pillClass: [{
|
|
2155
|
+
type: Input
|
|
2156
|
+
}], rootCause: [{
|
|
2157
|
+
type: Input
|
|
2158
|
+
}], rootCauseLabel: [{
|
|
2159
|
+
type: Input
|
|
2160
|
+
}], showRootCause: [{
|
|
2161
|
+
type: Input
|
|
2162
|
+
}], lastFailed: [{
|
|
2163
|
+
type: Input
|
|
2164
|
+
}], lastFailedLabel: [{
|
|
2165
|
+
type: Input
|
|
2166
|
+
}], cardClass: [{
|
|
2167
|
+
type: Input
|
|
2168
|
+
}], leftAccentClass: [{
|
|
2169
|
+
type: Input
|
|
2170
|
+
}] } });
|
|
2171
|
+
|
|
2172
|
+
class SelectedFiltersComponent {
|
|
2173
|
+
constructor() {
|
|
2174
|
+
this.filterApplied = false;
|
|
2175
|
+
this.chips = [];
|
|
2176
|
+
this.removeChip = new EventEmitter();
|
|
2177
|
+
this.clearAll = new EventEmitter();
|
|
2178
|
+
}
|
|
2179
|
+
}
|
|
2180
|
+
SelectedFiltersComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: SelectedFiltersComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2181
|
+
SelectedFiltersComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: SelectedFiltersComponent, selector: "cqa-selected-filters", inputs: { filterApplied: "filterApplied", chips: "chips" }, outputs: { removeChip: "removeChip", clearAll: "clearAll" }, ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <div class=\"cqa-w-full cqa-flex cqa-flex-wrap cqa-justify-end cqa-gap-2 cqa-mb-3\"\n *ngIf=\"filterApplied && (chips?.length || 0)\">\n <div\n class=\"cqa-inline-flex cqa-items-center cqa-gap-2 cqa-px-2 cqa-py-1 cqa-rounded-full cqa-border cqa-border-success-100 cqa-bg-primary-surface\"\n *ngFor=\"let chip of chips\" [matTooltip]=\"chip.hasMore ? chip.fullText : ''\" [matTooltipDisabled]=\"!chip.hasMore\"\n matTooltipPosition=\"above\">\n <span class=\"cqa-text-[12px] cqa-leading-[16px] cqa-font-medium cqa-text-primary\">{{ chip.label || chip.key\n }}:</span>\n <span class=\"cqa-text-[12px] cqa-leading-[16px]\">{{ chip.text }}</span>\n <button type=\"button\"\n class=\"cqa-ml-1 cqa-inline-flex cqa-items-center cqa-justify-center cqa-rounded-full cqa-border cqa-border-transparent hover:cqa-bg-[#EEF2FF]\"\n (click)=\"removeChip.emit(chip)\" aria-label=\"Remove filter\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 12 11\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M8.625 2.875L3.375 8.125\" stroke=\"#3F43EE\" stroke-width=\"0.875\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M3.375 2.875L8.625 8.125\" stroke=\"#3F43EE\" stroke-width=\"0.875\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </button>\n </div>\n\n <button type=\"button\" class=\"cqa-text-[12px] cqa-leading-[16px] cqa-text-grey-300 hover:cqa-underline\"\n (click)=\"clearAll.emit()\">\n Clear All\n </button>\n </div>\n</div>", directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1$2.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2182
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: SelectedFiltersComponent, decorators: [{
|
|
2183
|
+
type: Component,
|
|
2184
|
+
args: [{ selector: 'cqa-selected-filters', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div id=\"cqa-ui-root\">\n <div class=\"cqa-w-full cqa-flex cqa-flex-wrap cqa-justify-end cqa-gap-2 cqa-mb-3\"\n *ngIf=\"filterApplied && (chips?.length || 0)\">\n <div\n class=\"cqa-inline-flex cqa-items-center cqa-gap-2 cqa-px-2 cqa-py-1 cqa-rounded-full cqa-border cqa-border-success-100 cqa-bg-primary-surface\"\n *ngFor=\"let chip of chips\" [matTooltip]=\"chip.hasMore ? chip.fullText : ''\" [matTooltipDisabled]=\"!chip.hasMore\"\n matTooltipPosition=\"above\">\n <span class=\"cqa-text-[12px] cqa-leading-[16px] cqa-font-medium cqa-text-primary\">{{ chip.label || chip.key\n }}:</span>\n <span class=\"cqa-text-[12px] cqa-leading-[16px]\">{{ chip.text }}</span>\n <button type=\"button\"\n class=\"cqa-ml-1 cqa-inline-flex cqa-items-center cqa-justify-center cqa-rounded-full cqa-border cqa-border-transparent hover:cqa-bg-[#EEF2FF]\"\n (click)=\"removeChip.emit(chip)\" aria-label=\"Remove filter\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 12 11\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M8.625 2.875L3.375 8.125\" stroke=\"#3F43EE\" stroke-width=\"0.875\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M3.375 2.875L8.625 8.125\" stroke=\"#3F43EE\" stroke-width=\"0.875\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </button>\n </div>\n\n <button type=\"button\" class=\"cqa-text-[12px] cqa-leading-[16px] cqa-text-grey-300 hover:cqa-underline\"\n (click)=\"clearAll.emit()\">\n Clear All\n </button>\n </div>\n</div>", styles: [] }]
|
|
2185
|
+
}], propDecorators: { filterApplied: [{
|
|
2186
|
+
type: Input
|
|
2187
|
+
}], chips: [{
|
|
2188
|
+
type: Input
|
|
2189
|
+
}], removeChip: [{
|
|
2190
|
+
type: Output
|
|
2191
|
+
}], clearAll: [{
|
|
2192
|
+
type: Output
|
|
2193
|
+
}] } });
|
|
2194
|
+
|
|
2195
|
+
/**
|
|
2196
|
+
* Utility for getting consistent colors for metadata values
|
|
2197
|
+
* Used across Status, Priority, and Result fields
|
|
2198
|
+
*
|
|
2199
|
+
* Colors are defined here and also exported in metadata-colors.constants.js for tailwind.config.js
|
|
2200
|
+
*/
|
|
2201
|
+
// Color constants (also exported in metadata-colors.constants.js for Tailwind)
|
|
2202
|
+
const PRIORITY_COLOR_VALUES = {
|
|
2203
|
+
critical: '#DC2626',
|
|
2204
|
+
major: '#C10007',
|
|
2205
|
+
medium: '#CA8A04',
|
|
2206
|
+
minor: '#2563EB',
|
|
2207
|
+
'not-set': '#101828', // Default dark
|
|
2208
|
+
};
|
|
2209
|
+
const RESULT_COLOR_VALUES = {
|
|
2210
|
+
passed: '#16A34A',
|
|
2211
|
+
failed: '#DC2626',
|
|
2212
|
+
aborted: '#EA580C',
|
|
2213
|
+
'in-review': '#2563EB',
|
|
2214
|
+
'not-executed': '#101828', // Default dark
|
|
2215
|
+
};
|
|
2216
|
+
const STATUS_COLOR_VALUES = {
|
|
2217
|
+
active: '#16A34A',
|
|
2218
|
+
inactive: '#6B7280',
|
|
2219
|
+
pending: '#CA8A04',
|
|
2220
|
+
completed: '#16A34A', // Green-600
|
|
2221
|
+
};
|
|
2222
|
+
const DEFAULT_METADATA_COLOR_VALUE = '#101828';
|
|
2223
|
+
/**
|
|
2224
|
+
* Color mappings for Priority values
|
|
2225
|
+
*/
|
|
2226
|
+
const PRIORITY_COLORS = {
|
|
2227
|
+
'critical': PRIORITY_COLOR_VALUES.critical,
|
|
2228
|
+
'major': PRIORITY_COLOR_VALUES.major,
|
|
2229
|
+
'medium': PRIORITY_COLOR_VALUES.medium,
|
|
2230
|
+
'minor': PRIORITY_COLOR_VALUES.minor,
|
|
2231
|
+
'not set': PRIORITY_COLOR_VALUES['not-set'],
|
|
2232
|
+
};
|
|
2233
|
+
/**
|
|
2234
|
+
* Color mappings for Result values
|
|
2235
|
+
*/
|
|
2236
|
+
const RESULT_COLORS = {
|
|
2237
|
+
'passed': RESULT_COLOR_VALUES.passed,
|
|
2238
|
+
'failed': RESULT_COLOR_VALUES.failed,
|
|
2239
|
+
'aborted': RESULT_COLOR_VALUES.aborted,
|
|
2240
|
+
'in review': RESULT_COLOR_VALUES['in-review'],
|
|
2241
|
+
'not executed': RESULT_COLOR_VALUES['not-executed'],
|
|
2242
|
+
};
|
|
2243
|
+
/**
|
|
2244
|
+
* Color mappings for Status values
|
|
2245
|
+
*/
|
|
2246
|
+
const STATUS_COLORS = {
|
|
2247
|
+
'active': STATUS_COLOR_VALUES.active,
|
|
2248
|
+
'inactive': STATUS_COLOR_VALUES.inactive,
|
|
2249
|
+
'pending': STATUS_COLOR_VALUES.pending,
|
|
2250
|
+
'completed': STATUS_COLOR_VALUES.completed,
|
|
2251
|
+
};
|
|
2252
|
+
/**
|
|
2253
|
+
* Default color for metadata values
|
|
2254
|
+
*/
|
|
2255
|
+
const DEFAULT_METADATA_COLOR = DEFAULT_METADATA_COLOR_VALUE;
|
|
2256
|
+
/**
|
|
2257
|
+
* Gets the color for a metadata value based on its key and value
|
|
2258
|
+
* @param key - The metadata key (priority, result, or status)
|
|
2259
|
+
* @param value - The metadata value (string or object with value property)
|
|
2260
|
+
* @returns Color hex code as a string
|
|
2261
|
+
*/
|
|
2262
|
+
function getMetadataColor(key, value) {
|
|
2263
|
+
// Extract the actual value
|
|
2264
|
+
const actualValue = typeof value === 'string' ? value : value.value;
|
|
2265
|
+
const normalizedValue = actualValue.toLowerCase().trim();
|
|
2266
|
+
const normalizedKey = key.toLowerCase().trim();
|
|
2267
|
+
// Get color based on key
|
|
2268
|
+
let colorMap;
|
|
2269
|
+
switch (normalizedKey) {
|
|
2270
|
+
case 'priority':
|
|
2271
|
+
colorMap = PRIORITY_COLORS;
|
|
2272
|
+
break;
|
|
2273
|
+
case 'result':
|
|
2274
|
+
colorMap = RESULT_COLORS;
|
|
2275
|
+
break;
|
|
2276
|
+
case 'status':
|
|
2277
|
+
colorMap = STATUS_COLORS;
|
|
2278
|
+
break;
|
|
2279
|
+
default:
|
|
2280
|
+
return DEFAULT_METADATA_COLOR;
|
|
2281
|
+
}
|
|
2282
|
+
// Return color for the value, or default if not found
|
|
2283
|
+
return colorMap[normalizedValue] || DEFAULT_METADATA_COLOR;
|
|
2284
|
+
}
|
|
2285
|
+
/**
|
|
2286
|
+
* Gets inline style object for metadata value color
|
|
2287
|
+
* @param key - The metadata key
|
|
2288
|
+
* @param value - The metadata value
|
|
2289
|
+
* @returns Style object with color property
|
|
2290
|
+
*/
|
|
2291
|
+
function getMetadataValueStyle(key, value) {
|
|
2292
|
+
return { color: getMetadataColor(key, value) };
|
|
2293
|
+
}
|
|
2294
|
+
|
|
2295
|
+
class BadgeComponent {
|
|
2296
|
+
constructor() {
|
|
2297
|
+
this.label = '';
|
|
2298
|
+
this.variant = 'default';
|
|
2299
|
+
}
|
|
2300
|
+
get badgeClasses() {
|
|
2301
|
+
const baseClasses = [
|
|
2302
|
+
'cqa-inline-flex',
|
|
2303
|
+
'cqa-items-center',
|
|
2304
|
+
'cqa-justify-center',
|
|
2305
|
+
'cqa-rounded-[6px]',
|
|
2306
|
+
'cqa-font-normal',
|
|
2307
|
+
'cqa-leading-[17px]'
|
|
2308
|
+
];
|
|
2309
|
+
// Only apply variant-specific Tailwind classes if custom colors are not provided
|
|
2310
|
+
if (!this.backgroundColor && !this.textColor) {
|
|
2311
|
+
switch (this.variant) {
|
|
2312
|
+
case 'error':
|
|
2313
|
+
return [...baseClasses, 'cqa-bg-[#FCD9D9]', 'cqa-text-[#9F2A2A]'].join(' ');
|
|
2314
|
+
case 'warning':
|
|
2315
|
+
return [...baseClasses, 'cqa-bg-[#FFF9E9]', 'cqa-text-[#7E6012]'].join(' ');
|
|
2316
|
+
case 'info':
|
|
2317
|
+
return [...baseClasses, 'cqa-bg-blue-100', 'cqa-text-blue-800'].join(' ');
|
|
2318
|
+
case 'success':
|
|
2319
|
+
return [...baseClasses, 'cqa-bg-green-100', 'cqa-text-green-800'].join(' ');
|
|
2320
|
+
case 'outline':
|
|
2321
|
+
return [...baseClasses, 'cqa-bg-transparent', 'cqa-text-gray-800'].join(' ');
|
|
2322
|
+
default:
|
|
2323
|
+
return [...baseClasses, 'cqa-bg-gray-100', 'cqa-text-gray-800'].join(' ');
|
|
2324
|
+
}
|
|
2325
|
+
}
|
|
2326
|
+
// If custom colors are provided, only return base classes
|
|
2327
|
+
return baseClasses.join(' ');
|
|
2328
|
+
}
|
|
2329
|
+
get badgeStyles() {
|
|
2330
|
+
const styles = {};
|
|
2331
|
+
if (this.backgroundColor) {
|
|
2332
|
+
styles['background-color'] = this.backgroundColor;
|
|
2333
|
+
}
|
|
2334
|
+
else if (this.variant === 'outline') {
|
|
2335
|
+
styles['background-color'] = 'transparent';
|
|
2336
|
+
}
|
|
2337
|
+
if (this.textColor) {
|
|
2338
|
+
styles['color'] = this.textColor;
|
|
2339
|
+
}
|
|
2340
|
+
return styles;
|
|
2341
|
+
}
|
|
2342
|
+
get iconContainerClasses() {
|
|
2343
|
+
const baseClasses = [
|
|
2344
|
+
'cqa-inline-flex',
|
|
2345
|
+
'cqa-items-center',
|
|
2346
|
+
'cqa-justify-center',
|
|
2347
|
+
'cqa-flex-shrink-0',
|
|
2348
|
+
'cqa-mr-1.5'
|
|
2349
|
+
];
|
|
2350
|
+
// No circular background for any variant - just return base classes
|
|
2351
|
+
return baseClasses.join(' ');
|
|
2352
|
+
}
|
|
2353
|
+
get iconContainerStyles() {
|
|
2354
|
+
const styles = {
|
|
2355
|
+
'display': 'inline-flex',
|
|
2356
|
+
'align-items': 'center',
|
|
2357
|
+
'justify-content': 'center'
|
|
2358
|
+
};
|
|
2359
|
+
// No circular background - only apply custom icon background color if explicitly provided
|
|
2360
|
+
if (this.iconBackgroundColor) {
|
|
2361
|
+
styles['background-color'] = this.iconBackgroundColor;
|
|
2362
|
+
// If custom background is provided, add circle dimensions
|
|
2363
|
+
styles['width'] = '16px';
|
|
2364
|
+
styles['height'] = '16px';
|
|
2365
|
+
styles['min-width'] = '16px';
|
|
2366
|
+
styles['min-height'] = '16px';
|
|
2367
|
+
styles['border-radius'] = '50%';
|
|
2368
|
+
}
|
|
2369
|
+
return styles;
|
|
2370
|
+
}
|
|
2371
|
+
get iconClasses() {
|
|
2372
|
+
const baseClasses = [];
|
|
2373
|
+
// Only apply white text class if custom icon color is not provided
|
|
2374
|
+
if (!this.iconColor) {
|
|
2375
|
+
return [...baseClasses, 'cqa-text-white'].join(' ');
|
|
2376
|
+
}
|
|
2377
|
+
return baseClasses.join(' ');
|
|
2378
|
+
}
|
|
2379
|
+
get iconStyles() {
|
|
2380
|
+
const styles = {
|
|
2381
|
+
'font-size': '14px',
|
|
2382
|
+
'width': '14px',
|
|
2383
|
+
'height': '14px',
|
|
2384
|
+
'line-height': '14px'
|
|
2385
|
+
};
|
|
2386
|
+
if (this.iconColor) {
|
|
2387
|
+
styles['color'] = this.iconColor;
|
|
2388
|
+
}
|
|
2389
|
+
else {
|
|
2390
|
+
// Use variant-specific text color for icon (no white background anymore)
|
|
2391
|
+
switch (this.variant) {
|
|
2392
|
+
case 'error':
|
|
2393
|
+
styles['color'] = '#991B1B'; // red-800
|
|
2394
|
+
break;
|
|
2395
|
+
case 'warning':
|
|
2396
|
+
styles['color'] = '#854D0E'; // yellow-800
|
|
2397
|
+
break;
|
|
2398
|
+
case 'info':
|
|
2399
|
+
styles['color'] = '#1E40AF'; // blue-800
|
|
2400
|
+
break;
|
|
2401
|
+
case 'success':
|
|
2402
|
+
styles['color'] = '#166534'; // green-800
|
|
2403
|
+
break;
|
|
2404
|
+
default:
|
|
2405
|
+
styles['color'] = this.textColor || '#374151'; // gray-700 default
|
|
2406
|
+
}
|
|
2407
|
+
}
|
|
2408
|
+
return styles;
|
|
2409
|
+
}
|
|
2410
|
+
}
|
|
2411
|
+
BadgeComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: BadgeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2412
|
+
BadgeComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: BadgeComponent, selector: "cqa-badge", inputs: { label: "label", icon: "icon", variant: "variant", backgroundColor: "backgroundColor", textColor: "textColor", iconBackgroundColor: "iconBackgroundColor", iconColor: "iconColor" }, ngImport: i0, template: "<div id=\"cqa-ui-root\" style=\"display: inline-block;\">\n <span \n [ngClass]=\"badgeClasses\" \n [ngStyle]=\"badgeStyles\"\n class=\"cqa-font-inter cqa-font-normal cqa-text-sm cqa-leading-[17px] cqa-py-[4px] cqa-px-3\">\n <span \n *ngIf=\"icon\" \n [ngClass]=\"iconContainerClasses\"\n [ngStyle]=\"iconContainerStyles\">\n <mat-icon \n [ngClass]=\"iconClasses\"\n [ngStyle]=\"iconStyles\">{{ icon }}</mat-icon>\n </span>\n {{ label }}\n </span>\n</div>\n\n", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
|
|
2413
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: BadgeComponent, decorators: [{
|
|
2414
|
+
type: Component,
|
|
2415
|
+
args: [{ selector: 'cqa-badge', template: "<div id=\"cqa-ui-root\" style=\"display: inline-block;\">\n <span \n [ngClass]=\"badgeClasses\" \n [ngStyle]=\"badgeStyles\"\n class=\"cqa-font-inter cqa-font-normal cqa-text-sm cqa-leading-[17px] cqa-py-[4px] cqa-px-3\">\n <span \n *ngIf=\"icon\" \n [ngClass]=\"iconContainerClasses\"\n [ngStyle]=\"iconContainerStyles\">\n <mat-icon \n [ngClass]=\"iconClasses\"\n [ngStyle]=\"iconStyles\">{{ icon }}</mat-icon>\n </span>\n {{ label }}\n </span>\n</div>\n\n", styles: [] }]
|
|
2416
|
+
}], propDecorators: { label: [{
|
|
2417
|
+
type: Input
|
|
2418
|
+
}], icon: [{
|
|
2419
|
+
type: Input
|
|
2420
|
+
}], variant: [{
|
|
2421
|
+
type: Input
|
|
2422
|
+
}], backgroundColor: [{
|
|
2423
|
+
type: Input
|
|
2424
|
+
}], textColor: [{
|
|
2425
|
+
type: Input
|
|
2426
|
+
}], iconBackgroundColor: [{
|
|
2427
|
+
type: Input
|
|
2428
|
+
}], iconColor: [{
|
|
2429
|
+
type: Input
|
|
2430
|
+
}] } });
|
|
2431
|
+
|
|
2432
|
+
class InsightCardComponent {
|
|
2433
|
+
constructor() {
|
|
2434
|
+
this.title = '';
|
|
2435
|
+
this.description = '';
|
|
2436
|
+
this._badges = [];
|
|
2437
|
+
this.metadataExpanded = true;
|
|
2438
|
+
this.isPrerequisiteMissing = false;
|
|
2439
|
+
this.isTestDataMissing = false;
|
|
2440
|
+
// Track expanded state for sections
|
|
2441
|
+
this.sectionExpandedState = new Map();
|
|
2442
|
+
// Loading state for main action
|
|
2443
|
+
this.isApplying = false;
|
|
2444
|
+
this.metadataToggle = new EventEmitter();
|
|
2445
|
+
this.sectionToggle = new EventEmitter();
|
|
2446
|
+
this.sectionActionClick = new EventEmitter();
|
|
2447
|
+
this.onApplySuggestionClick = new EventEmitter();
|
|
2448
|
+
this.onAttachPrerequisitesClick = new EventEmitter();
|
|
2449
|
+
this.onImportTestDataClick = new EventEmitter();
|
|
2450
|
+
}
|
|
2451
|
+
set badges(value) {
|
|
2452
|
+
this._badges = value;
|
|
2453
|
+
}
|
|
2454
|
+
get badges() {
|
|
2455
|
+
return this._badges;
|
|
2456
|
+
}
|
|
2457
|
+
toggleMetadata() {
|
|
2458
|
+
this.metadataExpanded = !this.metadataExpanded;
|
|
2459
|
+
this.metadataToggle.emit(this.metadataExpanded);
|
|
2460
|
+
}
|
|
2461
|
+
toggleSection(section) {
|
|
2462
|
+
const currentState = this.sectionExpandedState.get(section.id) ?? (section.expanded ?? true);
|
|
2463
|
+
const newState = !currentState;
|
|
2464
|
+
this.sectionExpandedState.set(section.id, newState);
|
|
2465
|
+
this.sectionToggle.emit({ id: section.id, expanded: newState });
|
|
2466
|
+
}
|
|
2467
|
+
onSectionAction(sectionId) {
|
|
2468
|
+
this.sectionActionClick.emit(sectionId);
|
|
2469
|
+
// Emit specific events for known actions
|
|
2470
|
+
if (sectionId === 'prerequisite') {
|
|
2471
|
+
this.onAttachPrerequisitesClick.emit();
|
|
2472
|
+
}
|
|
2473
|
+
else if (sectionId === 'test-data') {
|
|
2474
|
+
this.onImportTestDataClick.emit();
|
|
2475
|
+
}
|
|
2476
|
+
}
|
|
2477
|
+
get visibleBadges() {
|
|
2478
|
+
const visible = [];
|
|
2479
|
+
if (this.isPrerequisiteMissing) {
|
|
2480
|
+
visible.push({ label: 'Prerequisite Missing', variant: 'warning' });
|
|
2481
|
+
}
|
|
2482
|
+
if (this.isTestDataMissing) {
|
|
2483
|
+
visible.push({ label: 'Test Data Missing', variant: 'error' });
|
|
2484
|
+
}
|
|
2485
|
+
// Also include any custom badges
|
|
2486
|
+
if (this.badges) {
|
|
2487
|
+
visible.push(...this.badges);
|
|
2488
|
+
}
|
|
2489
|
+
return visible;
|
|
2490
|
+
}
|
|
2491
|
+
get visibleSections() {
|
|
2492
|
+
const visible = [];
|
|
2493
|
+
if (this.isPrerequisiteMissing && this.prerequisiteSection) {
|
|
2494
|
+
// Use stored state if available, otherwise default to true
|
|
2495
|
+
const expanded = this.sectionExpandedState.has('prerequisite')
|
|
2496
|
+
? this.sectionExpandedState.get('prerequisite')
|
|
2497
|
+
: true;
|
|
2498
|
+
visible.push({
|
|
2499
|
+
id: 'prerequisite',
|
|
2500
|
+
title: 'Prerequisite Missing',
|
|
2501
|
+
variant: 'warning',
|
|
2502
|
+
reason: this.prerequisiteSection,
|
|
2503
|
+
actionButtonLabel: 'Attach Prerequisites',
|
|
2504
|
+
expanded: expanded,
|
|
2505
|
+
});
|
|
2506
|
+
}
|
|
2507
|
+
if (this.isTestDataMissing && this.testDataSection) {
|
|
2508
|
+
// Use stored state if available, otherwise default to true
|
|
2509
|
+
const expanded = this.sectionExpandedState.has('test-data')
|
|
2510
|
+
? this.sectionExpandedState.get('test-data')
|
|
2511
|
+
: true;
|
|
2512
|
+
visible.push({
|
|
2513
|
+
id: 'test-data',
|
|
2514
|
+
title: 'Test Data Missing',
|
|
2515
|
+
variant: 'error',
|
|
2516
|
+
reason: this.testDataSection,
|
|
2517
|
+
actionButtonLabel: 'Import Test Data',
|
|
2518
|
+
expanded: expanded,
|
|
2519
|
+
});
|
|
2520
|
+
}
|
|
2521
|
+
return visible;
|
|
2522
|
+
}
|
|
2523
|
+
async onMainAction() {
|
|
2524
|
+
if (this.isApplying) {
|
|
2525
|
+
return; // Prevent multiple clicks
|
|
2526
|
+
}
|
|
2527
|
+
this.isApplying = true;
|
|
2528
|
+
try {
|
|
2529
|
+
this.onApplySuggestionClick.emit();
|
|
2530
|
+
}
|
|
2531
|
+
finally {
|
|
2532
|
+
// Reset loading state after action completes
|
|
2533
|
+
// If you need to keep the loading state longer, call resetApplyingState() manually
|
|
2534
|
+
// after your async operation completes
|
|
2535
|
+
this.isApplying = false;
|
|
2536
|
+
}
|
|
2537
|
+
}
|
|
2538
|
+
// Method to reset loading state (can be called externally if needed)
|
|
2539
|
+
resetApplyingState() {
|
|
2540
|
+
this.isApplying = false;
|
|
2541
|
+
}
|
|
2542
|
+
// Removed getBadgeClasses - now using BadgeComponent
|
|
2543
|
+
getSectionBorderClass(section) {
|
|
2544
|
+
switch (section.variant) {
|
|
2545
|
+
case 'warning':
|
|
2546
|
+
return 'cqa-border-l-4 cqa-border-l-yellow-500';
|
|
2547
|
+
case 'error':
|
|
2548
|
+
return 'cqa-border-l-4 cqa-border-l-red-500';
|
|
2549
|
+
default:
|
|
2550
|
+
return 'cqa-border-l-4 cqa-border-l-gray-500';
|
|
2551
|
+
}
|
|
2552
|
+
}
|
|
2553
|
+
getMetadataValueClasses(key, value) {
|
|
2554
|
+
// Base classes for all values (font-size: 14px, line-height: 18px, font-weight: 400)
|
|
2555
|
+
return 'cqa-font-normal cqa-leading-[18px] cqa-tracking-normal';
|
|
2556
|
+
}
|
|
2557
|
+
getMetadataValue(value) {
|
|
2558
|
+
if (typeof value === 'string') {
|
|
2559
|
+
return value;
|
|
2560
|
+
}
|
|
2561
|
+
return value.value;
|
|
2562
|
+
}
|
|
2563
|
+
getMetadataValueStyle(key, value) {
|
|
2564
|
+
// Use the shared utility function for consistent colors
|
|
2565
|
+
return getMetadataValueStyle(key, value);
|
|
2566
|
+
}
|
|
2567
|
+
getSectionTitleClasses(section) {
|
|
2568
|
+
const baseClasses = ['cqa-text-sm', 'cqa-leading-[17px]', 'cqa-font-semibold'];
|
|
2569
|
+
switch (section.variant) {
|
|
2570
|
+
case 'warning':
|
|
2571
|
+
return [...baseClasses, 'cqa-text-[#78350F]'].join(' ');
|
|
2572
|
+
case 'error':
|
|
2573
|
+
return [...baseClasses, 'cqa-text-[#881337]'].join(' ');
|
|
2574
|
+
default:
|
|
2575
|
+
return [...baseClasses, 'cqa-text-ink'].join(' ');
|
|
2576
|
+
}
|
|
2577
|
+
}
|
|
2578
|
+
getSectionIconColor(section) {
|
|
2579
|
+
switch (section.variant) {
|
|
2580
|
+
case 'warning':
|
|
2581
|
+
return 'cqa-text-[#78350F]';
|
|
2582
|
+
case 'error':
|
|
2583
|
+
return 'cqa-text-[#881337]';
|
|
2584
|
+
default:
|
|
2585
|
+
return 'cqa-text-gray-400';
|
|
2586
|
+
}
|
|
2587
|
+
}
|
|
2588
|
+
}
|
|
2589
|
+
InsightCardComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: InsightCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2590
|
+
InsightCardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: InsightCardComponent, selector: "cqa-insight-card", inputs: { title: "title", description: "description", badges: "badges", metadata: "metadata", prerequisiteSection: "prerequisiteSection", testDataSection: "testDataSection", metadataExpanded: "metadataExpanded", isPrerequisiteMissing: "isPrerequisiteMissing", isTestDataMissing: "isTestDataMissing" }, outputs: { metadataToggle: "metadataToggle", sectionToggle: "sectionToggle", sectionActionClick: "sectionActionClick", onApplySuggestionClick: "onApplySuggestionClick", onAttachPrerequisitesClick: "onAttachPrerequisitesClick", onImportTestDataClick: "onImportTestDataClick" }, ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <div class=\"cqa-font-inter cqa-flex cqa-flex-col cqa-gap-4 cqa-px-[21px] cqa-py-3 cqa-border cqa-border-[#ECECEC] cqa-rounded-xl cqa-shadow-card\">\n <!-- Section 1: Badges -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-3 cqapy-[1.5]\" *ngIf=\"visibleBadges.length > 0\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M14.4866 12.0005L9.15329 2.66714C9.037 2.46194 8.86836 2.29127 8.66457 2.17252C8.46078 2.05378 8.22915 1.99121 7.99329 1.99121C7.75743 1.99121 7.52579 2.05378 7.322 2.17252C7.11822 2.29127 6.94958 2.46194 6.83329 2.66714L1.49995 12.0005C1.38241 12.204 1.32077 12.4351 1.32129 12.6701C1.32181 12.9052 1.38447 13.136 1.50292 13.339C1.62136 13.5421 1.79138 13.7102 1.99575 13.8264C2.20011 13.9425 2.43156 14.0026 2.66662 14.0005H13.3333C13.5672 14.0002 13.797 13.9385 13.9995 13.8213C14.202 13.7042 14.3701 13.5359 14.487 13.3332C14.6038 13.1306 14.6653 12.9007 14.6653 12.6668C14.6652 12.4329 14.6036 12.2031 14.4866 12.0005Z\" stroke=\"#E2AC20\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M8 6V8.66667\" stroke=\"#E2AC20\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M8 11.333H8.00667\" stroke=\"#E2AC20\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n <div class=\"cqa-flex cqa-flex-wrap cqa-gap-2\">\n <cqa-badge \n *ngFor=\"let badge of visibleBadges\" \n [label]=\"badge.label\"\n [icon]=\"badge.icon\"\n [variant]=\"badge.variant || 'default'\"\n ></cqa-badge>\n </div>\n </div>\n\n <!-- Section 2: Title & Description -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <h2 class=\"cqa-font-medium cqa-text-lg cqa-leading-[22px] cqa-text-title\">\n {{ title }}\n </h2>\n <p class=\"cqa-text-base cqa-font-normal cqa-text-description\">\n {{ description }}\n </p>\n </div>\n\n <!-- Section 3: Metadata Section (always visible) -->\n <div *ngIf=\"metadata\" class=\"cqa-flex cqa-flex-col cqa-gap-4\">\n <div class=\"cqa-bg-surface-default cqa-rounded-[10px] cqa-px-4 cqa-py-3 cqa-border-t cqa-border-t-primary-surface\">\n <div class=\"cqa-flex cqa-flex-wrap cqa-items-center cqa-gap-[25px]\">\n <ng-container *ngFor=\"let item of metadata | keyvalue; let last = last\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-[6px]\">\n <span class=\"cqa-text-xs cqa-font-normal cqa-font-inter cqa-text-metadata-key\">\n {{ item.key }}:\n </span>\n <span \n [ngClass]=\"getMetadataValueClasses(item.key, item.value)\" \n [ngStyle]=\"getMetadataValueStyle(item.key, item.value)\"\n class=\"cqa-font-normal cqa-leading-[18px] cqa-font-inter cqa-text-sm cqa-text-title\">\n {{ getMetadataValue(item.value) }}\n </span>\n </div>\n <div *ngIf=\"!last\" class=\"cqa-h-4 cqa-w-px cqa-bg-gray-200\"></div>\n </ng-container>\n </div>\n </div>\n\n <!-- Section 4: Metadata toggle -->\n <button *ngIf=\"metadata && (isPrerequisiteMissing || isTestDataMissing)\" type=\"button\"\n class=\"cqa-text-sm cqa-text-primary cqa-inline-flex cqa-font-inter cqa-items-center cqa-gap-[6px]\"\n (click)=\"toggleMetadata()\">\n <span>{{ metadataExpanded ? 'Hide details' : 'Show details' }}</span>\n <mat-icon class=\"cqa-w-[14px] cqa-h-[14px] cqa-text-[14px] cqa-leading-[14px]\">\n {{ metadataExpanded ? 'expand_less' : 'expand_more' }}\n </mat-icon>\n </button>\n\n <!-- Section 5: Sections (toggle visibility) -->\n <div *ngIf=\"metadataExpanded && visibleSections?.length\" class=\"cqa-flex cqa-flex-col cqa-gap-4\">\n <div\n *ngFor=\"let section of visibleSections\"\n class=\"cqa-border-l-4 cqa-border-[#FBBF24] cqa-rounded-[10px] cqa-overflow-hidden\"\n [ngClass]=\"getSectionBorderClass(section)\"\n >\n <div class=\"cqa-p-[10px] cqa-pl-[20px] cqa-flex cqa-flex-col cqa-gap-3\">\n <!-- Section Title with Inline Collapse Button -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <h3 [ngClass]=\"getSectionTitleClasses(section)\" class=\"\">\n {{ section.title }}\n </h3>\n <button\n type=\"button\"\n class=\"cqa-ml-auto cqa-inline-flex\"\n (click)=\"toggleSection(section)\"\n [attr.aria-label]=\"section.expanded !== false ? 'Collapse section' : 'Expand section'\"\n >\n <mat-icon [ngClass]=\"getSectionIconColor(section)\" class=\"cqa-w-4 cqa-h-4 cqa-text-[16px] cqa-leading-[16px]\">\n {{ section.expanded !== false ? 'expand_less' : 'expand_more' }}\n </mat-icon>\n </button>\n </div>\n\n <!-- Collapsible Content: Reason and Action Button -->\n <div *ngIf=\"section.expanded !== false\" class=\"cqa-flex cqa-flex-col cqa-gap-[10px]\">\n <!-- Reason -->\n <p class=\"cqa-text-sm cqa-font-normal cqa-leading-[18px] cqa-text-neutral-600\">\n Reason: {{ section.reason }}\n </p>\n \n <!-- Action Button -->\n <div>\n <cqa-button\n variant=\"outlined\"\n (clicked)=\"onSectionAction(section.id)\"\n [customClass]=\"'cqa-py-[9px] cqa-text-[14px] cqa-leading-[17px] cqa-border-slate cqa-text-slate'\"\n >\n {{ section.actionButtonLabel }}\n </cqa-button>\n </div>\n </div>\n </div>\n </div>\n </div>\n \n <cqa-button\n variant=\"filled\"\n (clicked)=\"onMainAction()\"\n [disabled]=\"isApplying\"\n [customClass]=\"'!cqa-w-full !cqa-text-[14px] !cqa-leading-[20px] !cqa-font-semibold'\"\n >\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 18 18\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M9.01882 0C9.12979 0.0454767 9.17718 0.15653 9.22261 0.259691C9.24539 0.319799 9.26628 0.380234 9.28657 0.44115C9.29452 0.464493 9.30246 0.487836 9.31065 0.511886C9.41613 0.826009 9.51008 1.1435 9.60457 1.46076C9.62593 1.53238 9.64739 1.60397 9.66885 1.67557C9.7781 2.04007 9.88654 2.4048 9.99438 2.76969C10.0095 2.82093 10.0247 2.87218 10.0398 2.92342C10.0826 3.0679 10.1252 3.21239 10.1677 3.35694C10.2573 3.66239 10.3495 3.96695 10.4476 4.27002C10.4561 4.29653 10.4647 4.32305 10.4735 4.35036C10.7284 5.12999 11.0896 5.82875 11.6818 6.42393C11.6965 6.4394 11.7111 6.45488 11.7262 6.47083C11.979 6.72875 12.3034 6.93541 12.6276 7.10221C12.6441 7.11085 12.6606 7.11948 12.6776 7.12838C13.6317 7.61851 14.779 7.83407 15.8124 8.12101C16.2652 8.24681 16.7166 8.37658 17.1663 8.51206C17.1979 8.52157 17.2296 8.53107 17.2612 8.54055C17.3557 8.5689 17.45 8.59774 17.5442 8.62694C17.5662 8.63358 17.5882 8.64023 17.6108 8.64707C17.7406 8.68812 17.8648 8.73658 17.9713 8.82054C18.0038 8.88837 18.0038 8.88837 17.995 8.95619C17.8913 9.05472 17.7884 9.10092 17.6516 9.14599C17.632 9.15264 17.6124 9.1593 17.5923 9.16615C17.3612 9.24366 17.127 9.31149 16.8925 9.37871C16.8444 9.39261 16.7963 9.40651 16.7482 9.42042C16.4514 9.50603 16.1542 9.5898 15.8566 9.67263C15.4646 9.78175 15.0733 9.89268 14.6823 10.0049C14.6182 10.0232 14.5541 10.0416 14.49 10.0598C14.1534 10.1557 13.8185 10.2551 13.4863 10.3642C13.4587 10.3732 13.4312 10.3822 13.4028 10.3915C12.2902 10.7616 11.4422 11.4522 10.9114 12.462C10.6253 13.0295 10.4565 13.6432 10.2843 14.2489C10.2377 14.4124 10.1882 14.5749 10.1381 14.7374C10.0988 14.8652 10.0604 14.9933 10.023 15.1216C10.0185 15.1369 10.0141 15.1522 10.0095 15.1679C9.98788 15.2419 9.96638 15.3159 9.94503 15.3899C9.89039 15.5776 9.83156 15.7637 9.77111 15.9498C9.66383 16.2804 9.5662 16.6135 9.46917 16.947C9.32288 17.4491 9.32288 17.4491 9.23993 17.6905C9.23443 17.7067 9.22893 17.7229 9.22326 17.7396C9.19298 17.8256 9.16183 17.9047 9.10453 17.9774C9.01734 17.9958 9.01734 17.9958 8.93901 18C8.84946 17.8752 8.79016 17.7542 8.74265 17.6102C8.73574 17.5897 8.72882 17.5693 8.7217 17.5483C8.63368 17.285 8.55502 17.0189 8.47634 16.7529C8.45832 16.6921 8.44022 16.6313 8.42211 16.5705C8.2872 16.1173 8.15451 15.6635 8.02202 15.2096C7.47014 12.9645 7.47014 12.9645 6.078 11.1493C6.05569 11.1319 6.03338 11.1145 6.01039 11.0966C5.09826 10.398 3.89667 10.1394 2.7963 9.83627C2.52415 9.76124 2.2521 9.68587 1.98006 9.61046C1.95628 9.60386 1.95628 9.60386 1.93201 9.59714C1.53962 9.48834 1.14735 9.37925 0.756448 9.26566C0.739911 9.26089 0.723375 9.25612 0.706338 9.25121C0.105798 9.07767 0.105798 9.07767 0.00129307 8.95619C-0.00166252 8.90108 -0.00166252 8.90108 0.0249378 8.84315C0.134167 8.7408 0.240153 8.69696 0.38432 8.65238C0.405194 8.64567 0.426068 8.63897 0.447574 8.63206C0.511506 8.61164 0.575577 8.59169 0.639702 8.57183C0.658001 8.56609 0.676301 8.56035 0.695155 8.55443C0.82457 8.51385 0.95445 8.47479 1.08452 8.43618C1.11648 8.42665 1.11648 8.42665 1.14909 8.41693C1.70454 8.25174 2.26361 8.09801 2.82252 7.94392C3.23899 7.82909 3.65476 7.71236 4.06921 7.59097C4.08825 7.58542 4.1073 7.57987 4.12692 7.57415C5.087 7.29393 6.02557 6.89632 6.64547 6.1074C6.65475 6.09569 6.66403 6.08399 6.6736 6.07194C7.36395 5.1963 7.63315 4.13145 7.93391 3.09241C8.03285 2.75069 8.13298 2.40929 8.23345 2.06798C8.26127 1.97347 8.28906 1.87894 8.31673 1.78439C8.42788 1.40458 8.5407 1.02528 8.66 0.647727C8.67116 0.612372 8.68227 0.577001 8.69333 0.541614C8.86035 0.00797522 8.86035 0.00797522 9.01882 0Z\" fill=\"#FBFCFF\"/><path d=\"M14.4719 1.11069C14.5805 1.22817 14.6022 1.36624 14.636 1.51625C14.7487 1.98751 14.8786 2.42084 15.3293 2.6946C15.6074 2.84167 15.9389 2.90859 16.247 2.9718C16.3771 2.99902 16.4869 3.03515 16.5985 3.1074C16.6236 3.14555 16.6236 3.14555 16.6221 3.21197C16.5963 3.29273 16.5736 3.31878 16.5054 3.37165C16.4308 3.39549 16.4308 3.39549 16.3413 3.41404C16.3075 3.42147 16.2736 3.42898 16.2398 3.43656C16.2217 3.44058 16.2036 3.4446 16.1849 3.44874C15.6339 3.57062 15.6339 3.57062 15.1576 3.84645C15.1421 3.85837 15.1267 3.87029 15.1107 3.88257C14.7703 4.16959 14.6983 4.64703 14.5958 5.04699C14.59 5.06896 14.5841 5.09092 14.578 5.11355C14.573 5.133 14.5679 5.15244 14.5627 5.17248C14.5405 5.23185 14.5176 5.27057 14.4719 5.31607C14.3447 5.33152 14.3447 5.33152 14.2828 5.31607C14.1843 5.24309 14.1623 5.15997 14.1366 5.04828C14.1322 5.03099 14.1279 5.01369 14.1235 4.99587C14.1098 4.94064 14.0965 4.88531 14.0833 4.82996C13.9796 4.39891 13.8625 3.976 13.449 3.72333C13.1258 3.55101 12.7329 3.46951 12.3717 3.4037C12.2727 3.38399 12.216 3.3592 12.1547 3.28121C12.1414 3.20208 12.1414 3.20208 12.1547 3.12294C12.2489 3.02971 12.348 3.00696 12.4754 2.97881C12.5156 2.9693 12.5557 2.95973 12.5958 2.9501C12.6165 2.94516 12.6372 2.94022 12.6586 2.93512C12.7642 2.90911 12.8689 2.87995 12.9734 2.85021C12.9924 2.84494 13.0114 2.83967 13.031 2.83424C13.2436 2.77346 13.4271 2.69571 13.5971 2.5577C13.6129 2.54523 13.6288 2.53276 13.6451 2.5199C13.9096 2.29228 13.9995 1.95032 14.081 1.63124C14.0873 1.60702 14.0935 1.5828 14.0999 1.55784C14.1123 1.50918 14.1244 1.46046 14.1363 1.4117C14.1449 1.37776 14.1449 1.37776 14.1535 1.34315C14.1585 1.32288 14.1635 1.30261 14.1686 1.28172C14.1904 1.21719 14.219 1.16652 14.2591 1.11069C14.3362 1.07385 14.3903 1.0905 14.4719 1.11069Z\" fill=\"#FBFCFF\"/><path d=\"M3.59089 12.4942C3.61902 12.4944 3.61902 12.4944 3.64772 12.4946C3.84954 12.5004 3.98609 12.5623 4.13472 12.692C4.30767 12.8707 4.38753 13.0722 4.38299 13.313C4.36357 13.5082 4.24316 13.6787 4.09547 13.8107C3.92163 13.9448 3.74626 13.9892 3.52411 13.983C3.33681 13.9621 3.1606 13.877 3.02785 13.749C2.86276 13.5336 2.8145 13.3361 2.83869 13.0707C2.88867 12.8618 3.03274 12.6923 3.21701 12.5733C3.34502 12.5113 3.44798 12.493 3.59089 12.4942Z\" fill=\"#FBFCFF\"/></svg>\n {{ isApplying ? 'Applying suggestion' : 'Apply suggestion' }}\n </cqa-button>\n </div>\n</div>\n \n", components: [{ type: BadgeComponent, selector: "cqa-badge", inputs: ["label", "icon", "variant", "backgroundColor", "textColor", "iconBackgroundColor", "iconColor"] }, { type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { type: ButtonComponent, selector: "cqa-button", inputs: ["variant", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass"], outputs: ["clicked"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], pipes: { "keyvalue": i2.KeyValuePipe } });
|
|
2591
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: InsightCardComponent, decorators: [{
|
|
2592
|
+
type: Component,
|
|
2593
|
+
args: [{ selector: 'cqa-insight-card', template: "<div id=\"cqa-ui-root\">\n <div class=\"cqa-font-inter cqa-flex cqa-flex-col cqa-gap-4 cqa-px-[21px] cqa-py-3 cqa-border cqa-border-[#ECECEC] cqa-rounded-xl cqa-shadow-card\">\n <!-- Section 1: Badges -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-3 cqapy-[1.5]\" *ngIf=\"visibleBadges.length > 0\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M14.4866 12.0005L9.15329 2.66714C9.037 2.46194 8.86836 2.29127 8.66457 2.17252C8.46078 2.05378 8.22915 1.99121 7.99329 1.99121C7.75743 1.99121 7.52579 2.05378 7.322 2.17252C7.11822 2.29127 6.94958 2.46194 6.83329 2.66714L1.49995 12.0005C1.38241 12.204 1.32077 12.4351 1.32129 12.6701C1.32181 12.9052 1.38447 13.136 1.50292 13.339C1.62136 13.5421 1.79138 13.7102 1.99575 13.8264C2.20011 13.9425 2.43156 14.0026 2.66662 14.0005H13.3333C13.5672 14.0002 13.797 13.9385 13.9995 13.8213C14.202 13.7042 14.3701 13.5359 14.487 13.3332C14.6038 13.1306 14.6653 12.9007 14.6653 12.6668C14.6652 12.4329 14.6036 12.2031 14.4866 12.0005Z\" stroke=\"#E2AC20\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M8 6V8.66667\" stroke=\"#E2AC20\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M8 11.333H8.00667\" stroke=\"#E2AC20\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n <div class=\"cqa-flex cqa-flex-wrap cqa-gap-2\">\n <cqa-badge \n *ngFor=\"let badge of visibleBadges\" \n [label]=\"badge.label\"\n [icon]=\"badge.icon\"\n [variant]=\"badge.variant || 'default'\"\n ></cqa-badge>\n </div>\n </div>\n\n <!-- Section 2: Title & Description -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <h2 class=\"cqa-font-medium cqa-text-lg cqa-leading-[22px] cqa-text-title\">\n {{ title }}\n </h2>\n <p class=\"cqa-text-base cqa-font-normal cqa-text-description\">\n {{ description }}\n </p>\n </div>\n\n <!-- Section 3: Metadata Section (always visible) -->\n <div *ngIf=\"metadata\" class=\"cqa-flex cqa-flex-col cqa-gap-4\">\n <div class=\"cqa-bg-surface-default cqa-rounded-[10px] cqa-px-4 cqa-py-3 cqa-border-t cqa-border-t-primary-surface\">\n <div class=\"cqa-flex cqa-flex-wrap cqa-items-center cqa-gap-[25px]\">\n <ng-container *ngFor=\"let item of metadata | keyvalue; let last = last\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-[6px]\">\n <span class=\"cqa-text-xs cqa-font-normal cqa-font-inter cqa-text-metadata-key\">\n {{ item.key }}:\n </span>\n <span \n [ngClass]=\"getMetadataValueClasses(item.key, item.value)\" \n [ngStyle]=\"getMetadataValueStyle(item.key, item.value)\"\n class=\"cqa-font-normal cqa-leading-[18px] cqa-font-inter cqa-text-sm cqa-text-title\">\n {{ getMetadataValue(item.value) }}\n </span>\n </div>\n <div *ngIf=\"!last\" class=\"cqa-h-4 cqa-w-px cqa-bg-gray-200\"></div>\n </ng-container>\n </div>\n </div>\n\n <!-- Section 4: Metadata toggle -->\n <button *ngIf=\"metadata && (isPrerequisiteMissing || isTestDataMissing)\" type=\"button\"\n class=\"cqa-text-sm cqa-text-primary cqa-inline-flex cqa-font-inter cqa-items-center cqa-gap-[6px]\"\n (click)=\"toggleMetadata()\">\n <span>{{ metadataExpanded ? 'Hide details' : 'Show details' }}</span>\n <mat-icon class=\"cqa-w-[14px] cqa-h-[14px] cqa-text-[14px] cqa-leading-[14px]\">\n {{ metadataExpanded ? 'expand_less' : 'expand_more' }}\n </mat-icon>\n </button>\n\n <!-- Section 5: Sections (toggle visibility) -->\n <div *ngIf=\"metadataExpanded && visibleSections?.length\" class=\"cqa-flex cqa-flex-col cqa-gap-4\">\n <div\n *ngFor=\"let section of visibleSections\"\n class=\"cqa-border-l-4 cqa-border-[#FBBF24] cqa-rounded-[10px] cqa-overflow-hidden\"\n [ngClass]=\"getSectionBorderClass(section)\"\n >\n <div class=\"cqa-p-[10px] cqa-pl-[20px] cqa-flex cqa-flex-col cqa-gap-3\">\n <!-- Section Title with Inline Collapse Button -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <h3 [ngClass]=\"getSectionTitleClasses(section)\" class=\"\">\n {{ section.title }}\n </h3>\n <button\n type=\"button\"\n class=\"cqa-ml-auto cqa-inline-flex\"\n (click)=\"toggleSection(section)\"\n [attr.aria-label]=\"section.expanded !== false ? 'Collapse section' : 'Expand section'\"\n >\n <mat-icon [ngClass]=\"getSectionIconColor(section)\" class=\"cqa-w-4 cqa-h-4 cqa-text-[16px] cqa-leading-[16px]\">\n {{ section.expanded !== false ? 'expand_less' : 'expand_more' }}\n </mat-icon>\n </button>\n </div>\n\n <!-- Collapsible Content: Reason and Action Button -->\n <div *ngIf=\"section.expanded !== false\" class=\"cqa-flex cqa-flex-col cqa-gap-[10px]\">\n <!-- Reason -->\n <p class=\"cqa-text-sm cqa-font-normal cqa-leading-[18px] cqa-text-neutral-600\">\n Reason: {{ section.reason }}\n </p>\n \n <!-- Action Button -->\n <div>\n <cqa-button\n variant=\"outlined\"\n (clicked)=\"onSectionAction(section.id)\"\n [customClass]=\"'cqa-py-[9px] cqa-text-[14px] cqa-leading-[17px] cqa-border-slate cqa-text-slate'\"\n >\n {{ section.actionButtonLabel }}\n </cqa-button>\n </div>\n </div>\n </div>\n </div>\n </div>\n \n <cqa-button\n variant=\"filled\"\n (clicked)=\"onMainAction()\"\n [disabled]=\"isApplying\"\n [customClass]=\"'!cqa-w-full !cqa-text-[14px] !cqa-leading-[20px] !cqa-font-semibold'\"\n >\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 18 18\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M9.01882 0C9.12979 0.0454767 9.17718 0.15653 9.22261 0.259691C9.24539 0.319799 9.26628 0.380234 9.28657 0.44115C9.29452 0.464493 9.30246 0.487836 9.31065 0.511886C9.41613 0.826009 9.51008 1.1435 9.60457 1.46076C9.62593 1.53238 9.64739 1.60397 9.66885 1.67557C9.7781 2.04007 9.88654 2.4048 9.99438 2.76969C10.0095 2.82093 10.0247 2.87218 10.0398 2.92342C10.0826 3.0679 10.1252 3.21239 10.1677 3.35694C10.2573 3.66239 10.3495 3.96695 10.4476 4.27002C10.4561 4.29653 10.4647 4.32305 10.4735 4.35036C10.7284 5.12999 11.0896 5.82875 11.6818 6.42393C11.6965 6.4394 11.7111 6.45488 11.7262 6.47083C11.979 6.72875 12.3034 6.93541 12.6276 7.10221C12.6441 7.11085 12.6606 7.11948 12.6776 7.12838C13.6317 7.61851 14.779 7.83407 15.8124 8.12101C16.2652 8.24681 16.7166 8.37658 17.1663 8.51206C17.1979 8.52157 17.2296 8.53107 17.2612 8.54055C17.3557 8.5689 17.45 8.59774 17.5442 8.62694C17.5662 8.63358 17.5882 8.64023 17.6108 8.64707C17.7406 8.68812 17.8648 8.73658 17.9713 8.82054C18.0038 8.88837 18.0038 8.88837 17.995 8.95619C17.8913 9.05472 17.7884 9.10092 17.6516 9.14599C17.632 9.15264 17.6124 9.1593 17.5923 9.16615C17.3612 9.24366 17.127 9.31149 16.8925 9.37871C16.8444 9.39261 16.7963 9.40651 16.7482 9.42042C16.4514 9.50603 16.1542 9.5898 15.8566 9.67263C15.4646 9.78175 15.0733 9.89268 14.6823 10.0049C14.6182 10.0232 14.5541 10.0416 14.49 10.0598C14.1534 10.1557 13.8185 10.2551 13.4863 10.3642C13.4587 10.3732 13.4312 10.3822 13.4028 10.3915C12.2902 10.7616 11.4422 11.4522 10.9114 12.462C10.6253 13.0295 10.4565 13.6432 10.2843 14.2489C10.2377 14.4124 10.1882 14.5749 10.1381 14.7374C10.0988 14.8652 10.0604 14.9933 10.023 15.1216C10.0185 15.1369 10.0141 15.1522 10.0095 15.1679C9.98788 15.2419 9.96638 15.3159 9.94503 15.3899C9.89039 15.5776 9.83156 15.7637 9.77111 15.9498C9.66383 16.2804 9.5662 16.6135 9.46917 16.947C9.32288 17.4491 9.32288 17.4491 9.23993 17.6905C9.23443 17.7067 9.22893 17.7229 9.22326 17.7396C9.19298 17.8256 9.16183 17.9047 9.10453 17.9774C9.01734 17.9958 9.01734 17.9958 8.93901 18C8.84946 17.8752 8.79016 17.7542 8.74265 17.6102C8.73574 17.5897 8.72882 17.5693 8.7217 17.5483C8.63368 17.285 8.55502 17.0189 8.47634 16.7529C8.45832 16.6921 8.44022 16.6313 8.42211 16.5705C8.2872 16.1173 8.15451 15.6635 8.02202 15.2096C7.47014 12.9645 7.47014 12.9645 6.078 11.1493C6.05569 11.1319 6.03338 11.1145 6.01039 11.0966C5.09826 10.398 3.89667 10.1394 2.7963 9.83627C2.52415 9.76124 2.2521 9.68587 1.98006 9.61046C1.95628 9.60386 1.95628 9.60386 1.93201 9.59714C1.53962 9.48834 1.14735 9.37925 0.756448 9.26566C0.739911 9.26089 0.723375 9.25612 0.706338 9.25121C0.105798 9.07767 0.105798 9.07767 0.00129307 8.95619C-0.00166252 8.90108 -0.00166252 8.90108 0.0249378 8.84315C0.134167 8.7408 0.240153 8.69696 0.38432 8.65238C0.405194 8.64567 0.426068 8.63897 0.447574 8.63206C0.511506 8.61164 0.575577 8.59169 0.639702 8.57183C0.658001 8.56609 0.676301 8.56035 0.695155 8.55443C0.82457 8.51385 0.95445 8.47479 1.08452 8.43618C1.11648 8.42665 1.11648 8.42665 1.14909 8.41693C1.70454 8.25174 2.26361 8.09801 2.82252 7.94392C3.23899 7.82909 3.65476 7.71236 4.06921 7.59097C4.08825 7.58542 4.1073 7.57987 4.12692 7.57415C5.087 7.29393 6.02557 6.89632 6.64547 6.1074C6.65475 6.09569 6.66403 6.08399 6.6736 6.07194C7.36395 5.1963 7.63315 4.13145 7.93391 3.09241C8.03285 2.75069 8.13298 2.40929 8.23345 2.06798C8.26127 1.97347 8.28906 1.87894 8.31673 1.78439C8.42788 1.40458 8.5407 1.02528 8.66 0.647727C8.67116 0.612372 8.68227 0.577001 8.69333 0.541614C8.86035 0.00797522 8.86035 0.00797522 9.01882 0Z\" fill=\"#FBFCFF\"/><path d=\"M14.4719 1.11069C14.5805 1.22817 14.6022 1.36624 14.636 1.51625C14.7487 1.98751 14.8786 2.42084 15.3293 2.6946C15.6074 2.84167 15.9389 2.90859 16.247 2.9718C16.3771 2.99902 16.4869 3.03515 16.5985 3.1074C16.6236 3.14555 16.6236 3.14555 16.6221 3.21197C16.5963 3.29273 16.5736 3.31878 16.5054 3.37165C16.4308 3.39549 16.4308 3.39549 16.3413 3.41404C16.3075 3.42147 16.2736 3.42898 16.2398 3.43656C16.2217 3.44058 16.2036 3.4446 16.1849 3.44874C15.6339 3.57062 15.6339 3.57062 15.1576 3.84645C15.1421 3.85837 15.1267 3.87029 15.1107 3.88257C14.7703 4.16959 14.6983 4.64703 14.5958 5.04699C14.59 5.06896 14.5841 5.09092 14.578 5.11355C14.573 5.133 14.5679 5.15244 14.5627 5.17248C14.5405 5.23185 14.5176 5.27057 14.4719 5.31607C14.3447 5.33152 14.3447 5.33152 14.2828 5.31607C14.1843 5.24309 14.1623 5.15997 14.1366 5.04828C14.1322 5.03099 14.1279 5.01369 14.1235 4.99587C14.1098 4.94064 14.0965 4.88531 14.0833 4.82996C13.9796 4.39891 13.8625 3.976 13.449 3.72333C13.1258 3.55101 12.7329 3.46951 12.3717 3.4037C12.2727 3.38399 12.216 3.3592 12.1547 3.28121C12.1414 3.20208 12.1414 3.20208 12.1547 3.12294C12.2489 3.02971 12.348 3.00696 12.4754 2.97881C12.5156 2.9693 12.5557 2.95973 12.5958 2.9501C12.6165 2.94516 12.6372 2.94022 12.6586 2.93512C12.7642 2.90911 12.8689 2.87995 12.9734 2.85021C12.9924 2.84494 13.0114 2.83967 13.031 2.83424C13.2436 2.77346 13.4271 2.69571 13.5971 2.5577C13.6129 2.54523 13.6288 2.53276 13.6451 2.5199C13.9096 2.29228 13.9995 1.95032 14.081 1.63124C14.0873 1.60702 14.0935 1.5828 14.0999 1.55784C14.1123 1.50918 14.1244 1.46046 14.1363 1.4117C14.1449 1.37776 14.1449 1.37776 14.1535 1.34315C14.1585 1.32288 14.1635 1.30261 14.1686 1.28172C14.1904 1.21719 14.219 1.16652 14.2591 1.11069C14.3362 1.07385 14.3903 1.0905 14.4719 1.11069Z\" fill=\"#FBFCFF\"/><path d=\"M3.59089 12.4942C3.61902 12.4944 3.61902 12.4944 3.64772 12.4946C3.84954 12.5004 3.98609 12.5623 4.13472 12.692C4.30767 12.8707 4.38753 13.0722 4.38299 13.313C4.36357 13.5082 4.24316 13.6787 4.09547 13.8107C3.92163 13.9448 3.74626 13.9892 3.52411 13.983C3.33681 13.9621 3.1606 13.877 3.02785 13.749C2.86276 13.5336 2.8145 13.3361 2.83869 13.0707C2.88867 12.8618 3.03274 12.6923 3.21701 12.5733C3.34502 12.5113 3.44798 12.493 3.59089 12.4942Z\" fill=\"#FBFCFF\"/></svg>\n {{ isApplying ? 'Applying suggestion' : 'Apply suggestion' }}\n </cqa-button>\n </div>\n</div>\n \n", styles: [] }]
|
|
2594
|
+
}], propDecorators: { title: [{
|
|
2595
|
+
type: Input
|
|
2596
|
+
}], description: [{
|
|
2597
|
+
type: Input
|
|
2598
|
+
}], badges: [{
|
|
2599
|
+
type: Input
|
|
2600
|
+
}], metadata: [{
|
|
2601
|
+
type: Input
|
|
2602
|
+
}], prerequisiteSection: [{
|
|
2603
|
+
type: Input
|
|
2604
|
+
}], testDataSection: [{
|
|
2605
|
+
type: Input
|
|
2606
|
+
}], metadataExpanded: [{
|
|
2607
|
+
type: Input
|
|
2608
|
+
}], isPrerequisiteMissing: [{
|
|
2609
|
+
type: Input
|
|
2610
|
+
}], isTestDataMissing: [{
|
|
2611
|
+
type: Input
|
|
2612
|
+
}], metadataToggle: [{
|
|
2613
|
+
type: Output
|
|
2614
|
+
}], sectionToggle: [{
|
|
2615
|
+
type: Output
|
|
2616
|
+
}], sectionActionClick: [{
|
|
2617
|
+
type: Output
|
|
2618
|
+
}], onApplySuggestionClick: [{
|
|
2619
|
+
type: Output
|
|
2620
|
+
}], onAttachPrerequisitesClick: [{
|
|
2621
|
+
type: Output
|
|
2622
|
+
}], onImportTestDataClick: [{
|
|
2623
|
+
type: Output
|
|
2624
|
+
}] } });
|
|
2625
|
+
|
|
2626
|
+
class DropdownButtonComponent {
|
|
2627
|
+
constructor() {
|
|
2628
|
+
this.label = 'Select an option';
|
|
2629
|
+
this.options = [];
|
|
2630
|
+
this.disabled = false;
|
|
2631
|
+
this.selectionChange = new EventEmitter();
|
|
2632
|
+
this.opened = new EventEmitter();
|
|
2633
|
+
this.closed = new EventEmitter();
|
|
2634
|
+
this.isOpen = false;
|
|
2635
|
+
this.clickInside = false;
|
|
2636
|
+
}
|
|
2637
|
+
get displayLabel() {
|
|
2638
|
+
if (this.selectedValue !== undefined && this.selectedValue !== null) {
|
|
2639
|
+
const selectedOption = this.options.find(opt => opt.value === this.selectedValue);
|
|
2640
|
+
return selectedOption ? selectedOption.label : this.label;
|
|
2641
|
+
}
|
|
2642
|
+
return this.placeholder || this.label;
|
|
2643
|
+
}
|
|
2644
|
+
get buttonClasses() {
|
|
2645
|
+
const baseClasses = [
|
|
2646
|
+
'cqa-h-9',
|
|
2647
|
+
'cqa-px-3',
|
|
2648
|
+
'cqa-py-2',
|
|
2649
|
+
'cqa-bg-gray-100',
|
|
2650
|
+
'cqa-rounded-[5px]',
|
|
2651
|
+
'cqa-outline',
|
|
2652
|
+
'cqa-outline-1',
|
|
2653
|
+
'cqa-outline-offset-[-1px]',
|
|
2654
|
+
'cqa-outline-gray-200',
|
|
2655
|
+
'cqa-inline-flex',
|
|
2656
|
+
'cqa-justify-center',
|
|
2657
|
+
'cqa-items-center',
|
|
2658
|
+
'cqa-gap-1',
|
|
2659
|
+
'cqa-cursor-pointer',
|
|
2660
|
+
'cqa-transition-colors'
|
|
2661
|
+
];
|
|
2662
|
+
if (this.disabled) {
|
|
2663
|
+
baseClasses.push('cqa-opacity-50', 'cqa-cursor-not-allowed');
|
|
2664
|
+
}
|
|
2665
|
+
else {
|
|
2666
|
+
baseClasses.push('cqa-hover:cqa-bg-gray-200');
|
|
2667
|
+
}
|
|
2668
|
+
if (this.isOpen) {
|
|
2669
|
+
baseClasses.push('cqa-bg-gray-200');
|
|
2670
|
+
}
|
|
2671
|
+
return baseClasses.join(' ');
|
|
2672
|
+
}
|
|
2673
|
+
get labelClasses() {
|
|
2674
|
+
return [
|
|
2675
|
+
'cqa-text-center',
|
|
2676
|
+
'cqa-justify-center',
|
|
2677
|
+
'cqa-text-gray-950',
|
|
2678
|
+
'cqa-text-xs',
|
|
2679
|
+
'cqa-font-medium',
|
|
2680
|
+
'cqa-leading-4'
|
|
2681
|
+
].join(' ');
|
|
2682
|
+
}
|
|
2683
|
+
get arrowClasses() {
|
|
2684
|
+
const baseClasses = [
|
|
2685
|
+
'cqa-w-4',
|
|
2686
|
+
'cqa-h-4',
|
|
2687
|
+
'cqa-relative',
|
|
2688
|
+
'cqa-transition-transform'
|
|
2689
|
+
];
|
|
2690
|
+
if (this.isOpen) {
|
|
2691
|
+
baseClasses.push('cqa-rotate-180');
|
|
2692
|
+
}
|
|
2693
|
+
return baseClasses.join(' ');
|
|
2694
|
+
}
|
|
2695
|
+
toggleDropdown(event) {
|
|
2696
|
+
if (this.disabled)
|
|
2697
|
+
return;
|
|
2698
|
+
if (event) {
|
|
2699
|
+
event.stopPropagation();
|
|
2700
|
+
event.preventDefault();
|
|
2701
|
+
this.clickInside = true;
|
|
2702
|
+
}
|
|
2703
|
+
this.isOpen = !this.isOpen;
|
|
2704
|
+
// Reset clickInside flag after a short delay
|
|
2705
|
+
setTimeout(() => {
|
|
2706
|
+
this.clickInside = false;
|
|
2707
|
+
if (this.isOpen) {
|
|
2708
|
+
this.opened.emit();
|
|
2709
|
+
}
|
|
2710
|
+
else {
|
|
2711
|
+
this.closed.emit();
|
|
2712
|
+
}
|
|
2713
|
+
}, 100);
|
|
2714
|
+
}
|
|
2715
|
+
selectOption(option, event) {
|
|
2716
|
+
if (option.disabled)
|
|
2717
|
+
return;
|
|
2718
|
+
if (event) {
|
|
2719
|
+
event.stopPropagation();
|
|
2720
|
+
this.clickInside = true;
|
|
2721
|
+
}
|
|
2722
|
+
this.selectedValue = option.value;
|
|
2723
|
+
this.isOpen = false;
|
|
2724
|
+
this.selectionChange.emit(option.value);
|
|
2725
|
+
this.closed.emit();
|
|
2726
|
+
// Reset flag after selection
|
|
2727
|
+
setTimeout(() => {
|
|
2728
|
+
this.clickInside = false;
|
|
2729
|
+
}, 100);
|
|
2730
|
+
}
|
|
2731
|
+
getButtonWidth() {
|
|
2732
|
+
if (this.buttonElement?.nativeElement) {
|
|
2733
|
+
const width = this.buttonElement.nativeElement.offsetWidth;
|
|
2734
|
+
return width > 0 ? width : 150; // Fallback to 150px if width is 0
|
|
2735
|
+
}
|
|
2736
|
+
return 150; // Default fallback width
|
|
2737
|
+
}
|
|
2738
|
+
getOptionClasses(option) {
|
|
2739
|
+
const baseClasses = [
|
|
2740
|
+
'cqa-p-1.5',
|
|
2741
|
+
'cqa-rounded-md',
|
|
2742
|
+
'cqa-inline-flex',
|
|
2743
|
+
'cqa-justify-start',
|
|
2744
|
+
'cqa-items-center',
|
|
2745
|
+
'cqa-cursor-pointer',
|
|
2746
|
+
'cqa-transition-colors'
|
|
2747
|
+
];
|
|
2748
|
+
if (option.disabled) {
|
|
2749
|
+
baseClasses.push('cqa-opacity-50', 'cqa-cursor-not-allowed');
|
|
2750
|
+
}
|
|
2751
|
+
else {
|
|
2752
|
+
baseClasses.push('cqa-hover:cqa-bg-gray-50');
|
|
2753
|
+
}
|
|
2754
|
+
if (this.selectedValue === option.value) {
|
|
2755
|
+
baseClasses.push('cqa-bg-primary-surface');
|
|
2756
|
+
}
|
|
2757
|
+
return baseClasses.join(' ');
|
|
2758
|
+
}
|
|
2759
|
+
onDocumentClick(event) {
|
|
2760
|
+
// Ignore if click was inside the component (button click)
|
|
2761
|
+
if (this.clickInside) {
|
|
2762
|
+
return;
|
|
2763
|
+
}
|
|
2764
|
+
// Use a longer delay to ensure dropdown has time to render
|
|
2765
|
+
setTimeout(() => {
|
|
2766
|
+
if (!this.isOpen)
|
|
2767
|
+
return;
|
|
2768
|
+
const target = event.target;
|
|
2769
|
+
// Check if click is inside the component container
|
|
2770
|
+
if (this.dropdownContainer?.nativeElement?.contains(target)) {
|
|
2771
|
+
return;
|
|
2772
|
+
}
|
|
2773
|
+
// Close dropdown if click is outside
|
|
2774
|
+
this.isOpen = false;
|
|
2775
|
+
this.closed.emit();
|
|
2776
|
+
}, 200);
|
|
2777
|
+
}
|
|
2778
|
+
}
|
|
2779
|
+
DropdownButtonComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DropdownButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2780
|
+
DropdownButtonComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: DropdownButtonComponent, selector: "cqa-dropdown-button", inputs: { label: "label", options: "options", selectedValue: "selectedValue", disabled: "disabled", placeholder: "placeholder" }, outputs: { selectionChange: "selectionChange", opened: "opened", closed: "closed" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, viewQueries: [{ propertyName: "dropdownContainer", first: true, predicate: ["dropdownContainer"], descendants: true }, { propertyName: "buttonElement", first: true, predicate: ["buttonElement"], descendants: true }], ngImport: i0, template: "<div id=\"cqa-ui-root\" #dropdownContainer style=\"position: relative; display: inline-block; width: auto;\">\n <button\n #buttonElement\n type=\"button\"\n [class]=\"buttonClasses\"\n [disabled]=\"disabled\"\n (click)=\"toggleDropdown($event)\"\n [attr.aria-expanded]=\"isOpen\"\n [attr.aria-haspopup]=\"true\"\n >\n <div [class]=\"labelClasses\">\n {{ displayLabel }}\n </div>\n <div [class]=\"arrowClasses\">\n <svg\n class=\"cqa-w-2 cqa-h-1 cqa-absolute cqa-left-[4px] cqa-top-[6px]\"\n viewBox=\"0 0 8 4\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M0 0L4 4L8 0\"\n stroke=\"#0B0B0C\"\n stroke-width=\"1.33\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </div>\n </button>\n\n <!-- Dropdown Menu -->\n <div\n *ngIf=\"isOpen && options && options.length > 0\"\n class=\"cqa-absolute cqa-top-full cqa-left-0 cqa-mt-1 cqa-p-1.5 cqa-bg-white cqa-rounded-lg cqa-shadow-[0px_2px_4px_-2px_rgba(0,0,0,0.10)] cqa-shadow-md cqa-outline cqa-outline-1 cqa-outline-offset-[-1px] cqa-outline-gray-200 cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-z-[9999] cqa-w-auto cqa-max-w-[350px]\"\n >\n <div class=\"cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-0.5 cqa-w-full\">\n <div\n *ngFor=\"let option of options\"\n (click)=\"selectOption(option, $event)\"\n [class]=\"getOptionClasses(option)\"\n class=\"cqa-w-full cqa-whitespace-nowrap\"\n >\n <div class=\"cqa-w-6 cqa-h-4 cqa-pr-2 cqa-inline-flex cqa-flex-col cqa-justify-center cqa-items-center\">\n <mat-icon\n *ngIf=\"selectedValue === option.value\"\n class=\"cqa-w-4 cqa-h-4 cqa-text-primary cqa-text-base cqa-leading-4\"\n >check</mat-icon>\n </div>\n <div class=\"cqa-flex-1 cqa-inline-flex cqa-flex-col cqa-justify-start cqa-items-start\">\n <div class=\"cqa-justify-center cqa-text-gray-950 cqa-text-sm cqa-font-normal cqa-leading-5 cqa-font-geist\">\n {{ option.label }}\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n\n", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
|
|
2781
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DropdownButtonComponent, decorators: [{
|
|
2782
|
+
type: Component,
|
|
2783
|
+
args: [{ selector: 'cqa-dropdown-button', template: "<div id=\"cqa-ui-root\" #dropdownContainer style=\"position: relative; display: inline-block; width: auto;\">\n <button\n #buttonElement\n type=\"button\"\n [class]=\"buttonClasses\"\n [disabled]=\"disabled\"\n (click)=\"toggleDropdown($event)\"\n [attr.aria-expanded]=\"isOpen\"\n [attr.aria-haspopup]=\"true\"\n >\n <div [class]=\"labelClasses\">\n {{ displayLabel }}\n </div>\n <div [class]=\"arrowClasses\">\n <svg\n class=\"cqa-w-2 cqa-h-1 cqa-absolute cqa-left-[4px] cqa-top-[6px]\"\n viewBox=\"0 0 8 4\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M0 0L4 4L8 0\"\n stroke=\"#0B0B0C\"\n stroke-width=\"1.33\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </div>\n </button>\n\n <!-- Dropdown Menu -->\n <div\n *ngIf=\"isOpen && options && options.length > 0\"\n class=\"cqa-absolute cqa-top-full cqa-left-0 cqa-mt-1 cqa-p-1.5 cqa-bg-white cqa-rounded-lg cqa-shadow-[0px_2px_4px_-2px_rgba(0,0,0,0.10)] cqa-shadow-md cqa-outline cqa-outline-1 cqa-outline-offset-[-1px] cqa-outline-gray-200 cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-z-[9999] cqa-w-auto cqa-max-w-[350px]\"\n >\n <div class=\"cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-0.5 cqa-w-full\">\n <div\n *ngFor=\"let option of options\"\n (click)=\"selectOption(option, $event)\"\n [class]=\"getOptionClasses(option)\"\n class=\"cqa-w-full cqa-whitespace-nowrap\"\n >\n <div class=\"cqa-w-6 cqa-h-4 cqa-pr-2 cqa-inline-flex cqa-flex-col cqa-justify-center cqa-items-center\">\n <mat-icon\n *ngIf=\"selectedValue === option.value\"\n class=\"cqa-w-4 cqa-h-4 cqa-text-primary cqa-text-base cqa-leading-4\"\n >check</mat-icon>\n </div>\n <div class=\"cqa-flex-1 cqa-inline-flex cqa-flex-col cqa-justify-start cqa-items-start\">\n <div class=\"cqa-justify-center cqa-text-gray-950 cqa-text-sm cqa-font-normal cqa-leading-5 cqa-font-geist\">\n {{ option.label }}\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n\n", styles: [] }]
|
|
2784
|
+
}], propDecorators: { label: [{
|
|
2785
|
+
type: Input
|
|
2786
|
+
}], options: [{
|
|
2787
|
+
type: Input
|
|
2788
|
+
}], selectedValue: [{
|
|
2789
|
+
type: Input
|
|
2790
|
+
}], disabled: [{
|
|
2791
|
+
type: Input
|
|
2792
|
+
}], placeholder: [{
|
|
2793
|
+
type: Input
|
|
2794
|
+
}], selectionChange: [{
|
|
2795
|
+
type: Output
|
|
2796
|
+
}], opened: [{
|
|
2797
|
+
type: Output
|
|
2798
|
+
}], closed: [{
|
|
2799
|
+
type: Output
|
|
2800
|
+
}], dropdownContainer: [{
|
|
2801
|
+
type: ViewChild,
|
|
2802
|
+
args: ['dropdownContainer', { static: false }]
|
|
2803
|
+
}], buttonElement: [{
|
|
2804
|
+
type: ViewChild,
|
|
2805
|
+
args: ['buttonElement', { static: false }]
|
|
2806
|
+
}], onDocumentClick: [{
|
|
2807
|
+
type: HostListener,
|
|
2808
|
+
args: ['document:click', ['$event']]
|
|
2809
|
+
}] } });
|
|
2810
|
+
|
|
2811
|
+
class HeatErrorMapCellComponent {
|
|
2812
|
+
constructor() {
|
|
2813
|
+
this.type = 'smoke';
|
|
2814
|
+
this.cases = 0;
|
|
2815
|
+
this.defects = 0;
|
|
2816
|
+
this.progress = 0; // Progress value from 0 to 100
|
|
2817
|
+
}
|
|
2818
|
+
get backgroundColorStyle() {
|
|
2819
|
+
switch (this.type) {
|
|
2820
|
+
case 'smoke':
|
|
2821
|
+
return { 'background-color': '#FDBA74' }; // orange-300
|
|
2822
|
+
case 'sanity':
|
|
2823
|
+
return { 'background-color': '#FCD34D' }; // amber-300
|
|
2824
|
+
case 'regression':
|
|
2825
|
+
return { 'background-color': '#A7F3D0' }; // emerald-200
|
|
2826
|
+
case 'revisit':
|
|
2827
|
+
return { 'background-color': '#F4F4F5' }; // zinc-100
|
|
2828
|
+
default:
|
|
2829
|
+
return { 'background-color': '#FDBA74' }; // orange-300
|
|
2830
|
+
}
|
|
2831
|
+
}
|
|
2832
|
+
get progressWidth() {
|
|
2833
|
+
// Clamp progress between 0 and 100
|
|
2834
|
+
const clampedProgress = Math.max(0, Math.min(100, this.progress));
|
|
2835
|
+
return `${clampedProgress}%`;
|
|
2836
|
+
}
|
|
2837
|
+
}
|
|
2838
|
+
HeatErrorMapCellComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: HeatErrorMapCellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2839
|
+
HeatErrorMapCellComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: HeatErrorMapCellComponent, selector: "cqa-heat-error-map-cell", inputs: { type: "type", cases: "cases", defects: "defects", progress: "progress" }, ngImport: i0, template: "<div id=\"cqa-ui-root\" style=\"width: 14rem; height: 6rem; display: inline-flex; justify-content: space-between; align-items: flex-start;\">\n <div class=\"min-w-56 min-h-24 cqa-self-stretch cqa-flex cqa-flex-col cqa-rounded-2xl cqa-justify-start cqa-items-start cqa-gap-4 cqa-p-4\" [ngStyle]=\"backgroundColorStyle\">\n <!-- section 1 -->\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-px\">\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start\">\n <div class=\"cqa-self-stretch cqa-justify-center cqa-text-gray-900 cqa-text-base cqa-font-bold cqa-leading-5 cqa-font-geist\">\n {{ cases }} cases\n </div>\n </div>\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start\">\n <div class=\"cqa-self-stretch cqa-justify-center cqa-text-gray-900 cqa-text-xs cqa-font-normal cqa-leading-4 cqa-font-geist\">\n {{ defects }} defects\n </div>\n </div>\n </div>\n <!-- section 2 -->\n <div class=\"cqa-self-stretch cqa-h-1 cqa-relative cqa-rounded-full cqa-overflow-hidden cqa-bg-white/70\">\n <div \n class=\"cqa-h-1 cqa-left-0 cqa-top-0 cqa-absolute cqa-bg-red-500 cqa-rounded-full\"\n [style.width]=\"progressWidth\"\n ></div>\n </div>\n </div>\n</div>\n\n\n", directives: [{ type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
|
|
2840
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: HeatErrorMapCellComponent, decorators: [{
|
|
2841
|
+
type: Component,
|
|
2842
|
+
args: [{ selector: 'cqa-heat-error-map-cell', template: "<div id=\"cqa-ui-root\" style=\"width: 14rem; height: 6rem; display: inline-flex; justify-content: space-between; align-items: flex-start;\">\n <div class=\"min-w-56 min-h-24 cqa-self-stretch cqa-flex cqa-flex-col cqa-rounded-2xl cqa-justify-start cqa-items-start cqa-gap-4 cqa-p-4\" [ngStyle]=\"backgroundColorStyle\">\n <!-- section 1 -->\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-px\">\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start\">\n <div class=\"cqa-self-stretch cqa-justify-center cqa-text-gray-900 cqa-text-base cqa-font-bold cqa-leading-5 cqa-font-geist\">\n {{ cases }} cases\n </div>\n </div>\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start\">\n <div class=\"cqa-self-stretch cqa-justify-center cqa-text-gray-900 cqa-text-xs cqa-font-normal cqa-leading-4 cqa-font-geist\">\n {{ defects }} defects\n </div>\n </div>\n </div>\n <!-- section 2 -->\n <div class=\"cqa-self-stretch cqa-h-1 cqa-relative cqa-rounded-full cqa-overflow-hidden cqa-bg-white/70\">\n <div \n class=\"cqa-h-1 cqa-left-0 cqa-top-0 cqa-absolute cqa-bg-red-500 cqa-rounded-full\"\n [style.width]=\"progressWidth\"\n ></div>\n </div>\n </div>\n</div>\n\n\n", styles: [] }]
|
|
2843
|
+
}], propDecorators: { type: [{
|
|
2844
|
+
type: Input
|
|
2845
|
+
}], cases: [{
|
|
2846
|
+
type: Input
|
|
2847
|
+
}], defects: [{
|
|
2848
|
+
type: Input
|
|
2849
|
+
}], progress: [{
|
|
2850
|
+
type: Input
|
|
2851
|
+
}] } });
|
|
2852
|
+
|
|
2853
|
+
class EmptyStateComponent {
|
|
2854
|
+
constructor() {
|
|
2855
|
+
this.title = '';
|
|
2856
|
+
this.description = '';
|
|
2857
|
+
this.actions = [];
|
|
2858
|
+
this.actionClick = new EventEmitter();
|
|
2859
|
+
}
|
|
2860
|
+
onActionClick(action, event) {
|
|
2861
|
+
if (!action.disabled) {
|
|
2862
|
+
if (action.onClick) {
|
|
2863
|
+
action.onClick();
|
|
2864
|
+
}
|
|
2865
|
+
this.actionClick.emit(action);
|
|
2866
|
+
}
|
|
2867
|
+
}
|
|
2868
|
+
}
|
|
2869
|
+
EmptyStateComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: EmptyStateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2870
|
+
EmptyStateComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: EmptyStateComponent, selector: "cqa-empty-state", inputs: { imageUrl: "imageUrl", title: "title", description: "description", actions: "actions" }, outputs: { actionClick: "actionClick" }, ngImport: i0, template: "<div id=\"cqa-ui-root\" style=\"background-color: white; border-radius: 14px; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 84.63px 33px 84.62px 33px;\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-[62px] cqa-items-center\">\n <!-- Icon Container -->\n <div *ngIf=\"imageUrl\" class=\"cqa-relative cqa-shrink-0 cqa-w-32 cqa-h-32\">\n <!-- Main Icon Container with Gradient Background and Shadow -->\n <div class=\"cqa-relative cqa-rounded-3xl cqa-w-32 cqa-h-32 cqa-shadow-sm\">\n <div class=\"cqa-absolute cqa-inset-0 cqa-bg-gradient-to-br cqa-from-indigo-500 cqa-to-violet-950 cqa-rounded-3xl cqa-opacity-10\"></div>\n <!-- Icon/Image centered inside on top layer - fully opaque -->\n <div class=\"cqa-absolute cqa-inset-0 cqa-flex cqa-items-center cqa-justify-center cqa-rounded-3xl\">\n <div class=\"cqa-w-20 cqa-h-20 cqa-flex cqa-items-center cqa-justify-center cqa-relative\">\n <img [src]=\"imageUrl\" alt=\"\" width=\"80px\" height=\"80px\" class=\"cqa-block cqa-max-w-none cqa-w-20 cqa-h-20 cqa-object-contain\" />\n </div>\n </div>\n </div>\n <!-- Decorative Dots -->\n <div class=\"cqa-absolute cqa-rounded-full cqa-bg-primary-300 cqa-opacity-[0.815]\" style=\"left: 120.79px; top: -9.21px; width: 18.416px; height: 18.416px; z-index: 20;\"></div>\n <div class=\"cqa-absolute cqa-rounded-full cqa-bg-primary-300 cqa-opacity-[0.695]\" style=\"left: -9.02px; top: 124.98px; width: 14.044px; height: 14.044px; z-index: 20;\"></div>\n </div>\n\n <!-- Content Container -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-9 cqa-items-center\">\n <!-- Title and Description -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-3 cqa-items-center cqa-w-full\">\n <!-- Title -->\n <div *ngIf=\"title\" class=\"cqa-flex cqa-flex-col cqa-items-center cqa-w-full\">\n <h3 class=\"cqa-font-inter cqa-text-lg cqa-font-medium cqa-leading-[18px] cqa-text-center cqa-text-neutral-900\">\n {{ title }}\n </h3>\n </div>\n <!-- Description -->\n <div *ngIf=\"description\" class=\"cqa-flex cqa-flex-col cqa-items-center cqa-w-full\">\n <p class=\"cqa-font-inter cqa-font-medium cqa-text-sm cqa-leading-[14px] cqa-text-center cqa-text-neutral-500\">\n {{ description }}\n </p>\n </div>\n </div>\n\n <!-- Action Buttons -->\n <div\n *ngIf=\"actions && actions.length > 0\"\n class=\"cqa-flex cqa-items-center cqa-justify-center\"\n [ngClass]=\"actions.length > 1 ? 'cqa-flex-row cqa-flex-wrap cqa-gap-4' : 'cqa-flex-col cqa-gap-2'\"\n >\n <cqa-button\n *ngFor=\"let action of actions\"\n [variant]=\"action.variant || 'filled'\"\n [icon]=\"action.icon\"\n [iconPosition]=\"action.iconPosition || 'start'\"\n [disabled]=\"action.disabled\"\n (clicked)=\"onActionClick(action, $event)\"\n >\n {{ action.label }}\n </cqa-button>\n </div>\n </div>\n </div>\n</div>\n\n", components: [{ type: ButtonComponent, selector: "cqa-button", inputs: ["variant", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass"], outputs: ["clicked"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
|
|
2871
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: EmptyStateComponent, decorators: [{
|
|
2872
|
+
type: Component,
|
|
2873
|
+
args: [{ selector: 'cqa-empty-state', template: "<div id=\"cqa-ui-root\" style=\"background-color: white; border-radius: 14px; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 84.63px 33px 84.62px 33px;\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-[62px] cqa-items-center\">\n <!-- Icon Container -->\n <div *ngIf=\"imageUrl\" class=\"cqa-relative cqa-shrink-0 cqa-w-32 cqa-h-32\">\n <!-- Main Icon Container with Gradient Background and Shadow -->\n <div class=\"cqa-relative cqa-rounded-3xl cqa-w-32 cqa-h-32 cqa-shadow-sm\">\n <div class=\"cqa-absolute cqa-inset-0 cqa-bg-gradient-to-br cqa-from-indigo-500 cqa-to-violet-950 cqa-rounded-3xl cqa-opacity-10\"></div>\n <!-- Icon/Image centered inside on top layer - fully opaque -->\n <div class=\"cqa-absolute cqa-inset-0 cqa-flex cqa-items-center cqa-justify-center cqa-rounded-3xl\">\n <div class=\"cqa-w-20 cqa-h-20 cqa-flex cqa-items-center cqa-justify-center cqa-relative\">\n <img [src]=\"imageUrl\" alt=\"\" width=\"80px\" height=\"80px\" class=\"cqa-block cqa-max-w-none cqa-w-20 cqa-h-20 cqa-object-contain\" />\n </div>\n </div>\n </div>\n <!-- Decorative Dots -->\n <div class=\"cqa-absolute cqa-rounded-full cqa-bg-primary-300 cqa-opacity-[0.815]\" style=\"left: 120.79px; top: -9.21px; width: 18.416px; height: 18.416px; z-index: 20;\"></div>\n <div class=\"cqa-absolute cqa-rounded-full cqa-bg-primary-300 cqa-opacity-[0.695]\" style=\"left: -9.02px; top: 124.98px; width: 14.044px; height: 14.044px; z-index: 20;\"></div>\n </div>\n\n <!-- Content Container -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-9 cqa-items-center\">\n <!-- Title and Description -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-3 cqa-items-center cqa-w-full\">\n <!-- Title -->\n <div *ngIf=\"title\" class=\"cqa-flex cqa-flex-col cqa-items-center cqa-w-full\">\n <h3 class=\"cqa-font-inter cqa-text-lg cqa-font-medium cqa-leading-[18px] cqa-text-center cqa-text-neutral-900\">\n {{ title }}\n </h3>\n </div>\n <!-- Description -->\n <div *ngIf=\"description\" class=\"cqa-flex cqa-flex-col cqa-items-center cqa-w-full\">\n <p class=\"cqa-font-inter cqa-font-medium cqa-text-sm cqa-leading-[14px] cqa-text-center cqa-text-neutral-500\">\n {{ description }}\n </p>\n </div>\n </div>\n\n <!-- Action Buttons -->\n <div\n *ngIf=\"actions && actions.length > 0\"\n class=\"cqa-flex cqa-items-center cqa-justify-center\"\n [ngClass]=\"actions.length > 1 ? 'cqa-flex-row cqa-flex-wrap cqa-gap-4' : 'cqa-flex-col cqa-gap-2'\"\n >\n <cqa-button\n *ngFor=\"let action of actions\"\n [variant]=\"action.variant || 'filled'\"\n [icon]=\"action.icon\"\n [iconPosition]=\"action.iconPosition || 'start'\"\n [disabled]=\"action.disabled\"\n (clicked)=\"onActionClick(action, $event)\"\n >\n {{ action.label }}\n </cqa-button>\n </div>\n </div>\n </div>\n</div>\n\n", styles: [] }]
|
|
2874
|
+
}], propDecorators: { imageUrl: [{
|
|
2875
|
+
type: Input
|
|
2876
|
+
}], title: [{
|
|
2877
|
+
type: Input
|
|
2878
|
+
}], description: [{
|
|
2879
|
+
type: Input
|
|
2880
|
+
}], actions: [{
|
|
2881
|
+
type: Input
|
|
2882
|
+
}], actionClick: [{
|
|
2883
|
+
type: Output
|
|
2884
|
+
}] } });
|
|
2885
|
+
|
|
2886
|
+
/**
|
|
2887
|
+
* Image assets constants for the UI library
|
|
2888
|
+
*
|
|
2889
|
+
* Place your image files in src/lib/assets/images/ and reference them here
|
|
2890
|
+
*
|
|
2891
|
+
* Usage in components:
|
|
2892
|
+
* import { EMPTY_STATE_IMAGES } from '../assets/images/image-assets.constants';
|
|
2893
|
+
* imageUrl: EMPTY_STATE_IMAGES.TEST_CASE
|
|
2894
|
+
*/
|
|
2895
|
+
const EMPTY_STATE_IMAGES = {
|
|
2896
|
+
// Test Case icon (document with gear)
|
|
2897
|
+
TEST_CASE: 'assets/images/TestCaseIcon.png',
|
|
2898
|
+
// Search/Debug icon (magnifying glass with question mark)
|
|
2899
|
+
SEARCH_DEBUG: 'assets/images/SearchIcon.png',
|
|
2900
|
+
// Upload/Folder icon (folder with upload arrow and plus)
|
|
2901
|
+
UPLOAD_FOLDER: 'assets/images/FilesIcon.png',
|
|
2902
|
+
// Dashboard overview
|
|
2903
|
+
DASHBOARD: 'assets/images/DashboardIcon.png',
|
|
2904
|
+
// Checklist/Add icon (clipboard with plus)
|
|
2905
|
+
CHECKLIST_ADD: 'assets/images/StepsIcon.png',
|
|
2906
|
+
// Document/Gear icon (document with gear overlay)
|
|
2907
|
+
DOCUMENT_GEAR: 'assets/images/document-gear-icon.svg',
|
|
2908
|
+
// Analytics/Chart icon (bar chart)
|
|
2909
|
+
ANALYTICS_CHART: 'assets/images/ReportsIcon.png',
|
|
2910
|
+
// Default empty state icon
|
|
2911
|
+
DEFAULT: 'assets/images/SearchIcon.png',
|
|
2912
|
+
};
|
|
2913
|
+
|
|
2914
|
+
class TableTemplateComponent {
|
|
2915
|
+
constructor() {
|
|
2916
|
+
// Search bar inputs
|
|
2917
|
+
this.searchPlaceholder = 'Search components';
|
|
2918
|
+
this.searchValue = '';
|
|
2919
|
+
this.showClear = true;
|
|
2920
|
+
this.showSearchBar = true;
|
|
2921
|
+
// Filter inputs
|
|
2922
|
+
this.filterConfig = [];
|
|
2923
|
+
this.showFilterPanel = false;
|
|
2924
|
+
this.showFilterButton = true;
|
|
2925
|
+
// Other button input
|
|
2926
|
+
this.otherButtonLabel = 'Other Button';
|
|
2927
|
+
this.otherButtonVariant = 'filled';
|
|
2928
|
+
this.showOtherButton = true;
|
|
2929
|
+
// Action menu button (three-dot menu in table rows)
|
|
2930
|
+
this.showActionButton = true;
|
|
2931
|
+
// Settings and refresh buttons
|
|
2932
|
+
this.showSettingsButton = true;
|
|
2933
|
+
this.showAutoRefreshButton = true;
|
|
2934
|
+
// Data input
|
|
2935
|
+
this.data = [];
|
|
2936
|
+
// Empty state inputs
|
|
2937
|
+
this.isEmptyState = false;
|
|
2938
|
+
this.emptyStateConfig = {
|
|
2939
|
+
title: 'No Data Available Yet',
|
|
2940
|
+
description: 'Run or upload your first test to see your analytics and trends here. Watch your quality metrics come to life with real-time insights.',
|
|
2941
|
+
imageUrl: EMPTY_STATE_IMAGES.DASHBOARD,
|
|
2942
|
+
actions: [{ label: 'Run Test Suite', variant: 'filled' }],
|
|
2943
|
+
};
|
|
2944
|
+
// Action bar inputs
|
|
2945
|
+
this.actions = [
|
|
2946
|
+
{
|
|
2947
|
+
id: 'delete',
|
|
2948
|
+
label: 'Delete',
|
|
2949
|
+
icon: 'delete',
|
|
2950
|
+
tooltip: 'Delete selected',
|
|
2951
|
+
onClick: (context) => {
|
|
2952
|
+
console.log('Delete action clicked:', context);
|
|
2953
|
+
}
|
|
2954
|
+
},
|
|
2955
|
+
{
|
|
2956
|
+
id: 'edit',
|
|
2957
|
+
label: 'Edit',
|
|
2958
|
+
icon: 'edit',
|
|
2959
|
+
tooltip: 'Edit selected',
|
|
2960
|
+
onClick: (context) => {
|
|
2961
|
+
console.log('Edit action clicked:', context);
|
|
2962
|
+
}
|
|
2963
|
+
},
|
|
2964
|
+
{
|
|
2965
|
+
id: 'add-tag',
|
|
2966
|
+
label: 'Add Tag',
|
|
2967
|
+
icon: 'local_offer',
|
|
2968
|
+
tooltip: 'Add tags',
|
|
2969
|
+
onClick: (context) => {
|
|
2970
|
+
console.log('Add tag action clicked:', context);
|
|
2971
|
+
}
|
|
2972
|
+
},
|
|
2973
|
+
{
|
|
2974
|
+
id: 'remove-tag',
|
|
2975
|
+
label: 'Remove Tag',
|
|
2976
|
+
icon: 'label_off',
|
|
2977
|
+
tooltip: 'Remove tags',
|
|
2978
|
+
onClick: (context) => {
|
|
2979
|
+
console.log('Remove tag action clicked:', context);
|
|
2980
|
+
}
|
|
2981
|
+
},
|
|
2982
|
+
];
|
|
2983
|
+
// Chips inputs
|
|
2984
|
+
this.chips = [];
|
|
2985
|
+
this.filterApplied = false;
|
|
2986
|
+
// Table inputs
|
|
2987
|
+
this.columns = [];
|
|
2988
|
+
this.selectedAutoRefreshInterval = 0;
|
|
2989
|
+
this.pageIndex = 0;
|
|
2990
|
+
this.pageSize = 10;
|
|
2991
|
+
// Backward-compatibility flag; if provided, dynamic table will use it when specific flags are undefined
|
|
2992
|
+
// Internal state for column visibility
|
|
2993
|
+
this._columnVisibility = {};
|
|
2994
|
+
this._cachedVisibilityColumns = [];
|
|
2995
|
+
this.filteredRows = [];
|
|
2996
|
+
this.pagedRows = [];
|
|
2997
|
+
}
|
|
2998
|
+
// Derived columns with visibility applied. Avoid mutating @Input() columns so parent bindings aren't overridden.
|
|
2999
|
+
get computedColumns() {
|
|
3000
|
+
const visibility = this._columnVisibility || {};
|
|
3001
|
+
const source = this.columns || [];
|
|
3002
|
+
return source.map(col => {
|
|
3003
|
+
if (['checkbox', 'actions'].includes(col.fieldId)) {
|
|
3004
|
+
return col;
|
|
3005
|
+
}
|
|
3006
|
+
const show = visibility[col.fieldId];
|
|
3007
|
+
return { ...col, isShow: show !== false };
|
|
3008
|
+
});
|
|
3009
|
+
}
|
|
3010
|
+
// Auto-generated visibility columns from columns input (excludes default columns and checkbox/actions)
|
|
3011
|
+
// Cached to avoid creating new arrays on every change detection cycle
|
|
3012
|
+
get visibilityColumns() {
|
|
3013
|
+
return this._cachedVisibilityColumns;
|
|
3014
|
+
}
|
|
3015
|
+
// Internal column visibility state
|
|
3016
|
+
get columnVisibility() {
|
|
3017
|
+
return this._columnVisibility;
|
|
3018
|
+
}
|
|
3019
|
+
ngOnInit() {
|
|
3020
|
+
this.initializeComponent();
|
|
3021
|
+
}
|
|
3022
|
+
ngOnChanges(changes) {
|
|
3023
|
+
if (changes['data'] || changes['isEmptyState']) {
|
|
3024
|
+
this.initializeComponent();
|
|
3025
|
+
}
|
|
3026
|
+
if (changes['columns']) {
|
|
3027
|
+
this.initializeColumnVisibility();
|
|
3028
|
+
}
|
|
3029
|
+
}
|
|
3030
|
+
initializeComponent() {
|
|
3031
|
+
if (this.isEmptyState) {
|
|
3032
|
+
this.filteredRows = [];
|
|
3033
|
+
this.pagedRows = [];
|
|
3034
|
+
return;
|
|
3035
|
+
}
|
|
3036
|
+
this.filteredRows = [...this.data];
|
|
3037
|
+
this.applyPagination();
|
|
3038
|
+
this.initializeColumnVisibility();
|
|
3039
|
+
}
|
|
3040
|
+
initializeColumnVisibility() {
|
|
3041
|
+
// Cache visibility columns to avoid creating new arrays on every change detection
|
|
3042
|
+
this._cachedVisibilityColumns = this.mapVisibilityColumns();
|
|
3043
|
+
// Initialize visibility state for all visibility columns (default to true)
|
|
3044
|
+
for (const col of this._cachedVisibilityColumns) {
|
|
3045
|
+
if (this._columnVisibility[col.id] === undefined) {
|
|
3046
|
+
this._columnVisibility[col.id] = true;
|
|
3047
|
+
}
|
|
3048
|
+
}
|
|
3049
|
+
}
|
|
3050
|
+
get anyRowSelected() {
|
|
3051
|
+
return !!(this.pagedRows && this.pagedRows.some(r => !!r.isSelected));
|
|
3052
|
+
}
|
|
3053
|
+
get currentSelectedItems() {
|
|
3054
|
+
return (this.pagedRows || []).filter(r => !!r.isSelected);
|
|
3055
|
+
}
|
|
3056
|
+
actionClick(data) {
|
|
3057
|
+
console.log('action toolbar', data);
|
|
3058
|
+
}
|
|
3059
|
+
view(id) {
|
|
3060
|
+
console.log('View', id);
|
|
3061
|
+
}
|
|
3062
|
+
edit(row) {
|
|
3063
|
+
console.log('Edit', row);
|
|
3064
|
+
}
|
|
3065
|
+
delete(row) {
|
|
3066
|
+
console.log('Delete', row);
|
|
3067
|
+
}
|
|
3068
|
+
onRowCheckboxChange(event, row) {
|
|
3069
|
+
const input = event.target;
|
|
3070
|
+
const checked = !!input?.checked;
|
|
3071
|
+
row.isSelected = checked;
|
|
3072
|
+
}
|
|
3073
|
+
toggleFilter() {
|
|
3074
|
+
this.showFilterPanel = !this.showFilterPanel;
|
|
3075
|
+
}
|
|
3076
|
+
onColumnVisibilityChange(cfg) {
|
|
3077
|
+
this._columnVisibility = { ...cfg };
|
|
3078
|
+
// Do not mutate this.columns; computedColumns getter will reflect changes
|
|
3079
|
+
}
|
|
3080
|
+
onAutoRefreshChange(intervalMs) {
|
|
3081
|
+
this.selectedAutoRefreshInterval = intervalMs;
|
|
3082
|
+
console.log('Auto refresh interval', intervalMs);
|
|
3083
|
+
}
|
|
3084
|
+
valueChange(value) {
|
|
3085
|
+
console.log('Value changed', value);
|
|
3086
|
+
}
|
|
3087
|
+
search(value) {
|
|
3088
|
+
console.log('Search', value);
|
|
3089
|
+
}
|
|
3090
|
+
cleared() {
|
|
3091
|
+
console.log('Cleared');
|
|
3092
|
+
}
|
|
3093
|
+
resultBadgeClass(result) {
|
|
3094
|
+
const value = (result || '').toUpperCase();
|
|
3095
|
+
if (value === 'SUCCESS')
|
|
3096
|
+
return 'cqa-bg-green-100 cqa-text-green-700';
|
|
3097
|
+
if (value === 'FAILURE' || value === 'ABORTED')
|
|
3098
|
+
return 'cqa-bg-red-100 cqa-text-red-700';
|
|
3099
|
+
if (value === 'QUEUED' || value === 'NOT_EXECUTED' || value === 'STOPPED')
|
|
3100
|
+
return 'cqa-bg-gray-100 cqa-text-gray-700';
|
|
3101
|
+
return 'cqa-bg-gray-100 cqa-text-gray-700';
|
|
3102
|
+
}
|
|
3103
|
+
onEmptyAction(action) {
|
|
3104
|
+
if (action?.label === 'Show filters') {
|
|
3105
|
+
this.toggleFilter();
|
|
3106
|
+
}
|
|
3107
|
+
}
|
|
3108
|
+
onFiltersChanged(current) {
|
|
3109
|
+
this.filteredRows = this.data.filter(r => this.passFilters(current, r));
|
|
3110
|
+
this.pageIndex = 0;
|
|
3111
|
+
this.applyPagination();
|
|
3112
|
+
const chips = [];
|
|
3113
|
+
if (current) {
|
|
3114
|
+
for (const key of Object.keys(current)) {
|
|
3115
|
+
const value = current[key];
|
|
3116
|
+
if (value == null || value === '' || (Array.isArray(value) && value.length === 0))
|
|
3117
|
+
continue;
|
|
3118
|
+
let text = '';
|
|
3119
|
+
if (Array.isArray(value)) {
|
|
3120
|
+
text = value.map((v) => (v?.name ?? v?.label ?? v?.value ?? v)).join(', ');
|
|
3121
|
+
}
|
|
3122
|
+
else if (typeof value === 'object') {
|
|
3123
|
+
if ('start' in value || 'end' in value) {
|
|
3124
|
+
const s = value.start ? new Date(value.start).toLocaleDateString() : '';
|
|
3125
|
+
const e = value.end ? new Date(value.end).toLocaleDateString() : '';
|
|
3126
|
+
text = [s, e].filter(Boolean).join(' - ');
|
|
3127
|
+
}
|
|
3128
|
+
else {
|
|
3129
|
+
text = (value?.name ?? value?.label ?? value?.value ?? JSON.stringify(value));
|
|
3130
|
+
}
|
|
3131
|
+
}
|
|
3132
|
+
else {
|
|
3133
|
+
text = String(value);
|
|
3134
|
+
}
|
|
3135
|
+
chips.push({ key, text, fullText: text, hasMore: text.length > 30 });
|
|
3136
|
+
}
|
|
3137
|
+
}
|
|
3138
|
+
this.chips = chips;
|
|
3139
|
+
this.filterApplied = this.chips.length > 0;
|
|
3140
|
+
}
|
|
3141
|
+
onFiltersApplied(_) {
|
|
3142
|
+
// handled in onFiltersChanged for this demo
|
|
3143
|
+
}
|
|
3144
|
+
onPaginate(e) {
|
|
3145
|
+
this.pageIndex = e.pageIndex;
|
|
3146
|
+
this.pageSize = e.pageSize;
|
|
3147
|
+
this.applyPagination();
|
|
3148
|
+
}
|
|
3149
|
+
onPageSizeChange(size) {
|
|
3150
|
+
this.pageSize = size;
|
|
3151
|
+
this.pageIndex = 0;
|
|
3152
|
+
this.applyPagination();
|
|
3153
|
+
}
|
|
3154
|
+
onRemoveChip(chip) {
|
|
3155
|
+
this.chips = this.chips.filter(c => c !== chip);
|
|
3156
|
+
this.filterApplied = this.chips.length > 0;
|
|
3157
|
+
}
|
|
3158
|
+
onClearAllChips() {
|
|
3159
|
+
this.chips = [];
|
|
3160
|
+
this.filterApplied = false;
|
|
3161
|
+
}
|
|
3162
|
+
applyPagination() {
|
|
3163
|
+
const start = this.pageIndex * this.pageSize;
|
|
3164
|
+
const end = start + this.pageSize;
|
|
3165
|
+
this.pagedRows = this.filteredRows.slice(start, end);
|
|
3166
|
+
}
|
|
3167
|
+
mapVisibilityColumns() {
|
|
3168
|
+
return (this.columns || [])
|
|
3169
|
+
.filter(c => c.isDefault === false)
|
|
3170
|
+
.map(c => ({ id: c.fieldId, label: c.fieldName || c.fieldId }));
|
|
3171
|
+
}
|
|
3172
|
+
normalizeDate(d) {
|
|
3173
|
+
if (!d)
|
|
3174
|
+
return null;
|
|
3175
|
+
const ts = Date.parse(d);
|
|
3176
|
+
return isNaN(ts) ? null : ts;
|
|
3177
|
+
}
|
|
3178
|
+
passFilters(filters, row) {
|
|
3179
|
+
if (!filters)
|
|
3180
|
+
return true;
|
|
3181
|
+
if (filters.status && Array.isArray(filters.status) && filters.status.length) {
|
|
3182
|
+
if (!filters.status.includes(row.status))
|
|
3183
|
+
return false;
|
|
3184
|
+
}
|
|
3185
|
+
if (filters.priority && Array.isArray(filters.priority) && filters.priority.length) {
|
|
3186
|
+
if (!filters.priority.includes(row.priorityName))
|
|
3187
|
+
return false;
|
|
3188
|
+
}
|
|
3189
|
+
if (filters.testType && Array.isArray(filters.testType) && filters.testType.length) {
|
|
3190
|
+
if (!filters.testType.includes(row.testType))
|
|
3191
|
+
return false;
|
|
3192
|
+
}
|
|
3193
|
+
if (filters.created_date && (filters.created_date.start || filters.created_date.end)) {
|
|
3194
|
+
const startTs = this.normalizeDate(filters.created_date.start);
|
|
3195
|
+
const endTs = this.normalizeDate(filters.created_date.end);
|
|
3196
|
+
const rowTs = this.normalizeDate(row.createdAt);
|
|
3197
|
+
if (rowTs != null) {
|
|
3198
|
+
if (startTs != null && rowTs < startTs)
|
|
3199
|
+
return false;
|
|
3200
|
+
if (endTs != null && rowTs > endTs)
|
|
3201
|
+
return false;
|
|
3202
|
+
}
|
|
3203
|
+
}
|
|
3204
|
+
return true;
|
|
3205
|
+
}
|
|
3206
|
+
}
|
|
3207
|
+
TableTemplateComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TableTemplateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3208
|
+
TableTemplateComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TableTemplateComponent, selector: "cqa-table-template", inputs: { searchPlaceholder: "searchPlaceholder", searchValue: "searchValue", showClear: "showClear", showSearchBar: "showSearchBar", filterConfig: "filterConfig", showFilterPanel: "showFilterPanel", showFilterButton: "showFilterButton", otherButtonLabel: "otherButtonLabel", otherButtonVariant: "otherButtonVariant", showOtherButton: "showOtherButton", showActionButton: "showActionButton", showSettingsButton: "showSettingsButton", showAutoRefreshButton: "showAutoRefreshButton", data: "data", isEmptyState: "isEmptyState", emptyStateConfig: "emptyStateConfig", actions: "actions", chips: "chips", filterApplied: "filterApplied", columns: "columns", selectedAutoRefreshInterval: "selectedAutoRefreshInterval", pageIndex: "pageIndex", pageSize: "pageSize", isTableLoading: "isTableLoading", isTableDataLoading: "isTableDataLoading" }, usesOnChanges: true, ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <div class=\"cqa-w-full cqa-flex cqa-flex-col cqa-relative\">\n <div class=\"cqa-w-full cqa-flex cqa-items-center cqa-justify-between cqa-gap-3 cqa-flex-wrap cqa-mb-3\">\n <cqa-search-bar\n *ngIf=\"showSearchBar\"\n [placeholder]=\"searchPlaceholder\"\n [value]=\"searchValue\"\n [showClear]=\"showClear\"\n (valueChange)=\"valueChange($event)\"\n (search)=\"search($event)\"\n (cleared)=\"cleared()\"\n ></cqa-search-bar>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-flex-wrap\">\n <cqa-button\n *ngIf=\"showFilterButton\"\n variant=\"grey-solid\"\n icon=\"add\"\n [text]=\"'Filter'\"\n (clicked)=\"toggleFilter()\"\n >\n <span>Filter</span>\n </cqa-button>\n <cqa-column-visibility\n *ngIf=\"showSettingsButton\"\n [columns]=\"visibilityColumns\"\n [columnVisibility]=\"columnVisibility\"\n [selectedAutoRefreshInterval]=\"selectedAutoRefreshInterval\"\n (columnVisibilityChange)=\"onColumnVisibilityChange($event)\"\n (autoRefreshChange)=\"onAutoRefreshChange($event)\"\n ></cqa-column-visibility>\n <cqa-button *ngIf=\"showAutoRefreshButton\" variant=\"grey-solid\" icon=\"refresh\"></cqa-button>\n <cqa-button *ngIf=\"showOtherButton\" [variant]=\"otherButtonVariant\" [text]=\"otherButtonLabel\"></cqa-button>\n </div>\n </div>\n\n <cqa-selected-filters \n *ngIf=\"showFilterPanel\"\n [filterApplied]=\"filterApplied\"\n [chips]=\"chips\"\n (removeChip)=\"onRemoveChip($event)\"\n (clearAll)=\"onClearAllChips()\"\n >\n </cqa-selected-filters>\n\n <cqa-dynamic-filter\n *ngIf=\"showFilterPanel\"\n [config]=\"filterConfig\"\n [showFilterPanel]=\"showFilterPanel\"\n (filtersChanged)=\"onFiltersChanged($event)\"\n (filtersApplied)=\"onFiltersApplied($event)\"\n >\n </cqa-dynamic-filter>\n\n <div class=\"cqa-rounded-[7px] cqa-overflow-hidden cqa-border-t cqa-border-l cqa-border-r cqa-border-grey-200 cqa-relative\">\n <ng-container *ngIf=\"!isEmptyState && pagedRows && pagedRows.length > 0; else storyEmptyTpl\">\n <app-dynamic-table\n [columns]=\"computedColumns\"\n [data]=\"pagedRows\"\n [isTableLoading]=\"isTableLoading\"\n [isTableDataLoading]=\"isTableDataLoading\">\n <ng-template dynamicCell=\"checkbox\" let-row=\"row\">\n <div class=\"custom-checkbox\">\n <input\n type=\"checkbox\"\n class=\"hidden-checkbox\"\n [attr.id]=\"'row-checkbox-' + row.id\"\n [checked]=\"row.isSelected\"\n aria-label=\"Select row\"\n (change)=\"onRowCheckboxChange($event, row)\" />\n <label\n class=\"custom-checkbox-label\"\n [attr.for]=\"'row-checkbox-' + row.id\">\n </label>\n </div>\n </ng-template>\n\n <ng-template dynamicCell=\"testCases\" let-row=\"row\" let-value=\"value\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-1 cqa-text-[12.3px] cqa-leading-[17.5px] cqa-font-medium\">\n <div class=\"cqa-text-[#3F43EE] cqa-truncate\">\n #{{ row.id }}\n </div>\n <div class=\"cqa-text-[#0A0A0A]\">{{ value }}</div>\n </div>\n </ng-template>\n\n <ng-template dynamicCell=\"type\" let-row=\"row\" let-value=\"value\">\n <div class=\"cqa-text-xs cqa-text-[#111827] cqa-truncate\">{{ value }}</div>\n </ng-template>\n\n <ng-template dynamicCell=\"priority\" let-row=\"row\" let-value=\"value\">\n <span\n class=\"cqa-inline-flex cqa-items-center cqa-px-2 cqa-py-0.5 cqa-rounded cqa-text-xs\"\n [ngClass]=\"{\n 'cqa-bg-red-100 cqa-text-red-700': value === 'Critical' || value === 'Major',\n 'cqa-bg-yellow-100 cqa-text-yellow-700': value === 'Medium',\n 'cqa-bg-blue-100 cqa-text-blue-700': value === 'Minor',\n 'cqa-bg-gray-100 cqa-text-gray-700': !value || value === 'Not Set'\n }\"\n >{{ value || 'Not Set' }}</span\n >\n </ng-template>\n\n <ng-template dynamicCell=\"result\" let-row=\"row\" let-value=\"value\">\n <span class=\"cqa-inline-flex cqa-items-center cqa-px-2 cqa-py-0.5 cqa-rounded cqa-text-xs\" [ngClass]=\"resultBadgeClass(value)\">\n {{ value || 'NOT_EXECUTED' }}\n </span>\n </ng-template>\n\n <ng-template dynamicCell=\"status\" let-row=\"row\" let-value=\"value\">\n <span class=\"cqa-text-xs\">{{ value }}</span>\n </ng-template>\n\n <ng-template dynamicCell=\"labels\" let-row=\"row\" let-value=\"value\">\n <div class=\"cqa-flex cqa-flex-wrap cqa-gap-1\">\n <span *ngFor=\"let tag of (row.tags || []) | slice: 0:3\" class=\"cqa-px-2 cqa-py-0.5 cqa-rounded cqa-bg-gray-100 cqa-text-gray-700 cqa-text-xs\">\n {{ tag }}\n </span>\n <span *ngIf=\"(row.tags?.length || 0) > 3\" class=\"cqa-px-2 cqa-py-0.5 cqa-rounded cqa-bg-gray-100 cqa-text-gray-700 cqa-text-xs\">\n +{{ (row.tags?.length || 0) - 3 }} more\n </span>\n </div>\n </ng-template>\n\n <ng-template dynamicCell=\"createdBy\" let-row=\"row\" let-value=\"value\">\n <span class=\"cqa-text-xs\">{{ value }}</span>\n </ng-template>\n\n <ng-template dynamicCell=\"createdAt\" let-row=\"row\" let-value=\"value\">\n <span class=\"cqa-text-xs cqa-text-gray-700\">{{ value | date: 'medium' }}</span>\n </ng-template>\n\n <ng-template dynamicCell=\"updatedAt\" let-row=\"row\" let-value=\"value\">\n <span class=\"cqa-text-xs cqa-text-gray-700\">{{ value | date: 'medium' }}</span>\n </ng-template>\n\n <ng-template dynamicCell=\"lastRun\" let-row=\"row\">\n <div class=\"cqa-flex cqa-flex-col\">\n <span class=\"cqa-text-xs cqa-text-[#111827]\">{{ row.lastRun?.startTime | date: 'medium' }}</span>\n </div>\n </ng-template>\n\n <ng-template dynamicCell=\"actions\" let-row=\"row\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" *ngIf=\"showActionButton\">\n <cqa-action-menu-button\n [row]=\"row\"\n (view)=\"view($event)\"\n (edit)=\"edit($event)\"\n (delete)=\"delete($event)\"\n ></cqa-action-menu-button>\n </div>\n </ng-template>\n\n <ng-template #emptyTableTpl>\n <div class=\"cqa-flex cqa-flex-col cqa-items-center cqa-justify-center cqa-py-8\">\n <img src=\"/assets/illustrations/empty-state.svg\" alt=\"No data\" class=\"cqa-w-32 cqa-h-32 cqa-mb-4\" />\n <h3 class=\"cqa-text-lg cqa-font-semibold cqa-mb-2\">No test cases</h3>\n <p class=\"cqa-text-sm cqa-text-neutral-500 cqa-mb-4\">Try adjusting filters or create a new test case.</p>\n <cqa-button variant=\"filled\" (clicked)=\"toggleFilter()\">Show Filters</cqa-button>\n </div>\n </ng-template>\n </app-dynamic-table>\n </ng-container>\n\n <ng-template #storyEmptyTpl>\n <div class=\"cqa-p-6 cqa-flex cqa-flex-col cqa-items-center cqa-justify-center\">\n <cqa-empty-state\n *ngIf=\"isEmptyState\"\n [title]=\"emptyStateConfig.title\"\n [description]=\"emptyStateConfig.description\"\n [imageUrl]=\"emptyStateConfig.imageUrl\"\n [actions]=\"emptyStateConfig.actions\"\n (actionClick)=\"onEmptyAction($event)\"\n >\n </cqa-empty-state>\n </div>\n </ng-template>\n\n </div>\n\n <cqa-pagination\n [totalElements]=\"filteredRows.length\"\n [pageIndex]=\"pageIndex\"\n [pageSize]=\"pageSize\"\n [pageItemCount]=\"pagedRows.length\"\n (paginate)=\"onPaginate($event)\"\n (pageSizeChange)=\"onPageSizeChange($event)\"\n >\n </cqa-pagination>\n\n <div *ngIf=\"anyRowSelected\" class=\"cqa-absolute cqa-bottom-[18.75px] cqa-left-[50%] cqa-translate-x-[-50%] cqa-w-full lg:cqa-max-w-[68%] cqa-sm:max-w-[75%] cqa-max-w-[90%] cqa-z-[1]\" >\n <cqa-table-action-toolbar\n [selectedItems]=\"currentSelectedItems\"\n [actions]=\"actions\"\n (actionClick)=\"actionClick($event)\"\n ></cqa-table-action-toolbar>\n </div>\n \n </div>\n</div>\n\n", components: [{ type: SearchBarComponent, selector: "cqa-search-bar", inputs: ["placeholder", "value", "disabled", "showClear", "ariaLabel", "autoFocus", "size", "fullWidth"], outputs: ["valueChange", "search", "cleared"] }, { type: ButtonComponent, selector: "cqa-button", inputs: ["variant", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass"], outputs: ["clicked"] }, { type: ColumnVisibilityComponent, selector: "cqa-column-visibility", inputs: ["isStepGroup", "columns", "columnVisibility", "selectedAutoRefreshInterval"], outputs: ["columnVisibilityChange", "autoRefreshChange"] }, { type: SelectedFiltersComponent, selector: "cqa-selected-filters", inputs: ["filterApplied", "chips"], outputs: ["removeChip", "clearAll"] }, { type: DynamicFilterComponent, selector: "cqa-dynamic-filter", inputs: ["config", "model", "showFilterPanel"], outputs: ["filtersApplied", "filtersChanged", "resetAction"] }, { type: DynamicTableComponent, selector: "app-dynamic-table", inputs: ["data", "columns", "emptyState", "gridTemplateColumns", "screenWidth", "enableSelectAll", "enableLocalSort", "isTableLoading", "isTableDataLoading"], outputs: ["sortChange"] }, { type: ActionMenuButtonComponent, selector: "cqa-action-menu-button", inputs: ["row"], outputs: ["view", "edit", "delete"] }, { type: EmptyStateComponent, selector: "cqa-empty-state", inputs: ["imageUrl", "title", "description", "actions"], outputs: ["actionClick"] }, { type: PaginationComponent, selector: "cqa-pagination", inputs: ["totalElements", "totalPages", "pageIndex", "pageSize", "pageItemCount", "pageSizeOptions"], outputs: ["pageIndexChange", "pageSizeChange", "paginate"] }, { type: TableActionToolbarComponent, selector: "cqa-table-action-toolbar", inputs: ["selectedItems", "actions"], outputs: ["actionClick"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: DynamicCellTemplateDirective, selector: "ng-template[dynamicCell]", inputs: ["dynamicCell"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], pipes: { "slice": i2.SlicePipe, "date": i2.DatePipe } });
|
|
3209
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TableTemplateComponent, decorators: [{
|
|
3210
|
+
type: Component,
|
|
3211
|
+
args: [{ selector: 'cqa-table-template', template: "<div id=\"cqa-ui-root\">\n <div class=\"cqa-w-full cqa-flex cqa-flex-col cqa-relative\">\n <div class=\"cqa-w-full cqa-flex cqa-items-center cqa-justify-between cqa-gap-3 cqa-flex-wrap cqa-mb-3\">\n <cqa-search-bar\n *ngIf=\"showSearchBar\"\n [placeholder]=\"searchPlaceholder\"\n [value]=\"searchValue\"\n [showClear]=\"showClear\"\n (valueChange)=\"valueChange($event)\"\n (search)=\"search($event)\"\n (cleared)=\"cleared()\"\n ></cqa-search-bar>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-flex-wrap\">\n <cqa-button\n *ngIf=\"showFilterButton\"\n variant=\"grey-solid\"\n icon=\"add\"\n [text]=\"'Filter'\"\n (clicked)=\"toggleFilter()\"\n >\n <span>Filter</span>\n </cqa-button>\n <cqa-column-visibility\n *ngIf=\"showSettingsButton\"\n [columns]=\"visibilityColumns\"\n [columnVisibility]=\"columnVisibility\"\n [selectedAutoRefreshInterval]=\"selectedAutoRefreshInterval\"\n (columnVisibilityChange)=\"onColumnVisibilityChange($event)\"\n (autoRefreshChange)=\"onAutoRefreshChange($event)\"\n ></cqa-column-visibility>\n <cqa-button *ngIf=\"showAutoRefreshButton\" variant=\"grey-solid\" icon=\"refresh\"></cqa-button>\n <cqa-button *ngIf=\"showOtherButton\" [variant]=\"otherButtonVariant\" [text]=\"otherButtonLabel\"></cqa-button>\n </div>\n </div>\n\n <cqa-selected-filters \n *ngIf=\"showFilterPanel\"\n [filterApplied]=\"filterApplied\"\n [chips]=\"chips\"\n (removeChip)=\"onRemoveChip($event)\"\n (clearAll)=\"onClearAllChips()\"\n >\n </cqa-selected-filters>\n\n <cqa-dynamic-filter\n *ngIf=\"showFilterPanel\"\n [config]=\"filterConfig\"\n [showFilterPanel]=\"showFilterPanel\"\n (filtersChanged)=\"onFiltersChanged($event)\"\n (filtersApplied)=\"onFiltersApplied($event)\"\n >\n </cqa-dynamic-filter>\n\n <div class=\"cqa-rounded-[7px] cqa-overflow-hidden cqa-border-t cqa-border-l cqa-border-r cqa-border-grey-200 cqa-relative\">\n <ng-container *ngIf=\"!isEmptyState && pagedRows && pagedRows.length > 0; else storyEmptyTpl\">\n <app-dynamic-table\n [columns]=\"computedColumns\"\n [data]=\"pagedRows\"\n [isTableLoading]=\"isTableLoading\"\n [isTableDataLoading]=\"isTableDataLoading\">\n <ng-template dynamicCell=\"checkbox\" let-row=\"row\">\n <div class=\"custom-checkbox\">\n <input\n type=\"checkbox\"\n class=\"hidden-checkbox\"\n [attr.id]=\"'row-checkbox-' + row.id\"\n [checked]=\"row.isSelected\"\n aria-label=\"Select row\"\n (change)=\"onRowCheckboxChange($event, row)\" />\n <label\n class=\"custom-checkbox-label\"\n [attr.for]=\"'row-checkbox-' + row.id\">\n </label>\n </div>\n </ng-template>\n\n <ng-template dynamicCell=\"testCases\" let-row=\"row\" let-value=\"value\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-1 cqa-text-[12.3px] cqa-leading-[17.5px] cqa-font-medium\">\n <div class=\"cqa-text-[#3F43EE] cqa-truncate\">\n #{{ row.id }}\n </div>\n <div class=\"cqa-text-[#0A0A0A]\">{{ value }}</div>\n </div>\n </ng-template>\n\n <ng-template dynamicCell=\"type\" let-row=\"row\" let-value=\"value\">\n <div class=\"cqa-text-xs cqa-text-[#111827] cqa-truncate\">{{ value }}</div>\n </ng-template>\n\n <ng-template dynamicCell=\"priority\" let-row=\"row\" let-value=\"value\">\n <span\n class=\"cqa-inline-flex cqa-items-center cqa-px-2 cqa-py-0.5 cqa-rounded cqa-text-xs\"\n [ngClass]=\"{\n 'cqa-bg-red-100 cqa-text-red-700': value === 'Critical' || value === 'Major',\n 'cqa-bg-yellow-100 cqa-text-yellow-700': value === 'Medium',\n 'cqa-bg-blue-100 cqa-text-blue-700': value === 'Minor',\n 'cqa-bg-gray-100 cqa-text-gray-700': !value || value === 'Not Set'\n }\"\n >{{ value || 'Not Set' }}</span\n >\n </ng-template>\n\n <ng-template dynamicCell=\"result\" let-row=\"row\" let-value=\"value\">\n <span class=\"cqa-inline-flex cqa-items-center cqa-px-2 cqa-py-0.5 cqa-rounded cqa-text-xs\" [ngClass]=\"resultBadgeClass(value)\">\n {{ value || 'NOT_EXECUTED' }}\n </span>\n </ng-template>\n\n <ng-template dynamicCell=\"status\" let-row=\"row\" let-value=\"value\">\n <span class=\"cqa-text-xs\">{{ value }}</span>\n </ng-template>\n\n <ng-template dynamicCell=\"labels\" let-row=\"row\" let-value=\"value\">\n <div class=\"cqa-flex cqa-flex-wrap cqa-gap-1\">\n <span *ngFor=\"let tag of (row.tags || []) | slice: 0:3\" class=\"cqa-px-2 cqa-py-0.5 cqa-rounded cqa-bg-gray-100 cqa-text-gray-700 cqa-text-xs\">\n {{ tag }}\n </span>\n <span *ngIf=\"(row.tags?.length || 0) > 3\" class=\"cqa-px-2 cqa-py-0.5 cqa-rounded cqa-bg-gray-100 cqa-text-gray-700 cqa-text-xs\">\n +{{ (row.tags?.length || 0) - 3 }} more\n </span>\n </div>\n </ng-template>\n\n <ng-template dynamicCell=\"createdBy\" let-row=\"row\" let-value=\"value\">\n <span class=\"cqa-text-xs\">{{ value }}</span>\n </ng-template>\n\n <ng-template dynamicCell=\"createdAt\" let-row=\"row\" let-value=\"value\">\n <span class=\"cqa-text-xs cqa-text-gray-700\">{{ value | date: 'medium' }}</span>\n </ng-template>\n\n <ng-template dynamicCell=\"updatedAt\" let-row=\"row\" let-value=\"value\">\n <span class=\"cqa-text-xs cqa-text-gray-700\">{{ value | date: 'medium' }}</span>\n </ng-template>\n\n <ng-template dynamicCell=\"lastRun\" let-row=\"row\">\n <div class=\"cqa-flex cqa-flex-col\">\n <span class=\"cqa-text-xs cqa-text-[#111827]\">{{ row.lastRun?.startTime | date: 'medium' }}</span>\n </div>\n </ng-template>\n\n <ng-template dynamicCell=\"actions\" let-row=\"row\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" *ngIf=\"showActionButton\">\n <cqa-action-menu-button\n [row]=\"row\"\n (view)=\"view($event)\"\n (edit)=\"edit($event)\"\n (delete)=\"delete($event)\"\n ></cqa-action-menu-button>\n </div>\n </ng-template>\n\n <ng-template #emptyTableTpl>\n <div class=\"cqa-flex cqa-flex-col cqa-items-center cqa-justify-center cqa-py-8\">\n <img src=\"/assets/illustrations/empty-state.svg\" alt=\"No data\" class=\"cqa-w-32 cqa-h-32 cqa-mb-4\" />\n <h3 class=\"cqa-text-lg cqa-font-semibold cqa-mb-2\">No test cases</h3>\n <p class=\"cqa-text-sm cqa-text-neutral-500 cqa-mb-4\">Try adjusting filters or create a new test case.</p>\n <cqa-button variant=\"filled\" (clicked)=\"toggleFilter()\">Show Filters</cqa-button>\n </div>\n </ng-template>\n </app-dynamic-table>\n </ng-container>\n\n <ng-template #storyEmptyTpl>\n <div class=\"cqa-p-6 cqa-flex cqa-flex-col cqa-items-center cqa-justify-center\">\n <cqa-empty-state\n *ngIf=\"isEmptyState\"\n [title]=\"emptyStateConfig.title\"\n [description]=\"emptyStateConfig.description\"\n [imageUrl]=\"emptyStateConfig.imageUrl\"\n [actions]=\"emptyStateConfig.actions\"\n (actionClick)=\"onEmptyAction($event)\"\n >\n </cqa-empty-state>\n </div>\n </ng-template>\n\n </div>\n\n <cqa-pagination\n [totalElements]=\"filteredRows.length\"\n [pageIndex]=\"pageIndex\"\n [pageSize]=\"pageSize\"\n [pageItemCount]=\"pagedRows.length\"\n (paginate)=\"onPaginate($event)\"\n (pageSizeChange)=\"onPageSizeChange($event)\"\n >\n </cqa-pagination>\n\n <div *ngIf=\"anyRowSelected\" class=\"cqa-absolute cqa-bottom-[18.75px] cqa-left-[50%] cqa-translate-x-[-50%] cqa-w-full lg:cqa-max-w-[68%] cqa-sm:max-w-[75%] cqa-max-w-[90%] cqa-z-[1]\" >\n <cqa-table-action-toolbar\n [selectedItems]=\"currentSelectedItems\"\n [actions]=\"actions\"\n (actionClick)=\"actionClick($event)\"\n ></cqa-table-action-toolbar>\n </div>\n \n </div>\n</div>\n\n", styles: [] }]
|
|
3212
|
+
}], propDecorators: { searchPlaceholder: [{
|
|
3213
|
+
type: Input
|
|
3214
|
+
}], searchValue: [{
|
|
3215
|
+
type: Input
|
|
3216
|
+
}], showClear: [{
|
|
3217
|
+
type: Input
|
|
3218
|
+
}], showSearchBar: [{
|
|
3219
|
+
type: Input
|
|
3220
|
+
}], filterConfig: [{
|
|
3221
|
+
type: Input
|
|
3222
|
+
}], showFilterPanel: [{
|
|
3223
|
+
type: Input
|
|
3224
|
+
}], showFilterButton: [{
|
|
3225
|
+
type: Input
|
|
3226
|
+
}], otherButtonLabel: [{
|
|
3227
|
+
type: Input
|
|
3228
|
+
}], otherButtonVariant: [{
|
|
3229
|
+
type: Input
|
|
3230
|
+
}], showOtherButton: [{
|
|
3231
|
+
type: Input
|
|
3232
|
+
}], showActionButton: [{
|
|
3233
|
+
type: Input
|
|
3234
|
+
}], showSettingsButton: [{
|
|
3235
|
+
type: Input
|
|
3236
|
+
}], showAutoRefreshButton: [{
|
|
3237
|
+
type: Input
|
|
3238
|
+
}], data: [{
|
|
3239
|
+
type: Input
|
|
3240
|
+
}], isEmptyState: [{
|
|
3241
|
+
type: Input
|
|
3242
|
+
}], emptyStateConfig: [{
|
|
3243
|
+
type: Input
|
|
3244
|
+
}], actions: [{
|
|
3245
|
+
type: Input
|
|
3246
|
+
}], chips: [{
|
|
3247
|
+
type: Input
|
|
3248
|
+
}], filterApplied: [{
|
|
3249
|
+
type: Input
|
|
3250
|
+
}], columns: [{
|
|
3251
|
+
type: Input
|
|
3252
|
+
}], selectedAutoRefreshInterval: [{
|
|
3253
|
+
type: Input
|
|
3254
|
+
}], pageIndex: [{
|
|
3255
|
+
type: Input
|
|
3256
|
+
}], pageSize: [{
|
|
3257
|
+
type: Input
|
|
3258
|
+
}], isTableLoading: [{
|
|
3259
|
+
type: Input
|
|
3260
|
+
}], isTableDataLoading: [{
|
|
3261
|
+
type: Input
|
|
3262
|
+
}] } });
|
|
3263
|
+
|
|
3264
|
+
/**
|
|
3265
|
+
* Ensures Angular CDK overlay content (e.g., MatSelect, Datepicker panels)
|
|
3266
|
+
* is nested under an element with id="cqa-ui-root" so Tailwind utilities
|
|
3267
|
+
* configured with important: '#cqa-ui-root' are applied inside overlays.
|
|
3268
|
+
*/
|
|
3269
|
+
class TailwindOverlayContainer extends OverlayContainer {
|
|
3270
|
+
_createContainer() {
|
|
3271
|
+
super._createContainer();
|
|
3272
|
+
if (this._containerElement) {
|
|
3273
|
+
this._containerElement.id = 'cqa-ui-root';
|
|
3274
|
+
}
|
|
3275
|
+
}
|
|
3276
|
+
}
|
|
3277
|
+
TailwindOverlayContainer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TailwindOverlayContainer, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
3278
|
+
TailwindOverlayContainer.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TailwindOverlayContainer });
|
|
3279
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TailwindOverlayContainer, decorators: [{
|
|
3280
|
+
type: Injectable
|
|
3281
|
+
}] });
|
|
3282
|
+
|
|
3283
|
+
class UiKitModule {
|
|
3284
|
+
}
|
|
3285
|
+
UiKitModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: UiKitModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
3286
|
+
UiKitModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: UiKitModule, declarations: [ButtonComponent,
|
|
3287
|
+
SearchBarComponent,
|
|
3288
|
+
SegmentControlComponent,
|
|
3289
|
+
DialogComponent,
|
|
3290
|
+
DynamicTableComponent,
|
|
3291
|
+
DynamicCellTemplateDirective,
|
|
3292
|
+
DynamicHeaderTemplateDirective,
|
|
3293
|
+
InlineSortComponent,
|
|
3294
|
+
PaginationComponent,
|
|
3295
|
+
ActionMenuButtonComponent,
|
|
3296
|
+
OtherButtonComponent,
|
|
3297
|
+
DynamicFilterComponent,
|
|
3298
|
+
ColumnVisibilityComponent,
|
|
3299
|
+
TableActionToolbarComponent,
|
|
3300
|
+
MetricsCardComponent,
|
|
3301
|
+
MetricsBlockComponent,
|
|
3302
|
+
ChartCardComponent,
|
|
3303
|
+
ProgressTextCardComponent,
|
|
3304
|
+
DashboardHeaderComponent,
|
|
3305
|
+
CoverageModuleCardComponent,
|
|
3306
|
+
TestDistributionCardComponent,
|
|
3307
|
+
FailedTestCasesCardComponent,
|
|
3308
|
+
DynamicSelectFieldComponent,
|
|
3309
|
+
SelectedFiltersComponent,
|
|
3310
|
+
InsightCardComponent,
|
|
3311
|
+
BadgeComponent,
|
|
3312
|
+
DropdownButtonComponent,
|
|
3313
|
+
HeatErrorMapCellComponent,
|
|
3314
|
+
EmptyStateComponent,
|
|
3315
|
+
TableTemplateComponent,
|
|
3316
|
+
FullTableLoaderComponent,
|
|
3317
|
+
TableDataLoaderComponent], imports: [CommonModule,
|
|
3318
|
+
FormsModule,
|
|
3319
|
+
ReactiveFormsModule,
|
|
3320
|
+
MatIconModule,
|
|
3321
|
+
MatTooltipModule,
|
|
3322
|
+
MatMenuModule,
|
|
3323
|
+
MatButtonModule,
|
|
3324
|
+
MatFormFieldModule,
|
|
3325
|
+
MatSelectModule,
|
|
3326
|
+
MatOptionModule,
|
|
3327
|
+
MatCheckboxModule,
|
|
3328
|
+
MatRadioModule,
|
|
3329
|
+
MatDatepickerModule,
|
|
3330
|
+
MatNativeDateModule,
|
|
3331
|
+
MatProgressSpinnerModule,
|
|
3332
|
+
OverlayModule,
|
|
3333
|
+
PortalModule], exports: [ButtonComponent,
|
|
3334
|
+
SearchBarComponent,
|
|
3335
|
+
SegmentControlComponent,
|
|
3336
|
+
DialogComponent,
|
|
3337
|
+
DynamicTableComponent,
|
|
3338
|
+
DynamicCellTemplateDirective,
|
|
3339
|
+
DynamicHeaderTemplateDirective,
|
|
3340
|
+
InlineSortComponent,
|
|
3341
|
+
PaginationComponent,
|
|
3342
|
+
ActionMenuButtonComponent,
|
|
3343
|
+
OtherButtonComponent,
|
|
3344
|
+
DynamicFilterComponent,
|
|
3345
|
+
ColumnVisibilityComponent,
|
|
3346
|
+
TableActionToolbarComponent,
|
|
3347
|
+
MetricsCardComponent,
|
|
3348
|
+
ChartCardComponent,
|
|
3349
|
+
ProgressTextCardComponent,
|
|
3350
|
+
DashboardHeaderComponent,
|
|
3351
|
+
CoverageModuleCardComponent,
|
|
3352
|
+
TestDistributionCardComponent,
|
|
3353
|
+
FailedTestCasesCardComponent,
|
|
3354
|
+
DynamicSelectFieldComponent,
|
|
3355
|
+
SelectedFiltersComponent,
|
|
3356
|
+
InsightCardComponent,
|
|
3357
|
+
BadgeComponent,
|
|
3358
|
+
DropdownButtonComponent,
|
|
3359
|
+
HeatErrorMapCellComponent,
|
|
3360
|
+
EmptyStateComponent,
|
|
3361
|
+
TableTemplateComponent,
|
|
3362
|
+
FullTableLoaderComponent,
|
|
3363
|
+
TableDataLoaderComponent] });
|
|
3364
|
+
UiKitModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: UiKitModule, providers: [
|
|
3365
|
+
{ provide: OverlayContainer, useClass: TailwindOverlayContainer }
|
|
3366
|
+
], imports: [[
|
|
3367
|
+
CommonModule,
|
|
3368
|
+
FormsModule,
|
|
3369
|
+
ReactiveFormsModule,
|
|
3370
|
+
MatIconModule,
|
|
3371
|
+
MatTooltipModule,
|
|
3372
|
+
MatMenuModule,
|
|
3373
|
+
MatButtonModule,
|
|
3374
|
+
MatFormFieldModule,
|
|
3375
|
+
MatSelectModule,
|
|
3376
|
+
MatOptionModule,
|
|
3377
|
+
MatCheckboxModule,
|
|
3378
|
+
MatRadioModule,
|
|
3379
|
+
MatDatepickerModule,
|
|
3380
|
+
MatNativeDateModule,
|
|
3381
|
+
MatProgressSpinnerModule,
|
|
3382
|
+
OverlayModule,
|
|
3383
|
+
PortalModule
|
|
3384
|
+
]] });
|
|
3385
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: UiKitModule, decorators: [{
|
|
3386
|
+
type: NgModule,
|
|
3387
|
+
args: [{
|
|
3388
|
+
declarations: [
|
|
3389
|
+
ButtonComponent,
|
|
3390
|
+
SearchBarComponent,
|
|
3391
|
+
SegmentControlComponent,
|
|
3392
|
+
DialogComponent,
|
|
3393
|
+
DynamicTableComponent,
|
|
3394
|
+
DynamicCellTemplateDirective,
|
|
3395
|
+
DynamicHeaderTemplateDirective,
|
|
3396
|
+
InlineSortComponent,
|
|
3397
|
+
PaginationComponent,
|
|
3398
|
+
ActionMenuButtonComponent,
|
|
3399
|
+
OtherButtonComponent,
|
|
3400
|
+
DynamicFilterComponent,
|
|
3401
|
+
ColumnVisibilityComponent,
|
|
3402
|
+
TableActionToolbarComponent,
|
|
3403
|
+
MetricsCardComponent,
|
|
3404
|
+
MetricsBlockComponent,
|
|
3405
|
+
ChartCardComponent,
|
|
3406
|
+
ProgressTextCardComponent,
|
|
3407
|
+
DashboardHeaderComponent,
|
|
3408
|
+
CoverageModuleCardComponent,
|
|
3409
|
+
TestDistributionCardComponent,
|
|
3410
|
+
FailedTestCasesCardComponent,
|
|
3411
|
+
DynamicSelectFieldComponent,
|
|
3412
|
+
SelectedFiltersComponent,
|
|
3413
|
+
InsightCardComponent,
|
|
3414
|
+
BadgeComponent,
|
|
3415
|
+
DropdownButtonComponent,
|
|
3416
|
+
HeatErrorMapCellComponent,
|
|
3417
|
+
EmptyStateComponent,
|
|
3418
|
+
TableTemplateComponent,
|
|
3419
|
+
FullTableLoaderComponent,
|
|
3420
|
+
TableDataLoaderComponent
|
|
3421
|
+
],
|
|
3422
|
+
imports: [
|
|
3423
|
+
CommonModule,
|
|
3424
|
+
FormsModule,
|
|
3425
|
+
ReactiveFormsModule,
|
|
3426
|
+
MatIconModule,
|
|
3427
|
+
MatTooltipModule,
|
|
3428
|
+
MatMenuModule,
|
|
3429
|
+
MatButtonModule,
|
|
3430
|
+
MatFormFieldModule,
|
|
3431
|
+
MatSelectModule,
|
|
3432
|
+
MatOptionModule,
|
|
3433
|
+
MatCheckboxModule,
|
|
3434
|
+
MatRadioModule,
|
|
3435
|
+
MatDatepickerModule,
|
|
3436
|
+
MatNativeDateModule,
|
|
3437
|
+
MatProgressSpinnerModule,
|
|
3438
|
+
OverlayModule,
|
|
3439
|
+
PortalModule
|
|
3440
|
+
],
|
|
3441
|
+
exports: [
|
|
3442
|
+
ButtonComponent,
|
|
3443
|
+
SearchBarComponent,
|
|
3444
|
+
SegmentControlComponent,
|
|
3445
|
+
DialogComponent,
|
|
3446
|
+
DynamicTableComponent,
|
|
3447
|
+
DynamicCellTemplateDirective,
|
|
3448
|
+
DynamicHeaderTemplateDirective,
|
|
3449
|
+
InlineSortComponent,
|
|
3450
|
+
PaginationComponent,
|
|
3451
|
+
ActionMenuButtonComponent,
|
|
3452
|
+
OtherButtonComponent,
|
|
3453
|
+
DynamicFilterComponent,
|
|
3454
|
+
ColumnVisibilityComponent,
|
|
3455
|
+
TableActionToolbarComponent,
|
|
3456
|
+
MetricsCardComponent,
|
|
3457
|
+
ChartCardComponent,
|
|
3458
|
+
ProgressTextCardComponent,
|
|
3459
|
+
DashboardHeaderComponent,
|
|
3460
|
+
CoverageModuleCardComponent,
|
|
3461
|
+
TestDistributionCardComponent,
|
|
3462
|
+
FailedTestCasesCardComponent,
|
|
3463
|
+
DynamicSelectFieldComponent,
|
|
3464
|
+
SelectedFiltersComponent,
|
|
3465
|
+
InsightCardComponent,
|
|
3466
|
+
BadgeComponent,
|
|
3467
|
+
DropdownButtonComponent,
|
|
3468
|
+
HeatErrorMapCellComponent,
|
|
3469
|
+
EmptyStateComponent,
|
|
3470
|
+
TableTemplateComponent,
|
|
3471
|
+
FullTableLoaderComponent,
|
|
3472
|
+
TableDataLoaderComponent
|
|
3473
|
+
],
|
|
3474
|
+
providers: [
|
|
3475
|
+
{ provide: OverlayContainer, useClass: TailwindOverlayContainer }
|
|
742
3476
|
]
|
|
743
3477
|
}]
|
|
744
3478
|
}] });
|
|
@@ -864,18 +3598,18 @@ class DialogService {
|
|
|
864
3598
|
});
|
|
865
3599
|
}
|
|
866
3600
|
}
|
|
867
|
-
DialogService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DialogService, deps: [{ token: i1$
|
|
3601
|
+
DialogService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DialogService, deps: [{ token: i1$4.Overlay }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
868
3602
|
DialogService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DialogService, providedIn: 'root' });
|
|
869
3603
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DialogService, decorators: [{
|
|
870
3604
|
type: Injectable,
|
|
871
3605
|
args: [{
|
|
872
3606
|
providedIn: 'root',
|
|
873
3607
|
}]
|
|
874
|
-
}], ctorParameters: function () { return [{ type: i1$
|
|
3608
|
+
}], ctorParameters: function () { return [{ type: i1$4.Overlay }, { type: i0.Injector }]; } });
|
|
875
3609
|
|
|
876
3610
|
/**
|
|
877
3611
|
* Generated bundle index. Do not edit.
|
|
878
3612
|
*/
|
|
879
3613
|
|
|
880
|
-
export { ButtonComponent, DIALOG_DATA, DIALOG_REF, DialogComponent, DialogRef, DialogService, SearchBarComponent, SegmentControlComponent, UiKitModule };
|
|
3614
|
+
export { ActionMenuButtonComponent, BadgeComponent, ButtonComponent, ChartCardComponent, ColumnVisibilityComponent, CoverageModuleCardComponent, DEFAULT_METADATA_COLOR, DIALOG_DATA, DIALOG_REF, DashboardHeaderComponent, DialogComponent, DialogRef, DialogService, DropdownButtonComponent, DynamicCellTemplateDirective, DynamicFilterComponent, DynamicHeaderTemplateDirective, DynamicSelectFieldComponent, DynamicTableComponent, EMPTY_STATE_IMAGES, EmptyStateComponent, FailedTestCasesCardComponent, FullTableLoaderComponent, HeatErrorMapCellComponent, InlineSortComponent, InsightCardComponent, MetricsCardComponent, OtherButtonComponent, PRIORITY_COLORS, PaginationComponent, ProgressTextCardComponent, RESULT_COLORS, STATUS_COLORS, SearchBarComponent, SegmentControlComponent, SelectedFiltersComponent, TableActionToolbarComponent, TableDataLoaderComponent, TableTemplateComponent, TestDistributionCardComponent, UiKitModule, getMetadataColor, getMetadataValueStyle };
|
|
881
3615
|
//# sourceMappingURL=cqa-lib-cqa-ui.mjs.map
|