@cqa-lib/cqa-ui 1.1.188 → 1.1.189
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/dynamic-select/dynamic-select-field.component.mjs +27 -3
- package/esm2020/lib/test-case-details/step-details-drawer/step-details-drawer-data.mjs +3 -0
- package/esm2020/lib/test-case-details/step-details-drawer/step-details-drawer-field.config.mjs +188 -0
- package/esm2020/lib/test-case-details/step-details-drawer/step-details-drawer-ref.mjs +28 -0
- package/esm2020/lib/test-case-details/step-details-drawer/step-details-drawer.component.mjs +291 -0
- package/esm2020/lib/test-case-details/step-details-drawer/step-details-drawer.service.mjs +67 -0
- package/esm2020/lib/ui-kit.module.mjs +8 -3
- package/esm2020/lib/utils/tw-overlay-container.mjs +6 -3
- package/esm2020/public-api.mjs +6 -1
- package/fesm2015/cqa-lib-cqa-ui.mjs +596 -7
- package/fesm2015/cqa-lib-cqa-ui.mjs.map +1 -1
- package/fesm2020/cqa-lib-cqa-ui.mjs +586 -7
- package/fesm2020/cqa-lib-cqa-ui.mjs.map +1 -1
- package/lib/dynamic-select/dynamic-select-field.component.d.ts +6 -0
- package/lib/test-case-details/step-details-drawer/step-details-drawer-data.d.ts +7 -0
- package/lib/test-case-details/step-details-drawer/step-details-drawer-field.config.d.ts +51 -0
- package/lib/test-case-details/step-details-drawer/step-details-drawer-ref.d.ts +13 -0
- package/lib/test-case-details/step-details-drawer/step-details-drawer.component.d.ts +60 -0
- package/lib/test-case-details/step-details-drawer/step-details-drawer.service.d.ts +22 -0
- package/lib/ui-kit.module.d.ts +21 -20
- package/package.json +1 -1
- package/public-api.d.ts +5 -0
- package/styles.css +1 -1
|
@@ -1721,6 +1721,7 @@ class DynamicSelectFieldComponent {
|
|
|
1721
1721
|
throw new Error('cqa-dynamic-select: input "config.key" is required.');
|
|
1722
1722
|
}
|
|
1723
1723
|
this.applySelectedValueIfNeeded();
|
|
1724
|
+
this.syncDisabledState();
|
|
1724
1725
|
this.lastOptionsLength = (((_a = this.config) === null || _a === void 0 ? void 0 : _a.options) || []).length;
|
|
1725
1726
|
}
|
|
1726
1727
|
get displayPlaceholder() {
|
|
@@ -1733,6 +1734,9 @@ class DynamicSelectFieldComponent {
|
|
|
1733
1734
|
}
|
|
1734
1735
|
ngOnChanges(changes) {
|
|
1735
1736
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
1737
|
+
if ('config' in changes || 'form' in changes) {
|
|
1738
|
+
this.syncDisabledState();
|
|
1739
|
+
}
|
|
1736
1740
|
if ('config' in changes) {
|
|
1737
1741
|
// When config changes (including toggling multiple), ensure control value shape matches
|
|
1738
1742
|
this.syncControlValueForMultipleMode();
|
|
@@ -1829,6 +1833,27 @@ class DynamicSelectFieldComponent {
|
|
|
1829
1833
|
}
|
|
1830
1834
|
return !!value;
|
|
1831
1835
|
}
|
|
1836
|
+
/**
|
|
1837
|
+
* Sync the form control's disabled state from config.
|
|
1838
|
+
* Use the FormControl API instead of [disabled] in the template to avoid Angular's
|
|
1839
|
+
* "changed after checked" / reactive forms disabled-attribute warning.
|
|
1840
|
+
*/
|
|
1841
|
+
syncDisabledState() {
|
|
1842
|
+
var _a, _b;
|
|
1843
|
+
const key = (_a = this.config) === null || _a === void 0 ? void 0 : _a.key;
|
|
1844
|
+
if (!key || !this.form)
|
|
1845
|
+
return;
|
|
1846
|
+
const control = this.form.get(key);
|
|
1847
|
+
if (!control)
|
|
1848
|
+
return;
|
|
1849
|
+
const shouldDisable = this.toBoolean((_b = this.config) === null || _b === void 0 ? void 0 : _b.disabled);
|
|
1850
|
+
if (shouldDisable) {
|
|
1851
|
+
control.disable({ emitEvent: false });
|
|
1852
|
+
}
|
|
1853
|
+
else {
|
|
1854
|
+
control.enable({ emitEvent: false });
|
|
1855
|
+
}
|
|
1856
|
+
}
|
|
1832
1857
|
syncControlValueForMultipleMode() {
|
|
1833
1858
|
var _a;
|
|
1834
1859
|
const key = (_a = this.config) === null || _a === void 0 ? void 0 : _a.key;
|
|
@@ -2258,10 +2283,10 @@ class DynamicSelectFieldComponent {
|
|
|
2258
2283
|
}
|
|
2259
2284
|
}
|
|
2260
2285
|
DynamicSelectFieldComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DynamicSelectFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2261
|
-
DynamicSelectFieldComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: DynamicSelectFieldComponent, selector: "cqa-dynamic-select", inputs: { form: "form", config: "config" }, outputs: { selectionChange: "selectionChange", selectClick: "selectClick", searchChange: "searchChange", loadMore: "loadMore" }, 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 class=\"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]=\"displayPlaceholder\" [disabled]=\"isDisabled\" [multiple]=\"isMultiple\"\n disableOptionCentering [panelClass]=\"panelClass\" [formControlName]=\"config.key\"\n (openedChange)=\"onSelectOpenedChange($event, selectRef)\" (selectionChange)=\"onSelectionChange($event, selectRef)\">\n\n <mat-option *ngIf=\"config.searchable\" class=\"ts-select-search\" disabled>\n <input class=\"ts-select-search-input cqa-text-black-100\" 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 [ngClass]=\"{'checkmark': config.optionStyle === 'checkmark','checkbox': config.optionStyle !== 'checkmark','mat-selected': allSelected}\" [class]=\"config.optionStyle == 'checkmark' ? 'checkmark' : 'checkbox'\" *ngIf=\"isMultiple && config.showSelectAll\" [value]=\"SELECT_ALL_VALUE\">\n <ng-container *ngIf=\"useCheckboxStyle; else selectAllDefaultTpl\">\n <span class=\"cqa-flex cqa-items-center\">\n <span class=\"cqa-w-4 cqa-h-4 cqa-flex-shrink-0 cqa-rounded-[4px] cqa-border cqa-border-[#D1D5DB] cqa-mr-2 cqa-flex cqa-items-center cqa-justify-center cqa-border-solid\"\n [ngStyle]=\"allSelected ? {'background-color':'#4F46E5','border-color':'#4F46E5'} : {}\">\n <svg *ngIf=\"allSelected\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M10 3L4.5 8.5L2 6\" stroke=\"white\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <span class=\"cqa-min-w-0\">{{ config.selectAllLabel || 'All' }}</span>\n </span>\n </ng-container>\n <ng-template #selectAllDefaultTpl>\n {{ config.selectAllLabel || 'All' }}\n </ng-template>\n </mat-option>\n\n <mat-option [class]=\"config.optionStyle == 'checkmark' ? 'checkmark' : 'checkbox'\" *ngFor=\"let opt of filteredOptions(config)\" [value]=\"opt.id ?? opt.value\">\n <ng-container *ngIf=\"config.isCompareRuns\"> \n <ng-container *ngIf=\"useCheckboxStyle; else compareRunsDefaultOptionTpl\">\n <span class=\"cqa-flex cqa-items-center cqa-justify-between cqa-w-full cqa-compare-runs-item\">\n <span class=\"cqa-flex cqa-items-center\">\n <span class=\"cqa-w-4 cqa-h-4 cqa-flex-shrink-0 cqa-rounded-[4px] cqa-border cqa-border-[#D1D5DB] cqa-mr-2 cqa-flex cqa-items-center cqa-justify-center cqa-border-solid\"\n [ngStyle]=\"isOptionSelected(opt) ? {'background-color':'#4F46E5','border-color':'#4F46E5'} : {}\">\n <svg *ngIf=\"isOptionSelected(opt)\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M10 3L4.5 8.5L2 6\" stroke=\"white\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <span\n class=\"cqa-min-w-0 cqa-compare-runs\"\n *ngIf=\"hasHighlighting\"\n [style.color]=\"opt.statusColor || null\"\n [innerHTML]=\"highlightText(opt.name ?? opt.label ?? opt.value)\"></span>\n <ng-container *ngIf=\"!hasHighlighting\">\n <span\n class=\"cqa-min-w-0 cqa-compare-runs\"\n *ngIf=\"opt.runNumberLabel && opt.runDateLabel; else checkboxDefaultLabel\">\n <span [style.color]=\"opt.statusColor || null\">{{ opt.runNumberLabel }}</span>\n <span class=\"cqa-text-[#6B7280]\"> {{ opt.runDateLabel }} </span>\n </span>\n <ng-template #checkboxDefaultLabel>\n <span\n class=\"cqa-min-w-0 cqa-compare-runs\"\n [style.color]=\"opt.statusColor || null\">\n {{ opt.name ?? opt.label ?? opt.value }}\n </span>\n </ng-template>\n </ng-container>\n </span>\n <span\n *ngIf=\"opt.durationFormatted\"\n class=\"cqa-flex cqa-items-center cqa-justify-start cqa-gap-1 cqa-text-[12px] cqa-text-[#6B7280] cqa-flex-shrink-0 cqa-whitespace-nowrap cqa-max-w-[80px]\" \n [ngClass]=\"{\n 'cqa-min-w-[82px]': opt?.hasHourRun,\n 'cqa-min-w-[66px]': !opt?.hasHourRun && opt?.hasMinuteRun,\n 'cqa-min-w-[40px]': !opt?.hasHourRun && !opt?.hasMinuteRun\n }\">\n <svg class=\"cqa-min-w-[12px] cqa-max-w-[12px]\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"6\" cy=\"6\" r=\"4.5\" stroke=\"#9CA3AF\" stroke-width=\"1\"/>\n <path d=\"M6 3.5V6L7.5 7\" stroke=\"#4B5563\" stroke-width=\"1\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n <span>{{ opt.durationFormatted }}</span>\n </span>\n </span>\n </ng-container>\n <ng-template #compareRunsDefaultOptionTpl>\n <span class=\"cqa-flex cqa-items-center cqa-justify-between cqa-w-full cqa-compare-runs-item\">\n <span\n class=\"cqa-min-w-0 cqa-compare-runs\"\n *ngIf=\"hasHighlighting\"\n [style.color]=\"opt.statusColor || null\"\n [innerHTML]=\"highlightText(opt.name ?? opt.label ?? opt.value)\"></span>\n <ng-container *ngIf=\"!hasHighlighting\">\n <span\n class=\"cqa-min-w-0 cqa-compare-runs\"\n *ngIf=\"opt.runNumberLabel && opt.runDateLabel; else defaultLabel\">\n <span [style.color]=\"opt.statusColor || null\">{{ opt.runNumberLabel }}</span>\n <span class=\"cqa-text-[#6B7280]\"> {{ opt.runDateLabel }} </span>\n </span>\n <ng-template #defaultLabel>\n <span\n class=\"cqa-min-w-0 cqa-compare-runs\"\n [style.color]=\"opt.statusColor || null\">\n {{ opt.name ?? opt.label ?? opt.value }}\n </span>\n </ng-template>\n </ng-container>\n <span\n *ngIf=\"opt.durationFormatted\"\n class=\"cqa-flex cqa-items-center cqa-justify-start cqa-gap-1 cqa-text-[12px] cqa-text-[#6B7280] cqa-flex-shrink-0 cqa-whitespace-nowrap cqa-max-w-[80px]\" \n [ngClass]=\"{\n 'cqa-min-w-[82px]': opt?.hasHourRun,\n 'cqa-min-w-[66px]': !opt?.hasHourRun && opt?.hasMinuteRun,\n 'cqa-min-w-[40px]': !opt?.hasHourRun && !opt?.hasMinuteRun\n }\">\n <svg class=\"cqa-min-w-[12px] cqa-max-w-[12px]\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"6\" cy=\"6\" r=\"4.5\" stroke=\"#9CA3AF\" stroke-width=\"1\"/>\n <path d=\"M6 3.5V6L7.5 7\" stroke=\"#4B5563\" stroke-width=\"1\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n <span>{{ opt.durationFormatted }}</span>\n </span>\n </span>\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"!config.isCompareRuns\">\n <ng-container *ngIf=\"useCheckboxStyle; else defaultOptionTpl\">\n <span class=\"cqa-flex cqa-items-center\">\n <span class=\"cqa-w-4 cqa-h-4 cqa-flex-shrink-0 cqa-rounded-[4px] cqa-border cqa-border-[#D1D5DB] cqa-mr-2 cqa-flex cqa-items-center cqa-justify-center cqa-border-solid\"\n [ngStyle]=\"isOptionSelected(opt) ? {'background-color':'#4F46E5','border-color':'#4F46E5'} : {}\">\n <svg *ngIf=\"isOptionSelected(opt)\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M10 3L4.5 8.5L2 6\" stroke=\"white\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <!-- When displayLabelAsInnerHtml is true, render label as raw HTML -->\n <span class=\"cqa-min-w-0\"\n *ngIf=\"config?.displayLabelAsInnerHtml\"\n [innerHTML]=\"opt.label ?? opt.name ?? opt.value\">\n </span>\n <!-- Otherwise use normal/highlighted text rendering -->\n <span class=\"cqa-min-w-0\"\n *ngIf=\"!config?.displayLabelAsInnerHtml && hasHighlighting\"\n [innerHTML]=\"highlightText(opt.name ?? opt.label ?? opt.value)\">\n </span>\n <span class=\"cqa-min-w-0\"\n *ngIf=\"!config?.displayLabelAsInnerHtml && !hasHighlighting\">\n {{ opt.name ?? opt.label ?? opt.value }}\n </span>\n </span>\n </ng-container>\n <ng-template #defaultOptionTpl>\n <!-- When displayLabelAsInnerHtml is true, render label as raw HTML -->\n <span *ngIf=\"config?.displayLabelAsInnerHtml\"\n [innerHTML]=\"opt.label ?? opt.name ?? opt.value\">\n </span>\n <!-- Otherwise use normal/highlighted text rendering -->\n <span *ngIf=\"!config?.displayLabelAsInnerHtml && hasHighlighting\"\n [innerHTML]=\"highlightText(opt.name ?? opt.label ?? opt.value)\">\n </span>\n <span *ngIf=\"!config?.displayLabelAsInnerHtml && !hasHighlighting\">\n {{ opt.name ?? opt.label ?? opt.value }}\n </span>\n </ng-template>\n </ng-container>\n </mat-option>\n \n <!-- No results state (only when not loading and no options) -->\n <mat-option disabled *ngIf=\"!(config?.options?.length || 0) && !(config?.isLoading || loadingMore)\">\n No results\n </mat-option>\n <!-- Infinite scroll sentinel (serverSearch or explicit hasMore) -->\n <mat-option disabled class=\"load-more-sentinel\" *ngIf=\"config?.hasMore\">\n <span *ngIf=\"loadingMore || config?.isLoading\">Loading...</span>\n <span *ngIf=\"!loadingMore && !config?.isLoading\">Scroll to load more\u2026</span>\n </mat-option>\n </mat-select>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <!-- Inline spinner shown when loading more (infinite scroll) or when config.isLoading is true -->\n <svg *ngIf=\"loadingMore || config?.isLoading\" width=\"16\" height=\"16\" viewBox=\"0 0 50 50\" aria-label=\"loading\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"25\" cy=\"25\" r=\"20\" stroke=\"#E5E7EB\" stroke-width=\"6\" fill=\"none\"/>\n <path d=\"M45 25a20 20 0 0 0-20-20\" stroke=\"#4F46E5\" stroke-width=\"6\" fill=\"none\" stroke-linecap=\"round\">\n <animateTransform attributeName=\"transform\" type=\"rotate\" from=\"0 25 25\" to=\"360 25 25\"\n dur=\"0.8s\" repeatCount=\"indefinite\"/>\n </path>\n </svg>\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: i1$3.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: i2$2.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex"], exportAs: ["matSelect"] }, { type: i3$2.MatOption, selector: "mat-option", exportAs: ["matOption"] }], directives: [{ type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i2$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2286
|
+
DynamicSelectFieldComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: DynamicSelectFieldComponent, selector: "cqa-dynamic-select", inputs: { form: "form", config: "config" }, outputs: { selectionChange: "selectionChange", selectClick: "selectClick", searchChange: "searchChange", loadMore: "loadMore" }, 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 class=\"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]=\"displayPlaceholder\" [multiple]=\"isMultiple\"\n disableOptionCentering [panelClass]=\"panelClass\" [formControlName]=\"config.key\"\n (openedChange)=\"onSelectOpenedChange($event, selectRef)\" (selectionChange)=\"onSelectionChange($event, selectRef)\">\n\n <mat-option *ngIf=\"config.searchable\" class=\"ts-select-search\" disabled>\n <input class=\"ts-select-search-input cqa-text-black-100\" 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 [ngClass]=\"{'checkmark': config.optionStyle === 'checkmark','checkbox': config.optionStyle !== 'checkmark','mat-selected': allSelected}\" [class]=\"config.optionStyle == 'checkmark' ? 'checkmark' : 'checkbox'\" *ngIf=\"isMultiple && config.showSelectAll\" [value]=\"SELECT_ALL_VALUE\">\n <ng-container *ngIf=\"useCheckboxStyle; else selectAllDefaultTpl\">\n <span class=\"cqa-flex cqa-items-center\">\n <span class=\"cqa-w-4 cqa-h-4 cqa-flex-shrink-0 cqa-rounded-[4px] cqa-border cqa-border-[#D1D5DB] cqa-mr-2 cqa-flex cqa-items-center cqa-justify-center cqa-border-solid\"\n [ngStyle]=\"allSelected ? {'background-color':'#4F46E5','border-color':'#4F46E5'} : {}\">\n <svg *ngIf=\"allSelected\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M10 3L4.5 8.5L2 6\" stroke=\"white\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <span class=\"cqa-min-w-0\">{{ config.selectAllLabel || 'All' }}</span>\n </span>\n </ng-container>\n <ng-template #selectAllDefaultTpl>\n {{ config.selectAllLabel || 'All' }}\n </ng-template>\n </mat-option>\n\n <mat-option [class]=\"config.optionStyle == 'checkmark' ? 'checkmark' : 'checkbox'\" *ngFor=\"let opt of filteredOptions(config)\" [value]=\"opt.id ?? opt.value\">\n <ng-container *ngIf=\"config.isCompareRuns\"> \n <ng-container *ngIf=\"useCheckboxStyle; else compareRunsDefaultOptionTpl\">\n <span class=\"cqa-flex cqa-items-center cqa-justify-between cqa-w-full cqa-compare-runs-item\">\n <span class=\"cqa-flex cqa-items-center\">\n <span class=\"cqa-w-4 cqa-h-4 cqa-flex-shrink-0 cqa-rounded-[4px] cqa-border cqa-border-[#D1D5DB] cqa-mr-2 cqa-flex cqa-items-center cqa-justify-center cqa-border-solid\"\n [ngStyle]=\"isOptionSelected(opt) ? {'background-color':'#4F46E5','border-color':'#4F46E5'} : {}\">\n <svg *ngIf=\"isOptionSelected(opt)\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M10 3L4.5 8.5L2 6\" stroke=\"white\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <span\n class=\"cqa-min-w-0 cqa-compare-runs\"\n *ngIf=\"hasHighlighting\"\n [style.color]=\"opt.statusColor || null\"\n [innerHTML]=\"highlightText(opt.name ?? opt.label ?? opt.value)\"></span>\n <ng-container *ngIf=\"!hasHighlighting\">\n <span\n class=\"cqa-min-w-0 cqa-compare-runs\"\n *ngIf=\"opt.runNumberLabel && opt.runDateLabel; else checkboxDefaultLabel\">\n <span [style.color]=\"opt.statusColor || null\">{{ opt.runNumberLabel }}</span>\n <span class=\"cqa-text-[#6B7280]\"> {{ opt.runDateLabel }} </span>\n </span>\n <ng-template #checkboxDefaultLabel>\n <span\n class=\"cqa-min-w-0 cqa-compare-runs\"\n [style.color]=\"opt.statusColor || null\">\n {{ opt.name ?? opt.label ?? opt.value }}\n </span>\n </ng-template>\n </ng-container>\n </span>\n <span\n *ngIf=\"opt.durationFormatted\"\n class=\"cqa-flex cqa-items-center cqa-justify-start cqa-gap-1 cqa-text-[12px] cqa-text-[#6B7280] cqa-flex-shrink-0 cqa-whitespace-nowrap cqa-max-w-[80px]\" \n [ngClass]=\"{\n 'cqa-min-w-[82px]': opt?.hasHourRun,\n 'cqa-min-w-[66px]': !opt?.hasHourRun && opt?.hasMinuteRun,\n 'cqa-min-w-[40px]': !opt?.hasHourRun && !opt?.hasMinuteRun\n }\">\n <svg class=\"cqa-min-w-[12px] cqa-max-w-[12px]\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"6\" cy=\"6\" r=\"4.5\" stroke=\"#9CA3AF\" stroke-width=\"1\"/>\n <path d=\"M6 3.5V6L7.5 7\" stroke=\"#4B5563\" stroke-width=\"1\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n <span>{{ opt.durationFormatted }}</span>\n </span>\n </span>\n </ng-container>\n <ng-template #compareRunsDefaultOptionTpl>\n <span class=\"cqa-flex cqa-items-center cqa-justify-between cqa-w-full cqa-compare-runs-item\">\n <span\n class=\"cqa-min-w-0 cqa-compare-runs\"\n *ngIf=\"hasHighlighting\"\n [style.color]=\"opt.statusColor || null\"\n [innerHTML]=\"highlightText(opt.name ?? opt.label ?? opt.value)\"></span>\n <ng-container *ngIf=\"!hasHighlighting\">\n <span\n class=\"cqa-min-w-0 cqa-compare-runs\"\n *ngIf=\"opt.runNumberLabel && opt.runDateLabel; else defaultLabel\">\n <span [style.color]=\"opt.statusColor || null\">{{ opt.runNumberLabel }}</span>\n <span class=\"cqa-text-[#6B7280]\"> {{ opt.runDateLabel }} </span>\n </span>\n <ng-template #defaultLabel>\n <span\n class=\"cqa-min-w-0 cqa-compare-runs\"\n [style.color]=\"opt.statusColor || null\">\n {{ opt.name ?? opt.label ?? opt.value }}\n </span>\n </ng-template>\n </ng-container>\n <span\n *ngIf=\"opt.durationFormatted\"\n class=\"cqa-flex cqa-items-center cqa-justify-start cqa-gap-1 cqa-text-[12px] cqa-text-[#6B7280] cqa-flex-shrink-0 cqa-whitespace-nowrap cqa-max-w-[80px]\" \n [ngClass]=\"{\n 'cqa-min-w-[82px]': opt?.hasHourRun,\n 'cqa-min-w-[66px]': !opt?.hasHourRun && opt?.hasMinuteRun,\n 'cqa-min-w-[40px]': !opt?.hasHourRun && !opt?.hasMinuteRun\n }\">\n <svg class=\"cqa-min-w-[12px] cqa-max-w-[12px]\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"6\" cy=\"6\" r=\"4.5\" stroke=\"#9CA3AF\" stroke-width=\"1\"/>\n <path d=\"M6 3.5V6L7.5 7\" stroke=\"#4B5563\" stroke-width=\"1\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n <span>{{ opt.durationFormatted }}</span>\n </span>\n </span>\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"!config.isCompareRuns\">\n <ng-container *ngIf=\"useCheckboxStyle; else defaultOptionTpl\">\n <span class=\"cqa-flex cqa-items-center\">\n <span class=\"cqa-w-4 cqa-h-4 cqa-flex-shrink-0 cqa-rounded-[4px] cqa-border cqa-border-[#D1D5DB] cqa-mr-2 cqa-flex cqa-items-center cqa-justify-center cqa-border-solid\"\n [ngStyle]=\"isOptionSelected(opt) ? {'background-color':'#4F46E5','border-color':'#4F46E5'} : {}\">\n <svg *ngIf=\"isOptionSelected(opt)\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M10 3L4.5 8.5L2 6\" stroke=\"white\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <!-- When displayLabelAsInnerHtml is true, render label as raw HTML -->\n <span class=\"cqa-min-w-0\"\n *ngIf=\"config?.displayLabelAsInnerHtml\"\n [innerHTML]=\"opt.label ?? opt.name ?? opt.value\">\n </span>\n <!-- Otherwise use normal/highlighted text rendering -->\n <span class=\"cqa-min-w-0\"\n *ngIf=\"!config?.displayLabelAsInnerHtml && hasHighlighting\"\n [innerHTML]=\"highlightText(opt.name ?? opt.label ?? opt.value)\">\n </span>\n <span class=\"cqa-min-w-0\"\n *ngIf=\"!config?.displayLabelAsInnerHtml && !hasHighlighting\">\n {{ opt.name ?? opt.label ?? opt.value }}\n </span>\n </span>\n </ng-container>\n <ng-template #defaultOptionTpl>\n <!-- When displayLabelAsInnerHtml is true, render label as raw HTML -->\n <span *ngIf=\"config?.displayLabelAsInnerHtml\"\n [innerHTML]=\"opt.label ?? opt.name ?? opt.value\">\n </span>\n <!-- Otherwise use normal/highlighted text rendering -->\n <span *ngIf=\"!config?.displayLabelAsInnerHtml && hasHighlighting\"\n [innerHTML]=\"highlightText(opt.name ?? opt.label ?? opt.value)\">\n </span>\n <span *ngIf=\"!config?.displayLabelAsInnerHtml && !hasHighlighting\">\n {{ opt.name ?? opt.label ?? opt.value }}\n </span>\n </ng-template>\n </ng-container>\n </mat-option>\n \n <!-- No results state (only when not loading and no options) -->\n <mat-option disabled *ngIf=\"!(config?.options?.length || 0) && !(config?.isLoading || loadingMore)\">\n No results\n </mat-option>\n <!-- Infinite scroll sentinel (serverSearch or explicit hasMore) -->\n <mat-option disabled class=\"load-more-sentinel\" *ngIf=\"config?.hasMore\">\n <span *ngIf=\"loadingMore || config?.isLoading\">Loading...</span>\n <span *ngIf=\"!loadingMore && !config?.isLoading\">Scroll to load more\u2026</span>\n </mat-option>\n </mat-select>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <!-- Inline spinner shown when loading more (infinite scroll) or when config.isLoading is true -->\n <svg *ngIf=\"loadingMore || config?.isLoading\" width=\"16\" height=\"16\" viewBox=\"0 0 50 50\" aria-label=\"loading\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"25\" cy=\"25\" r=\"20\" stroke=\"#E5E7EB\" stroke-width=\"6\" fill=\"none\"/>\n <path d=\"M45 25a20 20 0 0 0-20-20\" stroke=\"#4F46E5\" stroke-width=\"6\" fill=\"none\" stroke-linecap=\"round\">\n <animateTransform attributeName=\"transform\" type=\"rotate\" from=\"0 25 25\" to=\"360 25 25\"\n dur=\"0.8s\" repeatCount=\"indefinite\"/>\n </path>\n </svg>\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: i1$3.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: i2$2.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex"], exportAs: ["matSelect"] }, { type: i3$2.MatOption, selector: "mat-option", exportAs: ["matOption"] }], directives: [{ type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i2$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2262
2287
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DynamicSelectFieldComponent, decorators: [{
|
|
2263
2288
|
type: Component,
|
|
2264
|
-
args: [{ selector: 'cqa-dynamic-select', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"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]=\"displayPlaceholder\" [disabled]=\"isDisabled\" [multiple]=\"isMultiple\"\n disableOptionCentering [panelClass]=\"panelClass\" [formControlName]=\"config.key\"\n (openedChange)=\"onSelectOpenedChange($event, selectRef)\" (selectionChange)=\"onSelectionChange($event, selectRef)\">\n\n <mat-option *ngIf=\"config.searchable\" class=\"ts-select-search\" disabled>\n <input class=\"ts-select-search-input cqa-text-black-100\" 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 [ngClass]=\"{'checkmark': config.optionStyle === 'checkmark','checkbox': config.optionStyle !== 'checkmark','mat-selected': allSelected}\" [class]=\"config.optionStyle == 'checkmark' ? 'checkmark' : 'checkbox'\" *ngIf=\"isMultiple && config.showSelectAll\" [value]=\"SELECT_ALL_VALUE\">\n <ng-container *ngIf=\"useCheckboxStyle; else selectAllDefaultTpl\">\n <span class=\"cqa-flex cqa-items-center\">\n <span class=\"cqa-w-4 cqa-h-4 cqa-flex-shrink-0 cqa-rounded-[4px] cqa-border cqa-border-[#D1D5DB] cqa-mr-2 cqa-flex cqa-items-center cqa-justify-center cqa-border-solid\"\n [ngStyle]=\"allSelected ? {'background-color':'#4F46E5','border-color':'#4F46E5'} : {}\">\n <svg *ngIf=\"allSelected\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M10 3L4.5 8.5L2 6\" stroke=\"white\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <span class=\"cqa-min-w-0\">{{ config.selectAllLabel || 'All' }}</span>\n </span>\n </ng-container>\n <ng-template #selectAllDefaultTpl>\n {{ config.selectAllLabel || 'All' }}\n </ng-template>\n </mat-option>\n\n <mat-option [class]=\"config.optionStyle == 'checkmark' ? 'checkmark' : 'checkbox'\" *ngFor=\"let opt of filteredOptions(config)\" [value]=\"opt.id ?? opt.value\">\n <ng-container *ngIf=\"config.isCompareRuns\"> \n <ng-container *ngIf=\"useCheckboxStyle; else compareRunsDefaultOptionTpl\">\n <span class=\"cqa-flex cqa-items-center cqa-justify-between cqa-w-full cqa-compare-runs-item\">\n <span class=\"cqa-flex cqa-items-center\">\n <span class=\"cqa-w-4 cqa-h-4 cqa-flex-shrink-0 cqa-rounded-[4px] cqa-border cqa-border-[#D1D5DB] cqa-mr-2 cqa-flex cqa-items-center cqa-justify-center cqa-border-solid\"\n [ngStyle]=\"isOptionSelected(opt) ? {'background-color':'#4F46E5','border-color':'#4F46E5'} : {}\">\n <svg *ngIf=\"isOptionSelected(opt)\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M10 3L4.5 8.5L2 6\" stroke=\"white\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <span\n class=\"cqa-min-w-0 cqa-compare-runs\"\n *ngIf=\"hasHighlighting\"\n [style.color]=\"opt.statusColor || null\"\n [innerHTML]=\"highlightText(opt.name ?? opt.label ?? opt.value)\"></span>\n <ng-container *ngIf=\"!hasHighlighting\">\n <span\n class=\"cqa-min-w-0 cqa-compare-runs\"\n *ngIf=\"opt.runNumberLabel && opt.runDateLabel; else checkboxDefaultLabel\">\n <span [style.color]=\"opt.statusColor || null\">{{ opt.runNumberLabel }}</span>\n <span class=\"cqa-text-[#6B7280]\"> {{ opt.runDateLabel }} </span>\n </span>\n <ng-template #checkboxDefaultLabel>\n <span\n class=\"cqa-min-w-0 cqa-compare-runs\"\n [style.color]=\"opt.statusColor || null\">\n {{ opt.name ?? opt.label ?? opt.value }}\n </span>\n </ng-template>\n </ng-container>\n </span>\n <span\n *ngIf=\"opt.durationFormatted\"\n class=\"cqa-flex cqa-items-center cqa-justify-start cqa-gap-1 cqa-text-[12px] cqa-text-[#6B7280] cqa-flex-shrink-0 cqa-whitespace-nowrap cqa-max-w-[80px]\" \n [ngClass]=\"{\n 'cqa-min-w-[82px]': opt?.hasHourRun,\n 'cqa-min-w-[66px]': !opt?.hasHourRun && opt?.hasMinuteRun,\n 'cqa-min-w-[40px]': !opt?.hasHourRun && !opt?.hasMinuteRun\n }\">\n <svg class=\"cqa-min-w-[12px] cqa-max-w-[12px]\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"6\" cy=\"6\" r=\"4.5\" stroke=\"#9CA3AF\" stroke-width=\"1\"/>\n <path d=\"M6 3.5V6L7.5 7\" stroke=\"#4B5563\" stroke-width=\"1\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n <span>{{ opt.durationFormatted }}</span>\n </span>\n </span>\n </ng-container>\n <ng-template #compareRunsDefaultOptionTpl>\n <span class=\"cqa-flex cqa-items-center cqa-justify-between cqa-w-full cqa-compare-runs-item\">\n <span\n class=\"cqa-min-w-0 cqa-compare-runs\"\n *ngIf=\"hasHighlighting\"\n [style.color]=\"opt.statusColor || null\"\n [innerHTML]=\"highlightText(opt.name ?? opt.label ?? opt.value)\"></span>\n <ng-container *ngIf=\"!hasHighlighting\">\n <span\n class=\"cqa-min-w-0 cqa-compare-runs\"\n *ngIf=\"opt.runNumberLabel && opt.runDateLabel; else defaultLabel\">\n <span [style.color]=\"opt.statusColor || null\">{{ opt.runNumberLabel }}</span>\n <span class=\"cqa-text-[#6B7280]\"> {{ opt.runDateLabel }} </span>\n </span>\n <ng-template #defaultLabel>\n <span\n class=\"cqa-min-w-0 cqa-compare-runs\"\n [style.color]=\"opt.statusColor || null\">\n {{ opt.name ?? opt.label ?? opt.value }}\n </span>\n </ng-template>\n </ng-container>\n <span\n *ngIf=\"opt.durationFormatted\"\n class=\"cqa-flex cqa-items-center cqa-justify-start cqa-gap-1 cqa-text-[12px] cqa-text-[#6B7280] cqa-flex-shrink-0 cqa-whitespace-nowrap cqa-max-w-[80px]\" \n [ngClass]=\"{\n 'cqa-min-w-[82px]': opt?.hasHourRun,\n 'cqa-min-w-[66px]': !opt?.hasHourRun && opt?.hasMinuteRun,\n 'cqa-min-w-[40px]': !opt?.hasHourRun && !opt?.hasMinuteRun\n }\">\n <svg class=\"cqa-min-w-[12px] cqa-max-w-[12px]\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"6\" cy=\"6\" r=\"4.5\" stroke=\"#9CA3AF\" stroke-width=\"1\"/>\n <path d=\"M6 3.5V6L7.5 7\" stroke=\"#4B5563\" stroke-width=\"1\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n <span>{{ opt.durationFormatted }}</span>\n </span>\n </span>\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"!config.isCompareRuns\">\n <ng-container *ngIf=\"useCheckboxStyle; else defaultOptionTpl\">\n <span class=\"cqa-flex cqa-items-center\">\n <span class=\"cqa-w-4 cqa-h-4 cqa-flex-shrink-0 cqa-rounded-[4px] cqa-border cqa-border-[#D1D5DB] cqa-mr-2 cqa-flex cqa-items-center cqa-justify-center cqa-border-solid\"\n [ngStyle]=\"isOptionSelected(opt) ? {'background-color':'#4F46E5','border-color':'#4F46E5'} : {}\">\n <svg *ngIf=\"isOptionSelected(opt)\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M10 3L4.5 8.5L2 6\" stroke=\"white\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <!-- When displayLabelAsInnerHtml is true, render label as raw HTML -->\n <span class=\"cqa-min-w-0\"\n *ngIf=\"config?.displayLabelAsInnerHtml\"\n [innerHTML]=\"opt.label ?? opt.name ?? opt.value\">\n </span>\n <!-- Otherwise use normal/highlighted text rendering -->\n <span class=\"cqa-min-w-0\"\n *ngIf=\"!config?.displayLabelAsInnerHtml && hasHighlighting\"\n [innerHTML]=\"highlightText(opt.name ?? opt.label ?? opt.value)\">\n </span>\n <span class=\"cqa-min-w-0\"\n *ngIf=\"!config?.displayLabelAsInnerHtml && !hasHighlighting\">\n {{ opt.name ?? opt.label ?? opt.value }}\n </span>\n </span>\n </ng-container>\n <ng-template #defaultOptionTpl>\n <!-- When displayLabelAsInnerHtml is true, render label as raw HTML -->\n <span *ngIf=\"config?.displayLabelAsInnerHtml\"\n [innerHTML]=\"opt.label ?? opt.name ?? opt.value\">\n </span>\n <!-- Otherwise use normal/highlighted text rendering -->\n <span *ngIf=\"!config?.displayLabelAsInnerHtml && hasHighlighting\"\n [innerHTML]=\"highlightText(opt.name ?? opt.label ?? opt.value)\">\n </span>\n <span *ngIf=\"!config?.displayLabelAsInnerHtml && !hasHighlighting\">\n {{ opt.name ?? opt.label ?? opt.value }}\n </span>\n </ng-template>\n </ng-container>\n </mat-option>\n \n <!-- No results state (only when not loading and no options) -->\n <mat-option disabled *ngIf=\"!(config?.options?.length || 0) && !(config?.isLoading || loadingMore)\">\n No results\n </mat-option>\n <!-- Infinite scroll sentinel (serverSearch or explicit hasMore) -->\n <mat-option disabled class=\"load-more-sentinel\" *ngIf=\"config?.hasMore\">\n <span *ngIf=\"loadingMore || config?.isLoading\">Loading...</span>\n <span *ngIf=\"!loadingMore && !config?.isLoading\">Scroll to load more\u2026</span>\n </mat-option>\n </mat-select>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <!-- Inline spinner shown when loading more (infinite scroll) or when config.isLoading is true -->\n <svg *ngIf=\"loadingMore || config?.isLoading\" width=\"16\" height=\"16\" viewBox=\"0 0 50 50\" aria-label=\"loading\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"25\" cy=\"25\" r=\"20\" stroke=\"#E5E7EB\" stroke-width=\"6\" fill=\"none\"/>\n <path d=\"M45 25a20 20 0 0 0-20-20\" stroke=\"#4F46E5\" stroke-width=\"6\" fill=\"none\" stroke-linecap=\"round\">\n <animateTransform attributeName=\"transform\" type=\"rotate\" from=\"0 25 25\" to=\"360 25 25\"\n dur=\"0.8s\" repeatCount=\"indefinite\"/>\n </path>\n </svg>\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>" }]
|
|
2289
|
+
args: [{ selector: 'cqa-dynamic-select', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"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]=\"displayPlaceholder\" [multiple]=\"isMultiple\"\n disableOptionCentering [panelClass]=\"panelClass\" [formControlName]=\"config.key\"\n (openedChange)=\"onSelectOpenedChange($event, selectRef)\" (selectionChange)=\"onSelectionChange($event, selectRef)\">\n\n <mat-option *ngIf=\"config.searchable\" class=\"ts-select-search\" disabled>\n <input class=\"ts-select-search-input cqa-text-black-100\" 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 [ngClass]=\"{'checkmark': config.optionStyle === 'checkmark','checkbox': config.optionStyle !== 'checkmark','mat-selected': allSelected}\" [class]=\"config.optionStyle == 'checkmark' ? 'checkmark' : 'checkbox'\" *ngIf=\"isMultiple && config.showSelectAll\" [value]=\"SELECT_ALL_VALUE\">\n <ng-container *ngIf=\"useCheckboxStyle; else selectAllDefaultTpl\">\n <span class=\"cqa-flex cqa-items-center\">\n <span class=\"cqa-w-4 cqa-h-4 cqa-flex-shrink-0 cqa-rounded-[4px] cqa-border cqa-border-[#D1D5DB] cqa-mr-2 cqa-flex cqa-items-center cqa-justify-center cqa-border-solid\"\n [ngStyle]=\"allSelected ? {'background-color':'#4F46E5','border-color':'#4F46E5'} : {}\">\n <svg *ngIf=\"allSelected\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M10 3L4.5 8.5L2 6\" stroke=\"white\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <span class=\"cqa-min-w-0\">{{ config.selectAllLabel || 'All' }}</span>\n </span>\n </ng-container>\n <ng-template #selectAllDefaultTpl>\n {{ config.selectAllLabel || 'All' }}\n </ng-template>\n </mat-option>\n\n <mat-option [class]=\"config.optionStyle == 'checkmark' ? 'checkmark' : 'checkbox'\" *ngFor=\"let opt of filteredOptions(config)\" [value]=\"opt.id ?? opt.value\">\n <ng-container *ngIf=\"config.isCompareRuns\"> \n <ng-container *ngIf=\"useCheckboxStyle; else compareRunsDefaultOptionTpl\">\n <span class=\"cqa-flex cqa-items-center cqa-justify-between cqa-w-full cqa-compare-runs-item\">\n <span class=\"cqa-flex cqa-items-center\">\n <span class=\"cqa-w-4 cqa-h-4 cqa-flex-shrink-0 cqa-rounded-[4px] cqa-border cqa-border-[#D1D5DB] cqa-mr-2 cqa-flex cqa-items-center cqa-justify-center cqa-border-solid\"\n [ngStyle]=\"isOptionSelected(opt) ? {'background-color':'#4F46E5','border-color':'#4F46E5'} : {}\">\n <svg *ngIf=\"isOptionSelected(opt)\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M10 3L4.5 8.5L2 6\" stroke=\"white\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <span\n class=\"cqa-min-w-0 cqa-compare-runs\"\n *ngIf=\"hasHighlighting\"\n [style.color]=\"opt.statusColor || null\"\n [innerHTML]=\"highlightText(opt.name ?? opt.label ?? opt.value)\"></span>\n <ng-container *ngIf=\"!hasHighlighting\">\n <span\n class=\"cqa-min-w-0 cqa-compare-runs\"\n *ngIf=\"opt.runNumberLabel && opt.runDateLabel; else checkboxDefaultLabel\">\n <span [style.color]=\"opt.statusColor || null\">{{ opt.runNumberLabel }}</span>\n <span class=\"cqa-text-[#6B7280]\"> {{ opt.runDateLabel }} </span>\n </span>\n <ng-template #checkboxDefaultLabel>\n <span\n class=\"cqa-min-w-0 cqa-compare-runs\"\n [style.color]=\"opt.statusColor || null\">\n {{ opt.name ?? opt.label ?? opt.value }}\n </span>\n </ng-template>\n </ng-container>\n </span>\n <span\n *ngIf=\"opt.durationFormatted\"\n class=\"cqa-flex cqa-items-center cqa-justify-start cqa-gap-1 cqa-text-[12px] cqa-text-[#6B7280] cqa-flex-shrink-0 cqa-whitespace-nowrap cqa-max-w-[80px]\" \n [ngClass]=\"{\n 'cqa-min-w-[82px]': opt?.hasHourRun,\n 'cqa-min-w-[66px]': !opt?.hasHourRun && opt?.hasMinuteRun,\n 'cqa-min-w-[40px]': !opt?.hasHourRun && !opt?.hasMinuteRun\n }\">\n <svg class=\"cqa-min-w-[12px] cqa-max-w-[12px]\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"6\" cy=\"6\" r=\"4.5\" stroke=\"#9CA3AF\" stroke-width=\"1\"/>\n <path d=\"M6 3.5V6L7.5 7\" stroke=\"#4B5563\" stroke-width=\"1\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n <span>{{ opt.durationFormatted }}</span>\n </span>\n </span>\n </ng-container>\n <ng-template #compareRunsDefaultOptionTpl>\n <span class=\"cqa-flex cqa-items-center cqa-justify-between cqa-w-full cqa-compare-runs-item\">\n <span\n class=\"cqa-min-w-0 cqa-compare-runs\"\n *ngIf=\"hasHighlighting\"\n [style.color]=\"opt.statusColor || null\"\n [innerHTML]=\"highlightText(opt.name ?? opt.label ?? opt.value)\"></span>\n <ng-container *ngIf=\"!hasHighlighting\">\n <span\n class=\"cqa-min-w-0 cqa-compare-runs\"\n *ngIf=\"opt.runNumberLabel && opt.runDateLabel; else defaultLabel\">\n <span [style.color]=\"opt.statusColor || null\">{{ opt.runNumberLabel }}</span>\n <span class=\"cqa-text-[#6B7280]\"> {{ opt.runDateLabel }} </span>\n </span>\n <ng-template #defaultLabel>\n <span\n class=\"cqa-min-w-0 cqa-compare-runs\"\n [style.color]=\"opt.statusColor || null\">\n {{ opt.name ?? opt.label ?? opt.value }}\n </span>\n </ng-template>\n </ng-container>\n <span\n *ngIf=\"opt.durationFormatted\"\n class=\"cqa-flex cqa-items-center cqa-justify-start cqa-gap-1 cqa-text-[12px] cqa-text-[#6B7280] cqa-flex-shrink-0 cqa-whitespace-nowrap cqa-max-w-[80px]\" \n [ngClass]=\"{\n 'cqa-min-w-[82px]': opt?.hasHourRun,\n 'cqa-min-w-[66px]': !opt?.hasHourRun && opt?.hasMinuteRun,\n 'cqa-min-w-[40px]': !opt?.hasHourRun && !opt?.hasMinuteRun\n }\">\n <svg class=\"cqa-min-w-[12px] cqa-max-w-[12px]\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"6\" cy=\"6\" r=\"4.5\" stroke=\"#9CA3AF\" stroke-width=\"1\"/>\n <path d=\"M6 3.5V6L7.5 7\" stroke=\"#4B5563\" stroke-width=\"1\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n <span>{{ opt.durationFormatted }}</span>\n </span>\n </span>\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"!config.isCompareRuns\">\n <ng-container *ngIf=\"useCheckboxStyle; else defaultOptionTpl\">\n <span class=\"cqa-flex cqa-items-center\">\n <span class=\"cqa-w-4 cqa-h-4 cqa-flex-shrink-0 cqa-rounded-[4px] cqa-border cqa-border-[#D1D5DB] cqa-mr-2 cqa-flex cqa-items-center cqa-justify-center cqa-border-solid\"\n [ngStyle]=\"isOptionSelected(opt) ? {'background-color':'#4F46E5','border-color':'#4F46E5'} : {}\">\n <svg *ngIf=\"isOptionSelected(opt)\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M10 3L4.5 8.5L2 6\" stroke=\"white\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <!-- When displayLabelAsInnerHtml is true, render label as raw HTML -->\n <span class=\"cqa-min-w-0\"\n *ngIf=\"config?.displayLabelAsInnerHtml\"\n [innerHTML]=\"opt.label ?? opt.name ?? opt.value\">\n </span>\n <!-- Otherwise use normal/highlighted text rendering -->\n <span class=\"cqa-min-w-0\"\n *ngIf=\"!config?.displayLabelAsInnerHtml && hasHighlighting\"\n [innerHTML]=\"highlightText(opt.name ?? opt.label ?? opt.value)\">\n </span>\n <span class=\"cqa-min-w-0\"\n *ngIf=\"!config?.displayLabelAsInnerHtml && !hasHighlighting\">\n {{ opt.name ?? opt.label ?? opt.value }}\n </span>\n </span>\n </ng-container>\n <ng-template #defaultOptionTpl>\n <!-- When displayLabelAsInnerHtml is true, render label as raw HTML -->\n <span *ngIf=\"config?.displayLabelAsInnerHtml\"\n [innerHTML]=\"opt.label ?? opt.name ?? opt.value\">\n </span>\n <!-- Otherwise use normal/highlighted text rendering -->\n <span *ngIf=\"!config?.displayLabelAsInnerHtml && hasHighlighting\"\n [innerHTML]=\"highlightText(opt.name ?? opt.label ?? opt.value)\">\n </span>\n <span *ngIf=\"!config?.displayLabelAsInnerHtml && !hasHighlighting\">\n {{ opt.name ?? opt.label ?? opt.value }}\n </span>\n </ng-template>\n </ng-container>\n </mat-option>\n \n <!-- No results state (only when not loading and no options) -->\n <mat-option disabled *ngIf=\"!(config?.options?.length || 0) && !(config?.isLoading || loadingMore)\">\n No results\n </mat-option>\n <!-- Infinite scroll sentinel (serverSearch or explicit hasMore) -->\n <mat-option disabled class=\"load-more-sentinel\" *ngIf=\"config?.hasMore\">\n <span *ngIf=\"loadingMore || config?.isLoading\">Loading...</span>\n <span *ngIf=\"!loadingMore && !config?.isLoading\">Scroll to load more\u2026</span>\n </mat-option>\n </mat-select>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <!-- Inline spinner shown when loading more (infinite scroll) or when config.isLoading is true -->\n <svg *ngIf=\"loadingMore || config?.isLoading\" width=\"16\" height=\"16\" viewBox=\"0 0 50 50\" aria-label=\"loading\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"25\" cy=\"25\" r=\"20\" stroke=\"#E5E7EB\" stroke-width=\"6\" fill=\"none\"/>\n <path d=\"M45 25a20 20 0 0 0-20-20\" stroke=\"#4F46E5\" stroke-width=\"6\" fill=\"none\" stroke-linecap=\"round\">\n <animateTransform attributeName=\"transform\" type=\"rotate\" from=\"0 25 25\" to=\"360 25 25\"\n dur=\"0.8s\" repeatCount=\"indefinite\"/>\n </path>\n </svg>\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>" }]
|
|
2265
2290
|
}], propDecorators: { form: [{
|
|
2266
2291
|
type: Input
|
|
2267
2292
|
}], config: [{
|
|
@@ -5865,7 +5890,8 @@ class TailwindOverlayContainer extends OverlayContainer {
|
|
|
5865
5890
|
pane.classList.contains('ctc-date-range-panel') ||
|
|
5866
5891
|
pane.classList.contains('visual-difference-dialog') ||
|
|
5867
5892
|
pane.classList.contains('cqa-custom-edit-step-panel') ||
|
|
5868
|
-
pane.classList.contains('cqa-test-data-modal-panel')
|
|
5893
|
+
pane.classList.contains('cqa-test-data-modal-panel') ||
|
|
5894
|
+
pane.classList.contains('cqa-step-details-drawer-panel');
|
|
5869
5895
|
// Also check for library components inside the pane
|
|
5870
5896
|
// These classes may be on child elements rather than the pane itself
|
|
5871
5897
|
const hasLibraryDialogInside = pane.querySelector('.cqa-dialog-panel') !== null;
|
|
@@ -5878,10 +5904,12 @@ class TailwindOverlayContainer extends OverlayContainer {
|
|
|
5878
5904
|
pane.querySelector('cqa-custom-edit-step') !== null;
|
|
5879
5905
|
const hasTestDataModalInside = pane.querySelector('.cqa-test-data-modal-panel') !== null ||
|
|
5880
5906
|
pane.querySelector('cqa-test-data-modal') !== null;
|
|
5907
|
+
const hasStepDetailsDrawerInside = pane.querySelector('.cqa-step-details-drawer-panel') !== null ||
|
|
5908
|
+
pane.querySelector('cqa-step-details-drawer') !== null;
|
|
5881
5909
|
const isLibraryOverlay = paneHasLibraryClass || hasLibraryDialogInside ||
|
|
5882
5910
|
hasLibrarySelectInside || hasLibraryDatePickerInside ||
|
|
5883
5911
|
hasVisualDifferenceDialogInside || hasCustomEditStepInside ||
|
|
5884
|
-
hasTestDataModalInside;
|
|
5912
|
+
hasTestDataModalInside || hasStepDetailsDrawerInside;
|
|
5885
5913
|
if (isLibraryOverlay) {
|
|
5886
5914
|
// This is a library overlay - add the class
|
|
5887
5915
|
pane.classList.add('cqa-ui-root');
|
|
@@ -22068,6 +22096,506 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
|
|
|
22068
22096
|
type: Output
|
|
22069
22097
|
}] } });
|
|
22070
22098
|
|
|
22099
|
+
/**
|
|
22100
|
+
* Configuration for Step Details Drawer (Edit In Depth).
|
|
22101
|
+
* Form is fully dynamic by Step Type – no hardcoded field lists.
|
|
22102
|
+
*/
|
|
22103
|
+
/**
|
|
22104
|
+
* Resolves drawer step type from a test case step config.
|
|
22105
|
+
*/
|
|
22106
|
+
function getStepDetailsStepType(step) {
|
|
22107
|
+
if (!step)
|
|
22108
|
+
return null;
|
|
22109
|
+
if (isApiStepConfig(step))
|
|
22110
|
+
return 'api';
|
|
22111
|
+
if (isAiAgentStepConfig(step))
|
|
22112
|
+
return 'aiAgent';
|
|
22113
|
+
if (isNormalStepConfig(step) && step.eventType === 'custom')
|
|
22114
|
+
return 'custom';
|
|
22115
|
+
return null;
|
|
22116
|
+
}
|
|
22117
|
+
/**
|
|
22118
|
+
* Fields shown per step type (configuration-based).
|
|
22119
|
+
* Custom: Description, Metadata, Retry Count (if configured), Advanced (if configured).
|
|
22120
|
+
* API: Method, URL, Headers, Body, Save Output as Variable, Advanced (if configured).
|
|
22121
|
+
* AI Agent: Agent Task, Type, Metadata, Environment, Description, Constraints (toggles + Max Retries), Advanced (toggles + Retry Count, Iframe locator, Other Locators).
|
|
22122
|
+
*/
|
|
22123
|
+
const STEP_DETAILS_FIELDS_BY_TYPE = {
|
|
22124
|
+
custom: ['description', 'metadata', 'retryCount', 'advanced'],
|
|
22125
|
+
api: ['method', 'url', 'headers', 'body', 'saveOutputAsVariable', 'advanced'],
|
|
22126
|
+
aiAgent: [
|
|
22127
|
+
'agentTask',
|
|
22128
|
+
'type',
|
|
22129
|
+
'metadata',
|
|
22130
|
+
'environment',
|
|
22131
|
+
'description',
|
|
22132
|
+
'onlyUseAttachedContext',
|
|
22133
|
+
'takeScreenshotsWhenVerifying',
|
|
22134
|
+
'maxRetries',
|
|
22135
|
+
'advanced',
|
|
22136
|
+
'retryCount',
|
|
22137
|
+
'iframeLocator',
|
|
22138
|
+
'otherLocators',
|
|
22139
|
+
],
|
|
22140
|
+
};
|
|
22141
|
+
const STEP_DETAILS_FIELD_META = {
|
|
22142
|
+
description: { key: 'description', label: 'Description', placeholder: 'Text Input', controlType: 'text', section: 'main' },
|
|
22143
|
+
metadata: { key: 'metadata', label: 'Metadata', placeholder: 'Text Input', controlType: 'text', section: 'main' },
|
|
22144
|
+
retryCount: {
|
|
22145
|
+
key: 'retryCount',
|
|
22146
|
+
label: 'Retry Count',
|
|
22147
|
+
placeholder: 'Dynamic search selector from library or manual',
|
|
22148
|
+
controlType: 'dropdown',
|
|
22149
|
+
section: 'advanced',
|
|
22150
|
+
options: [
|
|
22151
|
+
{ value: '0', label: '0' },
|
|
22152
|
+
{ value: '1', label: '1' },
|
|
22153
|
+
{ value: '2', label: '2' },
|
|
22154
|
+
{ value: '3', label: '3' },
|
|
22155
|
+
],
|
|
22156
|
+
},
|
|
22157
|
+
advanced: { key: 'advanced', label: 'Advanced', controlType: 'toggleGroup' },
|
|
22158
|
+
method: {
|
|
22159
|
+
key: 'method',
|
|
22160
|
+
label: 'Method',
|
|
22161
|
+
placeholder: 'Method',
|
|
22162
|
+
controlType: 'dropdown',
|
|
22163
|
+
section: 'main',
|
|
22164
|
+
options: [
|
|
22165
|
+
{ value: 'GET', label: 'GET' },
|
|
22166
|
+
{ value: 'POST', label: 'POST' },
|
|
22167
|
+
{ value: 'PUT', label: 'PUT' },
|
|
22168
|
+
{ value: 'DELETE', label: 'DELETE' },
|
|
22169
|
+
{ value: 'PATCH', label: 'PATCH' },
|
|
22170
|
+
],
|
|
22171
|
+
},
|
|
22172
|
+
url: { key: 'url', label: 'URL', placeholder: 'URL', controlType: 'text', section: 'main' },
|
|
22173
|
+
headers: { key: 'headers', label: 'Headers', controlType: 'text', section: 'main' },
|
|
22174
|
+
body: { key: 'body', label: 'Body', placeholder: 'Request body', controlType: 'code', section: 'main' },
|
|
22175
|
+
saveOutputAsVariable: {
|
|
22176
|
+
key: 'saveOutputAsVariable',
|
|
22177
|
+
label: 'Save Output as Variable',
|
|
22178
|
+
placeholder: 'Variable name',
|
|
22179
|
+
controlType: 'text',
|
|
22180
|
+
section: 'main',
|
|
22181
|
+
},
|
|
22182
|
+
agentTask: {
|
|
22183
|
+
key: 'agentTask',
|
|
22184
|
+
label: 'Agent Task',
|
|
22185
|
+
placeholder: 'What should the agent achieve?',
|
|
22186
|
+
controlType: 'textarea',
|
|
22187
|
+
section: 'main',
|
|
22188
|
+
required: true,
|
|
22189
|
+
rows: 4,
|
|
22190
|
+
tip: 'Tip: Use numbered steps or bullet points for complex tasks.',
|
|
22191
|
+
},
|
|
22192
|
+
type: {
|
|
22193
|
+
key: 'type',
|
|
22194
|
+
label: 'Type',
|
|
22195
|
+
placeholder: 'Type',
|
|
22196
|
+
controlType: 'dropdown',
|
|
22197
|
+
section: 'main',
|
|
22198
|
+
options: [
|
|
22199
|
+
{ value: 'default', label: 'Default' },
|
|
22200
|
+
{ value: 'browser', label: 'Browser' },
|
|
22201
|
+
],
|
|
22202
|
+
},
|
|
22203
|
+
environment: {
|
|
22204
|
+
key: 'environment',
|
|
22205
|
+
label: 'Environment',
|
|
22206
|
+
placeholder: 'Environment',
|
|
22207
|
+
controlType: 'dropdown',
|
|
22208
|
+
section: 'main',
|
|
22209
|
+
options: [
|
|
22210
|
+
{ value: 'default', label: 'Default' },
|
|
22211
|
+
{ value: 'staging', label: 'Staging' },
|
|
22212
|
+
{ value: 'prod', label: 'Production' },
|
|
22213
|
+
],
|
|
22214
|
+
},
|
|
22215
|
+
maxRetries: {
|
|
22216
|
+
key: 'maxRetries',
|
|
22217
|
+
label: 'Max Retries',
|
|
22218
|
+
placeholder: '3 retries (recommended)',
|
|
22219
|
+
controlType: 'dropdown',
|
|
22220
|
+
section: 'constraints',
|
|
22221
|
+
options: [
|
|
22222
|
+
{ value: '0', label: '0' },
|
|
22223
|
+
{ value: '1', label: '1' },
|
|
22224
|
+
{ value: '2', label: '2' },
|
|
22225
|
+
{ value: '3', label: '3 retries (recommended)' },
|
|
22226
|
+
],
|
|
22227
|
+
},
|
|
22228
|
+
onlyUseAttachedContext: {
|
|
22229
|
+
key: 'onlyUseAttachedContext',
|
|
22230
|
+
label: 'Use existing elements only',
|
|
22231
|
+
subLabel: 'Only use elements from the attached context',
|
|
22232
|
+
controlType: 'toggle',
|
|
22233
|
+
section: 'constraints',
|
|
22234
|
+
},
|
|
22235
|
+
takeScreenshotsWhenVerifying: {
|
|
22236
|
+
key: 'takeScreenshotsWhenVerifying',
|
|
22237
|
+
label: 'Capture evidence',
|
|
22238
|
+
subLabel: 'Take screenshots when verifying conditions',
|
|
22239
|
+
controlType: 'toggle',
|
|
22240
|
+
section: 'constraints',
|
|
22241
|
+
},
|
|
22242
|
+
iframeLocator: {
|
|
22243
|
+
key: 'iframeLocator',
|
|
22244
|
+
label: 'Iframe locator',
|
|
22245
|
+
placeholder: 'Dynamic search selector from library or manual',
|
|
22246
|
+
controlType: 'dropdown',
|
|
22247
|
+
section: 'advanced',
|
|
22248
|
+
options: [
|
|
22249
|
+
{ value: 'manual', label: 'Dynamic search selector from library or manual' },
|
|
22250
|
+
],
|
|
22251
|
+
},
|
|
22252
|
+
otherLocators: {
|
|
22253
|
+
key: 'otherLocators',
|
|
22254
|
+
label: 'Other Locators',
|
|
22255
|
+
placeholder: 'Dynamic search selector from library or manual',
|
|
22256
|
+
controlType: 'dropdown',
|
|
22257
|
+
section: 'advanced',
|
|
22258
|
+
options: [
|
|
22259
|
+
{ value: 'manual', label: 'Dynamic search selector from library or manual' },
|
|
22260
|
+
],
|
|
22261
|
+
},
|
|
22262
|
+
continueOnError: {
|
|
22263
|
+
key: 'continueOnError',
|
|
22264
|
+
label: 'Continue on Error',
|
|
22265
|
+
subLabel: "Don't fail the test if this step fails.",
|
|
22266
|
+
controlType: 'toggle',
|
|
22267
|
+
section: 'advanced',
|
|
22268
|
+
},
|
|
22269
|
+
disabled: {
|
|
22270
|
+
key: 'disabled',
|
|
22271
|
+
label: 'Disabled',
|
|
22272
|
+
subLabel: 'Skip this step during execution.',
|
|
22273
|
+
controlType: 'toggle',
|
|
22274
|
+
section: 'advanced',
|
|
22275
|
+
},
|
|
22276
|
+
};
|
|
22277
|
+
/** Toggle fields always shown inside the Advanced section. */
|
|
22278
|
+
const ADVANCED_TOGGLE_KEYS = ['continueOnError', 'disabled'];
|
|
22279
|
+
/** Field keys shown inside Advanced (per step type), in addition to ADVANCED_TOGGLE_KEYS. */
|
|
22280
|
+
const ADVANCED_SUBFIELDS_BY_TYPE = {
|
|
22281
|
+
custom: [],
|
|
22282
|
+
api: [],
|
|
22283
|
+
aiAgent: ['retryCount', 'iframeLocator', 'otherLocators'],
|
|
22284
|
+
};
|
|
22285
|
+
|
|
22286
|
+
class StepDetailsDrawerRef {
|
|
22287
|
+
constructor(overlayRef) {
|
|
22288
|
+
this.overlayRef = overlayRef;
|
|
22289
|
+
this.closed$ = new Subject();
|
|
22290
|
+
this.isClosed = false;
|
|
22291
|
+
this.overlayRef.detachments().subscribe(() => this.finishClose(undefined));
|
|
22292
|
+
}
|
|
22293
|
+
close(result) {
|
|
22294
|
+
if (this.isClosed)
|
|
22295
|
+
return;
|
|
22296
|
+
this.finishClose(result);
|
|
22297
|
+
this.overlayRef.dispose();
|
|
22298
|
+
}
|
|
22299
|
+
afterClosed() {
|
|
22300
|
+
return this.closed$.asObservable();
|
|
22301
|
+
}
|
|
22302
|
+
finishClose(result) {
|
|
22303
|
+
if (this.isClosed)
|
|
22304
|
+
return;
|
|
22305
|
+
this.isClosed = true;
|
|
22306
|
+
this.closed$.next(result);
|
|
22307
|
+
this.closed$.complete();
|
|
22308
|
+
}
|
|
22309
|
+
}
|
|
22310
|
+
const STEP_DETAILS_DRAWER_REF = new InjectionToken('STEP_DETAILS_DRAWER_REF');
|
|
22311
|
+
|
|
22312
|
+
const STEP_DETAILS_DRAWER_DATA = new InjectionToken('STEP_DETAILS_DRAWER_DATA');
|
|
22313
|
+
|
|
22314
|
+
/**
|
|
22315
|
+
* Step Details Drawer (Edit In Depth).
|
|
22316
|
+
* Single reusable component; form is dynamic by Step Type via configuration.
|
|
22317
|
+
* No Priority section. Uses CQA components only.
|
|
22318
|
+
*/
|
|
22319
|
+
class StepDetailsDrawerComponent {
|
|
22320
|
+
constructor(ref, fb, cdr, data) {
|
|
22321
|
+
var _a, _b;
|
|
22322
|
+
this.ref = ref;
|
|
22323
|
+
this.fb = fb;
|
|
22324
|
+
this.cdr = cdr;
|
|
22325
|
+
this.saveChanges = new EventEmitter();
|
|
22326
|
+
this.cancel = new EventEmitter();
|
|
22327
|
+
this.saveAsTemplate = new EventEmitter();
|
|
22328
|
+
/** Optional: when provided (e.g. from Storybook Controls), use instead of STEP_DETAILS_DRAWER_DATA. */
|
|
22329
|
+
this.stepData = null;
|
|
22330
|
+
this.stepNumberInput = null;
|
|
22331
|
+
this.stepType = null;
|
|
22332
|
+
this.visibleFields = [];
|
|
22333
|
+
this.fieldMeta = STEP_DETAILS_FIELD_META;
|
|
22334
|
+
this.advancedToggleKeys = ADVANCED_TOGGLE_KEYS;
|
|
22335
|
+
this.advancedExpanded = false;
|
|
22336
|
+
this.agentTaskExpanded = true;
|
|
22337
|
+
/** Cached select configs (stable references per key) to avoid infinite change detection in template. */
|
|
22338
|
+
this.selectConfigMap = this.buildSelectConfigMap();
|
|
22339
|
+
this.step = (_a = data === null || data === void 0 ? void 0 : data.step) !== null && _a !== void 0 ? _a : {};
|
|
22340
|
+
this.stepNumber = (_b = data === null || data === void 0 ? void 0 : data.stepNumber) !== null && _b !== void 0 ? _b : 1;
|
|
22341
|
+
this.form = this.fb.group({});
|
|
22342
|
+
this.syncStepTypeAndForm();
|
|
22343
|
+
}
|
|
22344
|
+
/** Subfields to show inside Advanced section for current step type. */
|
|
22345
|
+
get advancedSubfields() {
|
|
22346
|
+
return this.stepType ? ADVANCED_SUBFIELDS_BY_TYPE[this.stepType] : [];
|
|
22347
|
+
}
|
|
22348
|
+
ngOnInit() {
|
|
22349
|
+
var _a, _b;
|
|
22350
|
+
if (this.stepData != null) {
|
|
22351
|
+
this.step = this.stepData;
|
|
22352
|
+
this.stepNumber = (_b = (_a = this.stepNumberInput) !== null && _a !== void 0 ? _a : this.stepData.stepNumber) !== null && _b !== void 0 ? _b : 1;
|
|
22353
|
+
this.syncStepTypeAndForm();
|
|
22354
|
+
this.cdr.markForCheck();
|
|
22355
|
+
}
|
|
22356
|
+
}
|
|
22357
|
+
ngOnChanges(changes) {
|
|
22358
|
+
var _a, _b;
|
|
22359
|
+
if (changes['stepData'] || changes['stepNumberInput']) {
|
|
22360
|
+
if (this.stepData != null) {
|
|
22361
|
+
this.step = this.stepData;
|
|
22362
|
+
this.stepNumber = (_b = (_a = this.stepNumberInput) !== null && _a !== void 0 ? _a : this.stepData.stepNumber) !== null && _b !== void 0 ? _b : 1;
|
|
22363
|
+
}
|
|
22364
|
+
this.syncStepTypeAndForm();
|
|
22365
|
+
this.cdr.detectChanges();
|
|
22366
|
+
}
|
|
22367
|
+
}
|
|
22368
|
+
syncStepTypeAndForm() {
|
|
22369
|
+
this.stepType = getStepDetailsStepType(this.step);
|
|
22370
|
+
this.visibleFields = this.stepType ? STEP_DETAILS_FIELDS_BY_TYPE[this.stepType] : [];
|
|
22371
|
+
this.buildFormFromStep();
|
|
22372
|
+
}
|
|
22373
|
+
buildFormFromStep() {
|
|
22374
|
+
const group = {};
|
|
22375
|
+
for (const key of this.visibleFields) {
|
|
22376
|
+
if (key === 'advanced')
|
|
22377
|
+
continue;
|
|
22378
|
+
group[key] = [this.getStepValue(key)];
|
|
22379
|
+
}
|
|
22380
|
+
for (const key of ADVANCED_TOGGLE_KEYS) {
|
|
22381
|
+
if (!(key in group))
|
|
22382
|
+
group[key] = [this.getStepValue(key)];
|
|
22383
|
+
}
|
|
22384
|
+
this.form = this.fb.group(group);
|
|
22385
|
+
}
|
|
22386
|
+
getStepValue(key) {
|
|
22387
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
22388
|
+
const step = this.step;
|
|
22389
|
+
if (isNormalStepConfig(this.step) && this.step.eventType === 'custom') {
|
|
22390
|
+
if (key === 'description') {
|
|
22391
|
+
const params = this.step.parameters;
|
|
22392
|
+
return (_c = (_b = (_a = params === null || params === void 0 ? void 0 : params[0]) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : this.step.description) !== null && _c !== void 0 ? _c : '';
|
|
22393
|
+
}
|
|
22394
|
+
if (key === 'metadata') {
|
|
22395
|
+
const params = this.step.parameters;
|
|
22396
|
+
return (_e = (_d = params === null || params === void 0 ? void 0 : params[1]) === null || _d === void 0 ? void 0 : _d.value) !== null && _e !== void 0 ? _e : '';
|
|
22397
|
+
}
|
|
22398
|
+
}
|
|
22399
|
+
if (isApiStepConfig(this.step)) {
|
|
22400
|
+
const api = this.step;
|
|
22401
|
+
if (key === 'method')
|
|
22402
|
+
return (_f = api.method) !== null && _f !== void 0 ? _f : 'GET';
|
|
22403
|
+
if (key === 'url')
|
|
22404
|
+
return api.baseUrl ? `${api.baseUrl}${api.endpoint || ''}` : (_g = api.endpoint) !== null && _g !== void 0 ? _g : '';
|
|
22405
|
+
if (key === 'headers')
|
|
22406
|
+
return api.headers ? JSON.stringify(api.headers, null, 2) : '';
|
|
22407
|
+
if (key === 'body')
|
|
22408
|
+
return (_h = api.requestBody) !== null && _h !== void 0 ? _h : '';
|
|
22409
|
+
if (key === 'saveOutputAsVariable')
|
|
22410
|
+
return (_j = api.saveTo) !== null && _j !== void 0 ? _j : '';
|
|
22411
|
+
}
|
|
22412
|
+
if (isAiAgentStepConfig(this.step)) {
|
|
22413
|
+
const ai = this.step;
|
|
22414
|
+
if (key === 'agentTask')
|
|
22415
|
+
return (_k = ai.instructions) !== null && _k !== void 0 ? _k : '';
|
|
22416
|
+
if (key === 'description')
|
|
22417
|
+
return (_l = ai.description) !== null && _l !== void 0 ? _l : '';
|
|
22418
|
+
if (key === 'metadata')
|
|
22419
|
+
return (_m = step.metadata) !== null && _m !== void 0 ? _m : '';
|
|
22420
|
+
}
|
|
22421
|
+
if (key === 'onlyUseAttachedContext' ||
|
|
22422
|
+
key === 'takeScreenshotsWhenVerifying' ||
|
|
22423
|
+
key === 'continueOnError' ||
|
|
22424
|
+
key === 'disabled') {
|
|
22425
|
+
return step[key] === true;
|
|
22426
|
+
}
|
|
22427
|
+
return (_o = step[key]) !== null && _o !== void 0 ? _o : '';
|
|
22428
|
+
}
|
|
22429
|
+
setStepValue(key, value) {
|
|
22430
|
+
const step = this.step;
|
|
22431
|
+
if (isNormalStepConfig(this.step) && this.step.eventType === 'custom') {
|
|
22432
|
+
if (key === 'description') {
|
|
22433
|
+
const params = this.step.parameters;
|
|
22434
|
+
if (params === null || params === void 0 ? void 0 : params[0])
|
|
22435
|
+
params[0].value = String(value);
|
|
22436
|
+
else
|
|
22437
|
+
this.step.description = String(value);
|
|
22438
|
+
return;
|
|
22439
|
+
}
|
|
22440
|
+
if (key === 'metadata') {
|
|
22441
|
+
const params = this.step.parameters;
|
|
22442
|
+
if (params === null || params === void 0 ? void 0 : params[1])
|
|
22443
|
+
params[1].value = String(value);
|
|
22444
|
+
return;
|
|
22445
|
+
}
|
|
22446
|
+
}
|
|
22447
|
+
if (isApiStepConfig(this.step)) {
|
|
22448
|
+
const api = this.step;
|
|
22449
|
+
if (key === 'method') {
|
|
22450
|
+
api.method = value;
|
|
22451
|
+
return;
|
|
22452
|
+
}
|
|
22453
|
+
if (key === 'url') {
|
|
22454
|
+
api.endpoint = String(value);
|
|
22455
|
+
return;
|
|
22456
|
+
}
|
|
22457
|
+
if (key === 'headers') {
|
|
22458
|
+
try {
|
|
22459
|
+
api.headers = JSON.parse(String(value) || '{}');
|
|
22460
|
+
}
|
|
22461
|
+
catch (_a) {
|
|
22462
|
+
api.headers = {};
|
|
22463
|
+
}
|
|
22464
|
+
return;
|
|
22465
|
+
}
|
|
22466
|
+
if (key === 'body') {
|
|
22467
|
+
api.requestBody = String(value);
|
|
22468
|
+
return;
|
|
22469
|
+
}
|
|
22470
|
+
if (key === 'saveOutputAsVariable') {
|
|
22471
|
+
api.saveTo = String(value);
|
|
22472
|
+
return;
|
|
22473
|
+
}
|
|
22474
|
+
}
|
|
22475
|
+
if (isAiAgentStepConfig(this.step)) {
|
|
22476
|
+
const ai = this.step;
|
|
22477
|
+
if (key === 'agentTask') {
|
|
22478
|
+
ai.instructions = String(value);
|
|
22479
|
+
return;
|
|
22480
|
+
}
|
|
22481
|
+
if (key === 'description') {
|
|
22482
|
+
ai.description = String(value);
|
|
22483
|
+
return;
|
|
22484
|
+
}
|
|
22485
|
+
if (key === 'metadata') {
|
|
22486
|
+
step.metadata = value;
|
|
22487
|
+
return;
|
|
22488
|
+
}
|
|
22489
|
+
}
|
|
22490
|
+
step[key] = value;
|
|
22491
|
+
}
|
|
22492
|
+
onBack() {
|
|
22493
|
+
this.cancel.emit();
|
|
22494
|
+
this.ref.close(undefined);
|
|
22495
|
+
}
|
|
22496
|
+
onClose() {
|
|
22497
|
+
this.cancel.emit();
|
|
22498
|
+
this.ref.close(undefined);
|
|
22499
|
+
}
|
|
22500
|
+
onCancel() {
|
|
22501
|
+
this.cancel.emit();
|
|
22502
|
+
this.ref.close(undefined);
|
|
22503
|
+
}
|
|
22504
|
+
onSaveAsTemplate() {
|
|
22505
|
+
this.applyFormToStep();
|
|
22506
|
+
this.saveAsTemplate.emit(this.step);
|
|
22507
|
+
this.ref.close({ action: 'saveAsTemplate', step: this.step });
|
|
22508
|
+
}
|
|
22509
|
+
onSaveChanges() {
|
|
22510
|
+
this.applyFormToStep();
|
|
22511
|
+
this.saveChanges.emit(this.step);
|
|
22512
|
+
this.ref.close({ action: 'saveChanges', step: this.step });
|
|
22513
|
+
}
|
|
22514
|
+
applyFormToStep() {
|
|
22515
|
+
var _a, _b;
|
|
22516
|
+
for (const key of this.visibleFields) {
|
|
22517
|
+
if (key === 'advanced')
|
|
22518
|
+
continue;
|
|
22519
|
+
if (this.form.contains(key))
|
|
22520
|
+
this.setStepValue(key, (_a = this.form.get(key)) === null || _a === void 0 ? void 0 : _a.value);
|
|
22521
|
+
}
|
|
22522
|
+
for (const key of ADVANCED_TOGGLE_KEYS) {
|
|
22523
|
+
if (this.form.contains(key))
|
|
22524
|
+
this.setStepValue(key, (_b = this.form.get(key)) === null || _b === void 0 ? void 0 : _b.value);
|
|
22525
|
+
}
|
|
22526
|
+
}
|
|
22527
|
+
/** Build cached map of select configs from field meta (stable refs to prevent CD loops). */
|
|
22528
|
+
buildSelectConfigMap() {
|
|
22529
|
+
var _a, _b;
|
|
22530
|
+
const map = {};
|
|
22531
|
+
const keys = Object.keys(STEP_DETAILS_FIELD_META);
|
|
22532
|
+
for (const key of keys) {
|
|
22533
|
+
const meta = STEP_DETAILS_FIELD_META[key];
|
|
22534
|
+
if (!meta || meta.controlType !== 'dropdown' || !((_a = meta.options) === null || _a === void 0 ? void 0 : _a.length))
|
|
22535
|
+
continue;
|
|
22536
|
+
const options = meta.options.map((o) => ({ value: o.value, label: o.label }));
|
|
22537
|
+
map[key] = {
|
|
22538
|
+
key: meta.key,
|
|
22539
|
+
placeholder: (_b = meta.placeholder) !== null && _b !== void 0 ? _b : meta.label,
|
|
22540
|
+
options,
|
|
22541
|
+
};
|
|
22542
|
+
}
|
|
22543
|
+
return map;
|
|
22544
|
+
}
|
|
22545
|
+
/** Return cached select config for key (for template use; same reference every time). */
|
|
22546
|
+
getSelectConfig(key) {
|
|
22547
|
+
var _a;
|
|
22548
|
+
return (_a = this.selectConfigMap[key]) !== null && _a !== void 0 ? _a : null;
|
|
22549
|
+
}
|
|
22550
|
+
/** Whether this key is the first in its section (for showing section headings). */
|
|
22551
|
+
isFirstInSection(key, section) {
|
|
22552
|
+
const meta = STEP_DETAILS_FIELD_META[key];
|
|
22553
|
+
if (!meta || meta.section !== section)
|
|
22554
|
+
return false;
|
|
22555
|
+
const idx = this.visibleFields.indexOf(key);
|
|
22556
|
+
if (idx <= 0)
|
|
22557
|
+
return true;
|
|
22558
|
+
const prevMeta = STEP_DETAILS_FIELD_META[this.visibleFields[idx - 1]];
|
|
22559
|
+
return !prevMeta || prevMeta.section !== section;
|
|
22560
|
+
}
|
|
22561
|
+
/** Dynamic drawer title by step type (e.g. "AI Agent Step Details"). */
|
|
22562
|
+
get drawerTitle() {
|
|
22563
|
+
if (this.stepType === 'custom')
|
|
22564
|
+
return 'Custom Step Details';
|
|
22565
|
+
if (this.stepType === 'api')
|
|
22566
|
+
return 'API Step Details';
|
|
22567
|
+
if (this.stepType === 'aiAgent')
|
|
22568
|
+
return 'AI Agent Step Details';
|
|
22569
|
+
return 'Step Details';
|
|
22570
|
+
}
|
|
22571
|
+
}
|
|
22572
|
+
StepDetailsDrawerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StepDetailsDrawerComponent, deps: [{ token: STEP_DETAILS_DRAWER_REF }, { token: i2$1.FormBuilder }, { token: i0.ChangeDetectorRef }, { token: STEP_DETAILS_DRAWER_DATA, optional: true }], target: i0.ɵɵFactoryTarget.Component });
|
|
22573
|
+
StepDetailsDrawerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: StepDetailsDrawerComponent, selector: "cqa-step-details-drawer", inputs: { stepData: "stepData", stepNumberInput: "stepNumberInput" }, outputs: { saveChanges: "saveChanges", cancel: "cancel", saveAsTemplate: "saveAsTemplate" }, host: { classAttribute: "cqa-ui-root" }, usesOnChanges: true, ngImport: i0, template: "<!-- Step Details Drawer \u2013 Edit In Depth. No Priority. Fully config-driven. -->\n<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-w-full cqa-max-w-[480px] cqa-box-border\">\n <!-- Header: back chevron, dynamic title, Step N pill, close -->\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-gap-3 cqa-px-4 cqa-py-4 cqa-bg-white cqa-rounded-t-[12px] cqa-border cqa-border-[#E5E5E5]\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <button type=\"button\" (click)=\"onBack()\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-8 cqa-h-8 cqa-rounded cqa-text-[#6B7280] hover:cqa-bg-[#F3F4F6] cqa-p-0\"\n aria-label=\"Back\">\n <mat-icon class=\"!cqa-w-5 !cqa-h-5 !cqa-text-[20px]\">chevron_left</mat-icon>\n </button>\n <h2 class=\"cqa-text-[16px] cqa-leading-[24px] cqa-font-semibold cqa-text-[#111827] cqa-m-0 cqa-flex-1\">\n {{ drawerTitle }}\n </h2>\n <span class=\"cqa-px-2.5 cqa-py-1 cqa-rounded-lg cqa-bg-[#EDE9FE] cqa-text-[#7C3AED] cqa-text-[12px] cqa-font-medium\">\n Step {{ stepNumber }}\n </span>\n </div>\n <button type=\"button\" (click)=\"onClose()\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-min-h-[28px] cqa-min-w-[28px] cqa-rounded cqa-text-[#6B7280] hover:cqa-bg-[#F3F4F6] cqa-p-0\"\n title=\"Close\" aria-label=\"Close\">\n <mat-icon class=\"!cqa-w-5 !cqa-h-5 !cqa-text-[20px]\">close</mat-icon>\n </button>\n </div>\n <div class=\"cqa-border cqa-border-solid cqa-border-[#E5E5E5]\"> </div>\n\n <!-- Content: Attributes + dynamic fields from config -->\n <div class=\"cqa-flex-1 cqa-overflow-y-auto cqa-bg-white cqa-px-4 cqa-py-4\">\n <ng-container *ngIf=\"stepType\">\n <p class=\"cqa-text-[12px] cqa-font-medium cqa-text-[#6B7280] cqa-mb-3 cqa-mt-0\">Attributes</p>\n\n <div class=\"cqa-flex cqa-flex-col cqa-gap-4\">\n <ng-container *ngFor=\"let key of visibleFields\">\n <!-- Section heading: Constraints (first constraints field only) -->\n <ng-container *ngIf=\"key !== 'advanced' && isFirstInSection(key, 'constraints')\">\n <p class=\"cqa-text-[12px] cqa-font-medium cqa-text-[#6B7280] cqa-mb-2 cqa-mt-0\">Constraints</p>\n </ng-container>\n\n <!-- Advanced: expandable section with config-driven toggles + subfields -->\n <ng-container *ngIf=\"key === 'advanced'\">\n <button type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-between cqa-w-full cqa-text-left cqa-text-[12px] cqa-font-medium cqa-text-[#111827] cqa-py-2 cqa-border-b cqa-border-[#E5E7EB]\"\n (click)=\"advancedExpanded = !advancedExpanded\">\n <span>Advanced</span>\n <mat-icon class=\"cqa-text-[20px] cqa-transition-transform\" [class.cqa-rotate-180]=\"!advancedExpanded\">\n expand_less\n </mat-icon>\n </button>\n <div *ngIf=\"advancedExpanded\" class=\"cqa-flex cqa-flex-col cqa-gap-3 cqa-pt-2\">\n <!-- Advanced toggles from config -->\n <ng-container *ngFor=\"let toggleKey of advancedToggleKeys\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" *ngIf=\"fieldMeta[toggleKey]\">\n <cqa-custom-toggle\n [checked]=\"form.get(toggleKey)?.value\"\n (checkedChange)=\"form.get(toggleKey)?.setValue($event)\">\n </cqa-custom-toggle>\n <div class=\"cqa-flex cqa-flex-col\">\n <span class=\"cqa-text-[12px] cqa-font-medium cqa-text-[#737373]\">{{ fieldMeta[toggleKey].label }}</span>\n <span class=\"cqa-text-[12px] cqa-text-[#0A0A0A]\" *ngIf=\"fieldMeta[toggleKey].subLabel\">{{ fieldMeta[toggleKey].subLabel }}</span>\n </div>\n </div>\n </ng-container>\n <!-- Advanced subfields (e.g. Retry Count, Iframe locator, Other Locators for aiAgent) -->\n <ng-container *ngFor=\"let subKey of advancedSubfields\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-1.5 cqa-step-details-drawer-select\" *ngIf=\"fieldMeta[subKey]?.controlType === 'dropdown' && getSelectConfig(subKey) && form.contains(subKey)\">\n <label class=\"cqa-text-[12px] cqa-font-medium cqa-text-[#374151]\">{{ fieldMeta[subKey].label }}</label>\n <cqa-dynamic-select [form]=\"form\" [config]=\"getSelectConfig(subKey)!\">\n </cqa-dynamic-select>\n </div>\n </ng-container>\n </div>\n </ng-container>\n\n <!-- Skip: advanced key (already rendered) and fields that are rendered inside advanced for this step type -->\n <ng-container *ngIf=\"key !== 'advanced' && !(stepType === 'aiAgent' && advancedSubfields.includes(key))\">\n <!-- text -->\n <div *ngIf=\"fieldMeta[key]?.controlType === 'text'\" class=\"cqa-flex cqa-flex-col cqa-gap-1.5\">\n <label class=\"cqa-text-[12px] cqa-font-medium cqa-text-[#374151]\">{{ fieldMeta[key].label }}</label>\n <cqa-custom-input\n [placeholder]=\"fieldMeta[key].placeholder || ''\"\n [value]=\"form.get(key)?.value\"\n [fullWidth]=\"true\"\n (valueChange)=\"form.get(key)?.setValue($event)\">\n </cqa-custom-input>\n </div>\n\n <!-- textarea (including agentTask with optional required + tip) -->\n <div *ngIf=\"fieldMeta[key]?.controlType === 'textarea'\" class=\"cqa-flex cqa-flex-col cqa-gap-1.5\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <label class=\"cqa-text-[12px] cqa-font-medium cqa-text-[#374151]\">{{ fieldMeta[key].label }}</label>\n <span *ngIf=\"fieldMeta[key].required\" class=\"cqa-px-2 cqa-py-0.5 cqa-rounded-full cqa-bg-[#FEE2E2] cqa-text-[#DC2626] cqa-text-[10px] cqa-font-medium\">Required</span>\n </div>\n <p *ngIf=\"key === 'agentTask'\" class=\"cqa-text-[12px] cqa-text-[#6B7280] cqa-m-0\">What should the agent achieve?</p>\n <cqa-custom-textarea\n [placeholder]=\"fieldMeta[key].placeholder || ''\"\n [value]=\"form.get(key)?.value\"\n [fullWidth]=\"true\"\n [rows]=\"fieldMeta[key].rows || 4\"\n customClass=\"cqa-p-2 cqa-text-[14px] cqa-leading-[20px]\"\n (valueChange)=\"form.get(key)?.setValue($event)\">\n </cqa-custom-textarea>\n <p *ngIf=\"fieldMeta[key].tip\" class=\"cqa-text-[12px] cqa-text-[#6B7280] cqa-m-0\">{{ fieldMeta[key].tip }}</p>\n </div>\n\n <!-- code -->\n <div *ngIf=\"fieldMeta[key]?.controlType === 'code'\" class=\"cqa-flex cqa-flex-col cqa-gap-1.5\">\n <label class=\"cqa-text-[12px] cqa-font-medium cqa-text-[#374151]\">{{ fieldMeta[key].label }}</label>\n <cqa-custom-textarea\n [placeholder]=\"fieldMeta[key].placeholder || ''\"\n [value]=\"form.get(key)?.value\"\n [fullWidth]=\"true\"\n [rows]=\"8\"\n resize=\"vertical\"\n customClass=\"cqa-p-2 cqa-text-[14px] cqa-leading-[20px]\"\n (valueChange)=\"form.get(key)?.setValue($event)\">\n </cqa-custom-textarea>\n </div>\n\n <!-- dropdown (main + constraints; advanced-only dropdowns rendered inside Advanced section) -->\n <div *ngIf=\"fieldMeta[key]?.controlType === 'dropdown' && form.contains(key) && getSelectConfig(key) && !advancedSubfields.includes(key)\"\n class=\"cqa-flex cqa-flex-col cqa-gap-1.5 cqa-step-details-drawer-select\">\n <label class=\"cqa-text-[12px] cqa-font-medium cqa-text-[#374151]\">{{ fieldMeta[key].label }}</label>\n <cqa-dynamic-select [form]=\"form\" [config]=\"getSelectConfig(key)!\">\n </cqa-dynamic-select>\n </div>\n\n <!-- toggle (e.g. onlyUseAttachedContext, takeScreenshotsWhenVerifying) -->\n <div *ngIf=\"fieldMeta[key]?.controlType === 'toggle'\" class=\"cqa-flex cqa-items-center cqa-justify-between cqa-gap-2\">\n <div>\n <p class=\"cqa-text-[12px] cqa-text-[#111827] cqa-m-0\">{{ fieldMeta[key].label }}</p>\n <span *ngIf=\"fieldMeta[key].subLabel\" class=\"cqa-text-[12px] cqa-font-medium cqa-text-[#374151]\">{{ fieldMeta[key].subLabel }}</span>\n </div>\n <cqa-custom-toggle\n [checked]=\"form.get(key)?.value\"\n (checkedChange)=\"form.get(key)?.setValue($event)\">\n </cqa-custom-toggle>\n </div>\n </ng-container>\n </ng-container>\n </div>\n </ng-container>\n\n <p *ngIf=\"!stepType\" class=\"cqa-text-[14px] cqa-text-[#6B7280]\">This step type is not supported in the drawer.</p>\n </div>\n<div class=\"cqa-border cqa-border-solid cqa-border-[#E5E5E5]\"> </div>\n <!-- Footer -->\n <div class=\"cqa-flex cqa-items-center cqa-justify-start cqa-gap-2 cqa-px-4 cqa-py-4 cqa-border-t cqa-border-[#E5E7EB] cqa-bg-[#F5F5F54D]\">\n <cqa-button variant=\"text\" btnSize=\"lg\" [text]=\"'Cancel'\" (clicked)=\"onCancel()\"\n [customClass]=\"'cqa-text-[14px] cqa-py-[9px] cqa-text-[#374151]'\"></cqa-button>\n <div class=\"cqa-flex-1 cqa-min-w-0\"></div>\n <cqa-button variant=\"outlined\" btnSize=\"lg\" [text]=\"'Save as Template'\" (clicked)=\"onSaveAsTemplate()\"\n [customClass]=\"'cqa-text-[14px] cqa-py-[9px] cqa-border-[#414146]'\"></cqa-button>\n <cqa-button variant=\"filled\" btnSize=\"lg\" [text]=\"'Save Changes'\" (clicked)=\"onSaveChanges()\"\n [customClass]=\"'cqa-text-[14px] cqa-py-[9px] cqa-bg-[#3F43EE] cqa-border-[#3F43EE]'\"></cqa-button>\n </div>\n</div>\n", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { type: CustomToggleComponent, selector: "cqa-custom-toggle", inputs: ["checked", "disabled", "ariaLabel"], outputs: ["checkedChange", "change"] }, { type: DynamicSelectFieldComponent, selector: "cqa-dynamic-select", inputs: ["form", "config"], outputs: ["selectionChange", "selectClick", "searchChange", "loadMore"] }, { type: CustomInputComponent, selector: "cqa-custom-input", inputs: ["label", "type", "placeholder", "value", "disabled", "errors", "required", "ariaLabel", "size", "fullWidth", "maxLength", "showCharCount", "inputInlineStyle", "labelInlineStyle"], outputs: ["valueChange", "blurred", "focused", "enterPressed"] }, { type: CustomTextareaComponent, selector: "cqa-custom-textarea", inputs: ["label", "placeholder", "value", "disabled", "errors", "required", "ariaLabel", "size", "fullWidth", "maxLength", "showCharCount", "rows", "cols", "resize", "textareaInlineStyle", "labelInlineStyle", "customClass"], outputs: ["valueChange", "blurred", "focused"] }, { type: ButtonComponent, selector: "cqa-button", inputs: ["variant", "btnSize", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass", "inlineStyles", "tooltip", "tooltipPosition"], outputs: ["clicked"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
22574
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StepDetailsDrawerComponent, decorators: [{
|
|
22575
|
+
type: Component,
|
|
22576
|
+
args: [{ selector: 'cqa-step-details-drawer', host: { class: 'cqa-ui-root' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Step Details Drawer \u2013 Edit In Depth. No Priority. Fully config-driven. -->\n<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-w-full cqa-max-w-[480px] cqa-box-border\">\n <!-- Header: back chevron, dynamic title, Step N pill, close -->\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-gap-3 cqa-px-4 cqa-py-4 cqa-bg-white cqa-rounded-t-[12px] cqa-border cqa-border-[#E5E5E5]\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <button type=\"button\" (click)=\"onBack()\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-8 cqa-h-8 cqa-rounded cqa-text-[#6B7280] hover:cqa-bg-[#F3F4F6] cqa-p-0\"\n aria-label=\"Back\">\n <mat-icon class=\"!cqa-w-5 !cqa-h-5 !cqa-text-[20px]\">chevron_left</mat-icon>\n </button>\n <h2 class=\"cqa-text-[16px] cqa-leading-[24px] cqa-font-semibold cqa-text-[#111827] cqa-m-0 cqa-flex-1\">\n {{ drawerTitle }}\n </h2>\n <span class=\"cqa-px-2.5 cqa-py-1 cqa-rounded-lg cqa-bg-[#EDE9FE] cqa-text-[#7C3AED] cqa-text-[12px] cqa-font-medium\">\n Step {{ stepNumber }}\n </span>\n </div>\n <button type=\"button\" (click)=\"onClose()\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-min-h-[28px] cqa-min-w-[28px] cqa-rounded cqa-text-[#6B7280] hover:cqa-bg-[#F3F4F6] cqa-p-0\"\n title=\"Close\" aria-label=\"Close\">\n <mat-icon class=\"!cqa-w-5 !cqa-h-5 !cqa-text-[20px]\">close</mat-icon>\n </button>\n </div>\n <div class=\"cqa-border cqa-border-solid cqa-border-[#E5E5E5]\"> </div>\n\n <!-- Content: Attributes + dynamic fields from config -->\n <div class=\"cqa-flex-1 cqa-overflow-y-auto cqa-bg-white cqa-px-4 cqa-py-4\">\n <ng-container *ngIf=\"stepType\">\n <p class=\"cqa-text-[12px] cqa-font-medium cqa-text-[#6B7280] cqa-mb-3 cqa-mt-0\">Attributes</p>\n\n <div class=\"cqa-flex cqa-flex-col cqa-gap-4\">\n <ng-container *ngFor=\"let key of visibleFields\">\n <!-- Section heading: Constraints (first constraints field only) -->\n <ng-container *ngIf=\"key !== 'advanced' && isFirstInSection(key, 'constraints')\">\n <p class=\"cqa-text-[12px] cqa-font-medium cqa-text-[#6B7280] cqa-mb-2 cqa-mt-0\">Constraints</p>\n </ng-container>\n\n <!-- Advanced: expandable section with config-driven toggles + subfields -->\n <ng-container *ngIf=\"key === 'advanced'\">\n <button type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-between cqa-w-full cqa-text-left cqa-text-[12px] cqa-font-medium cqa-text-[#111827] cqa-py-2 cqa-border-b cqa-border-[#E5E7EB]\"\n (click)=\"advancedExpanded = !advancedExpanded\">\n <span>Advanced</span>\n <mat-icon class=\"cqa-text-[20px] cqa-transition-transform\" [class.cqa-rotate-180]=\"!advancedExpanded\">\n expand_less\n </mat-icon>\n </button>\n <div *ngIf=\"advancedExpanded\" class=\"cqa-flex cqa-flex-col cqa-gap-3 cqa-pt-2\">\n <!-- Advanced toggles from config -->\n <ng-container *ngFor=\"let toggleKey of advancedToggleKeys\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" *ngIf=\"fieldMeta[toggleKey]\">\n <cqa-custom-toggle\n [checked]=\"form.get(toggleKey)?.value\"\n (checkedChange)=\"form.get(toggleKey)?.setValue($event)\">\n </cqa-custom-toggle>\n <div class=\"cqa-flex cqa-flex-col\">\n <span class=\"cqa-text-[12px] cqa-font-medium cqa-text-[#737373]\">{{ fieldMeta[toggleKey].label }}</span>\n <span class=\"cqa-text-[12px] cqa-text-[#0A0A0A]\" *ngIf=\"fieldMeta[toggleKey].subLabel\">{{ fieldMeta[toggleKey].subLabel }}</span>\n </div>\n </div>\n </ng-container>\n <!-- Advanced subfields (e.g. Retry Count, Iframe locator, Other Locators for aiAgent) -->\n <ng-container *ngFor=\"let subKey of advancedSubfields\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-1.5 cqa-step-details-drawer-select\" *ngIf=\"fieldMeta[subKey]?.controlType === 'dropdown' && getSelectConfig(subKey) && form.contains(subKey)\">\n <label class=\"cqa-text-[12px] cqa-font-medium cqa-text-[#374151]\">{{ fieldMeta[subKey].label }}</label>\n <cqa-dynamic-select [form]=\"form\" [config]=\"getSelectConfig(subKey)!\">\n </cqa-dynamic-select>\n </div>\n </ng-container>\n </div>\n </ng-container>\n\n <!-- Skip: advanced key (already rendered) and fields that are rendered inside advanced for this step type -->\n <ng-container *ngIf=\"key !== 'advanced' && !(stepType === 'aiAgent' && advancedSubfields.includes(key))\">\n <!-- text -->\n <div *ngIf=\"fieldMeta[key]?.controlType === 'text'\" class=\"cqa-flex cqa-flex-col cqa-gap-1.5\">\n <label class=\"cqa-text-[12px] cqa-font-medium cqa-text-[#374151]\">{{ fieldMeta[key].label }}</label>\n <cqa-custom-input\n [placeholder]=\"fieldMeta[key].placeholder || ''\"\n [value]=\"form.get(key)?.value\"\n [fullWidth]=\"true\"\n (valueChange)=\"form.get(key)?.setValue($event)\">\n </cqa-custom-input>\n </div>\n\n <!-- textarea (including agentTask with optional required + tip) -->\n <div *ngIf=\"fieldMeta[key]?.controlType === 'textarea'\" class=\"cqa-flex cqa-flex-col cqa-gap-1.5\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <label class=\"cqa-text-[12px] cqa-font-medium cqa-text-[#374151]\">{{ fieldMeta[key].label }}</label>\n <span *ngIf=\"fieldMeta[key].required\" class=\"cqa-px-2 cqa-py-0.5 cqa-rounded-full cqa-bg-[#FEE2E2] cqa-text-[#DC2626] cqa-text-[10px] cqa-font-medium\">Required</span>\n </div>\n <p *ngIf=\"key === 'agentTask'\" class=\"cqa-text-[12px] cqa-text-[#6B7280] cqa-m-0\">What should the agent achieve?</p>\n <cqa-custom-textarea\n [placeholder]=\"fieldMeta[key].placeholder || ''\"\n [value]=\"form.get(key)?.value\"\n [fullWidth]=\"true\"\n [rows]=\"fieldMeta[key].rows || 4\"\n customClass=\"cqa-p-2 cqa-text-[14px] cqa-leading-[20px]\"\n (valueChange)=\"form.get(key)?.setValue($event)\">\n </cqa-custom-textarea>\n <p *ngIf=\"fieldMeta[key].tip\" class=\"cqa-text-[12px] cqa-text-[#6B7280] cqa-m-0\">{{ fieldMeta[key].tip }}</p>\n </div>\n\n <!-- code -->\n <div *ngIf=\"fieldMeta[key]?.controlType === 'code'\" class=\"cqa-flex cqa-flex-col cqa-gap-1.5\">\n <label class=\"cqa-text-[12px] cqa-font-medium cqa-text-[#374151]\">{{ fieldMeta[key].label }}</label>\n <cqa-custom-textarea\n [placeholder]=\"fieldMeta[key].placeholder || ''\"\n [value]=\"form.get(key)?.value\"\n [fullWidth]=\"true\"\n [rows]=\"8\"\n resize=\"vertical\"\n customClass=\"cqa-p-2 cqa-text-[14px] cqa-leading-[20px]\"\n (valueChange)=\"form.get(key)?.setValue($event)\">\n </cqa-custom-textarea>\n </div>\n\n <!-- dropdown (main + constraints; advanced-only dropdowns rendered inside Advanced section) -->\n <div *ngIf=\"fieldMeta[key]?.controlType === 'dropdown' && form.contains(key) && getSelectConfig(key) && !advancedSubfields.includes(key)\"\n class=\"cqa-flex cqa-flex-col cqa-gap-1.5 cqa-step-details-drawer-select\">\n <label class=\"cqa-text-[12px] cqa-font-medium cqa-text-[#374151]\">{{ fieldMeta[key].label }}</label>\n <cqa-dynamic-select [form]=\"form\" [config]=\"getSelectConfig(key)!\">\n </cqa-dynamic-select>\n </div>\n\n <!-- toggle (e.g. onlyUseAttachedContext, takeScreenshotsWhenVerifying) -->\n <div *ngIf=\"fieldMeta[key]?.controlType === 'toggle'\" class=\"cqa-flex cqa-items-center cqa-justify-between cqa-gap-2\">\n <div>\n <p class=\"cqa-text-[12px] cqa-text-[#111827] cqa-m-0\">{{ fieldMeta[key].label }}</p>\n <span *ngIf=\"fieldMeta[key].subLabel\" class=\"cqa-text-[12px] cqa-font-medium cqa-text-[#374151]\">{{ fieldMeta[key].subLabel }}</span>\n </div>\n <cqa-custom-toggle\n [checked]=\"form.get(key)?.value\"\n (checkedChange)=\"form.get(key)?.setValue($event)\">\n </cqa-custom-toggle>\n </div>\n </ng-container>\n </ng-container>\n </div>\n </ng-container>\n\n <p *ngIf=\"!stepType\" class=\"cqa-text-[14px] cqa-text-[#6B7280]\">This step type is not supported in the drawer.</p>\n </div>\n<div class=\"cqa-border cqa-border-solid cqa-border-[#E5E5E5]\"> </div>\n <!-- Footer -->\n <div class=\"cqa-flex cqa-items-center cqa-justify-start cqa-gap-2 cqa-px-4 cqa-py-4 cqa-border-t cqa-border-[#E5E7EB] cqa-bg-[#F5F5F54D]\">\n <cqa-button variant=\"text\" btnSize=\"lg\" [text]=\"'Cancel'\" (clicked)=\"onCancel()\"\n [customClass]=\"'cqa-text-[14px] cqa-py-[9px] cqa-text-[#374151]'\"></cqa-button>\n <div class=\"cqa-flex-1 cqa-min-w-0\"></div>\n <cqa-button variant=\"outlined\" btnSize=\"lg\" [text]=\"'Save as Template'\" (clicked)=\"onSaveAsTemplate()\"\n [customClass]=\"'cqa-text-[14px] cqa-py-[9px] cqa-border-[#414146]'\"></cqa-button>\n <cqa-button variant=\"filled\" btnSize=\"lg\" [text]=\"'Save Changes'\" (clicked)=\"onSaveChanges()\"\n [customClass]=\"'cqa-text-[14px] cqa-py-[9px] cqa-bg-[#3F43EE] cqa-border-[#3F43EE]'\"></cqa-button>\n </div>\n</div>\n" }]
|
|
22577
|
+
}], ctorParameters: function () {
|
|
22578
|
+
return [{ type: StepDetailsDrawerRef, decorators: [{
|
|
22579
|
+
type: Inject,
|
|
22580
|
+
args: [STEP_DETAILS_DRAWER_REF]
|
|
22581
|
+
}] }, { type: i2$1.FormBuilder }, { type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{
|
|
22582
|
+
type: Optional
|
|
22583
|
+
}, {
|
|
22584
|
+
type: Inject,
|
|
22585
|
+
args: [STEP_DETAILS_DRAWER_DATA]
|
|
22586
|
+
}] }];
|
|
22587
|
+
}, propDecorators: { saveChanges: [{
|
|
22588
|
+
type: Output
|
|
22589
|
+
}], cancel: [{
|
|
22590
|
+
type: Output
|
|
22591
|
+
}], saveAsTemplate: [{
|
|
22592
|
+
type: Output
|
|
22593
|
+
}], stepData: [{
|
|
22594
|
+
type: Input
|
|
22595
|
+
}], stepNumberInput: [{
|
|
22596
|
+
type: Input
|
|
22597
|
+
}] } });
|
|
22598
|
+
|
|
22071
22599
|
class UiKitModule {
|
|
22072
22600
|
constructor(iconRegistry) {
|
|
22073
22601
|
iconRegistry.registerFontClassAlias('material-symbols-outlined', 'material-symbols-outlined');
|
|
@@ -22180,7 +22708,8 @@ UiKitModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "1
|
|
|
22180
22708
|
StepBuilderDocumentGenerationTemplateStepComponent,
|
|
22181
22709
|
ElementListComponent,
|
|
22182
22710
|
StepBuilderDocumentComponent,
|
|
22183
|
-
StepBuilderApiComponent
|
|
22711
|
+
StepBuilderApiComponent,
|
|
22712
|
+
StepDetailsDrawerComponent], imports: [CommonModule,
|
|
22184
22713
|
FormsModule,
|
|
22185
22714
|
ReactiveFormsModule,
|
|
22186
22715
|
MatIconModule,
|
|
@@ -22304,7 +22833,8 @@ UiKitModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "1
|
|
|
22304
22833
|
StepBuilderDocumentGenerationTemplateStepComponent,
|
|
22305
22834
|
StepBuilderApiComponent,
|
|
22306
22835
|
ElementListComponent,
|
|
22307
|
-
StepBuilderDocumentComponent
|
|
22836
|
+
StepBuilderDocumentComponent,
|
|
22837
|
+
StepDetailsDrawerComponent] });
|
|
22308
22838
|
UiKitModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: UiKitModule, providers: [
|
|
22309
22839
|
{ provide: OverlayContainer, useClass: TailwindOverlayContainer },
|
|
22310
22840
|
{
|
|
@@ -22478,6 +23008,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
|
|
|
22478
23008
|
ElementListComponent,
|
|
22479
23009
|
StepBuilderDocumentComponent,
|
|
22480
23010
|
StepBuilderApiComponent,
|
|
23011
|
+
StepDetailsDrawerComponent,
|
|
22481
23012
|
],
|
|
22482
23013
|
imports: [
|
|
22483
23014
|
CommonModule,
|
|
@@ -22608,6 +23139,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
|
|
|
22608
23139
|
StepBuilderApiComponent,
|
|
22609
23140
|
ElementListComponent,
|
|
22610
23141
|
StepBuilderDocumentComponent,
|
|
23142
|
+
StepDetailsDrawerComponent,
|
|
22611
23143
|
],
|
|
22612
23144
|
providers: [
|
|
22613
23145
|
{ provide: OverlayContainer, useClass: TailwindOverlayContainer },
|
|
@@ -22784,9 +23316,66 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
|
|
|
22784
23316
|
}]
|
|
22785
23317
|
}], ctorParameters: function () { return [{ type: i1$6.Overlay }, { type: i0.Injector }]; } });
|
|
22786
23318
|
|
|
23319
|
+
/**
|
|
23320
|
+
* Opens the Step Details Drawer (Edit In Depth) from the right.
|
|
23321
|
+
*/
|
|
23322
|
+
class StepDetailsDrawerService {
|
|
23323
|
+
constructor(overlay, injector) {
|
|
23324
|
+
this.overlay = overlay;
|
|
23325
|
+
this.injector = injector;
|
|
23326
|
+
this.currentRef = null;
|
|
23327
|
+
}
|
|
23328
|
+
open(data) {
|
|
23329
|
+
if (this.currentRef)
|
|
23330
|
+
return this.currentRef;
|
|
23331
|
+
const drawerWidth = 480;
|
|
23332
|
+
const positionStrategy = this.overlay
|
|
23333
|
+
.position()
|
|
23334
|
+
.global()
|
|
23335
|
+
.right('0')
|
|
23336
|
+
.top('0')
|
|
23337
|
+
.bottom('0')
|
|
23338
|
+
.width(`${drawerWidth}px`);
|
|
23339
|
+
const overlayRef = this.overlay.create(new OverlayConfig({
|
|
23340
|
+
hasBackdrop: true,
|
|
23341
|
+
backdropClass: 'cdk-overlay-transparent-backdrop',
|
|
23342
|
+
scrollStrategy: this.overlay.scrollStrategies.block(),
|
|
23343
|
+
positionStrategy,
|
|
23344
|
+
panelClass: ['cqa-step-details-drawer-panel', 'cqa-ui-root'],
|
|
23345
|
+
width: `${drawerWidth}px`,
|
|
23346
|
+
maxWidth: '100vw',
|
|
23347
|
+
height: '100%',
|
|
23348
|
+
}));
|
|
23349
|
+
const drawerRef = new StepDetailsDrawerRef(overlayRef);
|
|
23350
|
+
const injector = Injector.create({
|
|
23351
|
+
parent: this.injector,
|
|
23352
|
+
providers: [
|
|
23353
|
+
{ provide: STEP_DETAILS_DRAWER_REF, useValue: drawerRef },
|
|
23354
|
+
{ provide: STEP_DETAILS_DRAWER_DATA, useValue: data },
|
|
23355
|
+
],
|
|
23356
|
+
});
|
|
23357
|
+
const portal = new ComponentPortal(StepDetailsDrawerComponent, undefined, injector);
|
|
23358
|
+
overlayRef.attach(portal);
|
|
23359
|
+
this.currentRef = drawerRef;
|
|
23360
|
+
drawerRef.afterClosed().subscribe(() => { this.currentRef = null; });
|
|
23361
|
+
overlayRef.backdropClick().subscribe(() => drawerRef.close({ action: 'cancel' }));
|
|
23362
|
+
overlayRef
|
|
23363
|
+
.keydownEvents()
|
|
23364
|
+
.pipe(filter((e) => e.key === 'Escape' || e.key === 'Esc'))
|
|
23365
|
+
.subscribe(() => drawerRef.close({ action: 'cancel' }));
|
|
23366
|
+
return drawerRef;
|
|
23367
|
+
}
|
|
23368
|
+
}
|
|
23369
|
+
StepDetailsDrawerService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StepDetailsDrawerService, deps: [{ token: i1$6.Overlay }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
23370
|
+
StepDetailsDrawerService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StepDetailsDrawerService, providedIn: 'root' });
|
|
23371
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StepDetailsDrawerService, decorators: [{
|
|
23372
|
+
type: Injectable,
|
|
23373
|
+
args: [{ providedIn: 'root' }]
|
|
23374
|
+
}], ctorParameters: function () { return [{ type: i1$6.Overlay }, { type: i0.Injector }]; } });
|
|
23375
|
+
|
|
22787
23376
|
/**
|
|
22788
23377
|
* Generated bundle index. Do not edit.
|
|
22789
23378
|
*/
|
|
22790
23379
|
|
|
22791
|
-
export { AIActionStepComponent, AIAgentStepComponent, ActionMenuButtonComponent, AddPrerequisiteCasesSectionComponent, AiDebugAlertComponent, AiReasoningComponent, ApiStepComponent, BadgeComponent, BasicStepComponent, ButtonComponent, CUSTOM_EDIT_STEP_DATA, CUSTOM_EDIT_STEP_EDIT_IN_DEPTH, CUSTOM_EDIT_STEP_REF, CUSTOM_ELEMENT_POPUP_REF, ChartCardComponent, ColumnVisibilityComponent, CompareRunsComponent, ConditionStepComponent, ConfigurationCardComponent, ConsoleAlertComponent, CoverageModuleCardComponent, CreateStepGroupComponent, CustomEditStepComponent, CustomEditStepRef, CustomEditStepService, CustomInputComponent, CustomTextareaComponent, CustomToggleComponent, DEFAULT_METADATA_COLOR, DIALOG_DATA, DIALOG_REF, DashboardHeaderComponent, DaterangepickerComponent, DaterangepickerDirective, DbQueryExecutionItemComponent, DbVerificationStepComponent, DeleteStepsComponent, DialogComponent, DialogRef, DialogService, DocumentVerificationStepComponent, DropdownButtonComponent, DynamicCellContainerDirective, DynamicCellTemplateDirective, DynamicFilterComponent, DynamicHeaderTemplateDirective, DynamicSelectFieldComponent, DynamicTableComponent, ELEMENT_POPUP_DATA, ELEMENT_POPUP_EDIT_IN_DEPTH, EMPTY_STATE_IMAGES, EMPTY_STATE_PRESETS, ElementListComponent, ElementPopupComponent, ElementPopupRef, ElementPopupService, EmptyStateComponent, ErrorModalComponent, ExecutionResultModalComponent, FailedStepCardComponent, FailedStepComponent, FailedTestCasesCardComponent, FileDownloadStepComponent, FileUploadComponent, FullTableLoaderComponent, HeatErrorMapCellComponent, InsightCardComponent, ItemListComponent, IterationsLoopComponent, LiveConversationComponent, LiveExecutionStepComponent, LoopStepComponent, MainStepCollapseComponent, MetricsCardComponent, NetworkRequestComponent, OtherButtonComponent, PRIORITY_COLORS, PaginationComponent, ProgressIndicatorComponent, ProgressTextCardComponent, RESULT_COLORS, RunHistoryCardComponent, STATUS_COLORS, SearchBarComponent, SegmentControlComponent, SelectedFiltersComponent, SelfHealAnalysisComponent, SimulatorComponent, StepBuilderActionComponent, StepBuilderAiAgentComponent, StepBuilderApiComponent, StepBuilderConditionComponent, StepBuilderCustomCodeComponent, StepBuilderDatabaseComponent, StepBuilderDocumentComponent, StepBuilderDocumentGenerationTemplateStepComponent, StepBuilderLoopComponent, StepBuilderRecordStepComponent, StepGroupComponent, StepProgressCardComponent, StepRendererComponent, StepStatusCardComponent, StepTypes, TEST_DATA_MODAL_DATA, TEST_DATA_MODAL_EDIT_IN_DEPTH, TEST_DATA_MODAL_REF, TableActionToolbarComponent, TableDataLoaderComponent, TableTemplateComponent, TailwindOverlayContainer, TestCaseAiAgentStepComponent, TestCaseAiVerifyStepComponent, TestCaseApiStepComponent, TestCaseConditionStepComponent, TestCaseCustomCodeStepComponent, TestCaseDatabaseStepComponent, TestCaseDetailsRendererComponent, TestCaseLoopStepComponent, TestCaseNormalStepComponent, TestCaseRestoreSessionStepComponent, TestCaseScreenshotStepComponent, TestCaseScrollStepComponent, TestCaseStepGroupComponent, TestCaseUploadStepComponent, TestCaseVerifyUrlStepComponent, TestDataModalComponent, TestDataModalRef, TestDataModalService, TestDistributionCardComponent, UiKitModule, UpdatedFailedStepComponent, ViewMoreFailedStepButtonComponent, VisualComparisonComponent, VisualDifferenceModalComponent, getEmptyStatePreset, getMetadataColor, getMetadataValueStyle, isAiAgentStepConfig, isAiVerifyStepConfig, isApiStepConfig, isConditionStepConfig, isCustomCodeStepConfig, isDatabaseStepConfig, isLoopStepConfig, isNormalStepConfig, isRestoreSessionStepConfig, isScreenshotStepConfig, isScrollStepConfig, isStepGroupConfig, isUploadStepConfig, isVerifyUrlStepConfig };
|
|
23380
|
+
export { ADVANCED_SUBFIELDS_BY_TYPE, ADVANCED_TOGGLE_KEYS, AIActionStepComponent, AIAgentStepComponent, ActionMenuButtonComponent, AddPrerequisiteCasesSectionComponent, AiDebugAlertComponent, AiReasoningComponent, ApiStepComponent, BadgeComponent, BasicStepComponent, ButtonComponent, CUSTOM_EDIT_STEP_DATA, CUSTOM_EDIT_STEP_EDIT_IN_DEPTH, CUSTOM_EDIT_STEP_REF, CUSTOM_ELEMENT_POPUP_REF, ChartCardComponent, ColumnVisibilityComponent, CompareRunsComponent, ConditionStepComponent, ConfigurationCardComponent, ConsoleAlertComponent, CoverageModuleCardComponent, CreateStepGroupComponent, CustomEditStepComponent, CustomEditStepRef, CustomEditStepService, CustomInputComponent, CustomTextareaComponent, CustomToggleComponent, DEFAULT_METADATA_COLOR, DIALOG_DATA, DIALOG_REF, DashboardHeaderComponent, DaterangepickerComponent, DaterangepickerDirective, DbQueryExecutionItemComponent, DbVerificationStepComponent, DeleteStepsComponent, DialogComponent, DialogRef, DialogService, DocumentVerificationStepComponent, DropdownButtonComponent, DynamicCellContainerDirective, DynamicCellTemplateDirective, DynamicFilterComponent, DynamicHeaderTemplateDirective, DynamicSelectFieldComponent, DynamicTableComponent, ELEMENT_POPUP_DATA, ELEMENT_POPUP_EDIT_IN_DEPTH, EMPTY_STATE_IMAGES, EMPTY_STATE_PRESETS, ElementListComponent, ElementPopupComponent, ElementPopupRef, ElementPopupService, EmptyStateComponent, ErrorModalComponent, ExecutionResultModalComponent, FailedStepCardComponent, FailedStepComponent, FailedTestCasesCardComponent, FileDownloadStepComponent, FileUploadComponent, FullTableLoaderComponent, HeatErrorMapCellComponent, InsightCardComponent, ItemListComponent, IterationsLoopComponent, LiveConversationComponent, LiveExecutionStepComponent, LoopStepComponent, MainStepCollapseComponent, MetricsCardComponent, NetworkRequestComponent, OtherButtonComponent, PRIORITY_COLORS, PaginationComponent, ProgressIndicatorComponent, ProgressTextCardComponent, RESULT_COLORS, RunHistoryCardComponent, STATUS_COLORS, STEP_DETAILS_DRAWER_DATA, STEP_DETAILS_DRAWER_REF, STEP_DETAILS_FIELDS_BY_TYPE, STEP_DETAILS_FIELD_META, SearchBarComponent, SegmentControlComponent, SelectedFiltersComponent, SelfHealAnalysisComponent, SimulatorComponent, StepBuilderActionComponent, StepBuilderAiAgentComponent, StepBuilderApiComponent, StepBuilderConditionComponent, StepBuilderCustomCodeComponent, StepBuilderDatabaseComponent, StepBuilderDocumentComponent, StepBuilderDocumentGenerationTemplateStepComponent, StepBuilderLoopComponent, StepBuilderRecordStepComponent, StepDetailsDrawerComponent, StepDetailsDrawerRef, StepDetailsDrawerService, StepGroupComponent, StepProgressCardComponent, StepRendererComponent, StepStatusCardComponent, StepTypes, TEST_DATA_MODAL_DATA, TEST_DATA_MODAL_EDIT_IN_DEPTH, TEST_DATA_MODAL_REF, TableActionToolbarComponent, TableDataLoaderComponent, TableTemplateComponent, TailwindOverlayContainer, TestCaseAiAgentStepComponent, TestCaseAiVerifyStepComponent, TestCaseApiStepComponent, TestCaseConditionStepComponent, TestCaseCustomCodeStepComponent, TestCaseDatabaseStepComponent, TestCaseDetailsRendererComponent, TestCaseLoopStepComponent, TestCaseNormalStepComponent, TestCaseRestoreSessionStepComponent, TestCaseScreenshotStepComponent, TestCaseScrollStepComponent, TestCaseStepGroupComponent, TestCaseUploadStepComponent, TestCaseVerifyUrlStepComponent, TestDataModalComponent, TestDataModalRef, TestDataModalService, TestDistributionCardComponent, UiKitModule, UpdatedFailedStepComponent, ViewMoreFailedStepButtonComponent, VisualComparisonComponent, VisualDifferenceModalComponent, getEmptyStatePreset, getMetadataColor, getMetadataValueStyle, getStepDetailsStepType, isAiAgentStepConfig, isAiVerifyStepConfig, isApiStepConfig, isConditionStepConfig, isCustomCodeStepConfig, isDatabaseStepConfig, isLoopStepConfig, isNormalStepConfig, isRestoreSessionStepConfig, isScreenshotStepConfig, isScrollStepConfig, isStepGroupConfig, isUploadStepConfig, isVerifyUrlStepConfig };
|
|
22792
23381
|
//# sourceMappingURL=cqa-lib-cqa-ui.mjs.map
|