@cqa-lib/cqa-ui 1.1.263 → 1.1.265
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/detail-side-panel/detail-side-panel.component.mjs +9 -127
- package/esm2020/lib/test-case-details/element-popup/element-form/element-form.component.mjs +15 -3
- package/fesm2015/cqa-lib-cqa-ui.mjs +571 -677
- package/fesm2015/cqa-lib-cqa-ui.mjs.map +1 -1
- package/fesm2020/cqa-lib-cqa-ui.mjs +571 -677
- package/fesm2020/cqa-lib-cqa-ui.mjs.map +1 -1
- package/lib/detail-side-panel/detail-side-panel.component.d.ts +4 -62
- package/lib/test-case-details/element-popup/element-form/element-form.component.d.ts +4 -0
- package/package.json +1 -1
- package/styles.css +1 -1
|
@@ -19420,12 +19420,23 @@ class ElementFormComponent {
|
|
|
19420
19420
|
this.addTag();
|
|
19421
19421
|
}
|
|
19422
19422
|
}
|
|
19423
|
+
/** Tags to render as chips (limited) */
|
|
19424
|
+
get visibleTags() {
|
|
19425
|
+
if (!this.formLabels || this.formLabels.length) {
|
|
19426
|
+
return this.formLabels || [];
|
|
19427
|
+
}
|
|
19428
|
+
return [];
|
|
19429
|
+
}
|
|
19430
|
+
/** Tooltip text showing all tags */
|
|
19431
|
+
get allTagsTooltip() {
|
|
19432
|
+
return (this.formLabels || []).join(', ');
|
|
19433
|
+
}
|
|
19423
19434
|
}
|
|
19424
19435
|
ElementFormComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: ElementFormComponent, deps: [{ token: i1$1.FormBuilder, optional: true }, { token: i0.ChangeDetectorRef, optional: true }], target: i0.ɵɵFactoryTarget.Component });
|
|
19425
|
-
ElementFormComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: ElementFormComponent, selector: "cqa-element-form", inputs: { elementId: "elementId", element: "element", screenNameOptions: "screenNameOptions", hasMoreScreenNames: "hasMoreScreenNames", isLoadingScreenNames: "isLoadingScreenNames", isElementLoading: "isElementLoading", isEditMode: "isEditMode", isCreateMode: "isCreateMode", isEditInDepthAvailable: "isEditInDepthAvailable" }, outputs: { createElement: "createElement", updateElement: "updateElement", createScreenNameRequest: "createScreenNameRequest", searchScreenName: "searchScreenName", loadMoreScreenNames: "loadMoreScreenNames", cancel: "cancel", editInDepth: "editInDepth" }, host: { classAttribute: "cqa-ui-root" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-flex cqa-flex-col cqa-gap-4 cqa-px-1 cqa-pt-3\">\n <div *ngIf=\"isElementLoading && isEditMode\" class=\"cqa-flex cqa-flex-col cqa-items-center cqa-justify-center cqa-gap-3 cqa-py-8\">\n <svg class=\"cqa-animate-spin cqa-h-6 cqa-w-6 cqa-text-[#3F43EE]\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"cqa-opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"cqa-opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n <span class=\"cqa-text-[#6B7280] cqa-text-sm\">Loading element data...</span>\n </div>\n <div *ngIf=\"!isElementLoading\" class=\"cqa-flex cqa-gap-1.5\">\n <cqa-custom-input \n class=\"cqa-w-1/2\" \n label=\"Name\" \n placeholder=\"default-element\"\n [value]=\"getFormControlValue('name')\"\n [errors]=\"getFormControl('name')?.touched && getFormControl('name')?.invalid ? ['Name is required'] : []\"\n [required]=\"true\"\n (valueChange)=\"onFormControlChange('name', $event)\">\n </cqa-custom-input>\n <div class=\"cqa-w-1/2\">\n <cqa-dynamic-select [form]=\"form\" [config]=\"screenNameSelectConfig\"\n (addCustomValue)=\"createScreenNameRequest.emit($event.value)\"\n class=\"cqa-w-full\">\n </cqa-dynamic-select>\n <div *ngIf=\"getFormControl('screenNameId')?.touched && getFormControl('screenNameId')?.invalid\" class=\"cqa-flex cqa-flex-col cqa-gap-1 cqa-mt-1.5\">\n <div class=\"cqa-flex cqa-items-start cqa-gap-1.5\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 14 14\"\n fill=\"none\"\n class=\"cqa-flex-shrink-0 cqa-mt-0.5\">\n <path d=\"M7 1.75C4.1 1.75 1.75 4.1 1.75 7C1.75 9.9 4.1 12.25 7 12.25C9.9 12.25 12.25 9.9 12.25 7C12.25 4.1 9.9 1.75 7 1.75ZM7 9.625C6.65625 9.625 6.375 9.34375 6.375 9V7C6.375 6.65625 6.65625 6.375 7 6.375C7.34375 6.375 7.625 6.65625 7.625 7V9C7.625 9.34375 7.34375 9.625 7 9.625ZM7.625 5.25H6.375V4H7.625V5.25Z\" fill=\"#EF4444\"/>\n </svg>\n <span class=\"cqa-text-xs cqa-text-[#EF4444] cqa-font-medium cqa-leading-[18px]\">\n Screen Name is required\n </span>\n </div>\n </div>\n </div>\n </div>\n <ng-container *ngIf=\"!isElementLoading\">\n <cqa-custom-input \n class=\"cqa-w-full\" \n label=\"Enter Value\" \n placeholder=\"#default_id or xpath\"\n [value]=\"getFormControlValue('value')\"\n [errors]=\"getFormControl('value')?.touched && getFormControl('value')?.invalid ? ['Value is required'] : []\"\n [required]=\"true\"\n (valueChange)=\"onFormControlChange('value', $event)\">\n </cqa-custom-input>\n <div class=\"cqa-w-full\">\n <label class=\"cqa-block cqa-text-[14px] cqa-font-medium cqa-text-[#374151] cqa-mb-1\">Labels (tags)</label>\n <div
|
|
19436
|
+
ElementFormComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: ElementFormComponent, selector: "cqa-element-form", inputs: { elementId: "elementId", element: "element", screenNameOptions: "screenNameOptions", hasMoreScreenNames: "hasMoreScreenNames", isLoadingScreenNames: "isLoadingScreenNames", isElementLoading: "isElementLoading", isEditMode: "isEditMode", isCreateMode: "isCreateMode", isEditInDepthAvailable: "isEditInDepthAvailable" }, outputs: { createElement: "createElement", updateElement: "updateElement", createScreenNameRequest: "createScreenNameRequest", searchScreenName: "searchScreenName", loadMoreScreenNames: "loadMoreScreenNames", cancel: "cancel", editInDepth: "editInDepth" }, host: { classAttribute: "cqa-ui-root" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-flex cqa-flex-col cqa-gap-4 cqa-px-1 cqa-pt-3\">\n <div *ngIf=\"isElementLoading && isEditMode\" class=\"cqa-flex cqa-flex-col cqa-items-center cqa-justify-center cqa-gap-3 cqa-py-8\">\n <svg class=\"cqa-animate-spin cqa-h-6 cqa-w-6 cqa-text-[#3F43EE]\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"cqa-opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"cqa-opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n <span class=\"cqa-text-[#6B7280] cqa-text-sm\">Loading element data...</span>\n </div>\n <div *ngIf=\"!isElementLoading\" class=\"cqa-flex cqa-gap-1.5\">\n <cqa-custom-input \n class=\"cqa-w-1/2\" \n label=\"Name\" \n placeholder=\"default-element\"\n [value]=\"getFormControlValue('name')\"\n [errors]=\"getFormControl('name')?.touched && getFormControl('name')?.invalid ? ['Name is required'] : []\"\n [required]=\"true\"\n (valueChange)=\"onFormControlChange('name', $event)\">\n </cqa-custom-input>\n <div class=\"cqa-w-1/2\">\n <cqa-dynamic-select [form]=\"form\" [config]=\"screenNameSelectConfig\"\n (addCustomValue)=\"createScreenNameRequest.emit($event.value)\"\n class=\"cqa-w-full\">\n </cqa-dynamic-select>\n <div *ngIf=\"getFormControl('screenNameId')?.touched && getFormControl('screenNameId')?.invalid\" class=\"cqa-flex cqa-flex-col cqa-gap-1 cqa-mt-1.5\">\n <div class=\"cqa-flex cqa-items-start cqa-gap-1.5\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 14 14\"\n fill=\"none\"\n class=\"cqa-flex-shrink-0 cqa-mt-0.5\">\n <path d=\"M7 1.75C4.1 1.75 1.75 4.1 1.75 7C1.75 9.9 4.1 12.25 7 12.25C9.9 12.25 12.25 9.9 12.25 7C12.25 4.1 9.9 1.75 7 1.75ZM7 9.625C6.65625 9.625 6.375 9.34375 6.375 9V7C6.375 6.65625 6.65625 6.375 7 6.375C7.34375 6.375 7.625 6.65625 7.625 7V9C7.625 9.34375 7.34375 9.625 7 9.625ZM7.625 5.25H6.375V4H7.625V5.25Z\" fill=\"#EF4444\"/>\n </svg>\n <span class=\"cqa-text-xs cqa-text-[#EF4444] cqa-font-medium cqa-leading-[18px]\">\n Screen Name is required\n </span>\n </div>\n </div>\n </div>\n </div>\n <ng-container *ngIf=\"!isElementLoading\">\n <cqa-custom-input \n class=\"cqa-w-full\" \n label=\"Enter Value\" \n placeholder=\"#default_id or xpath\"\n [value]=\"getFormControlValue('value')\"\n [errors]=\"getFormControl('value')?.touched && getFormControl('value')?.invalid ? ['Value is required'] : []\"\n [required]=\"true\"\n (valueChange)=\"onFormControlChange('value', $event)\">\n </cqa-custom-input>\n <div class=\"cqa-w-full\">\n <label class=\"cqa-block cqa-text-[14px] cqa-font-medium cqa-text-[#374151] cqa-mb-1\">Labels (tags)</label>\n <div\n class=\"cqa-flex cqa-flex-wrap cqa-gap-2 cqa-p-2 cqa-border cqa-border-solid cqa-border-gray-200 cqa-rounded-md cqa-min-h-[42px] cqa-max-h-[80px] cqa-overflow-y-auto cqa-scrollbar-thin cqa-scrollbar-track-transparent cqa-scrollbar-thumb-[#E5E7EB] cqa-scrollbar-thumb-rounded-full cqa-scrollbar-thumb-hover:cqa-bg-[#D1D5DB]\"\n *ngIf=\"formLabels?.length; else noTagsContainer\">\n <span *ngFor=\"let tag of visibleTags\"\n class=\"cqa-inline-flex cqa-items-center cqa-gap-1 cqa-px-2 cqa-py-1 cqa-bg-[#eff6ff] cqa-border cqa-border-[#c8e0ff] cqa-rounded-[8px] cqa-text-[12px] cqa-text-[#3F43EE]\"\n [matTooltip]=\"tag\"\n matTooltipPosition=\"above\"\n style=\"max-width: 140px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;\">\n <span class=\"cqa-max-w-full cqa-truncate\">{{ tag }}</span>\n <button type=\"button\" (click)=\"removeTag(tag)\" class=\"cqa-p-0.5 hover:cqa-bg-[#c8e0ff] cqa-rounded cqa-cursor-pointer cqa-h-[16px] cqa-w-[16px]\">\n <mat-icon class=\"!cqa-w-3 !cqa-h-3 !cqa-text-[14px]\">close</mat-icon>\n </button>\n </span>\n <input type=\"text\"\n class=\"cqa-flex-1 cqa-min-w-[120px] cqa-px-2 cqa-py-1 cqa-text-sm cqa-border-0 cqa-outline-none cqa-bg-transparent\"\n placeholder=\"Type and press Enter to add\"\n [(ngModel)]=\"tagInputValue\"\n (keydown)=\"onTagInputKeydown($event)\"\n (blur)=\"addTag()\"\n [ngModelOptions]=\"{standalone: true}\">\n </div>\n <ng-template #noTagsContainer>\n <div class=\"cqa-flex cqa-flex-wrap cqa-gap-2 cqa-p-2 cqa-border cqa-border-solid cqa-border-gray-200 cqa-rounded-md cqa-min-h-[42px]\">\n <input type=\"text\"\n class=\"cqa-flex-1 cqa-min-w-[120px] cqa-px-2 cqa-py-1 cqa-text-sm cqa-border-0 cqa-outline-none cqa-bg-transparent\"\n placeholder=\"Type and press Enter to add\"\n [(ngModel)]=\"tagInputValue\"\n (keydown)=\"onTagInputKeydown($event)\"\n (blur)=\"addTag()\"\n [ngModelOptions]=\"{standalone: true}\">\n </div>\n </ng-template>\n </div>\n\n <div class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <div class=\"cqa-flex cqa-items-stretch cqa-gap-2 cqa-w-full\">\n <div class=\"cqa-flex-1 cqa-min-w-0\">\n <cqa-button variant=\"outlined\" btnSize=\"lg\" [text]=\"(elementId ? 'Cancel' : 'Select from Element list')\" [fullWidth]=\"true\" (clicked)=\"onCancel()\"\n [customClass]=\"'cqa-text-[14px] cqa-py-[9px] cqa-border-[#414146]'\" [disabled]=\"saving\"></cqa-button>\n </div>\n <div class=\"cqa-flex-1 cqa-min-w-0\">\n <cqa-button variant=\"filled\" btnSize=\"lg\" [text]=\"saving ? 'Saving...' : (isEditMode ? 'Update' : 'Create')\" [fullWidth]=\"true\" (clicked)=\"onApply()\"\n [customClass]=\"'cqa-text-[14px] cqa-py-[9px] cqa-border-[#3F43EE]'\" [disabled]=\"saving\"></cqa-button>\n </div>\n </div>\n </div>\n <a href=\"#\" *ngIf=\"isEditInDepthAvailable\" (click)=\"onEditInDepth($event)\"\n class=\"cqa-text-[#3F43EE] cqa-text-[12px] cqa-leading-[18px] cqa-font-medium cqa-flex cqa-items-center cqa-gap-1.5 cqa-no-underline hover:cqa-no-underline cqa-self-center\">\n <mat-icon class=\"!cqa-w-4 !cqa-h-4 !cqa-text-[16px]\">open_in_new</mat-icon>\n Edit in depth (open detailed right panel)\n </a>\n </ng-container>\n</div>\n\n\n", components: [{ 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: DynamicSelectFieldComponent, selector: "cqa-dynamic-select", inputs: ["form", "config"], outputs: ["selectionChange", "selectClick", "searchChange", "loadMore", "addCustomValue"] }, { type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { 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"] }, { type: i5.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
19426
19437
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: ElementFormComponent, decorators: [{
|
|
19427
19438
|
type: Component,
|
|
19428
|
-
args: [{ selector: 'cqa-element-form', host: { class: 'cqa-ui-root' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"cqa-flex cqa-flex-col cqa-gap-4 cqa-px-1 cqa-pt-3\">\n <div *ngIf=\"isElementLoading && isEditMode\" class=\"cqa-flex cqa-flex-col cqa-items-center cqa-justify-center cqa-gap-3 cqa-py-8\">\n <svg class=\"cqa-animate-spin cqa-h-6 cqa-w-6 cqa-text-[#3F43EE]\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"cqa-opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"cqa-opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n <span class=\"cqa-text-[#6B7280] cqa-text-sm\">Loading element data...</span>\n </div>\n <div *ngIf=\"!isElementLoading\" class=\"cqa-flex cqa-gap-1.5\">\n <cqa-custom-input \n class=\"cqa-w-1/2\" \n label=\"Name\" \n placeholder=\"default-element\"\n [value]=\"getFormControlValue('name')\"\n [errors]=\"getFormControl('name')?.touched && getFormControl('name')?.invalid ? ['Name is required'] : []\"\n [required]=\"true\"\n (valueChange)=\"onFormControlChange('name', $event)\">\n </cqa-custom-input>\n <div class=\"cqa-w-1/2\">\n <cqa-dynamic-select [form]=\"form\" [config]=\"screenNameSelectConfig\"\n (addCustomValue)=\"createScreenNameRequest.emit($event.value)\"\n class=\"cqa-w-full\">\n </cqa-dynamic-select>\n <div *ngIf=\"getFormControl('screenNameId')?.touched && getFormControl('screenNameId')?.invalid\" class=\"cqa-flex cqa-flex-col cqa-gap-1 cqa-mt-1.5\">\n <div class=\"cqa-flex cqa-items-start cqa-gap-1.5\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 14 14\"\n fill=\"none\"\n class=\"cqa-flex-shrink-0 cqa-mt-0.5\">\n <path d=\"M7 1.75C4.1 1.75 1.75 4.1 1.75 7C1.75 9.9 4.1 12.25 7 12.25C9.9 12.25 12.25 9.9 12.25 7C12.25 4.1 9.9 1.75 7 1.75ZM7 9.625C6.65625 9.625 6.375 9.34375 6.375 9V7C6.375 6.65625 6.65625 6.375 7 6.375C7.34375 6.375 7.625 6.65625 7.625 7V9C7.625 9.34375 7.34375 9.625 7 9.625ZM7.625 5.25H6.375V4H7.625V5.25Z\" fill=\"#EF4444\"/>\n </svg>\n <span class=\"cqa-text-xs cqa-text-[#EF4444] cqa-font-medium cqa-leading-[18px]\">\n Screen Name is required\n </span>\n </div>\n </div>\n </div>\n </div>\n <ng-container *ngIf=\"!isElementLoading\">\n <cqa-custom-input \n class=\"cqa-w-full\" \n label=\"Enter Value\" \n placeholder=\"#default_id or xpath\"\n [value]=\"getFormControlValue('value')\"\n [errors]=\"getFormControl('value')?.touched && getFormControl('value')?.invalid ? ['Value is required'] : []\"\n [required]=\"true\"\n (valueChange)=\"onFormControlChange('value', $event)\">\n </cqa-custom-input>\n <div class=\"cqa-w-full\">\n <label class=\"cqa-block cqa-text-[14px] cqa-font-medium cqa-text-[#374151] cqa-mb-1\">Labels (tags)</label>\n <div
|
|
19439
|
+
args: [{ selector: 'cqa-element-form', host: { class: 'cqa-ui-root' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"cqa-flex cqa-flex-col cqa-gap-4 cqa-px-1 cqa-pt-3\">\n <div *ngIf=\"isElementLoading && isEditMode\" class=\"cqa-flex cqa-flex-col cqa-items-center cqa-justify-center cqa-gap-3 cqa-py-8\">\n <svg class=\"cqa-animate-spin cqa-h-6 cqa-w-6 cqa-text-[#3F43EE]\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"cqa-opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"cqa-opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n <span class=\"cqa-text-[#6B7280] cqa-text-sm\">Loading element data...</span>\n </div>\n <div *ngIf=\"!isElementLoading\" class=\"cqa-flex cqa-gap-1.5\">\n <cqa-custom-input \n class=\"cqa-w-1/2\" \n label=\"Name\" \n placeholder=\"default-element\"\n [value]=\"getFormControlValue('name')\"\n [errors]=\"getFormControl('name')?.touched && getFormControl('name')?.invalid ? ['Name is required'] : []\"\n [required]=\"true\"\n (valueChange)=\"onFormControlChange('name', $event)\">\n </cqa-custom-input>\n <div class=\"cqa-w-1/2\">\n <cqa-dynamic-select [form]=\"form\" [config]=\"screenNameSelectConfig\"\n (addCustomValue)=\"createScreenNameRequest.emit($event.value)\"\n class=\"cqa-w-full\">\n </cqa-dynamic-select>\n <div *ngIf=\"getFormControl('screenNameId')?.touched && getFormControl('screenNameId')?.invalid\" class=\"cqa-flex cqa-flex-col cqa-gap-1 cqa-mt-1.5\">\n <div class=\"cqa-flex cqa-items-start cqa-gap-1.5\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 14 14\"\n fill=\"none\"\n class=\"cqa-flex-shrink-0 cqa-mt-0.5\">\n <path d=\"M7 1.75C4.1 1.75 1.75 4.1 1.75 7C1.75 9.9 4.1 12.25 7 12.25C9.9 12.25 12.25 9.9 12.25 7C12.25 4.1 9.9 1.75 7 1.75ZM7 9.625C6.65625 9.625 6.375 9.34375 6.375 9V7C6.375 6.65625 6.65625 6.375 7 6.375C7.34375 6.375 7.625 6.65625 7.625 7V9C7.625 9.34375 7.34375 9.625 7 9.625ZM7.625 5.25H6.375V4H7.625V5.25Z\" fill=\"#EF4444\"/>\n </svg>\n <span class=\"cqa-text-xs cqa-text-[#EF4444] cqa-font-medium cqa-leading-[18px]\">\n Screen Name is required\n </span>\n </div>\n </div>\n </div>\n </div>\n <ng-container *ngIf=\"!isElementLoading\">\n <cqa-custom-input \n class=\"cqa-w-full\" \n label=\"Enter Value\" \n placeholder=\"#default_id or xpath\"\n [value]=\"getFormControlValue('value')\"\n [errors]=\"getFormControl('value')?.touched && getFormControl('value')?.invalid ? ['Value is required'] : []\"\n [required]=\"true\"\n (valueChange)=\"onFormControlChange('value', $event)\">\n </cqa-custom-input>\n <div class=\"cqa-w-full\">\n <label class=\"cqa-block cqa-text-[14px] cqa-font-medium cqa-text-[#374151] cqa-mb-1\">Labels (tags)</label>\n <div\n class=\"cqa-flex cqa-flex-wrap cqa-gap-2 cqa-p-2 cqa-border cqa-border-solid cqa-border-gray-200 cqa-rounded-md cqa-min-h-[42px] cqa-max-h-[80px] cqa-overflow-y-auto cqa-scrollbar-thin cqa-scrollbar-track-transparent cqa-scrollbar-thumb-[#E5E7EB] cqa-scrollbar-thumb-rounded-full cqa-scrollbar-thumb-hover:cqa-bg-[#D1D5DB]\"\n *ngIf=\"formLabels?.length; else noTagsContainer\">\n <span *ngFor=\"let tag of visibleTags\"\n class=\"cqa-inline-flex cqa-items-center cqa-gap-1 cqa-px-2 cqa-py-1 cqa-bg-[#eff6ff] cqa-border cqa-border-[#c8e0ff] cqa-rounded-[8px] cqa-text-[12px] cqa-text-[#3F43EE]\"\n [matTooltip]=\"tag\"\n matTooltipPosition=\"above\"\n style=\"max-width: 140px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;\">\n <span class=\"cqa-max-w-full cqa-truncate\">{{ tag }}</span>\n <button type=\"button\" (click)=\"removeTag(tag)\" class=\"cqa-p-0.5 hover:cqa-bg-[#c8e0ff] cqa-rounded cqa-cursor-pointer cqa-h-[16px] cqa-w-[16px]\">\n <mat-icon class=\"!cqa-w-3 !cqa-h-3 !cqa-text-[14px]\">close</mat-icon>\n </button>\n </span>\n <input type=\"text\"\n class=\"cqa-flex-1 cqa-min-w-[120px] cqa-px-2 cqa-py-1 cqa-text-sm cqa-border-0 cqa-outline-none cqa-bg-transparent\"\n placeholder=\"Type and press Enter to add\"\n [(ngModel)]=\"tagInputValue\"\n (keydown)=\"onTagInputKeydown($event)\"\n (blur)=\"addTag()\"\n [ngModelOptions]=\"{standalone: true}\">\n </div>\n <ng-template #noTagsContainer>\n <div class=\"cqa-flex cqa-flex-wrap cqa-gap-2 cqa-p-2 cqa-border cqa-border-solid cqa-border-gray-200 cqa-rounded-md cqa-min-h-[42px]\">\n <input type=\"text\"\n class=\"cqa-flex-1 cqa-min-w-[120px] cqa-px-2 cqa-py-1 cqa-text-sm cqa-border-0 cqa-outline-none cqa-bg-transparent\"\n placeholder=\"Type and press Enter to add\"\n [(ngModel)]=\"tagInputValue\"\n (keydown)=\"onTagInputKeydown($event)\"\n (blur)=\"addTag()\"\n [ngModelOptions]=\"{standalone: true}\">\n </div>\n </ng-template>\n </div>\n\n <div class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <div class=\"cqa-flex cqa-items-stretch cqa-gap-2 cqa-w-full\">\n <div class=\"cqa-flex-1 cqa-min-w-0\">\n <cqa-button variant=\"outlined\" btnSize=\"lg\" [text]=\"(elementId ? 'Cancel' : 'Select from Element list')\" [fullWidth]=\"true\" (clicked)=\"onCancel()\"\n [customClass]=\"'cqa-text-[14px] cqa-py-[9px] cqa-border-[#414146]'\" [disabled]=\"saving\"></cqa-button>\n </div>\n <div class=\"cqa-flex-1 cqa-min-w-0\">\n <cqa-button variant=\"filled\" btnSize=\"lg\" [text]=\"saving ? 'Saving...' : (isEditMode ? 'Update' : 'Create')\" [fullWidth]=\"true\" (clicked)=\"onApply()\"\n [customClass]=\"'cqa-text-[14px] cqa-py-[9px] cqa-border-[#3F43EE]'\" [disabled]=\"saving\"></cqa-button>\n </div>\n </div>\n </div>\n <a href=\"#\" *ngIf=\"isEditInDepthAvailable\" (click)=\"onEditInDepth($event)\"\n class=\"cqa-text-[#3F43EE] cqa-text-[12px] cqa-leading-[18px] cqa-font-medium cqa-flex cqa-items-center cqa-gap-1.5 cqa-no-underline hover:cqa-no-underline cqa-self-center\">\n <mat-icon class=\"!cqa-w-4 !cqa-h-4 !cqa-text-[16px]\">open_in_new</mat-icon>\n Edit in depth (open detailed right panel)\n </a>\n </ng-container>\n</div>\n\n\n" }]
|
|
19429
19440
|
}], ctorParameters: function () { return [{ type: i1$1.FormBuilder, decorators: [{
|
|
19430
19441
|
type: Optional
|
|
19431
19442
|
}] }, { type: i0.ChangeDetectorRef, decorators: [{
|
|
@@ -33493,252 +33504,524 @@ const DETAIL_SIDE_PANEL_SCROLL_STYLES = `
|
|
|
33493
33504
|
}
|
|
33494
33505
|
`;
|
|
33495
33506
|
|
|
33496
|
-
|
|
33497
|
-
|
|
33498
|
-
|
|
33499
|
-
|
|
33500
|
-
|
|
33501
|
-
|
|
33502
|
-
|
|
33503
|
-
testDataProfile: 'testDataProfile',
|
|
33504
|
-
testDataSet: 'testDataSet',
|
|
33505
|
-
videoRecording: 'videoRecording',
|
|
33506
|
-
enableAiSmartness: 'enableAiSmartness',
|
|
33507
|
-
defaultAiAction: 'defaultAiAction',
|
|
33508
|
-
knowledgeBaseDefaultTestCase: 'knowledgeBaseDefaultTestCase',
|
|
33509
|
-
useAiMetadata: 'useAiMetadata',
|
|
33510
|
-
defaultBrowser: 'defaultBrowser',
|
|
33511
|
-
defaultViewport: 'defaultViewport',
|
|
33512
|
-
deviceType: 'deviceType',
|
|
33513
|
-
deviceOS: 'deviceOS',
|
|
33514
|
-
};
|
|
33515
|
-
const FREQUENTLY_USED_LABELS = [
|
|
33516
|
-
'Case',
|
|
33517
|
-
'Critical',
|
|
33518
|
-
'PO',
|
|
33519
|
-
'Upload',
|
|
33520
|
-
'Validation',
|
|
33521
|
-
'Review',
|
|
33522
|
-
'Edge-cases',
|
|
33523
|
-
'Security',
|
|
33524
|
-
'Integration',
|
|
33525
|
-
'Smoke',
|
|
33526
|
-
];
|
|
33527
|
-
class TestCaseDetailsEditComponent {
|
|
33528
|
-
constructor(cdr) {
|
|
33529
|
-
this.cdr = cdr;
|
|
33530
|
-
this.descriptionTitle = 'Description';
|
|
33531
|
-
this.descriptionContent = '';
|
|
33532
|
-
/** When true, description uses Trix rich text editor (Bold, Italic, etc.). Host app must load Trix. */
|
|
33533
|
-
this.enableMarkdown = false;
|
|
33534
|
-
this.metadataItems = [];
|
|
33535
|
-
this.labels = [];
|
|
33536
|
-
this.configTitle = 'Configuration';
|
|
33537
|
-
this.configSections = [];
|
|
33538
|
-
this.configSectionsRow2 = [];
|
|
33539
|
-
/** Optional list of prerequisite test case options for the multi-select. If not provided, uses default sample options. */
|
|
33540
|
-
this.prerequisiteCaseOptions = [];
|
|
33541
|
-
/** Platform: 'web' shows Default Browser + Viewport; 'mobile' shows Device Type + OS. Defaults to 'web'. */
|
|
33542
|
-
this.platform = 'web';
|
|
33543
|
-
/** When true, hides Priority, Type, and Test Data Set fields (step groups don't have these). Defaults to false. */
|
|
33544
|
-
this.isStepGroup = false;
|
|
33545
|
-
/**
|
|
33546
|
-
* Override config per select key. Use for:
|
|
33547
|
-
* - API-driven options: pass options array (update when API returns)
|
|
33548
|
-
* - Server-side search: serverSearch: true, onSearch in override or listen to selectSearch
|
|
33549
|
-
* - Infinite scroll: hasMore: true, onLoadMore in override or listen to selectLoadMore
|
|
33550
|
-
* - Initial fetch on open: initialFetchOnOpen: true
|
|
33551
|
-
*/
|
|
33552
|
-
this.selectConfigOverrides = {};
|
|
33553
|
-
this.save = new EventEmitter();
|
|
33554
|
-
this.cancel = new EventEmitter();
|
|
33555
|
-
/** Emitted when user searches in a select (serverSearch mode). Call API and update options via selectConfigOverrides. */
|
|
33556
|
-
this.selectSearch = new EventEmitter();
|
|
33557
|
-
/** Emitted when user scrolls to load more. Call API, append to options via selectConfigOverrides. */
|
|
33558
|
-
this.selectLoadMore = new EventEmitter();
|
|
33559
|
-
/** Emitted when a select panel is opened. Use to call API for initial load (e.g. when initialFetchOnOpen). */
|
|
33560
|
-
this.selectOpened = new EventEmitter();
|
|
33561
|
-
/** Emitted when selection changes in any select. */
|
|
33562
|
-
this.selectionChange = new EventEmitter();
|
|
33563
|
-
/** Emitted when user adds a new custom label via the "New" option. */
|
|
33564
|
-
this.labelAdded = new EventEmitter();
|
|
33565
|
-
/** Form state */
|
|
33566
|
-
this.editDescription = '';
|
|
33567
|
-
this.editStatus = '';
|
|
33568
|
-
this.editPriority = '';
|
|
33569
|
-
this.editLabels = [];
|
|
33570
|
-
this.testCaseTimeout = '';
|
|
33571
|
-
this.waitTimeoutLocators = '';
|
|
33572
|
-
this.autoWaitEnabled = false;
|
|
33573
|
-
this.retryFailedSteps = '';
|
|
33574
|
-
this.configExpanded = true;
|
|
33575
|
-
this.executionExpanded = true;
|
|
33576
|
-
this.aiConfigExpanded = true;
|
|
33577
|
-
this.waitsRetriesExpanded = true;
|
|
33578
|
-
this.deviceExpanded = true;
|
|
33579
|
-
this.keyFlagsExpanded = true;
|
|
33580
|
-
this.mobileTestingEnabled = false;
|
|
33581
|
-
this.extensionUseEnabled = false;
|
|
33582
|
-
this.dataDrivenEnabled = false;
|
|
33583
|
-
this.frequentlyUsedLabels = FREQUENTLY_USED_LABELS;
|
|
33584
|
-
/** FormGroup for cqa-dynamic-select bindings */
|
|
33585
|
-
this.editForm = new FormGroup({
|
|
33586
|
-
status: new FormControl(''),
|
|
33587
|
-
priority: new FormControl(''),
|
|
33588
|
-
type: new FormControl(''),
|
|
33589
|
-
labels: new FormControl([]),
|
|
33590
|
-
prerequisiteCases: new FormControl([]),
|
|
33591
|
-
testDataProfile: new FormControl(''),
|
|
33592
|
-
testDataSet: new FormControl(''),
|
|
33593
|
-
defaultBrowser: new FormControl(''),
|
|
33594
|
-
videoRecording: new FormControl(''),
|
|
33595
|
-
defaultViewport: new FormControl(''),
|
|
33596
|
-
deviceType: new FormControl(''),
|
|
33597
|
-
deviceOS: new FormControl(''),
|
|
33598
|
-
enableAiSmartness: new FormControl(''),
|
|
33599
|
-
defaultAiAction: new FormControl(''),
|
|
33600
|
-
knowledgeBaseDefaultTestCase: new FormControl(''),
|
|
33601
|
-
useAiMetadata: new FormControl(''),
|
|
33602
|
-
});
|
|
33603
|
-
/** Cached configs to avoid new object refs each change detection (prevents infinite loops) */
|
|
33604
|
-
this.statusSelectConfig = {
|
|
33605
|
-
key: 'status',
|
|
33606
|
-
label: '',
|
|
33607
|
-
placeholder: 'Status',
|
|
33608
|
-
searchable: false,
|
|
33609
|
-
options: [
|
|
33610
|
-
{ value: 'Draft', name: 'Draft' },
|
|
33611
|
-
{ value: 'In Review', name: 'In Review' },
|
|
33612
|
-
{ value: 'Approved', name: 'Approved' },
|
|
33613
|
-
{ value: 'Active', name: 'Active' },
|
|
33614
|
-
{ value: 'Inactive', name: 'Inactive' },
|
|
33615
|
-
{ value: 'Blocked', name: 'Blocked' },
|
|
33616
|
-
],
|
|
33617
|
-
};
|
|
33618
|
-
this.typeSelectConfig = {
|
|
33619
|
-
key: 'type',
|
|
33620
|
-
label: '',
|
|
33621
|
-
placeholder: 'Type',
|
|
33622
|
-
searchable: true,
|
|
33623
|
-
options: [],
|
|
33624
|
-
};
|
|
33625
|
-
this.testDataProfileSelectConfig = {
|
|
33626
|
-
key: 'testDataProfile',
|
|
33627
|
-
label: '',
|
|
33628
|
-
placeholder: 'Test Data Profile',
|
|
33629
|
-
searchable: true,
|
|
33630
|
-
options: [],
|
|
33631
|
-
};
|
|
33632
|
-
this.testDataSetSelectConfig = {
|
|
33633
|
-
key: 'testDataSet',
|
|
33634
|
-
label: '',
|
|
33635
|
-
placeholder: 'Test Data Set',
|
|
33636
|
-
searchable: true,
|
|
33637
|
-
options: [],
|
|
33638
|
-
};
|
|
33639
|
-
this.defaultPrerequisiteCaseOptions = [
|
|
33640
|
-
{ value: 'TC-001', name: 'TC-001: Login flow' },
|
|
33641
|
-
{ value: 'TC-002', name: 'TC-002: User registration' },
|
|
33642
|
-
{ value: 'TC-003', name: 'TC-003: Password reset' },
|
|
33643
|
-
{ value: 'TC-004', name: 'TC-004: Dashboard load' },
|
|
33644
|
-
{ value: 'TC-005', name: 'TC-005: API health check' },
|
|
33507
|
+
class DetailSidePanelComponent {
|
|
33508
|
+
constructor() {
|
|
33509
|
+
/** Tabs - each tab has a side panel icon button; tabs and buttons are 1:1. Host defines tabs and content. */
|
|
33510
|
+
this.tabs = [
|
|
33511
|
+
{ label: 'Test Case', value: 'test-case', icon: 'description' },
|
|
33512
|
+
{ label: 'Data Library', value: 'data-library', icon: 'folder' },
|
|
33513
|
+
{ label: 'Variables', value: 'variables', icon: 'code' },
|
|
33645
33514
|
];
|
|
33646
|
-
|
|
33647
|
-
|
|
33648
|
-
|
|
33649
|
-
|
|
33650
|
-
|
|
33651
|
-
|
|
33652
|
-
|
|
33653
|
-
|
|
33654
|
-
|
|
33655
|
-
|
|
33656
|
-
|
|
33657
|
-
|
|
33658
|
-
|
|
33659
|
-
|
|
33660
|
-
|
|
33661
|
-
|
|
33662
|
-
|
|
33663
|
-
|
|
33664
|
-
|
|
33665
|
-
|
|
33666
|
-
|
|
33667
|
-
|
|
33668
|
-
|
|
33669
|
-
this.
|
|
33670
|
-
|
|
33671
|
-
|
|
33672
|
-
|
|
33673
|
-
|
|
33674
|
-
|
|
33675
|
-
|
|
33676
|
-
|
|
33677
|
-
|
|
33678
|
-
|
|
33679
|
-
|
|
33680
|
-
|
|
33681
|
-
|
|
33682
|
-
|
|
33683
|
-
|
|
33684
|
-
|
|
33685
|
-
|
|
33686
|
-
|
|
33687
|
-
|
|
33688
|
-
|
|
33689
|
-
|
|
33690
|
-
|
|
33691
|
-
|
|
33692
|
-
|
|
33693
|
-
|
|
33694
|
-
|
|
33695
|
-
|
|
33696
|
-
|
|
33697
|
-
|
|
33698
|
-
|
|
33699
|
-
|
|
33700
|
-
|
|
33701
|
-
|
|
33702
|
-
|
|
33703
|
-
|
|
33704
|
-
|
|
33705
|
-
|
|
33706
|
-
|
|
33707
|
-
|
|
33708
|
-
|
|
33709
|
-
|
|
33710
|
-
|
|
33711
|
-
|
|
33712
|
-
|
|
33713
|
-
|
|
33714
|
-
|
|
33715
|
-
|
|
33716
|
-
|
|
33717
|
-
|
|
33718
|
-
|
|
33719
|
-
|
|
33720
|
-
|
|
33721
|
-
|
|
33722
|
-
|
|
33723
|
-
|
|
33724
|
-
|
|
33725
|
-
|
|
33726
|
-
|
|
33727
|
-
|
|
33728
|
-
|
|
33729
|
-
|
|
33730
|
-
|
|
33731
|
-
|
|
33732
|
-
|
|
33733
|
-
|
|
33734
|
-
|
|
33735
|
-
|
|
33736
|
-
|
|
33737
|
-
|
|
33738
|
-
|
|
33739
|
-
|
|
33740
|
-
|
|
33741
|
-
|
|
33515
|
+
/** Currently active tab value */
|
|
33516
|
+
this.activeTab = 'test-case';
|
|
33517
|
+
/** Whether to show the close button in the side menu */
|
|
33518
|
+
this.showCloseButton = false;
|
|
33519
|
+
/** Whether the panel is expanded (affects expand button icon and panel width) */
|
|
33520
|
+
this.expanded = true;
|
|
33521
|
+
/** Panel width when expanded (e.g. '480px', '25%') */
|
|
33522
|
+
this.expandedWidth = '380px';
|
|
33523
|
+
/** Panel width when collapsed (e.g. '56px' - fits icon bar + back button) */
|
|
33524
|
+
this.collapsedWidth = '56px';
|
|
33525
|
+
this.hostOverflow = 'hidden';
|
|
33526
|
+
/** Tooltip for expand button when panel is collapsed */
|
|
33527
|
+
this.expandTooltip = 'Expand';
|
|
33528
|
+
/** Tooltip for expand button when panel is expanded (collapse) */
|
|
33529
|
+
this.collapseTooltip = 'Collapse';
|
|
33530
|
+
/** Tooltip for close button */
|
|
33531
|
+
this.closeTooltip = 'Close';
|
|
33532
|
+
this.back = new EventEmitter();
|
|
33533
|
+
this.tabChange = new EventEmitter();
|
|
33534
|
+
this.expandToggle = new EventEmitter();
|
|
33535
|
+
this.close = new EventEmitter();
|
|
33536
|
+
}
|
|
33537
|
+
get hostWidth() {
|
|
33538
|
+
return this.expanded ? this.expandedWidth : this.collapsedWidth;
|
|
33539
|
+
}
|
|
33540
|
+
get hostMinWidth() {
|
|
33541
|
+
return this.expanded ? this.expandedWidth : this.collapsedWidth;
|
|
33542
|
+
}
|
|
33543
|
+
get hostMaxWidth() {
|
|
33544
|
+
return this.expanded ? this.expandedWidth : this.collapsedWidth;
|
|
33545
|
+
}
|
|
33546
|
+
trackByTabValue(_i, tab) {
|
|
33547
|
+
return tab.value;
|
|
33548
|
+
}
|
|
33549
|
+
onBack() {
|
|
33550
|
+
this.back.emit();
|
|
33551
|
+
}
|
|
33552
|
+
onTabClick(tab) {
|
|
33553
|
+
if (!this.expanded) {
|
|
33554
|
+
this.expandToggle.emit();
|
|
33555
|
+
}
|
|
33556
|
+
if (tab.value !== this.activeTab) {
|
|
33557
|
+
this.tabChange.emit(tab.value);
|
|
33558
|
+
}
|
|
33559
|
+
}
|
|
33560
|
+
onExpandToggle() {
|
|
33561
|
+
this.expandToggle.emit();
|
|
33562
|
+
}
|
|
33563
|
+
onClose() {
|
|
33564
|
+
this.close.emit();
|
|
33565
|
+
}
|
|
33566
|
+
}
|
|
33567
|
+
DetailSidePanelComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DetailSidePanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
33568
|
+
DetailSidePanelComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: DetailSidePanelComponent, selector: "cqa-detail-side-panel", inputs: { tabs: "tabs", activeTab: "activeTab", showCloseButton: "showCloseButton", expanded: "expanded", expandedWidth: "expandedWidth", collapsedWidth: "collapsedWidth", expandTooltip: "expandTooltip", collapseTooltip: "collapseTooltip", closeTooltip: "closeTooltip" }, outputs: { back: "back", tabChange: "tabChange", expandToggle: "expandToggle", close: "close" }, host: { properties: { "style.width": "this.hostWidth", "style.min-width": "this.hostMinWidth", "style.max-width": "this.hostMaxWidth", "style.overflow": "this.hostOverflow" }, styleAttribute: "transition: width 0.3s ease-in-out", classAttribute: "cqa-ui-root cqa-flex cqa-flex-col cqa-h-full cqa-flex-shrink-0 cqa-flex-grow-0 cqa-bg-white cqa-shadow-[-4px_0_6px_-1px_rgba(0,0,0,0.05)]" }, ngImport: i0, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-min-w-0 cqa-bg-white\">\n <!-- Main content: Side menu + Scrollable content -->\n <div\n class=\"cqa-grid cqa-flex-1 cqa-min-h-0 cqa-min-w-0 cqa-overflow-hidden\"\n [style.grid-template-columns]=\"expanded ? 'auto 1fr' : 'auto 0fr'\"\n style=\"transition: grid-template-columns 0.3s ease-in-out\">\n <!-- Left vertical icon menu -->\n <div\n class=\"cqa-flex cqa-flex-col cqa-items-center cqa-gap-2 cqa-py-4 cqa-px-2 cqa-border-r cqa-border-[#F5F5F5] cqa-flex-shrink-0 cqa-text-[#0A0A0A]\"\n style=\"box-shadow: 1px 4px 12px 1px rgba(0, 0, 0, 0.05);\">\n <!-- Expand / Collapse button (always visible) -->\n <button\n type=\"button\"\n [matTooltip]=\"expanded ? collapseTooltip : expandTooltip\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onExpandToggle()\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">{{ expanded ? 'chevron_left' : 'chevron_right' }}</mat-icon>\n </button>\n <!-- Close button -->\n <button\n *ngIf=\"showCloseButton\"\n type=\"button\"\n [matTooltip]=\"closeTooltip\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onClose()\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">close</mat-icon>\n </button>\n <!-- Tab buttons (1:1 with tabs) -->\n <button\n *ngFor=\"let tab of tabs; trackBy: trackByTabValue\"\n type=\"button\"\n [matTooltip]=\"tab.label\"\n [class.cqa-bg-[#3F43EE]]=\"activeTab === tab.value\"\n [class.cqa-text-white]=\"activeTab === tab.value\"\n [class.cqa-text-[#64748B]]=\"activeTab !== tab.value\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onTabClick(tab)\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">{{ tab.icon || 'circle' }}</mat-icon>\n </button>\n </div>\n\n <!-- Scrollable content area (collapses with animation when expanded is false) -->\n <div class=\"cqa-flex cqa-flex-col cqa-min-h-0 cqa-min-w-0 cqa-overflow-hidden cqa-w-full cqa-h-full\">\n <div class=\"detail-side-panel-scroll cqa-flex-1 cqa-min-h-0 cqa-min-w-0 cqa-overflow-y-auto cqa-overflow-x-hidden cqa-p-4 cqa-space-y-4\" style=\"overflow-y: auto; overflow-x: hidden; min-height: 0; -webkit-overflow-scrolling: touch;\">\n <!-- Tabs: equally distributed (Figma: purple active, gray inactive) -->\n <div class=\"cqa-flex cqa-gap-[3.5px] cqa-p-[3.5px] cqa-bg-[#F1F5F9] cqa-rounded-lg cqa-w-full\" role=\"tablist\">\n <button\n *ngFor=\"let tab of tabs; trackBy: trackByTabValue\"\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === tab.value\"\n [class.cqa-bg-[#3F43EE]]=\"activeTab === tab.value\"\n [class.cqa-text-white]=\"activeTab === tab.value\"\n [class.cqa-text-[#64748B]]=\"activeTab !== tab.value\"\n class=\"cqa-flex-1 cqa-flex cqa-justify-center cqa-items-center cqa-py-2 cqa-rounded-lg cqa-text-xs cqa-font-medium cqa-transition-colors hover:cqa-opacity-90 focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onTabClick(tab)\">\n {{ tab.label }}\n </button>\n </div>\n\n <!-- Tab content: fully provided by host via content projection. Host uses *ngIf per tab so only active content is projected. Add/remove tabs in the host without changing cqa-ui-lib. -->\n <ng-content></ng-content>\n </div>\n </div>\n </div>\n</div>\n", styles: [".detail-side-panel-scroll{overflow-y:auto!important;overflow-x:hidden!important;min-height:0!important;-webkit-overflow-scrolling:touch}\n"], components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i5.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
33569
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DetailSidePanelComponent, decorators: [{
|
|
33570
|
+
type: Component,
|
|
33571
|
+
args: [{ selector: 'cqa-detail-side-panel', styles: [DETAIL_SIDE_PANEL_SCROLL_STYLES], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
33572
|
+
class: 'cqa-ui-root cqa-flex cqa-flex-col cqa-h-full cqa-flex-shrink-0 cqa-flex-grow-0 cqa-bg-white cqa-shadow-[-4px_0_6px_-1px_rgba(0,0,0,0.05)]',
|
|
33573
|
+
style: 'transition: width 0.3s ease-in-out',
|
|
33574
|
+
}, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-min-w-0 cqa-bg-white\">\n <!-- Main content: Side menu + Scrollable content -->\n <div\n class=\"cqa-grid cqa-flex-1 cqa-min-h-0 cqa-min-w-0 cqa-overflow-hidden\"\n [style.grid-template-columns]=\"expanded ? 'auto 1fr' : 'auto 0fr'\"\n style=\"transition: grid-template-columns 0.3s ease-in-out\">\n <!-- Left vertical icon menu -->\n <div\n class=\"cqa-flex cqa-flex-col cqa-items-center cqa-gap-2 cqa-py-4 cqa-px-2 cqa-border-r cqa-border-[#F5F5F5] cqa-flex-shrink-0 cqa-text-[#0A0A0A]\"\n style=\"box-shadow: 1px 4px 12px 1px rgba(0, 0, 0, 0.05);\">\n <!-- Expand / Collapse button (always visible) -->\n <button\n type=\"button\"\n [matTooltip]=\"expanded ? collapseTooltip : expandTooltip\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onExpandToggle()\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">{{ expanded ? 'chevron_left' : 'chevron_right' }}</mat-icon>\n </button>\n <!-- Close button -->\n <button\n *ngIf=\"showCloseButton\"\n type=\"button\"\n [matTooltip]=\"closeTooltip\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onClose()\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">close</mat-icon>\n </button>\n <!-- Tab buttons (1:1 with tabs) -->\n <button\n *ngFor=\"let tab of tabs; trackBy: trackByTabValue\"\n type=\"button\"\n [matTooltip]=\"tab.label\"\n [class.cqa-bg-[#3F43EE]]=\"activeTab === tab.value\"\n [class.cqa-text-white]=\"activeTab === tab.value\"\n [class.cqa-text-[#64748B]]=\"activeTab !== tab.value\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onTabClick(tab)\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">{{ tab.icon || 'circle' }}</mat-icon>\n </button>\n </div>\n\n <!-- Scrollable content area (collapses with animation when expanded is false) -->\n <div class=\"cqa-flex cqa-flex-col cqa-min-h-0 cqa-min-w-0 cqa-overflow-hidden cqa-w-full cqa-h-full\">\n <div class=\"detail-side-panel-scroll cqa-flex-1 cqa-min-h-0 cqa-min-w-0 cqa-overflow-y-auto cqa-overflow-x-hidden cqa-p-4 cqa-space-y-4\" style=\"overflow-y: auto; overflow-x: hidden; min-height: 0; -webkit-overflow-scrolling: touch;\">\n <!-- Tabs: equally distributed (Figma: purple active, gray inactive) -->\n <div class=\"cqa-flex cqa-gap-[3.5px] cqa-p-[3.5px] cqa-bg-[#F1F5F9] cqa-rounded-lg cqa-w-full\" role=\"tablist\">\n <button\n *ngFor=\"let tab of tabs; trackBy: trackByTabValue\"\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === tab.value\"\n [class.cqa-bg-[#3F43EE]]=\"activeTab === tab.value\"\n [class.cqa-text-white]=\"activeTab === tab.value\"\n [class.cqa-text-[#64748B]]=\"activeTab !== tab.value\"\n class=\"cqa-flex-1 cqa-flex cqa-justify-center cqa-items-center cqa-py-2 cqa-rounded-lg cqa-text-xs cqa-font-medium cqa-transition-colors hover:cqa-opacity-90 focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onTabClick(tab)\">\n {{ tab.label }}\n </button>\n </div>\n\n <!-- Tab content: fully provided by host via content projection. Host uses *ngIf per tab so only active content is projected. Add/remove tabs in the host without changing cqa-ui-lib. -->\n <ng-content></ng-content>\n </div>\n </div>\n </div>\n</div>\n" }]
|
|
33575
|
+
}], propDecorators: { tabs: [{
|
|
33576
|
+
type: Input
|
|
33577
|
+
}], activeTab: [{
|
|
33578
|
+
type: Input
|
|
33579
|
+
}], showCloseButton: [{
|
|
33580
|
+
type: Input
|
|
33581
|
+
}], expanded: [{
|
|
33582
|
+
type: Input
|
|
33583
|
+
}], expandedWidth: [{
|
|
33584
|
+
type: Input
|
|
33585
|
+
}], collapsedWidth: [{
|
|
33586
|
+
type: Input
|
|
33587
|
+
}], hostWidth: [{
|
|
33588
|
+
type: HostBinding,
|
|
33589
|
+
args: ['style.width']
|
|
33590
|
+
}], hostMinWidth: [{
|
|
33591
|
+
type: HostBinding,
|
|
33592
|
+
args: ['style.min-width']
|
|
33593
|
+
}], hostMaxWidth: [{
|
|
33594
|
+
type: HostBinding,
|
|
33595
|
+
args: ['style.max-width']
|
|
33596
|
+
}], hostOverflow: [{
|
|
33597
|
+
type: HostBinding,
|
|
33598
|
+
args: ['style.overflow']
|
|
33599
|
+
}], expandTooltip: [{
|
|
33600
|
+
type: Input
|
|
33601
|
+
}], collapseTooltip: [{
|
|
33602
|
+
type: Input
|
|
33603
|
+
}], closeTooltip: [{
|
|
33604
|
+
type: Input
|
|
33605
|
+
}], back: [{
|
|
33606
|
+
type: Output
|
|
33607
|
+
}], tabChange: [{
|
|
33608
|
+
type: Output
|
|
33609
|
+
}], expandToggle: [{
|
|
33610
|
+
type: Output
|
|
33611
|
+
}], close: [{
|
|
33612
|
+
type: Output
|
|
33613
|
+
}] } });
|
|
33614
|
+
|
|
33615
|
+
class DetailDrawerTabContentDirective {
|
|
33616
|
+
constructor(templateRef) {
|
|
33617
|
+
this.templateRef = templateRef;
|
|
33618
|
+
}
|
|
33619
|
+
}
|
|
33620
|
+
DetailDrawerTabContentDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DetailDrawerTabContentDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
|
|
33621
|
+
DetailDrawerTabContentDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.4.0", type: DetailDrawerTabContentDirective, selector: "[cqaTabContent]", ngImport: i0 });
|
|
33622
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DetailDrawerTabContentDirective, decorators: [{
|
|
33623
|
+
type: Directive,
|
|
33624
|
+
args: [{
|
|
33625
|
+
selector: '[cqaTabContent]',
|
|
33626
|
+
}]
|
|
33627
|
+
}], ctorParameters: function () { return [{ type: i0.TemplateRef }]; } });
|
|
33628
|
+
|
|
33629
|
+
class DetailDrawerTabComponent {
|
|
33630
|
+
constructor() {
|
|
33631
|
+
/** Tab label (shown in tooltip on icon button) */
|
|
33632
|
+
this.label = '';
|
|
33633
|
+
/** Tab value (unique identifier) */
|
|
33634
|
+
this.value = '';
|
|
33635
|
+
/** Material icon name for the tab button */
|
|
33636
|
+
this.icon = 'folder';
|
|
33637
|
+
}
|
|
33638
|
+
get contentTemplate() {
|
|
33639
|
+
return this.contentDirective?.templateRef ?? null;
|
|
33640
|
+
}
|
|
33641
|
+
}
|
|
33642
|
+
DetailDrawerTabComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DetailDrawerTabComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
33643
|
+
DetailDrawerTabComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: DetailDrawerTabComponent, selector: "cqa-detail-drawer-tab", inputs: { label: "label", value: "value", icon: "icon" }, host: { styleAttribute: "display: contents" }, queries: [{ propertyName: "contentDirective", first: true, predicate: DetailDrawerTabContentDirective, descendants: true }], ngImport: i0, template: '', isInline: true });
|
|
33644
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DetailDrawerTabComponent, decorators: [{
|
|
33645
|
+
type: Component,
|
|
33646
|
+
args: [{
|
|
33647
|
+
selector: 'cqa-detail-drawer-tab',
|
|
33648
|
+
template: '',
|
|
33649
|
+
host: {
|
|
33650
|
+
style: 'display: contents',
|
|
33651
|
+
},
|
|
33652
|
+
}]
|
|
33653
|
+
}], propDecorators: { label: [{
|
|
33654
|
+
type: Input
|
|
33655
|
+
}], value: [{
|
|
33656
|
+
type: Input
|
|
33657
|
+
}], icon: [{
|
|
33658
|
+
type: Input
|
|
33659
|
+
}], contentDirective: [{
|
|
33660
|
+
type: ContentChild,
|
|
33661
|
+
args: [DetailDrawerTabContentDirective]
|
|
33662
|
+
}] } });
|
|
33663
|
+
|
|
33664
|
+
class DetailDrawerComponent {
|
|
33665
|
+
constructor() {
|
|
33666
|
+
/** Currently active tab value */
|
|
33667
|
+
this.activeTab = '';
|
|
33668
|
+
/** Whether to show the close button */
|
|
33669
|
+
this.showCloseButton = true;
|
|
33670
|
+
/** Whether the drawer is expanded */
|
|
33671
|
+
this.expanded = true;
|
|
33672
|
+
/** Panel width when expanded */
|
|
33673
|
+
this.expandedWidth = '280px';
|
|
33674
|
+
/** Maximum width when expanded (e.g. '600px', '30vw'). Default: 30% of viewport */
|
|
33675
|
+
this.maxExpandedWidth = '30vw';
|
|
33676
|
+
/** Panel width when collapsed */
|
|
33677
|
+
this.collapsedWidth = '56px';
|
|
33678
|
+
this.expandTooltip = 'Expand';
|
|
33679
|
+
this.collapseTooltip = 'Collapse';
|
|
33680
|
+
this.closeTooltip = 'Close';
|
|
33681
|
+
this.activeTabChange = new EventEmitter();
|
|
33682
|
+
this.expandToggle = new EventEmitter();
|
|
33683
|
+
this.close = new EventEmitter();
|
|
33684
|
+
}
|
|
33685
|
+
get hostWidth() {
|
|
33686
|
+
return this.expanded ? this.expandedWidth : this.collapsedWidth;
|
|
33687
|
+
}
|
|
33688
|
+
get hostMinWidth() {
|
|
33689
|
+
return this.expanded && this.minExpandedWidth ? this.minExpandedWidth : null;
|
|
33690
|
+
}
|
|
33691
|
+
get hostMaxWidth() {
|
|
33692
|
+
return this.expanded ? this.maxExpandedWidth : null;
|
|
33693
|
+
}
|
|
33694
|
+
ngAfterContentInit() {
|
|
33695
|
+
this.ensureActiveTab();
|
|
33696
|
+
}
|
|
33697
|
+
ngAfterContentChecked() {
|
|
33698
|
+
this.ensureActiveTab();
|
|
33699
|
+
}
|
|
33700
|
+
ensureActiveTab() {
|
|
33701
|
+
const tabs = this.tabComponents?.toArray() ?? [];
|
|
33702
|
+
if (tabs.length > 0 && !this.activeTab) {
|
|
33703
|
+
this.activeTab = tabs[0].value;
|
|
33704
|
+
this.activeTabChange.emit(this.activeTab);
|
|
33705
|
+
}
|
|
33706
|
+
}
|
|
33707
|
+
onTabClick(tab) {
|
|
33708
|
+
// If drawer is collapsed, open it (but never close on tab click)
|
|
33709
|
+
if (!this.expanded) {
|
|
33710
|
+
this.expandToggle.emit();
|
|
33711
|
+
}
|
|
33712
|
+
// Select the tab
|
|
33713
|
+
if (tab.value !== this.activeTab) {
|
|
33714
|
+
this.activeTab = tab.value;
|
|
33715
|
+
this.activeTabChange.emit(this.activeTab);
|
|
33716
|
+
}
|
|
33717
|
+
}
|
|
33718
|
+
onExpandToggle() {
|
|
33719
|
+
this.expandToggle.emit();
|
|
33720
|
+
}
|
|
33721
|
+
onClose() {
|
|
33722
|
+
this.close.emit();
|
|
33723
|
+
}
|
|
33724
|
+
trackByValue(_i, tab) {
|
|
33725
|
+
return tab.value;
|
|
33726
|
+
}
|
|
33727
|
+
isTabActive(tab) {
|
|
33728
|
+
return tab.value === this.activeTab;
|
|
33729
|
+
}
|
|
33730
|
+
}
|
|
33731
|
+
DetailDrawerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DetailDrawerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
33732
|
+
DetailDrawerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: DetailDrawerComponent, selector: "cqa-detail-drawer", inputs: { activeTab: "activeTab", showCloseButton: "showCloseButton", expanded: "expanded", expandedWidth: "expandedWidth", minExpandedWidth: "minExpandedWidth", maxExpandedWidth: "maxExpandedWidth", collapsedWidth: "collapsedWidth", expandTooltip: "expandTooltip", collapseTooltip: "collapseTooltip", closeTooltip: "closeTooltip" }, outputs: { activeTabChange: "activeTabChange", expandToggle: "expandToggle", close: "close" }, host: { properties: { "style.width": "this.hostWidth", "style.min-width": "this.hostMinWidth", "style.max-width": "this.hostMaxWidth" }, styleAttribute: "transition: width 0.3s ease-in-out", classAttribute: "cqa-ui-root cqa-flex cqa-flex-col cqa-h-full cqa-bg-white cqa-shadow-[-4px_0_6px_-1px_rgba(0,0,0,0.05)]" }, queries: [{ propertyName: "tabComponents", predicate: DetailDrawerTabComponent }], ngImport: i0, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white\">\n <div\n class=\"cqa-grid cqa-flex-1 cqa-min-h-0 cqa-overflow-hidden\"\n [style.grid-template-columns]=\"expanded ? 'auto 1fr' : 'auto 0fr'\"\n style=\"transition: grid-template-columns 0.3s ease-in-out\">\n <!-- Left vertical icon bar: one button per tab -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1 cqa-min-h-0 cqa-items-center cqa-py-4 cqa-px-2 cqa-border-r cqa-border-[#E2E8F0] cqa-bg-[#FAFAFA] cqa-flex-shrink-0\">\n <!-- Expand / Collapse button (always visible) -->\n <button\n type=\"button\"\n [matTooltip]=\"expanded ? collapseTooltip : expandTooltip\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2 cqa-flex-shrink-0\"\n (click)=\"onExpandToggle()\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">{{ expanded ? 'unfold_less' : 'unfold_more' }}</mat-icon>\n </button>\n <!-- Close button -->\n <button\n *ngIf=\"showCloseButton\"\n type=\"button\"\n [matTooltip]=\"closeTooltip\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2 cqa-flex-shrink-0\"\n (click)=\"onClose()\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">close</mat-icon>\n </button>\n <!-- Tab buttons: equally distributed in remaining space -->\n <div class=\"cqa-flex cqa-flex-1 cqa-flex-col cqa-justify-evenly cqa-items-center cqa-w-full\">\n <button\n *ngFor=\"let tab of tabComponents; trackBy: trackByValue\"\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"isTabActive(tab)\"\n [matTooltip]=\"tab.label\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2 cqa-flex-shrink-0\"\n [ngClass]=\"{\n 'cqa-bg-[#3F43EE] cqa-text-white': isTabActive(tab),\n 'cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155]': !isTabActive(tab)\n }\"\n (click)=\"onTabClick(tab)\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">{{ tab.icon }}</mat-icon>\n </button>\n </div>\n </div>\n\n <!-- Content area: show only the active tab's content -->\n <div class=\"cqa-min-w-0 cqa-overflow-hidden\">\n <div class=\"cqa-h-full cqa-overflow-y-auto cqa-p-4\">\n <ng-container *ngFor=\"let tab of tabComponents\">\n <ng-container *ngIf=\"tab.value === activeTab && tab.contentTemplate\" [ngTemplateOutlet]=\"tab.contentTemplate\"></ng-container>\n </ng-container>\n </div>\n </div>\n </div>\n</div>\n", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i5.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
33733
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DetailDrawerComponent, decorators: [{
|
|
33734
|
+
type: Component,
|
|
33735
|
+
args: [{ selector: 'cqa-detail-drawer', changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
33736
|
+
class: 'cqa-ui-root cqa-flex cqa-flex-col cqa-h-full cqa-bg-white cqa-shadow-[-4px_0_6px_-1px_rgba(0,0,0,0.05)]',
|
|
33737
|
+
style: 'transition: width 0.3s ease-in-out',
|
|
33738
|
+
}, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white\">\n <div\n class=\"cqa-grid cqa-flex-1 cqa-min-h-0 cqa-overflow-hidden\"\n [style.grid-template-columns]=\"expanded ? 'auto 1fr' : 'auto 0fr'\"\n style=\"transition: grid-template-columns 0.3s ease-in-out\">\n <!-- Left vertical icon bar: one button per tab -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1 cqa-min-h-0 cqa-items-center cqa-py-4 cqa-px-2 cqa-border-r cqa-border-[#E2E8F0] cqa-bg-[#FAFAFA] cqa-flex-shrink-0\">\n <!-- Expand / Collapse button (always visible) -->\n <button\n type=\"button\"\n [matTooltip]=\"expanded ? collapseTooltip : expandTooltip\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2 cqa-flex-shrink-0\"\n (click)=\"onExpandToggle()\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">{{ expanded ? 'unfold_less' : 'unfold_more' }}</mat-icon>\n </button>\n <!-- Close button -->\n <button\n *ngIf=\"showCloseButton\"\n type=\"button\"\n [matTooltip]=\"closeTooltip\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2 cqa-flex-shrink-0\"\n (click)=\"onClose()\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">close</mat-icon>\n </button>\n <!-- Tab buttons: equally distributed in remaining space -->\n <div class=\"cqa-flex cqa-flex-1 cqa-flex-col cqa-justify-evenly cqa-items-center cqa-w-full\">\n <button\n *ngFor=\"let tab of tabComponents; trackBy: trackByValue\"\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"isTabActive(tab)\"\n [matTooltip]=\"tab.label\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2 cqa-flex-shrink-0\"\n [ngClass]=\"{\n 'cqa-bg-[#3F43EE] cqa-text-white': isTabActive(tab),\n 'cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155]': !isTabActive(tab)\n }\"\n (click)=\"onTabClick(tab)\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">{{ tab.icon }}</mat-icon>\n </button>\n </div>\n </div>\n\n <!-- Content area: show only the active tab's content -->\n <div class=\"cqa-min-w-0 cqa-overflow-hidden\">\n <div class=\"cqa-h-full cqa-overflow-y-auto cqa-p-4\">\n <ng-container *ngFor=\"let tab of tabComponents\">\n <ng-container *ngIf=\"tab.value === activeTab && tab.contentTemplate\" [ngTemplateOutlet]=\"tab.contentTemplate\"></ng-container>\n </ng-container>\n </div>\n </div>\n </div>\n</div>\n", styles: [] }]
|
|
33739
|
+
}], propDecorators: { tabComponents: [{
|
|
33740
|
+
type: ContentChildren,
|
|
33741
|
+
args: [DetailDrawerTabComponent]
|
|
33742
|
+
}], activeTab: [{
|
|
33743
|
+
type: Input
|
|
33744
|
+
}], showCloseButton: [{
|
|
33745
|
+
type: Input
|
|
33746
|
+
}], expanded: [{
|
|
33747
|
+
type: Input
|
|
33748
|
+
}], expandedWidth: [{
|
|
33749
|
+
type: Input
|
|
33750
|
+
}], minExpandedWidth: [{
|
|
33751
|
+
type: Input
|
|
33752
|
+
}], maxExpandedWidth: [{
|
|
33753
|
+
type: Input
|
|
33754
|
+
}], collapsedWidth: [{
|
|
33755
|
+
type: Input
|
|
33756
|
+
}], hostWidth: [{
|
|
33757
|
+
type: HostBinding,
|
|
33758
|
+
args: ['style.width']
|
|
33759
|
+
}], hostMinWidth: [{
|
|
33760
|
+
type: HostBinding,
|
|
33761
|
+
args: ['style.min-width']
|
|
33762
|
+
}], hostMaxWidth: [{
|
|
33763
|
+
type: HostBinding,
|
|
33764
|
+
args: ['style.max-width']
|
|
33765
|
+
}], expandTooltip: [{
|
|
33766
|
+
type: Input
|
|
33767
|
+
}], collapseTooltip: [{
|
|
33768
|
+
type: Input
|
|
33769
|
+
}], closeTooltip: [{
|
|
33770
|
+
type: Input
|
|
33771
|
+
}], activeTabChange: [{
|
|
33772
|
+
type: Output
|
|
33773
|
+
}], expandToggle: [{
|
|
33774
|
+
type: Output
|
|
33775
|
+
}], close: [{
|
|
33776
|
+
type: Output
|
|
33777
|
+
}] } });
|
|
33778
|
+
|
|
33779
|
+
/** Keys for each dynamic select in test-case-details-edit. Use these with selectConfigOverrides. */
|
|
33780
|
+
const TEST_CASE_DETAILS_SELECT_KEYS = {
|
|
33781
|
+
status: 'status',
|
|
33782
|
+
priority: 'priority',
|
|
33783
|
+
type: 'type',
|
|
33784
|
+
labels: 'labels',
|
|
33785
|
+
prerequisiteCases: 'prerequisiteCases',
|
|
33786
|
+
testDataProfile: 'testDataProfile',
|
|
33787
|
+
testDataSet: 'testDataSet',
|
|
33788
|
+
videoRecording: 'videoRecording',
|
|
33789
|
+
enableAiSmartness: 'enableAiSmartness',
|
|
33790
|
+
defaultAiAction: 'defaultAiAction',
|
|
33791
|
+
knowledgeBaseDefaultTestCase: 'knowledgeBaseDefaultTestCase',
|
|
33792
|
+
useAiMetadata: 'useAiMetadata',
|
|
33793
|
+
defaultBrowser: 'defaultBrowser',
|
|
33794
|
+
defaultViewport: 'defaultViewport',
|
|
33795
|
+
deviceType: 'deviceType',
|
|
33796
|
+
deviceOS: 'deviceOS',
|
|
33797
|
+
};
|
|
33798
|
+
const FREQUENTLY_USED_LABELS = [
|
|
33799
|
+
'Case',
|
|
33800
|
+
'Critical',
|
|
33801
|
+
'PO',
|
|
33802
|
+
'Upload',
|
|
33803
|
+
'Validation',
|
|
33804
|
+
'Review',
|
|
33805
|
+
'Edge-cases',
|
|
33806
|
+
'Security',
|
|
33807
|
+
'Integration',
|
|
33808
|
+
'Smoke',
|
|
33809
|
+
];
|
|
33810
|
+
class TestCaseDetailsEditComponent {
|
|
33811
|
+
constructor(cdr) {
|
|
33812
|
+
this.cdr = cdr;
|
|
33813
|
+
this.descriptionTitle = 'Description';
|
|
33814
|
+
this.descriptionContent = '';
|
|
33815
|
+
/** When true, description uses Trix rich text editor (Bold, Italic, etc.). Host app must load Trix. */
|
|
33816
|
+
this.enableMarkdown = false;
|
|
33817
|
+
this.metadataItems = [];
|
|
33818
|
+
this.labels = [];
|
|
33819
|
+
this.configTitle = 'Configuration';
|
|
33820
|
+
this.configSections = [];
|
|
33821
|
+
this.configSectionsRow2 = [];
|
|
33822
|
+
/** Optional list of prerequisite test case options for the multi-select. If not provided, uses default sample options. */
|
|
33823
|
+
this.prerequisiteCaseOptions = [];
|
|
33824
|
+
/** Platform: 'web' shows Default Browser + Viewport; 'mobile' shows Device Type + OS. Defaults to 'web'. */
|
|
33825
|
+
this.platform = 'web';
|
|
33826
|
+
/** When true, hides Priority, Type, and Test Data Set fields (step groups don't have these). Defaults to false. */
|
|
33827
|
+
this.isStepGroup = false;
|
|
33828
|
+
/**
|
|
33829
|
+
* Override config per select key. Use for:
|
|
33830
|
+
* - API-driven options: pass options array (update when API returns)
|
|
33831
|
+
* - Server-side search: serverSearch: true, onSearch in override or listen to selectSearch
|
|
33832
|
+
* - Infinite scroll: hasMore: true, onLoadMore in override or listen to selectLoadMore
|
|
33833
|
+
* - Initial fetch on open: initialFetchOnOpen: true
|
|
33834
|
+
*/
|
|
33835
|
+
this.selectConfigOverrides = {};
|
|
33836
|
+
this.save = new EventEmitter();
|
|
33837
|
+
this.cancel = new EventEmitter();
|
|
33838
|
+
/** Emitted when user searches in a select (serverSearch mode). Call API and update options via selectConfigOverrides. */
|
|
33839
|
+
this.selectSearch = new EventEmitter();
|
|
33840
|
+
/** Emitted when user scrolls to load more. Call API, append to options via selectConfigOverrides. */
|
|
33841
|
+
this.selectLoadMore = new EventEmitter();
|
|
33842
|
+
/** Emitted when a select panel is opened. Use to call API for initial load (e.g. when initialFetchOnOpen). */
|
|
33843
|
+
this.selectOpened = new EventEmitter();
|
|
33844
|
+
/** Emitted when selection changes in any select. */
|
|
33845
|
+
this.selectionChange = new EventEmitter();
|
|
33846
|
+
/** Emitted when user adds a new custom label via the "New" option. */
|
|
33847
|
+
this.labelAdded = new EventEmitter();
|
|
33848
|
+
/** Form state */
|
|
33849
|
+
this.editDescription = '';
|
|
33850
|
+
this.editStatus = '';
|
|
33851
|
+
this.editPriority = '';
|
|
33852
|
+
this.editLabels = [];
|
|
33853
|
+
this.testCaseTimeout = '';
|
|
33854
|
+
this.waitTimeoutLocators = '';
|
|
33855
|
+
this.autoWaitEnabled = false;
|
|
33856
|
+
this.retryFailedSteps = '';
|
|
33857
|
+
this.configExpanded = true;
|
|
33858
|
+
this.executionExpanded = true;
|
|
33859
|
+
this.aiConfigExpanded = true;
|
|
33860
|
+
this.waitsRetriesExpanded = true;
|
|
33861
|
+
this.deviceExpanded = true;
|
|
33862
|
+
this.keyFlagsExpanded = true;
|
|
33863
|
+
this.mobileTestingEnabled = false;
|
|
33864
|
+
this.extensionUseEnabled = false;
|
|
33865
|
+
this.dataDrivenEnabled = false;
|
|
33866
|
+
this.frequentlyUsedLabels = FREQUENTLY_USED_LABELS;
|
|
33867
|
+
/** FormGroup for cqa-dynamic-select bindings */
|
|
33868
|
+
this.editForm = new FormGroup({
|
|
33869
|
+
status: new FormControl(''),
|
|
33870
|
+
priority: new FormControl(''),
|
|
33871
|
+
type: new FormControl(''),
|
|
33872
|
+
labels: new FormControl([]),
|
|
33873
|
+
prerequisiteCases: new FormControl([]),
|
|
33874
|
+
testDataProfile: new FormControl(''),
|
|
33875
|
+
testDataSet: new FormControl(''),
|
|
33876
|
+
defaultBrowser: new FormControl(''),
|
|
33877
|
+
videoRecording: new FormControl(''),
|
|
33878
|
+
defaultViewport: new FormControl(''),
|
|
33879
|
+
deviceType: new FormControl(''),
|
|
33880
|
+
deviceOS: new FormControl(''),
|
|
33881
|
+
enableAiSmartness: new FormControl(''),
|
|
33882
|
+
defaultAiAction: new FormControl(''),
|
|
33883
|
+
knowledgeBaseDefaultTestCase: new FormControl(''),
|
|
33884
|
+
useAiMetadata: new FormControl(''),
|
|
33885
|
+
});
|
|
33886
|
+
/** Cached configs to avoid new object refs each change detection (prevents infinite loops) */
|
|
33887
|
+
this.statusSelectConfig = {
|
|
33888
|
+
key: 'status',
|
|
33889
|
+
label: '',
|
|
33890
|
+
placeholder: 'Status',
|
|
33891
|
+
searchable: false,
|
|
33892
|
+
options: [
|
|
33893
|
+
{ value: 'Draft', name: 'Draft' },
|
|
33894
|
+
{ value: 'In Review', name: 'In Review' },
|
|
33895
|
+
{ value: 'Approved', name: 'Approved' },
|
|
33896
|
+
{ value: 'Active', name: 'Active' },
|
|
33897
|
+
{ value: 'Inactive', name: 'Inactive' },
|
|
33898
|
+
{ value: 'Blocked', name: 'Blocked' },
|
|
33899
|
+
],
|
|
33900
|
+
};
|
|
33901
|
+
this.typeSelectConfig = {
|
|
33902
|
+
key: 'type',
|
|
33903
|
+
label: '',
|
|
33904
|
+
placeholder: 'Type',
|
|
33905
|
+
searchable: true,
|
|
33906
|
+
options: [],
|
|
33907
|
+
};
|
|
33908
|
+
this.testDataProfileSelectConfig = {
|
|
33909
|
+
key: 'testDataProfile',
|
|
33910
|
+
label: '',
|
|
33911
|
+
placeholder: 'Test Data Profile',
|
|
33912
|
+
searchable: true,
|
|
33913
|
+
options: [],
|
|
33914
|
+
};
|
|
33915
|
+
this.testDataSetSelectConfig = {
|
|
33916
|
+
key: 'testDataSet',
|
|
33917
|
+
label: '',
|
|
33918
|
+
placeholder: 'Test Data Set',
|
|
33919
|
+
searchable: true,
|
|
33920
|
+
options: [],
|
|
33921
|
+
};
|
|
33922
|
+
this.defaultPrerequisiteCaseOptions = [
|
|
33923
|
+
{ value: 'TC-001', name: 'TC-001: Login flow' },
|
|
33924
|
+
{ value: 'TC-002', name: 'TC-002: User registration' },
|
|
33925
|
+
{ value: 'TC-003', name: 'TC-003: Password reset' },
|
|
33926
|
+
{ value: 'TC-004', name: 'TC-004: Dashboard load' },
|
|
33927
|
+
{ value: 'TC-005', name: 'TC-005: API health check' },
|
|
33928
|
+
];
|
|
33929
|
+
this.videoRecordingSelectConfig = {
|
|
33930
|
+
key: 'videoRecording',
|
|
33931
|
+
label: 'Record test execution video',
|
|
33932
|
+
placeholder: 'Select',
|
|
33933
|
+
searchable: false,
|
|
33934
|
+
options: [
|
|
33935
|
+
{ value: 'true', name: 'True' },
|
|
33936
|
+
{ value: 'false', name: 'False' },
|
|
33937
|
+
{ value: 'Org level', name: 'Org level' },
|
|
33938
|
+
],
|
|
33939
|
+
};
|
|
33940
|
+
this.aiMetadataCollectionSelectConfig = {
|
|
33941
|
+
key: 'useAiMetadata',
|
|
33942
|
+
label: 'Enable AI metadata collection',
|
|
33943
|
+
placeholder: 'Select',
|
|
33944
|
+
searchable: false,
|
|
33945
|
+
options: [
|
|
33946
|
+
{ value: 'true', name: 'True' },
|
|
33947
|
+
{ value: 'false', name: 'False' },
|
|
33948
|
+
{ value: 'Org level', name: 'Org level' },
|
|
33949
|
+
],
|
|
33950
|
+
};
|
|
33951
|
+
/** Cached labels config to avoid new object on every CD (prevents freeze) */
|
|
33952
|
+
this._labelsSelectConfigCache = null;
|
|
33953
|
+
this._labelsSelectConfigDirty = true;
|
|
33954
|
+
this.prerequisiteCaseSelectConfig = {
|
|
33955
|
+
key: 'prerequisiteCases',
|
|
33956
|
+
label: 'Prerequisite Case',
|
|
33957
|
+
placeholder: 'Select',
|
|
33958
|
+
searchable: true,
|
|
33959
|
+
multiple: true,
|
|
33960
|
+
optionStyle: 'checkbox',
|
|
33961
|
+
showSelectAll: true,
|
|
33962
|
+
selectAllLabel: 'All',
|
|
33963
|
+
options: [
|
|
33964
|
+
{ value: 'TC-001', name: 'TC-001: Login flow' },
|
|
33965
|
+
{ value: 'TC-002', name: 'TC-002: User registration' },
|
|
33966
|
+
{ value: 'TC-003', name: 'TC-003: Password reset' },
|
|
33967
|
+
{ value: 'TC-004', name: 'TC-004: Dashboard load' },
|
|
33968
|
+
{ value: 'TC-005', name: 'TC-005: API health check' },
|
|
33969
|
+
],
|
|
33970
|
+
};
|
|
33971
|
+
this.defaultViewportSelectConfig = {
|
|
33972
|
+
key: 'defaultViewport',
|
|
33973
|
+
label: 'Default Viewport',
|
|
33974
|
+
placeholder: 'Select',
|
|
33975
|
+
searchable: false,
|
|
33976
|
+
options: [
|
|
33977
|
+
{ value: '1280x720', name: '1280x720' },
|
|
33978
|
+
],
|
|
33979
|
+
};
|
|
33980
|
+
this.deviceTypeSelectConfig = {
|
|
33981
|
+
key: 'deviceType',
|
|
33982
|
+
label: 'Device Type',
|
|
33983
|
+
placeholder: 'Select',
|
|
33984
|
+
searchable: false,
|
|
33985
|
+
options: [
|
|
33986
|
+
{ value: 'iPhone 14', name: 'iPhone 14' },
|
|
33987
|
+
{ value: 'iPhone 15', name: 'iPhone 15' },
|
|
33988
|
+
{ value: 'iPhone 17', name: 'iPhone 17' },
|
|
33989
|
+
{ value: 'Iphone 17', name: 'Iphone 17' },
|
|
33990
|
+
{ value: 'Samsung Galaxy', name: 'Samsung Galaxy' },
|
|
33991
|
+
{ value: 'Pixel', name: 'Pixel' },
|
|
33992
|
+
],
|
|
33993
|
+
};
|
|
33994
|
+
this.deviceOSSelectConfig = {
|
|
33995
|
+
key: 'deviceOS',
|
|
33996
|
+
label: 'OS',
|
|
33997
|
+
placeholder: 'Select',
|
|
33998
|
+
searchable: false,
|
|
33999
|
+
options: [
|
|
34000
|
+
{ value: 'ipa', name: 'iOS (ipa)' },
|
|
34001
|
+
{ value: 'apk', name: 'Android (apk)' },
|
|
34002
|
+
{ value: 'iOS 16', name: 'iOS 16' },
|
|
34003
|
+
{ value: 'iOS 17', name: 'iOS 17' },
|
|
34004
|
+
{ value: 'Android 13', name: 'Android 13' },
|
|
34005
|
+
{ value: 'Android 14', name: 'Android 14' },
|
|
34006
|
+
],
|
|
34007
|
+
};
|
|
34008
|
+
this.defaultBrowserSelectConfig = {
|
|
34009
|
+
key: 'defaultBrowser',
|
|
34010
|
+
label: 'Default Browser',
|
|
34011
|
+
placeholder: 'Chrome',
|
|
34012
|
+
searchable: false,
|
|
34013
|
+
options: [
|
|
34014
|
+
{ value: 'Chrome', name: 'Chrome' },
|
|
34015
|
+
{ value: 'Firefox', name: 'Firefox' },
|
|
34016
|
+
{ value: 'Safari', name: 'Safari' },
|
|
34017
|
+
{ value: 'Edge', name: 'Edge' },
|
|
34018
|
+
],
|
|
34019
|
+
};
|
|
34020
|
+
this.prioritySelectConfig = {
|
|
34021
|
+
key: 'priority',
|
|
34022
|
+
label: '',
|
|
34023
|
+
placeholder: 'Priority',
|
|
34024
|
+
searchable: false,
|
|
33742
34025
|
options: [
|
|
33743
34026
|
{ value: 'Critical', name: 'Critical' },
|
|
33744
34027
|
{ value: 'Major', name: 'Major' },
|
|
@@ -34413,234 +34696,43 @@ class TestCaseDetailsComponent {
|
|
|
34413
34696
|
return this.editing !== undefined ? this.editing : this._editing;
|
|
34414
34697
|
}
|
|
34415
34698
|
ngOnInit() {
|
|
34416
|
-
if (this.startInEditMode) {
|
|
34417
|
-
this._editing = true;
|
|
34418
|
-
}
|
|
34419
|
-
}
|
|
34420
|
-
/** Filtered metadata items - excludes Priority and Type for step groups */
|
|
34421
|
-
get filteredMetadataItems() {
|
|
34422
|
-
if (!this.isStepGroup) {
|
|
34423
|
-
return this.metadataItems;
|
|
34424
|
-
}
|
|
34425
|
-
return this.metadataItems.filter((item) => !this.stepGroupExcludedMetadataLabels.includes(item.label?.toLowerCase() ?? ''));
|
|
34426
|
-
}
|
|
34427
|
-
onEditClick() {
|
|
34428
|
-
if (this.editing === undefined) {
|
|
34429
|
-
this._editing = true;
|
|
34430
|
-
this.cdr.detectChanges();
|
|
34431
|
-
}
|
|
34432
|
-
this.editDescription.emit();
|
|
34433
|
-
}
|
|
34434
|
-
onSaveChanges(data) {
|
|
34435
|
-
if (this.editing === undefined) {
|
|
34436
|
-
this._editing = false;
|
|
34437
|
-
}
|
|
34438
|
-
this.cdr.detectChanges();
|
|
34439
|
-
this.saveChanges.emit(data);
|
|
34440
|
-
}
|
|
34441
|
-
onCancelEdit() {
|
|
34442
|
-
this.cancel.emit();
|
|
34443
|
-
if (this.editing === undefined) {
|
|
34444
|
-
this._editing = false;
|
|
34445
|
-
}
|
|
34446
|
-
this.cdr.detectChanges();
|
|
34447
|
-
}
|
|
34448
|
-
trackByConfigTitle(_i, section) {
|
|
34449
|
-
return section.title;
|
|
34450
|
-
}
|
|
34451
|
-
trackByMetadataLabel(_i, item) {
|
|
34452
|
-
return item.label;
|
|
34453
|
-
}
|
|
34454
|
-
onMetadataLinkClick(item) {
|
|
34455
|
-
if (item.link) {
|
|
34456
|
-
this.metadataLinkClick.emit(item);
|
|
34457
|
-
}
|
|
34458
|
-
}
|
|
34459
|
-
getStatusDotClass(item) {
|
|
34460
|
-
if (!item.statusColor)
|
|
34461
|
-
return '';
|
|
34462
|
-
switch (item.statusColor) {
|
|
34463
|
-
case 'yellow':
|
|
34464
|
-
return 'cqa-bg-[#EAB308]';
|
|
34465
|
-
case 'red':
|
|
34466
|
-
return 'cqa-bg-[#DC2626]';
|
|
34467
|
-
case 'green':
|
|
34468
|
-
return 'cqa-bg-[#16A34A]';
|
|
34469
|
-
case 'gray':
|
|
34470
|
-
default:
|
|
34471
|
-
return 'cqa-bg-[#94A3B8]';
|
|
34472
|
-
}
|
|
34473
|
-
}
|
|
34474
|
-
/** Text color for metadata value (e.g. red for critical priority) */
|
|
34475
|
-
getValueTextClass(item) {
|
|
34476
|
-
if (item.statusColor === 'red') {
|
|
34477
|
-
return 'cqa-text-[#DC2626]';
|
|
34478
|
-
}
|
|
34479
|
-
return 'cqa-text-[#111827]';
|
|
34480
|
-
}
|
|
34481
|
-
}
|
|
34482
|
-
TestCaseDetailsComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TestCaseDetailsComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
34483
|
-
TestCaseDetailsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TestCaseDetailsComponent, selector: "cqa-test-case-details", inputs: { editing: "editing", startInEditMode: "startInEditMode", descriptionTitle: "descriptionTitle", descriptionContent: "descriptionContent", enableMarkdown: "enableMarkdown", showEditButton: "showEditButton", metadataItems: "metadataItems", labels: "labels", configTitle: "configTitle", configSections: "configSections", configSectionsRow2: "configSectionsRow2", platform: "platform", isStepGroup: "isStepGroup", selectConfigOverrides: "selectConfigOverrides" }, outputs: { editDescription: "editDescription", cancel: "cancel", saveChanges: "saveChanges", metadataLinkClick: "metadataLinkClick", selectSearch: "selectSearch", selectLoadMore: "selectLoadMore", selectOpened: "selectOpened", selectionChange: "selectionChange", labelAdded: "labelAdded" }, ngImport: i0, template: "<!-- Edit mode: show edit form (Figma design) -->\n<cqa-test-case-details-edit\n *ngIf=\"isEditing\"\n [descriptionTitle]=\"descriptionTitle\"\n [descriptionContent]=\"descriptionContent\"\n [enableMarkdown]=\"enableMarkdown\"\n [metadataItems]=\"metadataItems\"\n [labels]=\"labels\"\n [configTitle]=\"configTitle\"\n [configSections]=\"configSections\"\n [configSectionsRow2]=\"configSectionsRow2\"\n [platform]=\"platform\"\n [isStepGroup]=\"isStepGroup\"\n [selectConfigOverrides]=\"selectConfigOverrides\"\n (save)=\"onSaveChanges($event)\"\n (cancel)=\"onCancelEdit()\"\n (selectSearch)=\"selectSearch.emit($event)\"\n (selectLoadMore)=\"selectLoadMore.emit($event)\"\n (selectOpened)=\"selectOpened.emit($event)\"\n (selectionChange)=\"selectionChange.emit($event)\"\n (labelAdded)=\"labelAdded.emit($event)\">\n</cqa-test-case-details-edit>\n\n<!-- View mode: read-only details -->\n<div *ngIf=\"!isEditing\" class=\"cqa-self-stretch cqa-py-4 cqa-px-0 cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-4 cqa-text-sm cqa-leading-[19.6px]\">\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-4 cqa-text-sm cqa-leading-[19.6px]\">\n <!-- Description Section -->\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2.5\">\n <div class=\"cqa-self-stretch cqa-inline-flex cqa-justify-between cqa-items-center\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-w-5 cqa-h-5 cqa-p-1 cqa-flex-shrink-0 cqa-bg-[#3F43EE1A] cqa-rounded-md cqa-inline-flex cqa-justify-center cqa-items-center\">\n <mat-icon class=\"cqa-text-[#1B1FEB] cqa-text-[12px] cqa-w-3 cqa-h-3 cqa-leading-none cqa-block\">description</mat-icon>\n </div>\n <span class=\"cqa-text-[#374151] cqa-text-sm cqa-font-semibold cqa-leading-[19.6px]\">{{ descriptionTitle }}</span>\n </div>\n <button\n *ngIf=\"showEditButton\"\n type=\"button\"\n class=\"cqa-flex cqa-justify-end cqa-items-center cqa-gap-2 cqa-text-[#A3A3A3] cqa-text-xs cqa-font-semibold hover:cqa-text-[#737373] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onEditClick()\">\n <mat-icon class=\"cqa-text-[14px] cqa-w-4 cqa-h-4\">edit</mat-icon>\n Edit\n </button>\n </div>\n <div *ngIf=\"descriptionContent\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start\">\n <div *ngIf=\"enableMarkdown\" class=\"cqa-self-stretch cqa-text-[#111827] cqa-text-sm cqa-leading-[19.6px] cqa-font-normal cqa-prose cqa-prose-sm cqa-max-w-none\" [innerHTML]=\"descriptionContent\"></div>\n <div *ngIf=\"!enableMarkdown\" class=\"cqa-self-stretch cqa-text-[#111827] cqa-text-sm cqa-leading-[19.6px] cqa-font-normal\">{{ descriptionContent }}</div>\n </div>\n </div>\n\n <!-- Metadata Section -->\n <div *ngIf=\"filteredMetadataItems.length\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2.5\">\n <div class=\"cqa-self-stretch cqa-grid cqa-grid-cols-2 cqa-gap-x-0 cqa-gap-y-4\">\n <ng-container *ngFor=\"let item of filteredMetadataItems; trackBy: trackByMetadataLabel\">\n <div class=\"cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-0.5\">\n <div class=\"cqa-text-[#6B7280] cqa-text-xs cqa-leading-[15px] cqa-font-medium\">{{ item.label }}</div>\n <div\n class=\"cqa-flex cqa-justify-start cqa-items-center cqa-gap-[5px] cqa-min-w-0 cqa-w-full cqa-text-left cqa-text-[#0A0A0A] cqa-border cqa-border-[#F5F5F5]\">\n <mat-icon *ngIf=\"item.icon && (!item.iconLibrary || item.iconLibrary === 'mat')\" class=\"cqa-text-[#6B7280] cqa-text-sm cqa-w-4 cqa-h-4\">\n {{ item.icon }}\n </mat-icon>\n <span *ngIf=\"item.statusColor\" class=\"cqa-w-3.5 cqa-h-3.5 cqa-rounded-full cqa-flex-shrink-0\" [ngClass]=\"getStatusDotClass(item)\"></span>\n <a\n *ngIf=\"item.link\"\n href=\"javascript:void(0)\"\n class=\"cqa-text-[#2563EB] cqa-text-xs cqa-leading-[12px] cqa-font-normal hover:cqa-underline cqa-cursor-pointer cqa-block cqa-truncate cqa-min-w-0\"\n (click)=\"onMetadataLinkClick(item); $event.preventDefault()\">\n {{ item.value }}\n </a>\n <span *ngIf=\"!item.link\" class=\"cqa-text-xs cqa-leading-[12px] cqa-font-normal cqa-align-middle\" [ngClass]=\"getValueTextClass(item)\">\n {{ item.value }}\n </span>\n </div>\n </div>\n </ng-container>\n </div>\n </div>\n\n <!-- Labels (Figma: Labels title, cqa-badge chips with tag icon) -->\n <div *ngIf=\"labels.length\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2 cqa-text-sm cqa-leading-[19.6px]\">\n <span class=\"cqa-text-[#111827] cqa-text-sm cqa-font-medium cqa-leading-5\">Labels</span>\n <div class=\"cqa-flex cqa-flex-wrap cqa-gap-2\">\n <cqa-badge\n *ngFor=\"let label of labels\"\n [label]=\"label\"\n icon=\"label\"\n variant=\"outline\"\n size=\"small\"\n backgroundColor=\"#ffffff\"\n textColor=\"#475569\"\n borderColor=\"#E2E8F0\"\n iconColor=\"#94A3B8\">\n </cqa-badge>\n </div>\n </div>\n\n <!-- Configuration Section -->\n <div *ngIf=\"configSections.length || configSectionsRow2.length\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2.5\">\n <div class=\"cqa-self-stretch cqa-inline-flex cqa-justify-start cqa-items-center\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-w-5 cqa-h-5 cqa-p-1 cqa-flex-shrink-0 cqa-bg-[#3F43EE1A] cqa-rounded-md cqa-inline-flex cqa-justify-center cqa-items-center\">\n <mat-icon class=\"cqa-text-[#1B1FEB] cqa-text-[12px] cqa-w-3 cqa-h-3 cqa-leading-none cqa-block\">settings</mat-icon>\n </div>\n <span class=\"cqa-text-[#374151] cqa-text-sm cqa-font-semibold cqa-leading-[19.6px]\">{{ configTitle }}</span>\n </div>\n </div>\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2.5\">\n <div class=\"cqa-self-stretch cqa-grid cqa-grid-cols-1 cqa-gap-2.5\">\n <ng-container *ngFor=\"let section of configSections; trackBy: trackByConfigTitle\">\n <cqa-configuration-card\n [icon]=\"section.icon || 'tune'\"\n [title]=\"section.title\"\n [data]=\"section.items\">\n </cqa-configuration-card>\n </ng-container>\n </div>\n <div *ngIf=\"configSectionsRow2.length\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-gap-4 cqa-text-sm cqa-leading-[19.6px]\">\n <cqa-configuration-card\n *ngFor=\"let section of configSectionsRow2; trackBy: trackByConfigTitle\"\n [icon]=\"section.icon || 'tune'\"\n [title]=\"section.title\"\n [data]=\"section.items\">\n </cqa-configuration-card>\n </div>\n </div>\n </div>\n </div>\n</div>\n", components: [{ type: TestCaseDetailsEditComponent, selector: "cqa-test-case-details-edit", inputs: ["descriptionTitle", "descriptionContent", "enableMarkdown", "metadataItems", "labels", "configTitle", "configSections", "configSectionsRow2", "prerequisiteCaseOptions", "platform", "isStepGroup", "selectConfigOverrides"], outputs: ["save", "cancel", "selectSearch", "selectLoadMore", "selectOpened", "selectionChange", "labelAdded"] }, { type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { type: BadgeComponent, selector: "cqa-badge", inputs: ["type", "label", "icon", "iconLibrary", "variant", "size", "backgroundColor", "textColor", "borderColor", "iconBackgroundColor", "iconColor", "iconSize", "inlineStyles", "key", "value", "keyTextColor", "valueTextColor", "isLoading"] }, { type: ConfigurationCardComponent, selector: "cqa-configuration-card", inputs: ["icon", "title", "data"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
34484
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TestCaseDetailsComponent, decorators: [{
|
|
34485
|
-
type: Component,
|
|
34486
|
-
args: [{ selector: 'cqa-test-case-details', changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Edit mode: show edit form (Figma design) -->\n<cqa-test-case-details-edit\n *ngIf=\"isEditing\"\n [descriptionTitle]=\"descriptionTitle\"\n [descriptionContent]=\"descriptionContent\"\n [enableMarkdown]=\"enableMarkdown\"\n [metadataItems]=\"metadataItems\"\n [labels]=\"labels\"\n [configTitle]=\"configTitle\"\n [configSections]=\"configSections\"\n [configSectionsRow2]=\"configSectionsRow2\"\n [platform]=\"platform\"\n [isStepGroup]=\"isStepGroup\"\n [selectConfigOverrides]=\"selectConfigOverrides\"\n (save)=\"onSaveChanges($event)\"\n (cancel)=\"onCancelEdit()\"\n (selectSearch)=\"selectSearch.emit($event)\"\n (selectLoadMore)=\"selectLoadMore.emit($event)\"\n (selectOpened)=\"selectOpened.emit($event)\"\n (selectionChange)=\"selectionChange.emit($event)\"\n (labelAdded)=\"labelAdded.emit($event)\">\n</cqa-test-case-details-edit>\n\n<!-- View mode: read-only details -->\n<div *ngIf=\"!isEditing\" class=\"cqa-self-stretch cqa-py-4 cqa-px-0 cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-4 cqa-text-sm cqa-leading-[19.6px]\">\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-4 cqa-text-sm cqa-leading-[19.6px]\">\n <!-- Description Section -->\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2.5\">\n <div class=\"cqa-self-stretch cqa-inline-flex cqa-justify-between cqa-items-center\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-w-5 cqa-h-5 cqa-p-1 cqa-flex-shrink-0 cqa-bg-[#3F43EE1A] cqa-rounded-md cqa-inline-flex cqa-justify-center cqa-items-center\">\n <mat-icon class=\"cqa-text-[#1B1FEB] cqa-text-[12px] cqa-w-3 cqa-h-3 cqa-leading-none cqa-block\">description</mat-icon>\n </div>\n <span class=\"cqa-text-[#374151] cqa-text-sm cqa-font-semibold cqa-leading-[19.6px]\">{{ descriptionTitle }}</span>\n </div>\n <button\n *ngIf=\"showEditButton\"\n type=\"button\"\n class=\"cqa-flex cqa-justify-end cqa-items-center cqa-gap-2 cqa-text-[#A3A3A3] cqa-text-xs cqa-font-semibold hover:cqa-text-[#737373] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onEditClick()\">\n <mat-icon class=\"cqa-text-[14px] cqa-w-4 cqa-h-4\">edit</mat-icon>\n Edit\n </button>\n </div>\n <div *ngIf=\"descriptionContent\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start\">\n <div *ngIf=\"enableMarkdown\" class=\"cqa-self-stretch cqa-text-[#111827] cqa-text-sm cqa-leading-[19.6px] cqa-font-normal cqa-prose cqa-prose-sm cqa-max-w-none\" [innerHTML]=\"descriptionContent\"></div>\n <div *ngIf=\"!enableMarkdown\" class=\"cqa-self-stretch cqa-text-[#111827] cqa-text-sm cqa-leading-[19.6px] cqa-font-normal\">{{ descriptionContent }}</div>\n </div>\n </div>\n\n <!-- Metadata Section -->\n <div *ngIf=\"filteredMetadataItems.length\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2.5\">\n <div class=\"cqa-self-stretch cqa-grid cqa-grid-cols-2 cqa-gap-x-0 cqa-gap-y-4\">\n <ng-container *ngFor=\"let item of filteredMetadataItems; trackBy: trackByMetadataLabel\">\n <div class=\"cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-0.5\">\n <div class=\"cqa-text-[#6B7280] cqa-text-xs cqa-leading-[15px] cqa-font-medium\">{{ item.label }}</div>\n <div\n class=\"cqa-flex cqa-justify-start cqa-items-center cqa-gap-[5px] cqa-min-w-0 cqa-w-full cqa-text-left cqa-text-[#0A0A0A] cqa-border cqa-border-[#F5F5F5]\">\n <mat-icon *ngIf=\"item.icon && (!item.iconLibrary || item.iconLibrary === 'mat')\" class=\"cqa-text-[#6B7280] cqa-text-sm cqa-w-4 cqa-h-4\">\n {{ item.icon }}\n </mat-icon>\n <span *ngIf=\"item.statusColor\" class=\"cqa-w-3.5 cqa-h-3.5 cqa-rounded-full cqa-flex-shrink-0\" [ngClass]=\"getStatusDotClass(item)\"></span>\n <a\n *ngIf=\"item.link\"\n href=\"javascript:void(0)\"\n class=\"cqa-text-[#2563EB] cqa-text-xs cqa-leading-[12px] cqa-font-normal hover:cqa-underline cqa-cursor-pointer cqa-block cqa-truncate cqa-min-w-0\"\n (click)=\"onMetadataLinkClick(item); $event.preventDefault()\">\n {{ item.value }}\n </a>\n <span *ngIf=\"!item.link\" class=\"cqa-text-xs cqa-leading-[12px] cqa-font-normal cqa-align-middle\" [ngClass]=\"getValueTextClass(item)\">\n {{ item.value }}\n </span>\n </div>\n </div>\n </ng-container>\n </div>\n </div>\n\n <!-- Labels (Figma: Labels title, cqa-badge chips with tag icon) -->\n <div *ngIf=\"labels.length\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2 cqa-text-sm cqa-leading-[19.6px]\">\n <span class=\"cqa-text-[#111827] cqa-text-sm cqa-font-medium cqa-leading-5\">Labels</span>\n <div class=\"cqa-flex cqa-flex-wrap cqa-gap-2\">\n <cqa-badge\n *ngFor=\"let label of labels\"\n [label]=\"label\"\n icon=\"label\"\n variant=\"outline\"\n size=\"small\"\n backgroundColor=\"#ffffff\"\n textColor=\"#475569\"\n borderColor=\"#E2E8F0\"\n iconColor=\"#94A3B8\">\n </cqa-badge>\n </div>\n </div>\n\n <!-- Configuration Section -->\n <div *ngIf=\"configSections.length || configSectionsRow2.length\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2.5\">\n <div class=\"cqa-self-stretch cqa-inline-flex cqa-justify-start cqa-items-center\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-w-5 cqa-h-5 cqa-p-1 cqa-flex-shrink-0 cqa-bg-[#3F43EE1A] cqa-rounded-md cqa-inline-flex cqa-justify-center cqa-items-center\">\n <mat-icon class=\"cqa-text-[#1B1FEB] cqa-text-[12px] cqa-w-3 cqa-h-3 cqa-leading-none cqa-block\">settings</mat-icon>\n </div>\n <span class=\"cqa-text-[#374151] cqa-text-sm cqa-font-semibold cqa-leading-[19.6px]\">{{ configTitle }}</span>\n </div>\n </div>\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2.5\">\n <div class=\"cqa-self-stretch cqa-grid cqa-grid-cols-1 cqa-gap-2.5\">\n <ng-container *ngFor=\"let section of configSections; trackBy: trackByConfigTitle\">\n <cqa-configuration-card\n [icon]=\"section.icon || 'tune'\"\n [title]=\"section.title\"\n [data]=\"section.items\">\n </cqa-configuration-card>\n </ng-container>\n </div>\n <div *ngIf=\"configSectionsRow2.length\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-gap-4 cqa-text-sm cqa-leading-[19.6px]\">\n <cqa-configuration-card\n *ngFor=\"let section of configSectionsRow2; trackBy: trackByConfigTitle\"\n [icon]=\"section.icon || 'tune'\"\n [title]=\"section.title\"\n [data]=\"section.items\">\n </cqa-configuration-card>\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: [] }]
|
|
34487
|
-
}], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }]; }, propDecorators: { editing: [{
|
|
34488
|
-
type: Input
|
|
34489
|
-
}], startInEditMode: [{
|
|
34490
|
-
type: Input
|
|
34491
|
-
}], descriptionTitle: [{
|
|
34492
|
-
type: Input
|
|
34493
|
-
}], descriptionContent: [{
|
|
34494
|
-
type: Input
|
|
34495
|
-
}], enableMarkdown: [{
|
|
34496
|
-
type: Input
|
|
34497
|
-
}], showEditButton: [{
|
|
34498
|
-
type: Input
|
|
34499
|
-
}], metadataItems: [{
|
|
34500
|
-
type: Input
|
|
34501
|
-
}], labels: [{
|
|
34502
|
-
type: Input
|
|
34503
|
-
}], configTitle: [{
|
|
34504
|
-
type: Input
|
|
34505
|
-
}], configSections: [{
|
|
34506
|
-
type: Input
|
|
34507
|
-
}], configSectionsRow2: [{
|
|
34508
|
-
type: Input
|
|
34509
|
-
}], platform: [{
|
|
34510
|
-
type: Input
|
|
34511
|
-
}], isStepGroup: [{
|
|
34512
|
-
type: Input
|
|
34513
|
-
}], selectConfigOverrides: [{
|
|
34514
|
-
type: Input
|
|
34515
|
-
}], editDescription: [{
|
|
34516
|
-
type: Output
|
|
34517
|
-
}], cancel: [{
|
|
34518
|
-
type: Output
|
|
34519
|
-
}], saveChanges: [{
|
|
34520
|
-
type: Output
|
|
34521
|
-
}], metadataLinkClick: [{
|
|
34522
|
-
type: Output
|
|
34523
|
-
}], selectSearch: [{
|
|
34524
|
-
type: Output
|
|
34525
|
-
}], selectLoadMore: [{
|
|
34526
|
-
type: Output
|
|
34527
|
-
}], selectOpened: [{
|
|
34528
|
-
type: Output
|
|
34529
|
-
}], selectionChange: [{
|
|
34530
|
-
type: Output
|
|
34531
|
-
}], labelAdded: [{
|
|
34532
|
-
type: Output
|
|
34533
|
-
}] } });
|
|
34534
|
-
|
|
34535
|
-
class DetailSidePanelComponent {
|
|
34536
|
-
constructor(cdr) {
|
|
34537
|
-
this.cdr = cdr;
|
|
34538
|
-
/** Tabs - each tab has a side panel icon button; tabs and buttons are 1:1 */
|
|
34539
|
-
this.tabs = [
|
|
34540
|
-
{ label: 'Test Case', value: 'test-case', icon: 'description' },
|
|
34541
|
-
{ label: 'Data Library', value: 'data-library', icon: 'folder' },
|
|
34542
|
-
{ label: 'Variables', value: 'variables', icon: 'code' },
|
|
34543
|
-
];
|
|
34544
|
-
/** Currently active tab value */
|
|
34545
|
-
this.activeTab = 'test-case';
|
|
34546
|
-
/** Description section title */
|
|
34547
|
-
this.descriptionTitle = 'Description';
|
|
34548
|
-
/** Description text content */
|
|
34549
|
-
this.descriptionContent = '';
|
|
34550
|
-
/** When true, description uses rich text editor and renders as HTML. Host app must load Trix. */
|
|
34551
|
-
this.enableMarkdown = false;
|
|
34552
|
-
/** Whether to show the Edit button in the Description header */
|
|
34553
|
-
this.showEditButton = true;
|
|
34554
|
-
/** Metadata items (Created on, Status, Priority, etc.) */
|
|
34555
|
-
this.metadataItems = [];
|
|
34556
|
-
/** Labels/tags (e.g. Automation, API, SDK, UI/UX) */
|
|
34557
|
-
this.labels = [];
|
|
34558
|
-
/** Configuration sections - full width (e.g. Execution, AI Configuration) */
|
|
34559
|
-
this.configSections = [];
|
|
34560
|
-
/** Optional config sections displayed in a 2-column row (e.g. Waits & Retries, Device) */
|
|
34561
|
-
this.configSectionsRow2 = [];
|
|
34562
|
-
/** Platform: 'web' or 'mobile'. Defaults to 'web'. Used for Device Settings. */
|
|
34563
|
-
this.platform = 'web';
|
|
34564
|
-
/** When true, hides Priority, Type, Test Data Set, and Prerequisite Case (step groups don't have these). Defaults to false. */
|
|
34565
|
-
this.isStepGroup = false;
|
|
34566
|
-
/** Configuration section title */
|
|
34567
|
-
this.configTitle = 'Configuration';
|
|
34568
|
-
/** Whether to show the close button in the side menu */
|
|
34569
|
-
this.showCloseButton = false;
|
|
34570
|
-
/** When true, test case details start in edit mode (useful for Storybook). */
|
|
34571
|
-
this.startInEditMode = false;
|
|
34572
|
-
/** Override config per select for API-driven options, server search, load more. */
|
|
34573
|
-
this.selectConfigOverrides = {};
|
|
34574
|
-
/** Whether the panel is expanded (affects expand button icon and panel width) */
|
|
34575
|
-
this.expanded = true;
|
|
34576
|
-
/** Panel width when expanded (e.g. '480px', '25%') */
|
|
34577
|
-
this.expandedWidth = '380px';
|
|
34578
|
-
/** Panel width when collapsed (e.g. '56px' - fits icon bar + back button) */
|
|
34579
|
-
this.collapsedWidth = '56px';
|
|
34580
|
-
this.hostOverflow = 'hidden';
|
|
34581
|
-
/** Tooltip for expand button when panel is collapsed */
|
|
34582
|
-
this.expandTooltip = 'Expand';
|
|
34583
|
-
/** Tooltip for expand button when panel is expanded (collapse) */
|
|
34584
|
-
this.collapseTooltip = 'Collapse';
|
|
34585
|
-
/** Tooltip for close button */
|
|
34586
|
-
this.closeTooltip = 'Close';
|
|
34587
|
-
this.back = new EventEmitter();
|
|
34588
|
-
this.tabChange = new EventEmitter();
|
|
34589
|
-
this.editDescription = new EventEmitter();
|
|
34590
|
-
this.cancel = new EventEmitter();
|
|
34591
|
-
this.saveChanges = new EventEmitter();
|
|
34592
|
-
this.metadataLinkClick = new EventEmitter();
|
|
34593
|
-
this.selectSearch = new EventEmitter();
|
|
34594
|
-
this.selectLoadMore = new EventEmitter();
|
|
34595
|
-
this.selectOpened = new EventEmitter();
|
|
34596
|
-
this.selectionChange = new EventEmitter();
|
|
34597
|
-
this.labelAdded = new EventEmitter();
|
|
34598
|
-
this.expandToggle = new EventEmitter();
|
|
34599
|
-
this.close = new EventEmitter();
|
|
34600
|
-
}
|
|
34601
|
-
get hostWidth() {
|
|
34602
|
-
return this.expanded ? this.expandedWidth : this.collapsedWidth;
|
|
34603
|
-
}
|
|
34604
|
-
get hostMinWidth() {
|
|
34605
|
-
return this.expanded ? this.expandedWidth : this.collapsedWidth;
|
|
34606
|
-
}
|
|
34607
|
-
get hostMaxWidth() {
|
|
34608
|
-
return this.expanded ? this.expandedWidth : this.collapsedWidth;
|
|
34609
|
-
}
|
|
34610
|
-
trackByTabValue(_i, tab) {
|
|
34611
|
-
return tab.value;
|
|
34612
|
-
}
|
|
34613
|
-
trackByMetadataLabel(_i, item) {
|
|
34614
|
-
return item.label;
|
|
34615
|
-
}
|
|
34616
|
-
trackByConfigTitle(_i, section) {
|
|
34617
|
-
return section.title;
|
|
34618
|
-
}
|
|
34619
|
-
onBack() {
|
|
34620
|
-
this.back.emit();
|
|
34621
|
-
}
|
|
34622
|
-
onTabClick(tab) {
|
|
34623
|
-
if (!this.expanded) {
|
|
34624
|
-
this.expandToggle.emit();
|
|
34699
|
+
if (this.startInEditMode) {
|
|
34700
|
+
this._editing = true;
|
|
34625
34701
|
}
|
|
34626
|
-
|
|
34627
|
-
|
|
34702
|
+
}
|
|
34703
|
+
/** Filtered metadata items - excludes Priority and Type for step groups */
|
|
34704
|
+
get filteredMetadataItems() {
|
|
34705
|
+
if (!this.isStepGroup) {
|
|
34706
|
+
return this.metadataItems;
|
|
34628
34707
|
}
|
|
34708
|
+
return this.metadataItems.filter((item) => !this.stepGroupExcludedMetadataLabels.includes(item.label?.toLowerCase() ?? ''));
|
|
34629
34709
|
}
|
|
34630
|
-
|
|
34710
|
+
onEditClick() {
|
|
34711
|
+
if (this.editing === undefined) {
|
|
34712
|
+
this._editing = true;
|
|
34713
|
+
this.cdr.detectChanges();
|
|
34714
|
+
}
|
|
34631
34715
|
this.editDescription.emit();
|
|
34632
34716
|
}
|
|
34633
34717
|
onSaveChanges(data) {
|
|
34718
|
+
if (this.editing === undefined) {
|
|
34719
|
+
this._editing = false;
|
|
34720
|
+
}
|
|
34721
|
+
this.cdr.detectChanges();
|
|
34634
34722
|
this.saveChanges.emit(data);
|
|
34635
34723
|
}
|
|
34636
|
-
|
|
34724
|
+
onCancelEdit() {
|
|
34637
34725
|
this.cancel.emit();
|
|
34726
|
+
if (this.editing === undefined) {
|
|
34727
|
+
this._editing = false;
|
|
34728
|
+
}
|
|
34729
|
+
this.cdr.detectChanges();
|
|
34638
34730
|
}
|
|
34639
|
-
|
|
34640
|
-
|
|
34731
|
+
trackByConfigTitle(_i, section) {
|
|
34732
|
+
return section.title;
|
|
34641
34733
|
}
|
|
34642
|
-
|
|
34643
|
-
|
|
34734
|
+
trackByMetadataLabel(_i, item) {
|
|
34735
|
+
return item.label;
|
|
34644
34736
|
}
|
|
34645
34737
|
onMetadataLinkClick(item) {
|
|
34646
34738
|
if (item.link) {
|
|
@@ -34662,18 +34754,22 @@ class DetailSidePanelComponent {
|
|
|
34662
34754
|
return 'cqa-bg-[#94A3B8]';
|
|
34663
34755
|
}
|
|
34664
34756
|
}
|
|
34757
|
+
/** Text color for metadata value (e.g. red for critical priority) */
|
|
34758
|
+
getValueTextClass(item) {
|
|
34759
|
+
if (item.statusColor === 'red') {
|
|
34760
|
+
return 'cqa-text-[#DC2626]';
|
|
34761
|
+
}
|
|
34762
|
+
return 'cqa-text-[#111827]';
|
|
34763
|
+
}
|
|
34665
34764
|
}
|
|
34666
|
-
|
|
34667
|
-
|
|
34668
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type:
|
|
34765
|
+
TestCaseDetailsComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TestCaseDetailsComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
34766
|
+
TestCaseDetailsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TestCaseDetailsComponent, selector: "cqa-test-case-details", inputs: { editing: "editing", startInEditMode: "startInEditMode", descriptionTitle: "descriptionTitle", descriptionContent: "descriptionContent", enableMarkdown: "enableMarkdown", showEditButton: "showEditButton", metadataItems: "metadataItems", labels: "labels", configTitle: "configTitle", configSections: "configSections", configSectionsRow2: "configSectionsRow2", platform: "platform", isStepGroup: "isStepGroup", selectConfigOverrides: "selectConfigOverrides" }, outputs: { editDescription: "editDescription", cancel: "cancel", saveChanges: "saveChanges", metadataLinkClick: "metadataLinkClick", selectSearch: "selectSearch", selectLoadMore: "selectLoadMore", selectOpened: "selectOpened", selectionChange: "selectionChange", labelAdded: "labelAdded" }, ngImport: i0, template: "<!-- Edit mode: show edit form (Figma design) -->\n<cqa-test-case-details-edit\n *ngIf=\"isEditing\"\n [descriptionTitle]=\"descriptionTitle\"\n [descriptionContent]=\"descriptionContent\"\n [enableMarkdown]=\"enableMarkdown\"\n [metadataItems]=\"metadataItems\"\n [labels]=\"labels\"\n [configTitle]=\"configTitle\"\n [configSections]=\"configSections\"\n [configSectionsRow2]=\"configSectionsRow2\"\n [platform]=\"platform\"\n [isStepGroup]=\"isStepGroup\"\n [selectConfigOverrides]=\"selectConfigOverrides\"\n (save)=\"onSaveChanges($event)\"\n (cancel)=\"onCancelEdit()\"\n (selectSearch)=\"selectSearch.emit($event)\"\n (selectLoadMore)=\"selectLoadMore.emit($event)\"\n (selectOpened)=\"selectOpened.emit($event)\"\n (selectionChange)=\"selectionChange.emit($event)\"\n (labelAdded)=\"labelAdded.emit($event)\">\n</cqa-test-case-details-edit>\n\n<!-- View mode: read-only details -->\n<div *ngIf=\"!isEditing\" class=\"cqa-self-stretch cqa-py-4 cqa-px-0 cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-4 cqa-text-sm cqa-leading-[19.6px]\">\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-4 cqa-text-sm cqa-leading-[19.6px]\">\n <!-- Description Section -->\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2.5\">\n <div class=\"cqa-self-stretch cqa-inline-flex cqa-justify-between cqa-items-center\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-w-5 cqa-h-5 cqa-p-1 cqa-flex-shrink-0 cqa-bg-[#3F43EE1A] cqa-rounded-md cqa-inline-flex cqa-justify-center cqa-items-center\">\n <mat-icon class=\"cqa-text-[#1B1FEB] cqa-text-[12px] cqa-w-3 cqa-h-3 cqa-leading-none cqa-block\">description</mat-icon>\n </div>\n <span class=\"cqa-text-[#374151] cqa-text-sm cqa-font-semibold cqa-leading-[19.6px]\">{{ descriptionTitle }}</span>\n </div>\n <button\n *ngIf=\"showEditButton\"\n type=\"button\"\n class=\"cqa-flex cqa-justify-end cqa-items-center cqa-gap-2 cqa-text-[#A3A3A3] cqa-text-xs cqa-font-semibold hover:cqa-text-[#737373] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onEditClick()\">\n <mat-icon class=\"cqa-text-[14px] cqa-w-4 cqa-h-4\">edit</mat-icon>\n Edit\n </button>\n </div>\n <div *ngIf=\"descriptionContent\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start\">\n <div *ngIf=\"enableMarkdown\" class=\"cqa-self-stretch cqa-text-[#111827] cqa-text-sm cqa-leading-[19.6px] cqa-font-normal cqa-prose cqa-prose-sm cqa-max-w-none\" [innerHTML]=\"descriptionContent\"></div>\n <div *ngIf=\"!enableMarkdown\" class=\"cqa-self-stretch cqa-text-[#111827] cqa-text-sm cqa-leading-[19.6px] cqa-font-normal\">{{ descriptionContent }}</div>\n </div>\n </div>\n\n <!-- Metadata Section -->\n <div *ngIf=\"filteredMetadataItems.length\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2.5\">\n <div class=\"cqa-self-stretch cqa-grid cqa-grid-cols-2 cqa-gap-x-0 cqa-gap-y-4\">\n <ng-container *ngFor=\"let item of filteredMetadataItems; trackBy: trackByMetadataLabel\">\n <div class=\"cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-0.5\">\n <div class=\"cqa-text-[#6B7280] cqa-text-xs cqa-leading-[15px] cqa-font-medium\">{{ item.label }}</div>\n <div\n class=\"cqa-flex cqa-justify-start cqa-items-center cqa-gap-[5px] cqa-min-w-0 cqa-w-full cqa-text-left cqa-text-[#0A0A0A] cqa-border cqa-border-[#F5F5F5]\">\n <mat-icon *ngIf=\"item.icon && (!item.iconLibrary || item.iconLibrary === 'mat')\" class=\"cqa-text-[#6B7280] cqa-text-sm cqa-w-4 cqa-h-4\">\n {{ item.icon }}\n </mat-icon>\n <span *ngIf=\"item.statusColor\" class=\"cqa-w-3.5 cqa-h-3.5 cqa-rounded-full cqa-flex-shrink-0\" [ngClass]=\"getStatusDotClass(item)\"></span>\n <a\n *ngIf=\"item.link\"\n href=\"javascript:void(0)\"\n class=\"cqa-text-[#2563EB] cqa-text-xs cqa-leading-[12px] cqa-font-normal hover:cqa-underline cqa-cursor-pointer cqa-block cqa-truncate cqa-min-w-0\"\n (click)=\"onMetadataLinkClick(item); $event.preventDefault()\">\n {{ item.value }}\n </a>\n <span *ngIf=\"!item.link\" class=\"cqa-text-xs cqa-leading-[12px] cqa-font-normal cqa-align-middle\" [ngClass]=\"getValueTextClass(item)\">\n {{ item.value }}\n </span>\n </div>\n </div>\n </ng-container>\n </div>\n </div>\n\n <!-- Labels (Figma: Labels title, cqa-badge chips with tag icon) -->\n <div *ngIf=\"labels.length\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2 cqa-text-sm cqa-leading-[19.6px]\">\n <span class=\"cqa-text-[#111827] cqa-text-sm cqa-font-medium cqa-leading-5\">Labels</span>\n <div class=\"cqa-flex cqa-flex-wrap cqa-gap-2\">\n <cqa-badge\n *ngFor=\"let label of labels\"\n [label]=\"label\"\n icon=\"label\"\n variant=\"outline\"\n size=\"small\"\n backgroundColor=\"#ffffff\"\n textColor=\"#475569\"\n borderColor=\"#E2E8F0\"\n iconColor=\"#94A3B8\">\n </cqa-badge>\n </div>\n </div>\n\n <!-- Configuration Section -->\n <div *ngIf=\"configSections.length || configSectionsRow2.length\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2.5\">\n <div class=\"cqa-self-stretch cqa-inline-flex cqa-justify-start cqa-items-center\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-w-5 cqa-h-5 cqa-p-1 cqa-flex-shrink-0 cqa-bg-[#3F43EE1A] cqa-rounded-md cqa-inline-flex cqa-justify-center cqa-items-center\">\n <mat-icon class=\"cqa-text-[#1B1FEB] cqa-text-[12px] cqa-w-3 cqa-h-3 cqa-leading-none cqa-block\">settings</mat-icon>\n </div>\n <span class=\"cqa-text-[#374151] cqa-text-sm cqa-font-semibold cqa-leading-[19.6px]\">{{ configTitle }}</span>\n </div>\n </div>\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2.5\">\n <div class=\"cqa-self-stretch cqa-grid cqa-grid-cols-1 cqa-gap-2.5\">\n <ng-container *ngFor=\"let section of configSections; trackBy: trackByConfigTitle\">\n <cqa-configuration-card\n [icon]=\"section.icon || 'tune'\"\n [title]=\"section.title\"\n [data]=\"section.items\">\n </cqa-configuration-card>\n </ng-container>\n </div>\n <div *ngIf=\"configSectionsRow2.length\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-gap-4 cqa-text-sm cqa-leading-[19.6px]\">\n <cqa-configuration-card\n *ngFor=\"let section of configSectionsRow2; trackBy: trackByConfigTitle\"\n [icon]=\"section.icon || 'tune'\"\n [title]=\"section.title\"\n [data]=\"section.items\">\n </cqa-configuration-card>\n </div>\n </div>\n </div>\n </div>\n</div>\n", components: [{ type: TestCaseDetailsEditComponent, selector: "cqa-test-case-details-edit", inputs: ["descriptionTitle", "descriptionContent", "enableMarkdown", "metadataItems", "labels", "configTitle", "configSections", "configSectionsRow2", "prerequisiteCaseOptions", "platform", "isStepGroup", "selectConfigOverrides"], outputs: ["save", "cancel", "selectSearch", "selectLoadMore", "selectOpened", "selectionChange", "labelAdded"] }, { type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { type: BadgeComponent, selector: "cqa-badge", inputs: ["type", "label", "icon", "iconLibrary", "variant", "size", "backgroundColor", "textColor", "borderColor", "iconBackgroundColor", "iconColor", "iconSize", "inlineStyles", "key", "value", "keyTextColor", "valueTextColor", "isLoading"] }, { type: ConfigurationCardComponent, selector: "cqa-configuration-card", inputs: ["icon", "title", "data"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
34767
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TestCaseDetailsComponent, decorators: [{
|
|
34669
34768
|
type: Component,
|
|
34670
|
-
args: [{ selector: 'cqa-
|
|
34671
|
-
|
|
34672
|
-
style: 'transition: width 0.3s ease-in-out',
|
|
34673
|
-
}, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-min-w-0 cqa-bg-white\">\n <!-- Main content: Side menu + Scrollable content -->\n <div\n class=\"cqa-grid cqa-flex-1 cqa-min-h-0 cqa-min-w-0 cqa-overflow-hidden\"\n [style.grid-template-columns]=\"expanded ? 'auto 1fr' : 'auto 0fr'\"\n style=\"transition: grid-template-columns 0.3s ease-in-out\">\n <!-- Left vertical icon menu -->\n <div\n class=\"cqa-flex cqa-flex-col cqa-items-center cqa-gap-2 cqa-py-4 cqa-px-2 cqa-border-r cqa-border-[#F5F5F5] cqa-flex-shrink-0 cqa-text-[#0A0A0A]\"\n style=\"box-shadow: 1px 4px 12px 1px rgba(0, 0, 0, 0.05);\">\n <!-- Expand / Collapse button (always visible) -->\n <button\n type=\"button\"\n [matTooltip]=\"expanded ? collapseTooltip : expandTooltip\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onExpandToggle()\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">{{ expanded ? 'chevron_left' : 'chevron_right' }}</mat-icon>\n </button>\n <!-- Close button -->\n <button\n *ngIf=\"showCloseButton\"\n type=\"button\"\n [matTooltip]=\"closeTooltip\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onClose()\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">close</mat-icon>\n </button>\n <!-- Tab buttons (1:1 with tabs) -->\n <button\n *ngFor=\"let tab of tabs; trackBy: trackByTabValue\"\n type=\"button\"\n [matTooltip]=\"tab.label\"\n [class.cqa-bg-[#3F43EE]]=\"activeTab === tab.value\"\n [class.cqa-text-white]=\"activeTab === tab.value\"\n [class.cqa-text-[#64748B]]=\"activeTab !== tab.value\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onTabClick(tab)\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">{{ tab.icon || 'circle' }}</mat-icon>\n </button>\n </div>\n\n <!-- Scrollable content area (collapses with animation when expanded is false) -->\n <div class=\"cqa-flex cqa-flex-col cqa-min-h-0 cqa-min-w-0 cqa-overflow-hidden cqa-w-full cqa-h-full\">\n <div class=\"detail-side-panel-scroll cqa-flex-1 cqa-min-h-0 cqa-min-w-0 cqa-overflow-y-auto cqa-overflow-x-hidden cqa-p-4 cqa-space-y-4\" style=\"overflow-y: auto; overflow-x: hidden; min-height: 0; -webkit-overflow-scrolling: touch;\">\n <!-- Tabs: equally distributed (Figma: purple active, gray inactive) -->\n <div class=\"cqa-flex cqa-gap-[3.5px] cqa-p-[3.5px] cqa-bg-[#F1F5F9] cqa-rounded-lg cqa-w-full\" role=\"tablist\">\n <button\n *ngFor=\"let tab of tabs; trackBy: trackByTabValue\"\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === tab.value\"\n [class.cqa-bg-[#3F43EE]]=\"activeTab === tab.value\"\n [class.cqa-text-white]=\"activeTab === tab.value\"\n [class.cqa-text-[#64748B]]=\"activeTab !== tab.value\"\n class=\"cqa-flex-1 cqa-flex cqa-justify-center cqa-items-center cqa-py-2 cqa-rounded-lg cqa-text-xs cqa-font-medium cqa-transition-colors hover:cqa-opacity-90 focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onTabClick(tab)\">\n {{ tab.label }}\n </button>\n </div>\n\n <!-- Test Case tab: use cqa-test-case-details (Figma design) -->\n <cqa-test-case-details\n *ngIf=\"activeTab === 'test-case'\"\n [descriptionTitle]=\"descriptionTitle\"\n [descriptionContent]=\"descriptionContent\"\n [enableMarkdown]=\"enableMarkdown\"\n [showEditButton]=\"showEditButton\"\n [startInEditMode]=\"startInEditMode\"\n [editing]=\"editing\"\n [selectConfigOverrides]=\"selectConfigOverrides\"\n [metadataItems]=\"metadataItems\"\n [labels]=\"labels\"\n [configTitle]=\"configTitle\"\n [configSections]=\"configSections\"\n [configSectionsRow2]=\"configSectionsRow2\"\n [platform]=\"platform\"\n [isStepGroup]=\"isStepGroup\"\n (editDescription)=\"onEditDescription()\"\n (cancel)=\"onCancel()\"\n (saveChanges)=\"onSaveChanges($event)\"\n (metadataLinkClick)=\"onMetadataLinkClick($event)\"\n (selectSearch)=\"selectSearch.emit($event)\"\n (selectLoadMore)=\"selectLoadMore.emit($event)\"\n (selectOpened)=\"selectOpened.emit($event)\"\n (selectionChange)=\"selectionChange.emit($event)\"\n (labelAdded)=\"labelAdded.emit($event)\">\n </cqa-test-case-details>\n\n <!-- Placeholder for other tabs (Data Library, Variables) -->\n <div *ngIf=\"activeTab !== 'test-case'\" class=\"cqa-p-4 cqa-text-[#64748B] cqa-text-sm\">\n {{ activeTab === 'data-library' ? 'Data Library content' : 'Variables content' }} \u2013 coming soon\n </div>\n </div>\n </div>\n </div>\n</div>\n" }]
|
|
34674
|
-
}], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }]; }, propDecorators: { tabs: [{
|
|
34769
|
+
args: [{ selector: 'cqa-test-case-details', changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Edit mode: show edit form (Figma design) -->\n<cqa-test-case-details-edit\n *ngIf=\"isEditing\"\n [descriptionTitle]=\"descriptionTitle\"\n [descriptionContent]=\"descriptionContent\"\n [enableMarkdown]=\"enableMarkdown\"\n [metadataItems]=\"metadataItems\"\n [labels]=\"labels\"\n [configTitle]=\"configTitle\"\n [configSections]=\"configSections\"\n [configSectionsRow2]=\"configSectionsRow2\"\n [platform]=\"platform\"\n [isStepGroup]=\"isStepGroup\"\n [selectConfigOverrides]=\"selectConfigOverrides\"\n (save)=\"onSaveChanges($event)\"\n (cancel)=\"onCancelEdit()\"\n (selectSearch)=\"selectSearch.emit($event)\"\n (selectLoadMore)=\"selectLoadMore.emit($event)\"\n (selectOpened)=\"selectOpened.emit($event)\"\n (selectionChange)=\"selectionChange.emit($event)\"\n (labelAdded)=\"labelAdded.emit($event)\">\n</cqa-test-case-details-edit>\n\n<!-- View mode: read-only details -->\n<div *ngIf=\"!isEditing\" class=\"cqa-self-stretch cqa-py-4 cqa-px-0 cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-4 cqa-text-sm cqa-leading-[19.6px]\">\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-4 cqa-text-sm cqa-leading-[19.6px]\">\n <!-- Description Section -->\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2.5\">\n <div class=\"cqa-self-stretch cqa-inline-flex cqa-justify-between cqa-items-center\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-w-5 cqa-h-5 cqa-p-1 cqa-flex-shrink-0 cqa-bg-[#3F43EE1A] cqa-rounded-md cqa-inline-flex cqa-justify-center cqa-items-center\">\n <mat-icon class=\"cqa-text-[#1B1FEB] cqa-text-[12px] cqa-w-3 cqa-h-3 cqa-leading-none cqa-block\">description</mat-icon>\n </div>\n <span class=\"cqa-text-[#374151] cqa-text-sm cqa-font-semibold cqa-leading-[19.6px]\">{{ descriptionTitle }}</span>\n </div>\n <button\n *ngIf=\"showEditButton\"\n type=\"button\"\n class=\"cqa-flex cqa-justify-end cqa-items-center cqa-gap-2 cqa-text-[#A3A3A3] cqa-text-xs cqa-font-semibold hover:cqa-text-[#737373] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onEditClick()\">\n <mat-icon class=\"cqa-text-[14px] cqa-w-4 cqa-h-4\">edit</mat-icon>\n Edit\n </button>\n </div>\n <div *ngIf=\"descriptionContent\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start\">\n <div *ngIf=\"enableMarkdown\" class=\"cqa-self-stretch cqa-text-[#111827] cqa-text-sm cqa-leading-[19.6px] cqa-font-normal cqa-prose cqa-prose-sm cqa-max-w-none\" [innerHTML]=\"descriptionContent\"></div>\n <div *ngIf=\"!enableMarkdown\" class=\"cqa-self-stretch cqa-text-[#111827] cqa-text-sm cqa-leading-[19.6px] cqa-font-normal\">{{ descriptionContent }}</div>\n </div>\n </div>\n\n <!-- Metadata Section -->\n <div *ngIf=\"filteredMetadataItems.length\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2.5\">\n <div class=\"cqa-self-stretch cqa-grid cqa-grid-cols-2 cqa-gap-x-0 cqa-gap-y-4\">\n <ng-container *ngFor=\"let item of filteredMetadataItems; trackBy: trackByMetadataLabel\">\n <div class=\"cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-0.5\">\n <div class=\"cqa-text-[#6B7280] cqa-text-xs cqa-leading-[15px] cqa-font-medium\">{{ item.label }}</div>\n <div\n class=\"cqa-flex cqa-justify-start cqa-items-center cqa-gap-[5px] cqa-min-w-0 cqa-w-full cqa-text-left cqa-text-[#0A0A0A] cqa-border cqa-border-[#F5F5F5]\">\n <mat-icon *ngIf=\"item.icon && (!item.iconLibrary || item.iconLibrary === 'mat')\" class=\"cqa-text-[#6B7280] cqa-text-sm cqa-w-4 cqa-h-4\">\n {{ item.icon }}\n </mat-icon>\n <span *ngIf=\"item.statusColor\" class=\"cqa-w-3.5 cqa-h-3.5 cqa-rounded-full cqa-flex-shrink-0\" [ngClass]=\"getStatusDotClass(item)\"></span>\n <a\n *ngIf=\"item.link\"\n href=\"javascript:void(0)\"\n class=\"cqa-text-[#2563EB] cqa-text-xs cqa-leading-[12px] cqa-font-normal hover:cqa-underline cqa-cursor-pointer cqa-block cqa-truncate cqa-min-w-0\"\n (click)=\"onMetadataLinkClick(item); $event.preventDefault()\">\n {{ item.value }}\n </a>\n <span *ngIf=\"!item.link\" class=\"cqa-text-xs cqa-leading-[12px] cqa-font-normal cqa-align-middle\" [ngClass]=\"getValueTextClass(item)\">\n {{ item.value }}\n </span>\n </div>\n </div>\n </ng-container>\n </div>\n </div>\n\n <!-- Labels (Figma: Labels title, cqa-badge chips with tag icon) -->\n <div *ngIf=\"labels.length\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2 cqa-text-sm cqa-leading-[19.6px]\">\n <span class=\"cqa-text-[#111827] cqa-text-sm cqa-font-medium cqa-leading-5\">Labels</span>\n <div class=\"cqa-flex cqa-flex-wrap cqa-gap-2\">\n <cqa-badge\n *ngFor=\"let label of labels\"\n [label]=\"label\"\n icon=\"label\"\n variant=\"outline\"\n size=\"small\"\n backgroundColor=\"#ffffff\"\n textColor=\"#475569\"\n borderColor=\"#E2E8F0\"\n iconColor=\"#94A3B8\">\n </cqa-badge>\n </div>\n </div>\n\n <!-- Configuration Section -->\n <div *ngIf=\"configSections.length || configSectionsRow2.length\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2.5\">\n <div class=\"cqa-self-stretch cqa-inline-flex cqa-justify-start cqa-items-center\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-w-5 cqa-h-5 cqa-p-1 cqa-flex-shrink-0 cqa-bg-[#3F43EE1A] cqa-rounded-md cqa-inline-flex cqa-justify-center cqa-items-center\">\n <mat-icon class=\"cqa-text-[#1B1FEB] cqa-text-[12px] cqa-w-3 cqa-h-3 cqa-leading-none cqa-block\">settings</mat-icon>\n </div>\n <span class=\"cqa-text-[#374151] cqa-text-sm cqa-font-semibold cqa-leading-[19.6px]\">{{ configTitle }}</span>\n </div>\n </div>\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2.5\">\n <div class=\"cqa-self-stretch cqa-grid cqa-grid-cols-1 cqa-gap-2.5\">\n <ng-container *ngFor=\"let section of configSections; trackBy: trackByConfigTitle\">\n <cqa-configuration-card\n [icon]=\"section.icon || 'tune'\"\n [title]=\"section.title\"\n [data]=\"section.items\">\n </cqa-configuration-card>\n </ng-container>\n </div>\n <div *ngIf=\"configSectionsRow2.length\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-gap-4 cqa-text-sm cqa-leading-[19.6px]\">\n <cqa-configuration-card\n *ngFor=\"let section of configSectionsRow2; trackBy: trackByConfigTitle\"\n [icon]=\"section.icon || 'tune'\"\n [title]=\"section.title\"\n [data]=\"section.items\">\n </cqa-configuration-card>\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: [] }]
|
|
34770
|
+
}], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }]; }, propDecorators: { editing: [{
|
|
34675
34771
|
type: Input
|
|
34676
|
-
}],
|
|
34772
|
+
}], startInEditMode: [{
|
|
34677
34773
|
type: Input
|
|
34678
34774
|
}], descriptionTitle: [{
|
|
34679
34775
|
type: Input
|
|
@@ -34687,6 +34783,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
|
|
|
34687
34783
|
type: Input
|
|
34688
34784
|
}], labels: [{
|
|
34689
34785
|
type: Input
|
|
34786
|
+
}], configTitle: [{
|
|
34787
|
+
type: Input
|
|
34690
34788
|
}], configSections: [{
|
|
34691
34789
|
type: Input
|
|
34692
34790
|
}], configSectionsRow2: [{
|
|
@@ -34695,44 +34793,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
|
|
|
34695
34793
|
type: Input
|
|
34696
34794
|
}], isStepGroup: [{
|
|
34697
34795
|
type: Input
|
|
34698
|
-
}], configTitle: [{
|
|
34699
|
-
type: Input
|
|
34700
|
-
}], showCloseButton: [{
|
|
34701
|
-
type: Input
|
|
34702
|
-
}], startInEditMode: [{
|
|
34703
|
-
type: Input
|
|
34704
|
-
}], editing: [{
|
|
34705
|
-
type: Input
|
|
34706
34796
|
}], selectConfigOverrides: [{
|
|
34707
34797
|
type: Input
|
|
34708
|
-
}], expanded: [{
|
|
34709
|
-
type: Input
|
|
34710
|
-
}], expandedWidth: [{
|
|
34711
|
-
type: Input
|
|
34712
|
-
}], collapsedWidth: [{
|
|
34713
|
-
type: Input
|
|
34714
|
-
}], hostWidth: [{
|
|
34715
|
-
type: HostBinding,
|
|
34716
|
-
args: ['style.width']
|
|
34717
|
-
}], hostMinWidth: [{
|
|
34718
|
-
type: HostBinding,
|
|
34719
|
-
args: ['style.min-width']
|
|
34720
|
-
}], hostMaxWidth: [{
|
|
34721
|
-
type: HostBinding,
|
|
34722
|
-
args: ['style.max-width']
|
|
34723
|
-
}], hostOverflow: [{
|
|
34724
|
-
type: HostBinding,
|
|
34725
|
-
args: ['style.overflow']
|
|
34726
|
-
}], expandTooltip: [{
|
|
34727
|
-
type: Input
|
|
34728
|
-
}], collapseTooltip: [{
|
|
34729
|
-
type: Input
|
|
34730
|
-
}], closeTooltip: [{
|
|
34731
|
-
type: Input
|
|
34732
|
-
}], back: [{
|
|
34733
|
-
type: Output
|
|
34734
|
-
}], tabChange: [{
|
|
34735
|
-
type: Output
|
|
34736
34798
|
}], editDescription: [{
|
|
34737
34799
|
type: Output
|
|
34738
34800
|
}], cancel: [{
|
|
@@ -34751,174 +34813,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
|
|
|
34751
34813
|
type: Output
|
|
34752
34814
|
}], labelAdded: [{
|
|
34753
34815
|
type: Output
|
|
34754
|
-
}], expandToggle: [{
|
|
34755
|
-
type: Output
|
|
34756
|
-
}], close: [{
|
|
34757
|
-
type: Output
|
|
34758
|
-
}] } });
|
|
34759
|
-
|
|
34760
|
-
class DetailDrawerTabContentDirective {
|
|
34761
|
-
constructor(templateRef) {
|
|
34762
|
-
this.templateRef = templateRef;
|
|
34763
|
-
}
|
|
34764
|
-
}
|
|
34765
|
-
DetailDrawerTabContentDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DetailDrawerTabContentDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
|
|
34766
|
-
DetailDrawerTabContentDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.4.0", type: DetailDrawerTabContentDirective, selector: "[cqaTabContent]", ngImport: i0 });
|
|
34767
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DetailDrawerTabContentDirective, decorators: [{
|
|
34768
|
-
type: Directive,
|
|
34769
|
-
args: [{
|
|
34770
|
-
selector: '[cqaTabContent]',
|
|
34771
|
-
}]
|
|
34772
|
-
}], ctorParameters: function () { return [{ type: i0.TemplateRef }]; } });
|
|
34773
|
-
|
|
34774
|
-
class DetailDrawerTabComponent {
|
|
34775
|
-
constructor() {
|
|
34776
|
-
/** Tab label (shown in tooltip on icon button) */
|
|
34777
|
-
this.label = '';
|
|
34778
|
-
/** Tab value (unique identifier) */
|
|
34779
|
-
this.value = '';
|
|
34780
|
-
/** Material icon name for the tab button */
|
|
34781
|
-
this.icon = 'folder';
|
|
34782
|
-
}
|
|
34783
|
-
get contentTemplate() {
|
|
34784
|
-
return this.contentDirective?.templateRef ?? null;
|
|
34785
|
-
}
|
|
34786
|
-
}
|
|
34787
|
-
DetailDrawerTabComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DetailDrawerTabComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
34788
|
-
DetailDrawerTabComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: DetailDrawerTabComponent, selector: "cqa-detail-drawer-tab", inputs: { label: "label", value: "value", icon: "icon" }, host: { styleAttribute: "display: contents" }, queries: [{ propertyName: "contentDirective", first: true, predicate: DetailDrawerTabContentDirective, descendants: true }], ngImport: i0, template: '', isInline: true });
|
|
34789
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DetailDrawerTabComponent, decorators: [{
|
|
34790
|
-
type: Component,
|
|
34791
|
-
args: [{
|
|
34792
|
-
selector: 'cqa-detail-drawer-tab',
|
|
34793
|
-
template: '',
|
|
34794
|
-
host: {
|
|
34795
|
-
style: 'display: contents',
|
|
34796
|
-
},
|
|
34797
|
-
}]
|
|
34798
|
-
}], propDecorators: { label: [{
|
|
34799
|
-
type: Input
|
|
34800
|
-
}], value: [{
|
|
34801
|
-
type: Input
|
|
34802
|
-
}], icon: [{
|
|
34803
|
-
type: Input
|
|
34804
|
-
}], contentDirective: [{
|
|
34805
|
-
type: ContentChild,
|
|
34806
|
-
args: [DetailDrawerTabContentDirective]
|
|
34807
|
-
}] } });
|
|
34808
|
-
|
|
34809
|
-
class DetailDrawerComponent {
|
|
34810
|
-
constructor() {
|
|
34811
|
-
/** Currently active tab value */
|
|
34812
|
-
this.activeTab = '';
|
|
34813
|
-
/** Whether to show the close button */
|
|
34814
|
-
this.showCloseButton = true;
|
|
34815
|
-
/** Whether the drawer is expanded */
|
|
34816
|
-
this.expanded = true;
|
|
34817
|
-
/** Panel width when expanded */
|
|
34818
|
-
this.expandedWidth = '280px';
|
|
34819
|
-
/** Maximum width when expanded (e.g. '600px', '30vw'). Default: 30% of viewport */
|
|
34820
|
-
this.maxExpandedWidth = '30vw';
|
|
34821
|
-
/** Panel width when collapsed */
|
|
34822
|
-
this.collapsedWidth = '56px';
|
|
34823
|
-
this.expandTooltip = 'Expand';
|
|
34824
|
-
this.collapseTooltip = 'Collapse';
|
|
34825
|
-
this.closeTooltip = 'Close';
|
|
34826
|
-
this.activeTabChange = new EventEmitter();
|
|
34827
|
-
this.expandToggle = new EventEmitter();
|
|
34828
|
-
this.close = new EventEmitter();
|
|
34829
|
-
}
|
|
34830
|
-
get hostWidth() {
|
|
34831
|
-
return this.expanded ? this.expandedWidth : this.collapsedWidth;
|
|
34832
|
-
}
|
|
34833
|
-
get hostMinWidth() {
|
|
34834
|
-
return this.expanded && this.minExpandedWidth ? this.minExpandedWidth : null;
|
|
34835
|
-
}
|
|
34836
|
-
get hostMaxWidth() {
|
|
34837
|
-
return this.expanded ? this.maxExpandedWidth : null;
|
|
34838
|
-
}
|
|
34839
|
-
ngAfterContentInit() {
|
|
34840
|
-
this.ensureActiveTab();
|
|
34841
|
-
}
|
|
34842
|
-
ngAfterContentChecked() {
|
|
34843
|
-
this.ensureActiveTab();
|
|
34844
|
-
}
|
|
34845
|
-
ensureActiveTab() {
|
|
34846
|
-
const tabs = this.tabComponents?.toArray() ?? [];
|
|
34847
|
-
if (tabs.length > 0 && !this.activeTab) {
|
|
34848
|
-
this.activeTab = tabs[0].value;
|
|
34849
|
-
this.activeTabChange.emit(this.activeTab);
|
|
34850
|
-
}
|
|
34851
|
-
}
|
|
34852
|
-
onTabClick(tab) {
|
|
34853
|
-
// If drawer is collapsed, open it (but never close on tab click)
|
|
34854
|
-
if (!this.expanded) {
|
|
34855
|
-
this.expandToggle.emit();
|
|
34856
|
-
}
|
|
34857
|
-
// Select the tab
|
|
34858
|
-
if (tab.value !== this.activeTab) {
|
|
34859
|
-
this.activeTab = tab.value;
|
|
34860
|
-
this.activeTabChange.emit(this.activeTab);
|
|
34861
|
-
}
|
|
34862
|
-
}
|
|
34863
|
-
onExpandToggle() {
|
|
34864
|
-
this.expandToggle.emit();
|
|
34865
|
-
}
|
|
34866
|
-
onClose() {
|
|
34867
|
-
this.close.emit();
|
|
34868
|
-
}
|
|
34869
|
-
trackByValue(_i, tab) {
|
|
34870
|
-
return tab.value;
|
|
34871
|
-
}
|
|
34872
|
-
isTabActive(tab) {
|
|
34873
|
-
return tab.value === this.activeTab;
|
|
34874
|
-
}
|
|
34875
|
-
}
|
|
34876
|
-
DetailDrawerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DetailDrawerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
34877
|
-
DetailDrawerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: DetailDrawerComponent, selector: "cqa-detail-drawer", inputs: { activeTab: "activeTab", showCloseButton: "showCloseButton", expanded: "expanded", expandedWidth: "expandedWidth", minExpandedWidth: "minExpandedWidth", maxExpandedWidth: "maxExpandedWidth", collapsedWidth: "collapsedWidth", expandTooltip: "expandTooltip", collapseTooltip: "collapseTooltip", closeTooltip: "closeTooltip" }, outputs: { activeTabChange: "activeTabChange", expandToggle: "expandToggle", close: "close" }, host: { properties: { "style.width": "this.hostWidth", "style.min-width": "this.hostMinWidth", "style.max-width": "this.hostMaxWidth" }, styleAttribute: "transition: width 0.3s ease-in-out", classAttribute: "cqa-ui-root cqa-flex cqa-flex-col cqa-h-full cqa-bg-white cqa-shadow-[-4px_0_6px_-1px_rgba(0,0,0,0.05)]" }, queries: [{ propertyName: "tabComponents", predicate: DetailDrawerTabComponent }], ngImport: i0, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white\">\n <div\n class=\"cqa-grid cqa-flex-1 cqa-min-h-0 cqa-overflow-hidden\"\n [style.grid-template-columns]=\"expanded ? 'auto 1fr' : 'auto 0fr'\"\n style=\"transition: grid-template-columns 0.3s ease-in-out\">\n <!-- Left vertical icon bar: one button per tab -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1 cqa-min-h-0 cqa-items-center cqa-py-4 cqa-px-2 cqa-border-r cqa-border-[#E2E8F0] cqa-bg-[#FAFAFA] cqa-flex-shrink-0\">\n <!-- Expand / Collapse button (always visible) -->\n <button\n type=\"button\"\n [matTooltip]=\"expanded ? collapseTooltip : expandTooltip\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2 cqa-flex-shrink-0\"\n (click)=\"onExpandToggle()\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">{{ expanded ? 'unfold_less' : 'unfold_more' }}</mat-icon>\n </button>\n <!-- Close button -->\n <button\n *ngIf=\"showCloseButton\"\n type=\"button\"\n [matTooltip]=\"closeTooltip\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2 cqa-flex-shrink-0\"\n (click)=\"onClose()\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">close</mat-icon>\n </button>\n <!-- Tab buttons: equally distributed in remaining space -->\n <div class=\"cqa-flex cqa-flex-1 cqa-flex-col cqa-justify-evenly cqa-items-center cqa-w-full\">\n <button\n *ngFor=\"let tab of tabComponents; trackBy: trackByValue\"\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"isTabActive(tab)\"\n [matTooltip]=\"tab.label\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2 cqa-flex-shrink-0\"\n [ngClass]=\"{\n 'cqa-bg-[#3F43EE] cqa-text-white': isTabActive(tab),\n 'cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155]': !isTabActive(tab)\n }\"\n (click)=\"onTabClick(tab)\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">{{ tab.icon }}</mat-icon>\n </button>\n </div>\n </div>\n\n <!-- Content area: show only the active tab's content -->\n <div class=\"cqa-min-w-0 cqa-overflow-hidden\">\n <div class=\"cqa-h-full cqa-overflow-y-auto cqa-p-4\">\n <ng-container *ngFor=\"let tab of tabComponents\">\n <ng-container *ngIf=\"tab.value === activeTab && tab.contentTemplate\" [ngTemplateOutlet]=\"tab.contentTemplate\"></ng-container>\n </ng-container>\n </div>\n </div>\n </div>\n</div>\n", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i5.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
34878
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DetailDrawerComponent, decorators: [{
|
|
34879
|
-
type: Component,
|
|
34880
|
-
args: [{ selector: 'cqa-detail-drawer', changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
34881
|
-
class: 'cqa-ui-root cqa-flex cqa-flex-col cqa-h-full cqa-bg-white cqa-shadow-[-4px_0_6px_-1px_rgba(0,0,0,0.05)]',
|
|
34882
|
-
style: 'transition: width 0.3s ease-in-out',
|
|
34883
|
-
}, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white\">\n <div\n class=\"cqa-grid cqa-flex-1 cqa-min-h-0 cqa-overflow-hidden\"\n [style.grid-template-columns]=\"expanded ? 'auto 1fr' : 'auto 0fr'\"\n style=\"transition: grid-template-columns 0.3s ease-in-out\">\n <!-- Left vertical icon bar: one button per tab -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1 cqa-min-h-0 cqa-items-center cqa-py-4 cqa-px-2 cqa-border-r cqa-border-[#E2E8F0] cqa-bg-[#FAFAFA] cqa-flex-shrink-0\">\n <!-- Expand / Collapse button (always visible) -->\n <button\n type=\"button\"\n [matTooltip]=\"expanded ? collapseTooltip : expandTooltip\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2 cqa-flex-shrink-0\"\n (click)=\"onExpandToggle()\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">{{ expanded ? 'unfold_less' : 'unfold_more' }}</mat-icon>\n </button>\n <!-- Close button -->\n <button\n *ngIf=\"showCloseButton\"\n type=\"button\"\n [matTooltip]=\"closeTooltip\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2 cqa-flex-shrink-0\"\n (click)=\"onClose()\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">close</mat-icon>\n </button>\n <!-- Tab buttons: equally distributed in remaining space -->\n <div class=\"cqa-flex cqa-flex-1 cqa-flex-col cqa-justify-evenly cqa-items-center cqa-w-full\">\n <button\n *ngFor=\"let tab of tabComponents; trackBy: trackByValue\"\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"isTabActive(tab)\"\n [matTooltip]=\"tab.label\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2 cqa-flex-shrink-0\"\n [ngClass]=\"{\n 'cqa-bg-[#3F43EE] cqa-text-white': isTabActive(tab),\n 'cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155]': !isTabActive(tab)\n }\"\n (click)=\"onTabClick(tab)\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">{{ tab.icon }}</mat-icon>\n </button>\n </div>\n </div>\n\n <!-- Content area: show only the active tab's content -->\n <div class=\"cqa-min-w-0 cqa-overflow-hidden\">\n <div class=\"cqa-h-full cqa-overflow-y-auto cqa-p-4\">\n <ng-container *ngFor=\"let tab of tabComponents\">\n <ng-container *ngIf=\"tab.value === activeTab && tab.contentTemplate\" [ngTemplateOutlet]=\"tab.contentTemplate\"></ng-container>\n </ng-container>\n </div>\n </div>\n </div>\n</div>\n", styles: [] }]
|
|
34884
|
-
}], propDecorators: { tabComponents: [{
|
|
34885
|
-
type: ContentChildren,
|
|
34886
|
-
args: [DetailDrawerTabComponent]
|
|
34887
|
-
}], activeTab: [{
|
|
34888
|
-
type: Input
|
|
34889
|
-
}], showCloseButton: [{
|
|
34890
|
-
type: Input
|
|
34891
|
-
}], expanded: [{
|
|
34892
|
-
type: Input
|
|
34893
|
-
}], expandedWidth: [{
|
|
34894
|
-
type: Input
|
|
34895
|
-
}], minExpandedWidth: [{
|
|
34896
|
-
type: Input
|
|
34897
|
-
}], maxExpandedWidth: [{
|
|
34898
|
-
type: Input
|
|
34899
|
-
}], collapsedWidth: [{
|
|
34900
|
-
type: Input
|
|
34901
|
-
}], hostWidth: [{
|
|
34902
|
-
type: HostBinding,
|
|
34903
|
-
args: ['style.width']
|
|
34904
|
-
}], hostMinWidth: [{
|
|
34905
|
-
type: HostBinding,
|
|
34906
|
-
args: ['style.min-width']
|
|
34907
|
-
}], hostMaxWidth: [{
|
|
34908
|
-
type: HostBinding,
|
|
34909
|
-
args: ['style.max-width']
|
|
34910
|
-
}], expandTooltip: [{
|
|
34911
|
-
type: Input
|
|
34912
|
-
}], collapseTooltip: [{
|
|
34913
|
-
type: Input
|
|
34914
|
-
}], closeTooltip: [{
|
|
34915
|
-
type: Input
|
|
34916
|
-
}], activeTabChange: [{
|
|
34917
|
-
type: Output
|
|
34918
|
-
}], expandToggle: [{
|
|
34919
|
-
type: Output
|
|
34920
|
-
}], close: [{
|
|
34921
|
-
type: Output
|
|
34922
34816
|
}] } });
|
|
34923
34817
|
|
|
34924
34818
|
class StepBuilderGroupComponent {
|