@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
|
@@ -1699,6 +1699,7 @@ class DynamicSelectFieldComponent {
|
|
|
1699
1699
|
throw new Error('cqa-dynamic-select: input "config.key" is required.');
|
|
1700
1700
|
}
|
|
1701
1701
|
this.applySelectedValueIfNeeded();
|
|
1702
|
+
this.syncDisabledState();
|
|
1702
1703
|
this.lastOptionsLength = (this.config?.options || []).length;
|
|
1703
1704
|
}
|
|
1704
1705
|
get displayPlaceholder() {
|
|
@@ -1709,6 +1710,9 @@ class DynamicSelectFieldComponent {
|
|
|
1709
1710
|
return this.hasExistingValue(controlValue) ? undefined : this.config?.placeholder;
|
|
1710
1711
|
}
|
|
1711
1712
|
ngOnChanges(changes) {
|
|
1713
|
+
if ('config' in changes || 'form' in changes) {
|
|
1714
|
+
this.syncDisabledState();
|
|
1715
|
+
}
|
|
1712
1716
|
if ('config' in changes) {
|
|
1713
1717
|
// When config changes (including toggling multiple), ensure control value shape matches
|
|
1714
1718
|
this.syncControlValueForMultipleMode();
|
|
@@ -1800,6 +1804,26 @@ class DynamicSelectFieldComponent {
|
|
|
1800
1804
|
}
|
|
1801
1805
|
return !!value;
|
|
1802
1806
|
}
|
|
1807
|
+
/**
|
|
1808
|
+
* Sync the form control's disabled state from config.
|
|
1809
|
+
* Use the FormControl API instead of [disabled] in the template to avoid Angular's
|
|
1810
|
+
* "changed after checked" / reactive forms disabled-attribute warning.
|
|
1811
|
+
*/
|
|
1812
|
+
syncDisabledState() {
|
|
1813
|
+
const key = this.config?.key;
|
|
1814
|
+
if (!key || !this.form)
|
|
1815
|
+
return;
|
|
1816
|
+
const control = this.form.get(key);
|
|
1817
|
+
if (!control)
|
|
1818
|
+
return;
|
|
1819
|
+
const shouldDisable = this.toBoolean(this.config?.disabled);
|
|
1820
|
+
if (shouldDisable) {
|
|
1821
|
+
control.disable({ emitEvent: false });
|
|
1822
|
+
}
|
|
1823
|
+
else {
|
|
1824
|
+
control.enable({ emitEvent: false });
|
|
1825
|
+
}
|
|
1826
|
+
}
|
|
1803
1827
|
syncControlValueForMultipleMode() {
|
|
1804
1828
|
const key = this.config?.key;
|
|
1805
1829
|
if (!key || !this.form)
|
|
@@ -2214,10 +2238,10 @@ class DynamicSelectFieldComponent {
|
|
|
2214
2238
|
}
|
|
2215
2239
|
}
|
|
2216
2240
|
DynamicSelectFieldComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DynamicSelectFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2217
|
-
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 });
|
|
2241
|
+
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 });
|
|
2218
2242
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DynamicSelectFieldComponent, decorators: [{
|
|
2219
2243
|
type: Component,
|
|
2220
|
-
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>" }]
|
|
2244
|
+
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>" }]
|
|
2221
2245
|
}], propDecorators: { form: [{
|
|
2222
2246
|
type: Input
|
|
2223
2247
|
}], config: [{
|
|
@@ -5801,7 +5825,8 @@ class TailwindOverlayContainer extends OverlayContainer {
|
|
|
5801
5825
|
pane.classList.contains('ctc-date-range-panel') ||
|
|
5802
5826
|
pane.classList.contains('visual-difference-dialog') ||
|
|
5803
5827
|
pane.classList.contains('cqa-custom-edit-step-panel') ||
|
|
5804
|
-
pane.classList.contains('cqa-test-data-modal-panel')
|
|
5828
|
+
pane.classList.contains('cqa-test-data-modal-panel') ||
|
|
5829
|
+
pane.classList.contains('cqa-step-details-drawer-panel');
|
|
5805
5830
|
// Also check for library components inside the pane
|
|
5806
5831
|
// These classes may be on child elements rather than the pane itself
|
|
5807
5832
|
const hasLibraryDialogInside = pane.querySelector('.cqa-dialog-panel') !== null;
|
|
@@ -5814,10 +5839,12 @@ class TailwindOverlayContainer extends OverlayContainer {
|
|
|
5814
5839
|
pane.querySelector('cqa-custom-edit-step') !== null;
|
|
5815
5840
|
const hasTestDataModalInside = pane.querySelector('.cqa-test-data-modal-panel') !== null ||
|
|
5816
5841
|
pane.querySelector('cqa-test-data-modal') !== null;
|
|
5842
|
+
const hasStepDetailsDrawerInside = pane.querySelector('.cqa-step-details-drawer-panel') !== null ||
|
|
5843
|
+
pane.querySelector('cqa-step-details-drawer') !== null;
|
|
5817
5844
|
const isLibraryOverlay = paneHasLibraryClass || hasLibraryDialogInside ||
|
|
5818
5845
|
hasLibrarySelectInside || hasLibraryDatePickerInside ||
|
|
5819
5846
|
hasVisualDifferenceDialogInside || hasCustomEditStepInside ||
|
|
5820
|
-
hasTestDataModalInside;
|
|
5847
|
+
hasTestDataModalInside || hasStepDetailsDrawerInside;
|
|
5821
5848
|
if (isLibraryOverlay) {
|
|
5822
5849
|
// This is a library overlay - add the class
|
|
5823
5850
|
pane.classList.add('cqa-ui-root');
|
|
@@ -21912,6 +21939,497 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
|
|
|
21912
21939
|
type: Output
|
|
21913
21940
|
}] } });
|
|
21914
21941
|
|
|
21942
|
+
/**
|
|
21943
|
+
* Configuration for Step Details Drawer (Edit In Depth).
|
|
21944
|
+
* Form is fully dynamic by Step Type – no hardcoded field lists.
|
|
21945
|
+
*/
|
|
21946
|
+
/**
|
|
21947
|
+
* Resolves drawer step type from a test case step config.
|
|
21948
|
+
*/
|
|
21949
|
+
function getStepDetailsStepType(step) {
|
|
21950
|
+
if (!step)
|
|
21951
|
+
return null;
|
|
21952
|
+
if (isApiStepConfig(step))
|
|
21953
|
+
return 'api';
|
|
21954
|
+
if (isAiAgentStepConfig(step))
|
|
21955
|
+
return 'aiAgent';
|
|
21956
|
+
if (isNormalStepConfig(step) && step.eventType === 'custom')
|
|
21957
|
+
return 'custom';
|
|
21958
|
+
return null;
|
|
21959
|
+
}
|
|
21960
|
+
/**
|
|
21961
|
+
* Fields shown per step type (configuration-based).
|
|
21962
|
+
* Custom: Description, Metadata, Retry Count (if configured), Advanced (if configured).
|
|
21963
|
+
* API: Method, URL, Headers, Body, Save Output as Variable, Advanced (if configured).
|
|
21964
|
+
* AI Agent: Agent Task, Type, Metadata, Environment, Description, Constraints (toggles + Max Retries), Advanced (toggles + Retry Count, Iframe locator, Other Locators).
|
|
21965
|
+
*/
|
|
21966
|
+
const STEP_DETAILS_FIELDS_BY_TYPE = {
|
|
21967
|
+
custom: ['description', 'metadata', 'retryCount', 'advanced'],
|
|
21968
|
+
api: ['method', 'url', 'headers', 'body', 'saveOutputAsVariable', 'advanced'],
|
|
21969
|
+
aiAgent: [
|
|
21970
|
+
'agentTask',
|
|
21971
|
+
'type',
|
|
21972
|
+
'metadata',
|
|
21973
|
+
'environment',
|
|
21974
|
+
'description',
|
|
21975
|
+
'onlyUseAttachedContext',
|
|
21976
|
+
'takeScreenshotsWhenVerifying',
|
|
21977
|
+
'maxRetries',
|
|
21978
|
+
'advanced',
|
|
21979
|
+
'retryCount',
|
|
21980
|
+
'iframeLocator',
|
|
21981
|
+
'otherLocators',
|
|
21982
|
+
],
|
|
21983
|
+
};
|
|
21984
|
+
const STEP_DETAILS_FIELD_META = {
|
|
21985
|
+
description: { key: 'description', label: 'Description', placeholder: 'Text Input', controlType: 'text', section: 'main' },
|
|
21986
|
+
metadata: { key: 'metadata', label: 'Metadata', placeholder: 'Text Input', controlType: 'text', section: 'main' },
|
|
21987
|
+
retryCount: {
|
|
21988
|
+
key: 'retryCount',
|
|
21989
|
+
label: 'Retry Count',
|
|
21990
|
+
placeholder: 'Dynamic search selector from library or manual',
|
|
21991
|
+
controlType: 'dropdown',
|
|
21992
|
+
section: 'advanced',
|
|
21993
|
+
options: [
|
|
21994
|
+
{ value: '0', label: '0' },
|
|
21995
|
+
{ value: '1', label: '1' },
|
|
21996
|
+
{ value: '2', label: '2' },
|
|
21997
|
+
{ value: '3', label: '3' },
|
|
21998
|
+
],
|
|
21999
|
+
},
|
|
22000
|
+
advanced: { key: 'advanced', label: 'Advanced', controlType: 'toggleGroup' },
|
|
22001
|
+
method: {
|
|
22002
|
+
key: 'method',
|
|
22003
|
+
label: 'Method',
|
|
22004
|
+
placeholder: 'Method',
|
|
22005
|
+
controlType: 'dropdown',
|
|
22006
|
+
section: 'main',
|
|
22007
|
+
options: [
|
|
22008
|
+
{ value: 'GET', label: 'GET' },
|
|
22009
|
+
{ value: 'POST', label: 'POST' },
|
|
22010
|
+
{ value: 'PUT', label: 'PUT' },
|
|
22011
|
+
{ value: 'DELETE', label: 'DELETE' },
|
|
22012
|
+
{ value: 'PATCH', label: 'PATCH' },
|
|
22013
|
+
],
|
|
22014
|
+
},
|
|
22015
|
+
url: { key: 'url', label: 'URL', placeholder: 'URL', controlType: 'text', section: 'main' },
|
|
22016
|
+
headers: { key: 'headers', label: 'Headers', controlType: 'text', section: 'main' },
|
|
22017
|
+
body: { key: 'body', label: 'Body', placeholder: 'Request body', controlType: 'code', section: 'main' },
|
|
22018
|
+
saveOutputAsVariable: {
|
|
22019
|
+
key: 'saveOutputAsVariable',
|
|
22020
|
+
label: 'Save Output as Variable',
|
|
22021
|
+
placeholder: 'Variable name',
|
|
22022
|
+
controlType: 'text',
|
|
22023
|
+
section: 'main',
|
|
22024
|
+
},
|
|
22025
|
+
agentTask: {
|
|
22026
|
+
key: 'agentTask',
|
|
22027
|
+
label: 'Agent Task',
|
|
22028
|
+
placeholder: 'What should the agent achieve?',
|
|
22029
|
+
controlType: 'textarea',
|
|
22030
|
+
section: 'main',
|
|
22031
|
+
required: true,
|
|
22032
|
+
rows: 4,
|
|
22033
|
+
tip: 'Tip: Use numbered steps or bullet points for complex tasks.',
|
|
22034
|
+
},
|
|
22035
|
+
type: {
|
|
22036
|
+
key: 'type',
|
|
22037
|
+
label: 'Type',
|
|
22038
|
+
placeholder: 'Type',
|
|
22039
|
+
controlType: 'dropdown',
|
|
22040
|
+
section: 'main',
|
|
22041
|
+
options: [
|
|
22042
|
+
{ value: 'default', label: 'Default' },
|
|
22043
|
+
{ value: 'browser', label: 'Browser' },
|
|
22044
|
+
],
|
|
22045
|
+
},
|
|
22046
|
+
environment: {
|
|
22047
|
+
key: 'environment',
|
|
22048
|
+
label: 'Environment',
|
|
22049
|
+
placeholder: 'Environment',
|
|
22050
|
+
controlType: 'dropdown',
|
|
22051
|
+
section: 'main',
|
|
22052
|
+
options: [
|
|
22053
|
+
{ value: 'default', label: 'Default' },
|
|
22054
|
+
{ value: 'staging', label: 'Staging' },
|
|
22055
|
+
{ value: 'prod', label: 'Production' },
|
|
22056
|
+
],
|
|
22057
|
+
},
|
|
22058
|
+
maxRetries: {
|
|
22059
|
+
key: 'maxRetries',
|
|
22060
|
+
label: 'Max Retries',
|
|
22061
|
+
placeholder: '3 retries (recommended)',
|
|
22062
|
+
controlType: 'dropdown',
|
|
22063
|
+
section: 'constraints',
|
|
22064
|
+
options: [
|
|
22065
|
+
{ value: '0', label: '0' },
|
|
22066
|
+
{ value: '1', label: '1' },
|
|
22067
|
+
{ value: '2', label: '2' },
|
|
22068
|
+
{ value: '3', label: '3 retries (recommended)' },
|
|
22069
|
+
],
|
|
22070
|
+
},
|
|
22071
|
+
onlyUseAttachedContext: {
|
|
22072
|
+
key: 'onlyUseAttachedContext',
|
|
22073
|
+
label: 'Use existing elements only',
|
|
22074
|
+
subLabel: 'Only use elements from the attached context',
|
|
22075
|
+
controlType: 'toggle',
|
|
22076
|
+
section: 'constraints',
|
|
22077
|
+
},
|
|
22078
|
+
takeScreenshotsWhenVerifying: {
|
|
22079
|
+
key: 'takeScreenshotsWhenVerifying',
|
|
22080
|
+
label: 'Capture evidence',
|
|
22081
|
+
subLabel: 'Take screenshots when verifying conditions',
|
|
22082
|
+
controlType: 'toggle',
|
|
22083
|
+
section: 'constraints',
|
|
22084
|
+
},
|
|
22085
|
+
iframeLocator: {
|
|
22086
|
+
key: 'iframeLocator',
|
|
22087
|
+
label: 'Iframe locator',
|
|
22088
|
+
placeholder: 'Dynamic search selector from library or manual',
|
|
22089
|
+
controlType: 'dropdown',
|
|
22090
|
+
section: 'advanced',
|
|
22091
|
+
options: [
|
|
22092
|
+
{ value: 'manual', label: 'Dynamic search selector from library or manual' },
|
|
22093
|
+
],
|
|
22094
|
+
},
|
|
22095
|
+
otherLocators: {
|
|
22096
|
+
key: 'otherLocators',
|
|
22097
|
+
label: 'Other Locators',
|
|
22098
|
+
placeholder: 'Dynamic search selector from library or manual',
|
|
22099
|
+
controlType: 'dropdown',
|
|
22100
|
+
section: 'advanced',
|
|
22101
|
+
options: [
|
|
22102
|
+
{ value: 'manual', label: 'Dynamic search selector from library or manual' },
|
|
22103
|
+
],
|
|
22104
|
+
},
|
|
22105
|
+
continueOnError: {
|
|
22106
|
+
key: 'continueOnError',
|
|
22107
|
+
label: 'Continue on Error',
|
|
22108
|
+
subLabel: "Don't fail the test if this step fails.",
|
|
22109
|
+
controlType: 'toggle',
|
|
22110
|
+
section: 'advanced',
|
|
22111
|
+
},
|
|
22112
|
+
disabled: {
|
|
22113
|
+
key: 'disabled',
|
|
22114
|
+
label: 'Disabled',
|
|
22115
|
+
subLabel: 'Skip this step during execution.',
|
|
22116
|
+
controlType: 'toggle',
|
|
22117
|
+
section: 'advanced',
|
|
22118
|
+
},
|
|
22119
|
+
};
|
|
22120
|
+
/** Toggle fields always shown inside the Advanced section. */
|
|
22121
|
+
const ADVANCED_TOGGLE_KEYS = ['continueOnError', 'disabled'];
|
|
22122
|
+
/** Field keys shown inside Advanced (per step type), in addition to ADVANCED_TOGGLE_KEYS. */
|
|
22123
|
+
const ADVANCED_SUBFIELDS_BY_TYPE = {
|
|
22124
|
+
custom: [],
|
|
22125
|
+
api: [],
|
|
22126
|
+
aiAgent: ['retryCount', 'iframeLocator', 'otherLocators'],
|
|
22127
|
+
};
|
|
22128
|
+
|
|
22129
|
+
class StepDetailsDrawerRef {
|
|
22130
|
+
constructor(overlayRef) {
|
|
22131
|
+
this.overlayRef = overlayRef;
|
|
22132
|
+
this.closed$ = new Subject();
|
|
22133
|
+
this.isClosed = false;
|
|
22134
|
+
this.overlayRef.detachments().subscribe(() => this.finishClose(undefined));
|
|
22135
|
+
}
|
|
22136
|
+
close(result) {
|
|
22137
|
+
if (this.isClosed)
|
|
22138
|
+
return;
|
|
22139
|
+
this.finishClose(result);
|
|
22140
|
+
this.overlayRef.dispose();
|
|
22141
|
+
}
|
|
22142
|
+
afterClosed() {
|
|
22143
|
+
return this.closed$.asObservable();
|
|
22144
|
+
}
|
|
22145
|
+
finishClose(result) {
|
|
22146
|
+
if (this.isClosed)
|
|
22147
|
+
return;
|
|
22148
|
+
this.isClosed = true;
|
|
22149
|
+
this.closed$.next(result);
|
|
22150
|
+
this.closed$.complete();
|
|
22151
|
+
}
|
|
22152
|
+
}
|
|
22153
|
+
const STEP_DETAILS_DRAWER_REF = new InjectionToken('STEP_DETAILS_DRAWER_REF');
|
|
22154
|
+
|
|
22155
|
+
const STEP_DETAILS_DRAWER_DATA = new InjectionToken('STEP_DETAILS_DRAWER_DATA');
|
|
22156
|
+
|
|
22157
|
+
/**
|
|
22158
|
+
* Step Details Drawer (Edit In Depth).
|
|
22159
|
+
* Single reusable component; form is dynamic by Step Type via configuration.
|
|
22160
|
+
* No Priority section. Uses CQA components only.
|
|
22161
|
+
*/
|
|
22162
|
+
class StepDetailsDrawerComponent {
|
|
22163
|
+
constructor(ref, fb, cdr, data) {
|
|
22164
|
+
this.ref = ref;
|
|
22165
|
+
this.fb = fb;
|
|
22166
|
+
this.cdr = cdr;
|
|
22167
|
+
this.saveChanges = new EventEmitter();
|
|
22168
|
+
this.cancel = new EventEmitter();
|
|
22169
|
+
this.saveAsTemplate = new EventEmitter();
|
|
22170
|
+
/** Optional: when provided (e.g. from Storybook Controls), use instead of STEP_DETAILS_DRAWER_DATA. */
|
|
22171
|
+
this.stepData = null;
|
|
22172
|
+
this.stepNumberInput = null;
|
|
22173
|
+
this.stepType = null;
|
|
22174
|
+
this.visibleFields = [];
|
|
22175
|
+
this.fieldMeta = STEP_DETAILS_FIELD_META;
|
|
22176
|
+
this.advancedToggleKeys = ADVANCED_TOGGLE_KEYS;
|
|
22177
|
+
this.advancedExpanded = false;
|
|
22178
|
+
this.agentTaskExpanded = true;
|
|
22179
|
+
/** Cached select configs (stable references per key) to avoid infinite change detection in template. */
|
|
22180
|
+
this.selectConfigMap = this.buildSelectConfigMap();
|
|
22181
|
+
this.step = data?.step ?? {};
|
|
22182
|
+
this.stepNumber = data?.stepNumber ?? 1;
|
|
22183
|
+
this.form = this.fb.group({});
|
|
22184
|
+
this.syncStepTypeAndForm();
|
|
22185
|
+
}
|
|
22186
|
+
/** Subfields to show inside Advanced section for current step type. */
|
|
22187
|
+
get advancedSubfields() {
|
|
22188
|
+
return this.stepType ? ADVANCED_SUBFIELDS_BY_TYPE[this.stepType] : [];
|
|
22189
|
+
}
|
|
22190
|
+
ngOnInit() {
|
|
22191
|
+
if (this.stepData != null) {
|
|
22192
|
+
this.step = this.stepData;
|
|
22193
|
+
this.stepNumber = this.stepNumberInput ?? this.stepData.stepNumber ?? 1;
|
|
22194
|
+
this.syncStepTypeAndForm();
|
|
22195
|
+
this.cdr.markForCheck();
|
|
22196
|
+
}
|
|
22197
|
+
}
|
|
22198
|
+
ngOnChanges(changes) {
|
|
22199
|
+
if (changes['stepData'] || changes['stepNumberInput']) {
|
|
22200
|
+
if (this.stepData != null) {
|
|
22201
|
+
this.step = this.stepData;
|
|
22202
|
+
this.stepNumber = this.stepNumberInput ?? this.stepData.stepNumber ?? 1;
|
|
22203
|
+
}
|
|
22204
|
+
this.syncStepTypeAndForm();
|
|
22205
|
+
this.cdr.detectChanges();
|
|
22206
|
+
}
|
|
22207
|
+
}
|
|
22208
|
+
syncStepTypeAndForm() {
|
|
22209
|
+
this.stepType = getStepDetailsStepType(this.step);
|
|
22210
|
+
this.visibleFields = this.stepType ? STEP_DETAILS_FIELDS_BY_TYPE[this.stepType] : [];
|
|
22211
|
+
this.buildFormFromStep();
|
|
22212
|
+
}
|
|
22213
|
+
buildFormFromStep() {
|
|
22214
|
+
const group = {};
|
|
22215
|
+
for (const key of this.visibleFields) {
|
|
22216
|
+
if (key === 'advanced')
|
|
22217
|
+
continue;
|
|
22218
|
+
group[key] = [this.getStepValue(key)];
|
|
22219
|
+
}
|
|
22220
|
+
for (const key of ADVANCED_TOGGLE_KEYS) {
|
|
22221
|
+
if (!(key in group))
|
|
22222
|
+
group[key] = [this.getStepValue(key)];
|
|
22223
|
+
}
|
|
22224
|
+
this.form = this.fb.group(group);
|
|
22225
|
+
}
|
|
22226
|
+
getStepValue(key) {
|
|
22227
|
+
const step = this.step;
|
|
22228
|
+
if (isNormalStepConfig(this.step) && this.step.eventType === 'custom') {
|
|
22229
|
+
if (key === 'description') {
|
|
22230
|
+
const params = this.step.parameters;
|
|
22231
|
+
return params?.[0]?.value ?? this.step.description ?? '';
|
|
22232
|
+
}
|
|
22233
|
+
if (key === 'metadata') {
|
|
22234
|
+
const params = this.step.parameters;
|
|
22235
|
+
return params?.[1]?.value ?? '';
|
|
22236
|
+
}
|
|
22237
|
+
}
|
|
22238
|
+
if (isApiStepConfig(this.step)) {
|
|
22239
|
+
const api = this.step;
|
|
22240
|
+
if (key === 'method')
|
|
22241
|
+
return api.method ?? 'GET';
|
|
22242
|
+
if (key === 'url')
|
|
22243
|
+
return api.baseUrl ? `${api.baseUrl}${api.endpoint || ''}` : api.endpoint ?? '';
|
|
22244
|
+
if (key === 'headers')
|
|
22245
|
+
return api.headers ? JSON.stringify(api.headers, null, 2) : '';
|
|
22246
|
+
if (key === 'body')
|
|
22247
|
+
return api.requestBody ?? '';
|
|
22248
|
+
if (key === 'saveOutputAsVariable')
|
|
22249
|
+
return api.saveTo ?? '';
|
|
22250
|
+
}
|
|
22251
|
+
if (isAiAgentStepConfig(this.step)) {
|
|
22252
|
+
const ai = this.step;
|
|
22253
|
+
if (key === 'agentTask')
|
|
22254
|
+
return ai.instructions ?? '';
|
|
22255
|
+
if (key === 'description')
|
|
22256
|
+
return ai.description ?? '';
|
|
22257
|
+
if (key === 'metadata')
|
|
22258
|
+
return step.metadata ?? '';
|
|
22259
|
+
}
|
|
22260
|
+
if (key === 'onlyUseAttachedContext' ||
|
|
22261
|
+
key === 'takeScreenshotsWhenVerifying' ||
|
|
22262
|
+
key === 'continueOnError' ||
|
|
22263
|
+
key === 'disabled') {
|
|
22264
|
+
return step[key] === true;
|
|
22265
|
+
}
|
|
22266
|
+
return step[key] ?? '';
|
|
22267
|
+
}
|
|
22268
|
+
setStepValue(key, value) {
|
|
22269
|
+
const step = this.step;
|
|
22270
|
+
if (isNormalStepConfig(this.step) && this.step.eventType === 'custom') {
|
|
22271
|
+
if (key === 'description') {
|
|
22272
|
+
const params = this.step.parameters;
|
|
22273
|
+
if (params?.[0])
|
|
22274
|
+
params[0].value = String(value);
|
|
22275
|
+
else
|
|
22276
|
+
this.step.description = String(value);
|
|
22277
|
+
return;
|
|
22278
|
+
}
|
|
22279
|
+
if (key === 'metadata') {
|
|
22280
|
+
const params = this.step.parameters;
|
|
22281
|
+
if (params?.[1])
|
|
22282
|
+
params[1].value = String(value);
|
|
22283
|
+
return;
|
|
22284
|
+
}
|
|
22285
|
+
}
|
|
22286
|
+
if (isApiStepConfig(this.step)) {
|
|
22287
|
+
const api = this.step;
|
|
22288
|
+
if (key === 'method') {
|
|
22289
|
+
api.method = value;
|
|
22290
|
+
return;
|
|
22291
|
+
}
|
|
22292
|
+
if (key === 'url') {
|
|
22293
|
+
api.endpoint = String(value);
|
|
22294
|
+
return;
|
|
22295
|
+
}
|
|
22296
|
+
if (key === 'headers') {
|
|
22297
|
+
try {
|
|
22298
|
+
api.headers = JSON.parse(String(value) || '{}');
|
|
22299
|
+
}
|
|
22300
|
+
catch {
|
|
22301
|
+
api.headers = {};
|
|
22302
|
+
}
|
|
22303
|
+
return;
|
|
22304
|
+
}
|
|
22305
|
+
if (key === 'body') {
|
|
22306
|
+
api.requestBody = String(value);
|
|
22307
|
+
return;
|
|
22308
|
+
}
|
|
22309
|
+
if (key === 'saveOutputAsVariable') {
|
|
22310
|
+
api.saveTo = String(value);
|
|
22311
|
+
return;
|
|
22312
|
+
}
|
|
22313
|
+
}
|
|
22314
|
+
if (isAiAgentStepConfig(this.step)) {
|
|
22315
|
+
const ai = this.step;
|
|
22316
|
+
if (key === 'agentTask') {
|
|
22317
|
+
ai.instructions = String(value);
|
|
22318
|
+
return;
|
|
22319
|
+
}
|
|
22320
|
+
if (key === 'description') {
|
|
22321
|
+
ai.description = String(value);
|
|
22322
|
+
return;
|
|
22323
|
+
}
|
|
22324
|
+
if (key === 'metadata') {
|
|
22325
|
+
step.metadata = value;
|
|
22326
|
+
return;
|
|
22327
|
+
}
|
|
22328
|
+
}
|
|
22329
|
+
step[key] = value;
|
|
22330
|
+
}
|
|
22331
|
+
onBack() {
|
|
22332
|
+
this.cancel.emit();
|
|
22333
|
+
this.ref.close(undefined);
|
|
22334
|
+
}
|
|
22335
|
+
onClose() {
|
|
22336
|
+
this.cancel.emit();
|
|
22337
|
+
this.ref.close(undefined);
|
|
22338
|
+
}
|
|
22339
|
+
onCancel() {
|
|
22340
|
+
this.cancel.emit();
|
|
22341
|
+
this.ref.close(undefined);
|
|
22342
|
+
}
|
|
22343
|
+
onSaveAsTemplate() {
|
|
22344
|
+
this.applyFormToStep();
|
|
22345
|
+
this.saveAsTemplate.emit(this.step);
|
|
22346
|
+
this.ref.close({ action: 'saveAsTemplate', step: this.step });
|
|
22347
|
+
}
|
|
22348
|
+
onSaveChanges() {
|
|
22349
|
+
this.applyFormToStep();
|
|
22350
|
+
this.saveChanges.emit(this.step);
|
|
22351
|
+
this.ref.close({ action: 'saveChanges', step: this.step });
|
|
22352
|
+
}
|
|
22353
|
+
applyFormToStep() {
|
|
22354
|
+
for (const key of this.visibleFields) {
|
|
22355
|
+
if (key === 'advanced')
|
|
22356
|
+
continue;
|
|
22357
|
+
if (this.form.contains(key))
|
|
22358
|
+
this.setStepValue(key, this.form.get(key)?.value);
|
|
22359
|
+
}
|
|
22360
|
+
for (const key of ADVANCED_TOGGLE_KEYS) {
|
|
22361
|
+
if (this.form.contains(key))
|
|
22362
|
+
this.setStepValue(key, this.form.get(key)?.value);
|
|
22363
|
+
}
|
|
22364
|
+
}
|
|
22365
|
+
/** Build cached map of select configs from field meta (stable refs to prevent CD loops). */
|
|
22366
|
+
buildSelectConfigMap() {
|
|
22367
|
+
const map = {};
|
|
22368
|
+
const keys = Object.keys(STEP_DETAILS_FIELD_META);
|
|
22369
|
+
for (const key of keys) {
|
|
22370
|
+
const meta = STEP_DETAILS_FIELD_META[key];
|
|
22371
|
+
if (!meta || meta.controlType !== 'dropdown' || !meta.options?.length)
|
|
22372
|
+
continue;
|
|
22373
|
+
const options = meta.options.map((o) => ({ value: o.value, label: o.label }));
|
|
22374
|
+
map[key] = {
|
|
22375
|
+
key: meta.key,
|
|
22376
|
+
placeholder: meta.placeholder ?? meta.label,
|
|
22377
|
+
options,
|
|
22378
|
+
};
|
|
22379
|
+
}
|
|
22380
|
+
return map;
|
|
22381
|
+
}
|
|
22382
|
+
/** Return cached select config for key (for template use; same reference every time). */
|
|
22383
|
+
getSelectConfig(key) {
|
|
22384
|
+
return this.selectConfigMap[key] ?? null;
|
|
22385
|
+
}
|
|
22386
|
+
/** Whether this key is the first in its section (for showing section headings). */
|
|
22387
|
+
isFirstInSection(key, section) {
|
|
22388
|
+
const meta = STEP_DETAILS_FIELD_META[key];
|
|
22389
|
+
if (!meta || meta.section !== section)
|
|
22390
|
+
return false;
|
|
22391
|
+
const idx = this.visibleFields.indexOf(key);
|
|
22392
|
+
if (idx <= 0)
|
|
22393
|
+
return true;
|
|
22394
|
+
const prevMeta = STEP_DETAILS_FIELD_META[this.visibleFields[idx - 1]];
|
|
22395
|
+
return !prevMeta || prevMeta.section !== section;
|
|
22396
|
+
}
|
|
22397
|
+
/** Dynamic drawer title by step type (e.g. "AI Agent Step Details"). */
|
|
22398
|
+
get drawerTitle() {
|
|
22399
|
+
if (this.stepType === 'custom')
|
|
22400
|
+
return 'Custom Step Details';
|
|
22401
|
+
if (this.stepType === 'api')
|
|
22402
|
+
return 'API Step Details';
|
|
22403
|
+
if (this.stepType === 'aiAgent')
|
|
22404
|
+
return 'AI Agent Step Details';
|
|
22405
|
+
return 'Step Details';
|
|
22406
|
+
}
|
|
22407
|
+
}
|
|
22408
|
+
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 });
|
|
22409
|
+
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 });
|
|
22410
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StepDetailsDrawerComponent, decorators: [{
|
|
22411
|
+
type: Component,
|
|
22412
|
+
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" }]
|
|
22413
|
+
}], ctorParameters: function () { return [{ type: StepDetailsDrawerRef, decorators: [{
|
|
22414
|
+
type: Inject,
|
|
22415
|
+
args: [STEP_DETAILS_DRAWER_REF]
|
|
22416
|
+
}] }, { type: i2$1.FormBuilder }, { type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{
|
|
22417
|
+
type: Optional
|
|
22418
|
+
}, {
|
|
22419
|
+
type: Inject,
|
|
22420
|
+
args: [STEP_DETAILS_DRAWER_DATA]
|
|
22421
|
+
}] }]; }, propDecorators: { saveChanges: [{
|
|
22422
|
+
type: Output
|
|
22423
|
+
}], cancel: [{
|
|
22424
|
+
type: Output
|
|
22425
|
+
}], saveAsTemplate: [{
|
|
22426
|
+
type: Output
|
|
22427
|
+
}], stepData: [{
|
|
22428
|
+
type: Input
|
|
22429
|
+
}], stepNumberInput: [{
|
|
22430
|
+
type: Input
|
|
22431
|
+
}] } });
|
|
22432
|
+
|
|
21915
22433
|
class UiKitModule {
|
|
21916
22434
|
constructor(iconRegistry) {
|
|
21917
22435
|
iconRegistry.registerFontClassAlias('material-symbols-outlined', 'material-symbols-outlined');
|
|
@@ -22024,7 +22542,8 @@ UiKitModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "1
|
|
|
22024
22542
|
StepBuilderDocumentGenerationTemplateStepComponent,
|
|
22025
22543
|
ElementListComponent,
|
|
22026
22544
|
StepBuilderDocumentComponent,
|
|
22027
|
-
StepBuilderApiComponent
|
|
22545
|
+
StepBuilderApiComponent,
|
|
22546
|
+
StepDetailsDrawerComponent], imports: [CommonModule,
|
|
22028
22547
|
FormsModule,
|
|
22029
22548
|
ReactiveFormsModule,
|
|
22030
22549
|
MatIconModule,
|
|
@@ -22148,7 +22667,8 @@ UiKitModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "1
|
|
|
22148
22667
|
StepBuilderDocumentGenerationTemplateStepComponent,
|
|
22149
22668
|
StepBuilderApiComponent,
|
|
22150
22669
|
ElementListComponent,
|
|
22151
|
-
StepBuilderDocumentComponent
|
|
22670
|
+
StepBuilderDocumentComponent,
|
|
22671
|
+
StepDetailsDrawerComponent] });
|
|
22152
22672
|
UiKitModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: UiKitModule, providers: [
|
|
22153
22673
|
{ provide: OverlayContainer, useClass: TailwindOverlayContainer },
|
|
22154
22674
|
{
|
|
@@ -22322,6 +22842,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
|
|
|
22322
22842
|
ElementListComponent,
|
|
22323
22843
|
StepBuilderDocumentComponent,
|
|
22324
22844
|
StepBuilderApiComponent,
|
|
22845
|
+
StepDetailsDrawerComponent,
|
|
22325
22846
|
],
|
|
22326
22847
|
imports: [
|
|
22327
22848
|
CommonModule,
|
|
@@ -22452,6 +22973,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
|
|
|
22452
22973
|
StepBuilderApiComponent,
|
|
22453
22974
|
ElementListComponent,
|
|
22454
22975
|
StepBuilderDocumentComponent,
|
|
22976
|
+
StepDetailsDrawerComponent,
|
|
22455
22977
|
],
|
|
22456
22978
|
providers: [
|
|
22457
22979
|
{ provide: OverlayContainer, useClass: TailwindOverlayContainer },
|
|
@@ -22626,9 +23148,66 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
|
|
|
22626
23148
|
}]
|
|
22627
23149
|
}], ctorParameters: function () { return [{ type: i1$6.Overlay }, { type: i0.Injector }]; } });
|
|
22628
23150
|
|
|
23151
|
+
/**
|
|
23152
|
+
* Opens the Step Details Drawer (Edit In Depth) from the right.
|
|
23153
|
+
*/
|
|
23154
|
+
class StepDetailsDrawerService {
|
|
23155
|
+
constructor(overlay, injector) {
|
|
23156
|
+
this.overlay = overlay;
|
|
23157
|
+
this.injector = injector;
|
|
23158
|
+
this.currentRef = null;
|
|
23159
|
+
}
|
|
23160
|
+
open(data) {
|
|
23161
|
+
if (this.currentRef)
|
|
23162
|
+
return this.currentRef;
|
|
23163
|
+
const drawerWidth = 480;
|
|
23164
|
+
const positionStrategy = this.overlay
|
|
23165
|
+
.position()
|
|
23166
|
+
.global()
|
|
23167
|
+
.right('0')
|
|
23168
|
+
.top('0')
|
|
23169
|
+
.bottom('0')
|
|
23170
|
+
.width(`${drawerWidth}px`);
|
|
23171
|
+
const overlayRef = this.overlay.create(new OverlayConfig({
|
|
23172
|
+
hasBackdrop: true,
|
|
23173
|
+
backdropClass: 'cdk-overlay-transparent-backdrop',
|
|
23174
|
+
scrollStrategy: this.overlay.scrollStrategies.block(),
|
|
23175
|
+
positionStrategy,
|
|
23176
|
+
panelClass: ['cqa-step-details-drawer-panel', 'cqa-ui-root'],
|
|
23177
|
+
width: `${drawerWidth}px`,
|
|
23178
|
+
maxWidth: '100vw',
|
|
23179
|
+
height: '100%',
|
|
23180
|
+
}));
|
|
23181
|
+
const drawerRef = new StepDetailsDrawerRef(overlayRef);
|
|
23182
|
+
const injector = Injector.create({
|
|
23183
|
+
parent: this.injector,
|
|
23184
|
+
providers: [
|
|
23185
|
+
{ provide: STEP_DETAILS_DRAWER_REF, useValue: drawerRef },
|
|
23186
|
+
{ provide: STEP_DETAILS_DRAWER_DATA, useValue: data },
|
|
23187
|
+
],
|
|
23188
|
+
});
|
|
23189
|
+
const portal = new ComponentPortal(StepDetailsDrawerComponent, undefined, injector);
|
|
23190
|
+
overlayRef.attach(portal);
|
|
23191
|
+
this.currentRef = drawerRef;
|
|
23192
|
+
drawerRef.afterClosed().subscribe(() => { this.currentRef = null; });
|
|
23193
|
+
overlayRef.backdropClick().subscribe(() => drawerRef.close({ action: 'cancel' }));
|
|
23194
|
+
overlayRef
|
|
23195
|
+
.keydownEvents()
|
|
23196
|
+
.pipe(filter((e) => e.key === 'Escape' || e.key === 'Esc'))
|
|
23197
|
+
.subscribe(() => drawerRef.close({ action: 'cancel' }));
|
|
23198
|
+
return drawerRef;
|
|
23199
|
+
}
|
|
23200
|
+
}
|
|
23201
|
+
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 });
|
|
23202
|
+
StepDetailsDrawerService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StepDetailsDrawerService, providedIn: 'root' });
|
|
23203
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StepDetailsDrawerService, decorators: [{
|
|
23204
|
+
type: Injectable,
|
|
23205
|
+
args: [{ providedIn: 'root' }]
|
|
23206
|
+
}], ctorParameters: function () { return [{ type: i1$6.Overlay }, { type: i0.Injector }]; } });
|
|
23207
|
+
|
|
22629
23208
|
/**
|
|
22630
23209
|
* Generated bundle index. Do not edit.
|
|
22631
23210
|
*/
|
|
22632
23211
|
|
|
22633
|
-
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 };
|
|
23212
|
+
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 };
|
|
22634
23213
|
//# sourceMappingURL=cqa-lib-cqa-ui.mjs.map
|