@cqa-lib/cqa-ui 1.1.225 → 1.1.226
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/step-builder/step-builder-action/step-builder-action.component.mjs +267 -44
- package/esm2020/lib/step-builder/step-builder-condition/step-builder-condition.component.mjs +183 -41
- package/esm2020/lib/step-builder/step-builder-loop/step-builder-loop.component.mjs +44 -3
- package/esm2020/lib/step-builder/template-variables-form/template-variables-form.component.mjs +218 -57
- package/esm2020/lib/test-case-details/element-popup/element-form/element-form.component.mjs +277 -0
- package/esm2020/lib/test-case-details/element-popup/element-popup.component.mjs +32 -192
- package/esm2020/lib/ui-kit.module.mjs +6 -1
- package/esm2020/public-api.mjs +2 -1
- package/fesm2015/cqa-lib-cqa-ui.mjs +1016 -325
- package/fesm2015/cqa-lib-cqa-ui.mjs.map +1 -1
- package/fesm2020/cqa-lib-cqa-ui.mjs +996 -316
- package/fesm2020/cqa-lib-cqa-ui.mjs.map +1 -1
- package/lib/step-builder/step-builder-action/step-builder-action.component.d.ts +50 -4
- package/lib/step-builder/step-builder-condition/step-builder-condition.component.d.ts +39 -2
- package/lib/step-builder/step-builder-loop/step-builder-loop.component.d.ts +17 -1
- package/lib/step-builder/template-variables-form/template-variables-form.component.d.ts +56 -5
- package/lib/test-case-details/element-popup/element-form/element-form.component.d.ts +77 -0
- package/lib/test-case-details/element-popup/element-popup.component.d.ts +13 -32
- package/lib/ui-kit.module.d.ts +42 -41
- package/package.json +1 -1
- package/public-api.d.ts +1 -0
- package/styles.css +1 -1
|
@@ -3,7 +3,7 @@ import { EventEmitter, Component, Input, Output, HostListener, ViewChildren, Vie
|
|
|
3
3
|
import * as i2 from '@angular/common';
|
|
4
4
|
import { CommonModule } from '@angular/common';
|
|
5
5
|
import * as i1$1 from '@angular/forms';
|
|
6
|
-
import { NG_VALUE_ACCESSOR, FormControl, FormGroup, Validators, FormBuilder, FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|
6
|
+
import { NG_VALUE_ACCESSOR, FormControl, FormGroup, Validators, FormBuilder, FormArray, FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|
7
7
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
|
8
8
|
import * as i1 from '@angular/material/icon';
|
|
9
9
|
import { MatIconModule } from '@angular/material/icon';
|
|
@@ -18472,6 +18472,274 @@ class ElementPopupRef {
|
|
|
18472
18472
|
}
|
|
18473
18473
|
const CUSTOM_ELEMENT_POPUP_REF = new InjectionToken('CUSTOM_ELEMENT_POPUP_REF');
|
|
18474
18474
|
|
|
18475
|
+
class ElementFormComponent {
|
|
18476
|
+
constructor(fb, cdr) {
|
|
18477
|
+
this.cdr = cdr;
|
|
18478
|
+
/** Current element data (for edit mode) */
|
|
18479
|
+
this.element = { title: '', selector: '', labels: [] };
|
|
18480
|
+
/** Screen name options for autocomplete (from API) */
|
|
18481
|
+
this.screenNameOptions = [];
|
|
18482
|
+
/** Whether more screen names are available for infinite scroll */
|
|
18483
|
+
this.hasMoreScreenNames = false;
|
|
18484
|
+
/** True while parent is loading screen names (search or load more) */
|
|
18485
|
+
this.isLoadingScreenNames = false;
|
|
18486
|
+
/** True while parent is fetching latest element data for edit (shows loading state) */
|
|
18487
|
+
this.isElementLoading = false;
|
|
18488
|
+
/** Whether we're in edit mode */
|
|
18489
|
+
this.isEditMode = false;
|
|
18490
|
+
/** Whether we're in create mode */
|
|
18491
|
+
this.isCreateMode = false;
|
|
18492
|
+
/** Whether edit in depth is available */
|
|
18493
|
+
this.isEditInDepthAvailable = true;
|
|
18494
|
+
/** Emitted when user creates a new element (parent should call API) */
|
|
18495
|
+
this.createElement = new EventEmitter();
|
|
18496
|
+
/** Emitted when user updates an element (parent should call API) */
|
|
18497
|
+
this.updateElement = new EventEmitter();
|
|
18498
|
+
/** Emitted when user requests to create a new screen name */
|
|
18499
|
+
this.createScreenNameRequest = new EventEmitter();
|
|
18500
|
+
/** Emitted when user searches screen names (server search) */
|
|
18501
|
+
this.searchScreenName = new EventEmitter();
|
|
18502
|
+
/** Emitted when user scrolls to load more screen names (passes current search query) */
|
|
18503
|
+
this.loadMoreScreenNames = new EventEmitter();
|
|
18504
|
+
/** Emitted when user clicks "Select from Element list" or "Cancel" */
|
|
18505
|
+
this.cancel = new EventEmitter();
|
|
18506
|
+
/** Emitted when user clicks "Edit in depth" */
|
|
18507
|
+
this.editInDepth = new EventEmitter();
|
|
18508
|
+
/** Labels (tags) as string array for multi-tag input */
|
|
18509
|
+
this.formLabels = [];
|
|
18510
|
+
/** Current tag input value */
|
|
18511
|
+
this.tagInputValue = '';
|
|
18512
|
+
/** Whether we're saving (disable buttons) */
|
|
18513
|
+
this.saving = false;
|
|
18514
|
+
this.fb = fb || new FormBuilder();
|
|
18515
|
+
this.initializeForm();
|
|
18516
|
+
}
|
|
18517
|
+
ngOnChanges(changes) {
|
|
18518
|
+
if (changes['screenNameOptions'] || changes['hasMoreScreenNames'] || changes['isLoadingScreenNames']) {
|
|
18519
|
+
this.updateScreenNameSelectConfig();
|
|
18520
|
+
}
|
|
18521
|
+
if ((changes['element'] || changes['elementId']) && this.elementId) {
|
|
18522
|
+
this.populateFormForEdit();
|
|
18523
|
+
}
|
|
18524
|
+
else if (changes['element'] && !this.elementId && this.isCreateMode) {
|
|
18525
|
+
this.populateFormForCreateWithElement();
|
|
18526
|
+
}
|
|
18527
|
+
}
|
|
18528
|
+
ngOnInit() {
|
|
18529
|
+
if (this.elementId) {
|
|
18530
|
+
this.populateFormForEdit();
|
|
18531
|
+
}
|
|
18532
|
+
else if (this.isCreateMode && this.element) {
|
|
18533
|
+
this.populateFormForCreateWithElement();
|
|
18534
|
+
}
|
|
18535
|
+
}
|
|
18536
|
+
initializeForm() {
|
|
18537
|
+
this.form = this.fb.group({
|
|
18538
|
+
name: ['', [Validators.required]],
|
|
18539
|
+
screenNameId: [null, [Validators.required]],
|
|
18540
|
+
value: ['', [Validators.required]],
|
|
18541
|
+
});
|
|
18542
|
+
this.updateScreenNameSelectConfig();
|
|
18543
|
+
}
|
|
18544
|
+
updateScreenNameSelectConfig() {
|
|
18545
|
+
const opts = (this.screenNameOptions || []).map((o) => ({
|
|
18546
|
+
id: o.id,
|
|
18547
|
+
value: o.id,
|
|
18548
|
+
name: o.name,
|
|
18549
|
+
label: o.name,
|
|
18550
|
+
}));
|
|
18551
|
+
const currentId = this.form?.get('screenNameId')?.value;
|
|
18552
|
+
if (currentId && this.element?.screenNameId === currentId && this.element?.screenName) {
|
|
18553
|
+
const exists = opts.some((o) => o.id === currentId);
|
|
18554
|
+
if (!exists) {
|
|
18555
|
+
opts.unshift({
|
|
18556
|
+
id: currentId,
|
|
18557
|
+
value: currentId,
|
|
18558
|
+
name: String(this.element.screenName),
|
|
18559
|
+
label: String(this.element.screenName),
|
|
18560
|
+
});
|
|
18561
|
+
}
|
|
18562
|
+
}
|
|
18563
|
+
this.screenNameSelectConfig = {
|
|
18564
|
+
key: 'screenNameId',
|
|
18565
|
+
label: 'Screen Name',
|
|
18566
|
+
placeholder: 'Select or create screen',
|
|
18567
|
+
searchable: true,
|
|
18568
|
+
serverSearch: true,
|
|
18569
|
+
allowCustomValue: true,
|
|
18570
|
+
options: opts,
|
|
18571
|
+
hasMore: this.hasMoreScreenNames,
|
|
18572
|
+
isLoading: this.isLoadingScreenNames,
|
|
18573
|
+
onSearch: (q) => this.searchScreenName.emit(q || ''),
|
|
18574
|
+
onLoadMore: (q) => this.loadMoreScreenNames.emit(q || ''),
|
|
18575
|
+
};
|
|
18576
|
+
this.cdr?.markForCheck();
|
|
18577
|
+
}
|
|
18578
|
+
populateFormForEdit() {
|
|
18579
|
+
if (this.element && this.elementId != null) {
|
|
18580
|
+
this.isEditMode = true;
|
|
18581
|
+
this.isCreateMode = false;
|
|
18582
|
+
this.form.patchValue({
|
|
18583
|
+
name: this.element.title ?? '',
|
|
18584
|
+
screenNameId: this.element.screenNameId ?? null,
|
|
18585
|
+
value: this.element.selector ?? '',
|
|
18586
|
+
});
|
|
18587
|
+
this.formLabels = [...(this.element.labels || [])];
|
|
18588
|
+
this.updateScreenNameSelectConfig();
|
|
18589
|
+
}
|
|
18590
|
+
else {
|
|
18591
|
+
this.isEditMode = false;
|
|
18592
|
+
this.isCreateMode = false;
|
|
18593
|
+
this.formLabels = [];
|
|
18594
|
+
}
|
|
18595
|
+
this.cdr?.markForCheck();
|
|
18596
|
+
}
|
|
18597
|
+
populateFormForCreateWithElement() {
|
|
18598
|
+
if (this.element) {
|
|
18599
|
+
this.isCreateMode = true;
|
|
18600
|
+
this.isEditMode = false;
|
|
18601
|
+
this.form.patchValue({
|
|
18602
|
+
name: this.element.title ?? '',
|
|
18603
|
+
screenNameId: this.element.screenNameId ?? null,
|
|
18604
|
+
value: this.element.selector ?? '',
|
|
18605
|
+
});
|
|
18606
|
+
this.formLabels = [...(this.element.labels || [])];
|
|
18607
|
+
this.updateScreenNameSelectConfig();
|
|
18608
|
+
}
|
|
18609
|
+
else {
|
|
18610
|
+
this.isCreateMode = true;
|
|
18611
|
+
this.isEditMode = false;
|
|
18612
|
+
this.formLabels = [];
|
|
18613
|
+
}
|
|
18614
|
+
this.cdr?.markForCheck();
|
|
18615
|
+
}
|
|
18616
|
+
/** Called by parent when a new screen name was created (so we can set the selected value) */
|
|
18617
|
+
setCreatedScreenName(opt) {
|
|
18618
|
+
this.form.get('screenNameId')?.setValue(opt.id);
|
|
18619
|
+
this.updateScreenNameSelectConfig();
|
|
18620
|
+
this.cdr?.markForCheck();
|
|
18621
|
+
}
|
|
18622
|
+
onApply() {
|
|
18623
|
+
if (this.form.invalid) {
|
|
18624
|
+
Object.keys(this.form.controls).forEach((key) => this.form.get(key)?.markAsTouched());
|
|
18625
|
+
return;
|
|
18626
|
+
}
|
|
18627
|
+
const formValue = this.form.value;
|
|
18628
|
+
const screenNameId = formValue.screenNameId;
|
|
18629
|
+
const selectedOpt = this.screenNameOptions.find((o) => o.id === screenNameId);
|
|
18630
|
+
const screenNameName = selectedOpt?.name ? String(selectedOpt.name).trim() : '';
|
|
18631
|
+
if (!screenNameId || !screenNameName) {
|
|
18632
|
+
this.form.get('screenNameId')?.setErrors({ required: true });
|
|
18633
|
+
this.form.get('screenNameId')?.markAsTouched();
|
|
18634
|
+
return;
|
|
18635
|
+
}
|
|
18636
|
+
this.saving = true;
|
|
18637
|
+
this.cdr?.markForCheck();
|
|
18638
|
+
const payload = {
|
|
18639
|
+
name: formValue.name.trim(),
|
|
18640
|
+
screenNameId,
|
|
18641
|
+
screenNameName,
|
|
18642
|
+
locatorValue: formValue.value.trim(),
|
|
18643
|
+
labels: [...this.formLabels],
|
|
18644
|
+
};
|
|
18645
|
+
if (this.isEditMode && this.elementId) {
|
|
18646
|
+
this.updateElement.emit({
|
|
18647
|
+
...payload,
|
|
18648
|
+
elementId: this.elementId,
|
|
18649
|
+
});
|
|
18650
|
+
}
|
|
18651
|
+
else {
|
|
18652
|
+
this.createElement.emit(payload);
|
|
18653
|
+
}
|
|
18654
|
+
}
|
|
18655
|
+
onCreateOrUpdateSuccess() {
|
|
18656
|
+
this.saving = false;
|
|
18657
|
+
this.cdr?.markForCheck();
|
|
18658
|
+
}
|
|
18659
|
+
onCreateOrUpdateError() {
|
|
18660
|
+
this.saving = false;
|
|
18661
|
+
this.cdr?.markForCheck();
|
|
18662
|
+
}
|
|
18663
|
+
onCancel() {
|
|
18664
|
+
this.cancel.emit();
|
|
18665
|
+
}
|
|
18666
|
+
onEditInDepth(event) {
|
|
18667
|
+
event.preventDefault();
|
|
18668
|
+
this.editInDepth.emit();
|
|
18669
|
+
}
|
|
18670
|
+
getFormControl(controlName) {
|
|
18671
|
+
return this.form.get(controlName);
|
|
18672
|
+
}
|
|
18673
|
+
getFormControlValue(controlName) {
|
|
18674
|
+
return this.form.get(controlName)?.value || '';
|
|
18675
|
+
}
|
|
18676
|
+
onFormControlChange(controlName, value) {
|
|
18677
|
+
this.form.patchValue({ [controlName]: value });
|
|
18678
|
+
this.cdr?.markForCheck();
|
|
18679
|
+
}
|
|
18680
|
+
/** Add a tag (label) */
|
|
18681
|
+
addTag(tag) {
|
|
18682
|
+
const t = (tag || this.tagInputValue || '').trim();
|
|
18683
|
+
if (t && !this.formLabels.includes(t)) {
|
|
18684
|
+
this.formLabels = [...this.formLabels, t];
|
|
18685
|
+
this.tagInputValue = '';
|
|
18686
|
+
this.cdr?.markForCheck();
|
|
18687
|
+
}
|
|
18688
|
+
}
|
|
18689
|
+
removeTag(tag) {
|
|
18690
|
+
this.formLabels = this.formLabels.filter((l) => l !== tag);
|
|
18691
|
+
this.cdr?.markForCheck();
|
|
18692
|
+
}
|
|
18693
|
+
onTagInputKeydown(event) {
|
|
18694
|
+
if (event.key === 'Enter' || event.key === ',') {
|
|
18695
|
+
event.preventDefault();
|
|
18696
|
+
this.addTag();
|
|
18697
|
+
}
|
|
18698
|
+
}
|
|
18699
|
+
}
|
|
18700
|
+
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 });
|
|
18701
|
+
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 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 <span *ngFor=\"let tag of formLabels\"\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-full cqa-text-[12px] cqa-text-[#3F43EE]\">\n {{ tag }}\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 </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: 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 });
|
|
18702
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: ElementFormComponent, decorators: [{
|
|
18703
|
+
type: Component,
|
|
18704
|
+
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 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 <span *ngFor=\"let tag of formLabels\"\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-full cqa-text-[12px] cqa-text-[#3F43EE]\">\n {{ tag }}\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 </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" }]
|
|
18705
|
+
}], ctorParameters: function () { return [{ type: i1$1.FormBuilder, decorators: [{
|
|
18706
|
+
type: Optional
|
|
18707
|
+
}] }, { type: i0.ChangeDetectorRef, decorators: [{
|
|
18708
|
+
type: Optional
|
|
18709
|
+
}] }]; }, propDecorators: { elementId: [{
|
|
18710
|
+
type: Input
|
|
18711
|
+
}], element: [{
|
|
18712
|
+
type: Input
|
|
18713
|
+
}], screenNameOptions: [{
|
|
18714
|
+
type: Input
|
|
18715
|
+
}], hasMoreScreenNames: [{
|
|
18716
|
+
type: Input
|
|
18717
|
+
}], isLoadingScreenNames: [{
|
|
18718
|
+
type: Input
|
|
18719
|
+
}], isElementLoading: [{
|
|
18720
|
+
type: Input
|
|
18721
|
+
}], isEditMode: [{
|
|
18722
|
+
type: Input
|
|
18723
|
+
}], isCreateMode: [{
|
|
18724
|
+
type: Input
|
|
18725
|
+
}], isEditInDepthAvailable: [{
|
|
18726
|
+
type: Input
|
|
18727
|
+
}], createElement: [{
|
|
18728
|
+
type: Output
|
|
18729
|
+
}], updateElement: [{
|
|
18730
|
+
type: Output
|
|
18731
|
+
}], createScreenNameRequest: [{
|
|
18732
|
+
type: Output
|
|
18733
|
+
}], searchScreenName: [{
|
|
18734
|
+
type: Output
|
|
18735
|
+
}], loadMoreScreenNames: [{
|
|
18736
|
+
type: Output
|
|
18737
|
+
}], cancel: [{
|
|
18738
|
+
type: Output
|
|
18739
|
+
}], editInDepth: [{
|
|
18740
|
+
type: Output
|
|
18741
|
+
}] } });
|
|
18742
|
+
|
|
18475
18743
|
class ElementListComponent {
|
|
18476
18744
|
constructor() {
|
|
18477
18745
|
/** Array of items to display */
|
|
@@ -18582,7 +18850,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
|
|
|
18582
18850
|
}] } });
|
|
18583
18851
|
|
|
18584
18852
|
class ElementPopupComponent {
|
|
18585
|
-
constructor(ref, data,
|
|
18853
|
+
constructor(ref, data, cdr) {
|
|
18586
18854
|
this.ref = ref;
|
|
18587
18855
|
this.cdr = cdr;
|
|
18588
18856
|
this.value = '';
|
|
@@ -18633,26 +18901,15 @@ class ElementPopupComponent {
|
|
|
18633
18901
|
this.isEditMode = false;
|
|
18634
18902
|
/** Whether we're in create mode (no elementId) */
|
|
18635
18903
|
this.isCreateMode = false;
|
|
18636
|
-
/** Labels (tags) as string array for multi-tag input */
|
|
18637
|
-
this.formLabels = [];
|
|
18638
|
-
/** Current tag input value */
|
|
18639
|
-
this.tagInputValue = '';
|
|
18640
18904
|
/** Current search input value (bound to search bar) */
|
|
18641
18905
|
this.searchValue = '';
|
|
18642
|
-
/** Whether we're saving (disable buttons) */
|
|
18643
|
-
this.saving = false;
|
|
18644
18906
|
this.injectedData = data;
|
|
18645
|
-
this.fb = fb || new FormBuilder();
|
|
18646
|
-
this.initializeForm();
|
|
18647
18907
|
}
|
|
18648
18908
|
ngOnChanges(changes) {
|
|
18649
|
-
if (changes['screenNameOptions'] || changes['hasMoreScreenNames'] || changes['isLoadingScreenNames']) {
|
|
18650
|
-
this.updateScreenNameSelectConfig();
|
|
18651
|
-
}
|
|
18652
18909
|
if ((changes['element'] || changes['elementId']) && this.enableForm) {
|
|
18653
18910
|
if (this.elementId) {
|
|
18654
18911
|
this.isCreateMode = false;
|
|
18655
|
-
this.
|
|
18912
|
+
this.isEditMode = true;
|
|
18656
18913
|
}
|
|
18657
18914
|
else {
|
|
18658
18915
|
this.isCreateMode = true;
|
|
@@ -18675,145 +18932,25 @@ class ElementPopupComponent {
|
|
|
18675
18932
|
}
|
|
18676
18933
|
}
|
|
18677
18934
|
}
|
|
18678
|
-
initializeForm() {
|
|
18679
|
-
this.form = this.fb.group({
|
|
18680
|
-
name: ['', [Validators.required]],
|
|
18681
|
-
screenNameId: [null, [Validators.required]],
|
|
18682
|
-
value: ['', [Validators.required]],
|
|
18683
|
-
});
|
|
18684
|
-
this.updateScreenNameSelectConfig();
|
|
18685
|
-
}
|
|
18686
|
-
updateScreenNameSelectConfig() {
|
|
18687
|
-
const opts = (this.screenNameOptions || []).map((o) => ({
|
|
18688
|
-
id: o.id,
|
|
18689
|
-
value: o.id,
|
|
18690
|
-
name: o.name,
|
|
18691
|
-
label: o.name,
|
|
18692
|
-
}));
|
|
18693
|
-
const currentId = this.form?.get('screenNameId')?.value;
|
|
18694
|
-
if (currentId && this.element?.screenNameId === currentId && this.element?.screenName) {
|
|
18695
|
-
const exists = opts.some((o) => o.id === currentId);
|
|
18696
|
-
if (!exists) {
|
|
18697
|
-
opts.unshift({
|
|
18698
|
-
id: currentId,
|
|
18699
|
-
value: currentId,
|
|
18700
|
-
name: String(this.element.screenName),
|
|
18701
|
-
label: String(this.element.screenName),
|
|
18702
|
-
});
|
|
18703
|
-
}
|
|
18704
|
-
}
|
|
18705
|
-
this.screenNameSelectConfig = {
|
|
18706
|
-
key: 'screenNameId',
|
|
18707
|
-
label: 'Screen Name',
|
|
18708
|
-
placeholder: 'Select or create screen',
|
|
18709
|
-
searchable: true,
|
|
18710
|
-
serverSearch: true,
|
|
18711
|
-
allowCustomValue: true,
|
|
18712
|
-
options: opts,
|
|
18713
|
-
hasMore: this.hasMoreScreenNames,
|
|
18714
|
-
isLoading: this.isLoadingScreenNames,
|
|
18715
|
-
onSearch: (q) => this.searchScreenName.emit(q || ''),
|
|
18716
|
-
onLoadMore: (q) => this.loadMoreScreenNames.emit(q || ''),
|
|
18717
|
-
};
|
|
18718
|
-
this.cdr?.markForCheck();
|
|
18719
|
-
}
|
|
18720
|
-
populateFormForEdit() {
|
|
18721
|
-
if (this.element && this.elementId != null) {
|
|
18722
|
-
this.isEditMode = true;
|
|
18723
|
-
this.isCreateMode = false;
|
|
18724
|
-
this.form.patchValue({
|
|
18725
|
-
name: this.element.title ?? '',
|
|
18726
|
-
screenNameId: this.element.screenNameId ?? null,
|
|
18727
|
-
value: this.element.selector ?? '',
|
|
18728
|
-
});
|
|
18729
|
-
this.formLabels = [...(this.element.labels || [])];
|
|
18730
|
-
this.updateScreenNameSelectConfig();
|
|
18731
|
-
}
|
|
18732
|
-
else {
|
|
18733
|
-
this.isEditMode = false;
|
|
18734
|
-
this.isCreateMode = false;
|
|
18735
|
-
this.formLabels = [];
|
|
18736
|
-
}
|
|
18737
|
-
this.cdr?.markForCheck();
|
|
18738
|
-
}
|
|
18739
|
-
populateFormForCreateWithElement() {
|
|
18740
|
-
if (this.element) {
|
|
18741
|
-
this.isCreateMode = true;
|
|
18742
|
-
this.isEditMode = false;
|
|
18743
|
-
this.form.patchValue({
|
|
18744
|
-
name: this.element.title ?? '',
|
|
18745
|
-
screenNameId: this.element.screenNameId ?? null,
|
|
18746
|
-
value: this.element.selector ?? '',
|
|
18747
|
-
});
|
|
18748
|
-
this.formLabels = [...(this.element.labels || [])];
|
|
18749
|
-
this.updateScreenNameSelectConfig();
|
|
18750
|
-
}
|
|
18751
|
-
else {
|
|
18752
|
-
this.isCreateMode = true;
|
|
18753
|
-
this.isEditMode = false;
|
|
18754
|
-
this.formLabels = [];
|
|
18755
|
-
}
|
|
18756
|
-
this.cdr?.markForCheck();
|
|
18757
|
-
}
|
|
18758
18935
|
resetForm() {
|
|
18759
18936
|
this.isEditMode = false;
|
|
18760
18937
|
this.isCreateMode = false;
|
|
18761
|
-
this.formLabels = [];
|
|
18762
|
-
this.tagInputValue = '';
|
|
18763
|
-
this.form.reset({
|
|
18764
|
-
name: '',
|
|
18765
|
-
screenNameId: null,
|
|
18766
|
-
value: '',
|
|
18767
|
-
});
|
|
18768
|
-
this.updateScreenNameSelectConfig();
|
|
18769
18938
|
}
|
|
18770
|
-
|
|
18771
|
-
|
|
18772
|
-
this.form.get('screenNameId')?.setValue(opt.id);
|
|
18773
|
-
this.updateScreenNameSelectConfig();
|
|
18774
|
-
this.cdr?.markForCheck();
|
|
18939
|
+
onElementFormCreate(payload) {
|
|
18940
|
+
this.createElement.emit(payload);
|
|
18775
18941
|
}
|
|
18776
|
-
|
|
18777
|
-
|
|
18778
|
-
|
|
18779
|
-
|
|
18780
|
-
|
|
18781
|
-
const formValue = this.form.value;
|
|
18782
|
-
const screenNameId = formValue.screenNameId;
|
|
18783
|
-
const selectedOpt = this.screenNameOptions.find((o) => o.id === screenNameId);
|
|
18784
|
-
const screenNameName = selectedOpt?.name ? String(selectedOpt.name).trim() : '';
|
|
18785
|
-
if (!screenNameId || !screenNameName) {
|
|
18786
|
-
this.form.get('screenNameId')?.setErrors({ required: true });
|
|
18787
|
-
this.form.get('screenNameId')?.markAsTouched();
|
|
18788
|
-
return;
|
|
18789
|
-
}
|
|
18790
|
-
this.saving = true;
|
|
18791
|
-
this.cdr?.markForCheck();
|
|
18792
|
-
const payload = {
|
|
18793
|
-
name: formValue.name.trim(),
|
|
18794
|
-
screenNameId,
|
|
18795
|
-
screenNameName,
|
|
18796
|
-
locatorValue: formValue.value.trim(),
|
|
18797
|
-
labels: [...this.formLabels],
|
|
18798
|
-
};
|
|
18799
|
-
if (this.isEditMode && this.elementId) {
|
|
18800
|
-
this.updateElement.emit({
|
|
18801
|
-
...payload,
|
|
18802
|
-
elementId: this.elementId,
|
|
18803
|
-
});
|
|
18804
|
-
}
|
|
18805
|
-
else {
|
|
18806
|
-
this.createElement.emit(payload);
|
|
18807
|
-
}
|
|
18942
|
+
onElementFormUpdate(payload) {
|
|
18943
|
+
this.updateElement.emit(payload);
|
|
18944
|
+
}
|
|
18945
|
+
onElementFormCancel() {
|
|
18946
|
+
this.toggleForm();
|
|
18808
18947
|
}
|
|
18809
18948
|
onCreateOrUpdateSuccess() {
|
|
18810
|
-
this.saving = false;
|
|
18811
18949
|
this.enableForm = false;
|
|
18812
18950
|
this.resetForm();
|
|
18813
18951
|
this.cdr?.markForCheck();
|
|
18814
18952
|
}
|
|
18815
18953
|
onCreateOrUpdateError() {
|
|
18816
|
-
this.saving = false;
|
|
18817
18954
|
this.cdr?.markForCheck();
|
|
18818
18955
|
}
|
|
18819
18956
|
toggleForm() {
|
|
@@ -18822,8 +18959,6 @@ class ElementPopupComponent {
|
|
|
18822
18959
|
if (!this.elementId) {
|
|
18823
18960
|
this.isCreateMode = true;
|
|
18824
18961
|
this.isEditMode = false;
|
|
18825
|
-
// Patch form with current element values when Edit clicked without elementId
|
|
18826
|
-
this.populateFormForCreateWithElement();
|
|
18827
18962
|
this.formOpenRequest.emit({ mode: 'create' });
|
|
18828
18963
|
}
|
|
18829
18964
|
else {
|
|
@@ -18880,8 +19015,7 @@ class ElementPopupComponent {
|
|
|
18880
19015
|
onClose() {
|
|
18881
19016
|
this.onCancel();
|
|
18882
19017
|
}
|
|
18883
|
-
onEditInDepth(
|
|
18884
|
-
event.preventDefault();
|
|
19018
|
+
onEditInDepth() {
|
|
18885
19019
|
this.editInDepth.emit();
|
|
18886
19020
|
if (this.ref)
|
|
18887
19021
|
this.ref.close(ELEMENT_POPUP_EDIT_IN_DEPTH);
|
|
@@ -18898,35 +19032,6 @@ class ElementPopupComponent {
|
|
|
18898
19032
|
window.open(this.helpUrl, '_blank');
|
|
18899
19033
|
}
|
|
18900
19034
|
}
|
|
18901
|
-
getFormControl(controlName) {
|
|
18902
|
-
return this.form.get(controlName);
|
|
18903
|
-
}
|
|
18904
|
-
getFormControlValue(controlName) {
|
|
18905
|
-
return this.form.get(controlName)?.value || '';
|
|
18906
|
-
}
|
|
18907
|
-
onFormControlChange(controlName, value) {
|
|
18908
|
-
this.form.patchValue({ [controlName]: value });
|
|
18909
|
-
this.cdr?.markForCheck();
|
|
18910
|
-
}
|
|
18911
|
-
/** Add a tag (label) */
|
|
18912
|
-
addTag(tag) {
|
|
18913
|
-
const t = (tag || this.tagInputValue || '').trim();
|
|
18914
|
-
if (t && !this.formLabels.includes(t)) {
|
|
18915
|
-
this.formLabels = [...this.formLabels, t];
|
|
18916
|
-
this.tagInputValue = '';
|
|
18917
|
-
this.cdr?.markForCheck();
|
|
18918
|
-
}
|
|
18919
|
-
}
|
|
18920
|
-
removeTag(tag) {
|
|
18921
|
-
this.formLabels = this.formLabels.filter((l) => l !== tag);
|
|
18922
|
-
this.cdr?.markForCheck();
|
|
18923
|
-
}
|
|
18924
|
-
onTagInputKeydown(event) {
|
|
18925
|
-
if (event.key === 'Enter' || event.key === ',') {
|
|
18926
|
-
event.preventDefault();
|
|
18927
|
-
this.addTag();
|
|
18928
|
-
}
|
|
18929
|
-
}
|
|
18930
19035
|
onElementClick(element) {
|
|
18931
19036
|
this.element = element;
|
|
18932
19037
|
this.elementSelect.emit(element);
|
|
@@ -18948,12 +19053,16 @@ class ElementPopupComponent {
|
|
|
18948
19053
|
this.searchElement.emit(item);
|
|
18949
19054
|
this.cdr?.markForCheck();
|
|
18950
19055
|
}
|
|
19056
|
+
/** Called by parent when a new screen name was created (so we can set the selected value) */
|
|
19057
|
+
setCreatedScreenName(opt) {
|
|
19058
|
+
this.elementFormComponent?.setCreatedScreenName(opt);
|
|
19059
|
+
}
|
|
18951
19060
|
}
|
|
18952
|
-
ElementPopupComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: ElementPopupComponent, deps: [{ token: CUSTOM_ELEMENT_POPUP_REF, optional: true }, { token: ELEMENT_POPUP_DATA, optional: true }, { token:
|
|
18953
|
-
ElementPopupComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: ElementPopupComponent, selector: "cqa-element-popup", inputs: { value: "value", helpUrl: "helpUrl", labels: "labels", element: "element", elements: "elements", enableForm: "enableForm", isOnRecord: "isOnRecord", hasMoreElements: "hasMoreElements", elementId: "elementId", screenNameOptions: "screenNameOptions", hasMoreScreenNames: "hasMoreScreenNames", isLoadingScreenNames: "isLoadingScreenNames", suggestedTags: "suggestedTags", isElementLoading: "isElementLoading", recentSearchedItems: "recentSearchedItems" }, outputs: { apply: "apply", cancel: "cancel", editInDepth: "editInDepth", searchElement: "searchElement", recentItemClick: "recentItemClick", loadMoreElements: "loadMoreElements", createElement: "createElement", updateElement: "updateElement", createScreenNameRequest: "createScreenNameRequest", searchScreenName: "searchScreenName", loadMoreScreenNames: "loadMoreScreenNames", formOpenRequest: "formOpenRequest", elementSelect: "elementSelect", toggleRecord: "toggleRecord" }, host: { classAttribute: "cqa-ui-root" }, usesOnChanges: true, ngImport: i0, template: "<div\n class=\"cqa-bg-white cqa-rounded-[12px] cqa-shadow-lg cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-w-[500px] cqa-flex cqa-flex-col cqa-gap-[12px] cqa-p-2 cqa-box-border\">\n <!-- Header: title left; Need help? + close icon right -->\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-gap-2 cqa-px-4\">\n <h2 class=\"cqa-text-[16px] cqa-leading-[24px] cqa-font-bold cqa-text-[#111827] cqa-m-0 cqa-font-[600]\">\n Element\n </h2>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <!-- Need help? with custom tooltip (works inside overlay) -->\n <div class=\"cqa-relative cqa-inline-flex\"\n (mouseenter)=\"showHelpTooltip = true\" (mouseleave)=\"showHelpTooltip = false\">\n <a *ngIf=\"helpUrl\" href=\"#\" (click)=\"onHelp($event)\"\n class=\"cqa-flex cqa-items-center cqa-gap-1 cqa-text-[#3F43EE] cqa-text-[12px] cqa-leading-[21px] cqa-no-underline cqa-cursor-pointer\">\n <svg width=\"17\" height=\"16\" viewBox=\"0 0 17 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" class=\"cqa-flex-shrink-0\" aria-hidden=\"true\">\n <g clip-path=\"url(#help-icon-clip)\">\n <path d=\"M8.50033 14.6663C12.4123 14.6663 15.5837 11.6816 15.5837 7.99967C15.5837 4.31778 12.4123 1.33301 8.50033 1.33301C4.58831 1.33301 1.41699 4.31778 1.41699 7.99967C1.41699 11.6816 4.58831 14.6663 8.50033 14.6663Z\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6.43848 6.00038C6.60501 5.55483 6.93371 5.17912 7.36636 4.9398C7.79901 4.70049 8.30769 4.61301 8.80231 4.69285C9.29693 4.7727 9.74556 5.01473 10.0687 5.37607C10.3919 5.7374 10.5688 6.19473 10.5681 6.66705C10.5681 8.00038 8.44306 8.66705 8.44306 8.66705\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M8.5 11.333H8.50966\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </g>\n <defs>\n <clipPath id=\"help-icon-clip\">\n <rect width=\"17\" height=\"16\" fill=\"white\"/>\n </clipPath>\n </defs>\n </svg>\n Need help ?\n </a>\n <span *ngIf=\"!helpUrl\" class=\"cqa-flex cqa-items-center cqa-gap-1.5 cqa-font-[500] cqa-text-[10px] cqa-cursor-default\">\n <svg width=\"17\" height=\"16\" viewBox=\"0 0 17 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" class=\"cqa-flex-shrink-0 cqa-text-[#3F43EE]\" aria-hidden=\"true\">\n <g clip-path=\"url(#help-icon-clip-nolink)\">\n <path d=\"M8.50033 14.6663C12.4123 14.6663 15.5837 11.6816 15.5837 7.99967C15.5837 4.31778 12.4123 1.33301 8.50033 1.33301C4.58831 1.33301 1.41699 4.31778 1.41699 7.99967C1.41699 11.6816 4.58831 14.6663 8.50033 14.6663Z\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6.43848 6.00038C6.60501 5.55483 6.93371 5.17912 7.36636 4.9398C7.79901 4.70049 8.30769 4.61301 8.80231 4.69285C9.29693 4.7727 9.74556 5.01473 10.0687 5.37607C10.3919 5.7374 10.5688 6.19473 10.5681 6.66705C10.5681 8.00038 8.44306 8.66705 8.44306 8.66705\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M8.5 11.333H8.50966\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </g>\n <defs>\n <clipPath id=\"help-icon-clip-nolink\">\n <rect width=\"17\" height=\"16\" fill=\"white\"/>\n </clipPath>\n </defs>\n </svg>\n Need help ?\n </span>\n <!-- Custom tooltip (exact spec: 306\u00D720 content, 6px radius, #0A0A0A, no arrow) -->\n <div *ngIf=\"showHelpTooltip\" class=\"cqa-absolute cqa-pointer-events-none cqa-z-[100]\"\n style=\"top: -24px; left: -125px;\"\n role=\"tooltip\">\n <div class=\"cqa-text-white cqa-text-center cqa-whitespace-nowrap\"\n style=\"width: 306px; min-height: 20px; border-radius: 6px; opacity: 1; padding: 4px 8px; background-color: #0A0A0A; line-height: 20px; font-size: 8px;\">\n {{ helpTooltipText }}\n </div>\n </div>\n </div>\n <button type=\"button\" (click)=\"onClose()\"\n class=\"cqa-p-1 cqa-rounded cqa-text-[#6B7280] hover:cqa-bg-[#F3F4F6] cqa-flex cqa-items-center cqa-justify-center\"\n title=\"Close\" aria-label=\"Close\">\n <mat-icon class=\"!cqa-w-5 !cqa-h-5 !cqa-text-[20px]\">close</mat-icon>\n </button>\n </div>\n </div>\n\n <!-- Line below header (full width of modal, no side margin) -->\n <div class=\"cqa--mx-2 cqa-w-[calc(100%+1rem)] cqa-flex-shrink-0\">\n <div class=\"cqa-h-px cqa-w-full cqa-bg-[#E5E7EB]\" role=\"presentation\"></div>\n </div>\n\n <ng-container *ngIf=\"enableForm && !isOnRecord\">\n <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 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 <span *ngFor=\"let tag of formLabels\"\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-full cqa-text-[12px] cqa-text-[#3F43EE]\">\n {{ tag }}\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 </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)=\"toggleForm()\"\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=\"#\" (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 </ng-container>\n\n<ng-container *ngIf=\"isOnRecord && !enableForm\">\n <div\n class=\"cqa-flex cqa-flex-col cqa-items-center cqa-justify-center cqa-text-center cqa-gap-3 cqa-pt-10\">\n\n <!-- Video Icon -->\n <div\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-[64px] cqa-h-[64px] cqa-rounded-full cqa-bg-[#FEE2E2]\">\n <svg width=\"32\" height=\"32\" viewBox=\"0 0 32 32\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M21.333 17.3333L28.297 21.9759C28.3974 22.0428 28.514 22.0811 28.6345 22.0868C28.7549 22.0926 28.8747 22.0656 28.981 22.0087C29.0873 21.9517 29.1762 21.8671 29.2382 21.7636C29.3002 21.6602 29.3329 21.5419 29.333 21.4213V10.4933C29.333 10.376 29.3021 10.2607 29.2434 10.1592C29.1846 10.0577 29.1001 9.97344 28.9984 9.91501C28.8967 9.85658 28.7814 9.82602 28.6641 9.82642C28.5468 9.82682 28.4317 9.85816 28.3303 9.91728L21.333 13.9999\" stroke=\"#E7000B\" stroke-width=\"2.66667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M18.667 8H5.33366C3.8609 8 2.66699 9.19391 2.66699 10.6667V21.3333C2.66699 22.8061 3.8609 24 5.33366 24H18.667C20.1398 24 21.3337 22.8061 21.3337 21.3333V10.6667C21.3337 9.19391 20.1398 8 18.667 8Z\" stroke=\"#E7000B\" stroke-width=\"2.66667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n \n </div>\n\n <!-- Title -->\n <h4 class=\"cqa-m-0 cqa-text-[16px] cqa-leading-[24px] cqa-font-[600] cqa-text-[#0A0A0A]\">\n Recording Mode Active\n </h4>\n\n <!-- Subtitle -->\n <p class=\"cqa-m-0 cqa-text-[12px] cqa-leading-[18px] cqa-text-[#6B7280]\">\n Click on any element in the browser to capture it\n </p>\n </div>\n\n <!-- Footer -->\n <div class=\"cqa-flex cqa-justify-center cqa-pb-4\">\n <cqa-button\n variant=\"outlined\"\n btnSize=\"lg\"\n [text]=\"'Cancel Recording'\"\n (clicked)=\"onToggleRecordClick()\"\n [customClass]=\"'cqa-text-[14px] cqa-px-16 cqa-py-[9px] cqa-border-[#414146]'\">\n </cqa-button>\n </div>\n</ng-container>\n\n\n <ng-container *ngIf=\"!enableForm && !isOnRecord\">\n<div class=\"cqa-flex cqa-flex-col cqa-gap-4 cqa-px-1 cqa-pt-3\">\n\n <!-- Selected -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-2\">\n <span class=\"cqa-text-[12px] cqa-text-[#6B7280]\">Selected</span>\n\n <div\n class=\"cqa-flex cqa-items-center cqa-justify-between\n cqa-bg-[#FFFBEB] cqa-border cqa-border-[#fadfba]\n cqa-rounded-lg cqa-p-3 cqa-border-solid cqa-gap-3\">\n\n <div class=\"cqa-flex cqa-px-3 cqa-py-2 cqa-rounded-lg cqa-flex-col cqa-gap-0.5 cqa-bg-[#f5f5f5] cqa-flex-1\">\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-gap-2\">\n <span class=\"cqa-text-[14px] cqa-font-[600] cqa-text-[#111827]\">\n {{element.title}}\n </span>\n\n <div class=\"cqa-flex cqa-gap-2\">\n <span *ngFor=\"let l of element.labels\"\n class=\"cqa-text-[10px] cqa-px-1.5 cqa-py-0.5\n cqa-rounded cqa-bg-[#EEF2FF] cqa-text-[#3F43EE] cqa-rounded-full cqa-px-2 cqa-bg-[#eff6ff] cqa-border cqa-border-solid cqa-border-[#c8e0ff]\">\n {{l}}\n </span>\n </div>\n </div>\n\n <span class=\"cqa-text-[11px] cqa-text-[#6B7280]\">\n {{element.selector}}\n </span>\n </div>\n <cqa-button variant=\"outlined\" icon=\"edit\" btnSize=\"lg\" [text]=\"'Edit'\" [fullWidth]=\"true\" (clicked)=\"toggleForm()\"\n [customClass]=\"'cqa-text-[14px] cqa-py-[9px] cqa-border-[#414146]'\"></cqa-button>\n </div>\n </div>\n\n <!-- Recent -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-2\" *ngIf=\"recentSearchedItems.length > 0\">\n <span class=\"cqa-text-[12px] cqa-text-[#6B7280]\">Recent</span>\n\n <div class=\"cqa-flex cqa-gap-2 cqa-overflow-x-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\n <div *ngFor=\"let item of recentSearchedItems\" \n class=\"cqa-cursor-pointer cqa-inline-block\"\n (click)=\"onRecentItemClick(item)\">\n <cqa-badge \n class=\"cqa-element-badge cqa-mb-2 cqa-chip !cqa-bg-white !cqa-text-[12px] cqa-whitespace-nowrap\" \n [label]=\"item\"></cqa-badge>\n </div>\n </div>\n </div>\n\n <!-- Element Library -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-2\">\n <span class=\"cqa-text-[12px] cqa-text-[#6B7280]\">Element Library</span>\n <cqa-search-bar [fullWidth]=\"true\" [value]=\"searchValue\" placeholder=\"Search library\" (valueChange)=\"search($event)\"></cqa-search-bar> \n </div>\n\n <cqa-element-list \n [items]=\"elements\"\n [titleKey]=\"'title'\"\n [selectorKey]=\"'selector'\"\n [labelsKey]=\"'labels'\"\n [maxHeight]=\"'200px'\"\n [hasMore]=\"hasMoreElements\"\n (itemClick)=\"onElementClick($event)\"\n (loadMore)=\"onLoadMoreElements()\">\n </cqa-element-list>\n</div>\n\n\n <!-- Footer: Cancel, Apply (full width in one row) -->\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\" icon=\"radio_button_checked\" btnSize=\"lg\" [text]=\"'Record'\" [fullWidth]=\"true\" (clicked)=\"onToggleRecordClick()\"\n [customClass]=\"'cqa-text-[14px] cqa-py-[9px] cqa-border-[#414146]'\"></cqa-button>\n </div>\n <div class=\"cqa-flex-1 cqa-min-w-0\">\n <cqa-button variant=\"outlined\" icon=\"add\" btnSize=\"lg\" [text]=\"'Create New'\" [fullWidth]=\"true\" (clicked)=\"openCreateForm()\"\n [customClass]=\"'cqa-text-[14px] cqa-py-[9px] cqa-border-[#414146]'\"></cqa-button>\n </div>\n </div>\n </div>\n </ng-container>\n\n</div>\n", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { 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: ButtonComponent, selector: "cqa-button", inputs: ["variant", "btnSize", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass", "inlineStyles", "tooltip", "tooltipPosition"], outputs: ["clicked"] }, { 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: SearchBarComponent, selector: "cqa-search-bar", inputs: ["placeholder", "value", "disabled", "showClear", "ariaLabel", "autoFocus", "size", "fullWidth"], outputs: ["valueChange", "search", "cleared"] }, { type: ElementListComponent, selector: "cqa-element-list", inputs: ["items", "titleKey", "selectorKey", "labelsKey", "maxHeight", "hasMore"], outputs: ["itemClick", "loadMore"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { 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 });
|
|
19061
|
+
ElementPopupComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: ElementPopupComponent, deps: [{ token: CUSTOM_ELEMENT_POPUP_REF, optional: true }, { token: ELEMENT_POPUP_DATA, optional: true }, { token: i0.ChangeDetectorRef, optional: true }], target: i0.ɵɵFactoryTarget.Component });
|
|
19062
|
+
ElementPopupComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: ElementPopupComponent, selector: "cqa-element-popup", inputs: { value: "value", helpUrl: "helpUrl", labels: "labels", element: "element", elements: "elements", enableForm: "enableForm", isOnRecord: "isOnRecord", hasMoreElements: "hasMoreElements", elementId: "elementId", screenNameOptions: "screenNameOptions", hasMoreScreenNames: "hasMoreScreenNames", isLoadingScreenNames: "isLoadingScreenNames", suggestedTags: "suggestedTags", isElementLoading: "isElementLoading", recentSearchedItems: "recentSearchedItems" }, outputs: { apply: "apply", cancel: "cancel", editInDepth: "editInDepth", searchElement: "searchElement", recentItemClick: "recentItemClick", loadMoreElements: "loadMoreElements", createElement: "createElement", updateElement: "updateElement", createScreenNameRequest: "createScreenNameRequest", searchScreenName: "searchScreenName", loadMoreScreenNames: "loadMoreScreenNames", formOpenRequest: "formOpenRequest", elementSelect: "elementSelect", toggleRecord: "toggleRecord" }, host: { classAttribute: "cqa-ui-root" }, viewQueries: [{ propertyName: "elementFormComponent", first: true, predicate: ElementFormComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"cqa-bg-white cqa-rounded-[12px] cqa-shadow-lg cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-w-[500px] cqa-flex cqa-flex-col cqa-gap-[12px] cqa-p-2 cqa-box-border\">\n <!-- Header: title left; Need help? + close icon right -->\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-gap-2 cqa-px-4\">\n <h2 class=\"cqa-text-[16px] cqa-leading-[24px] cqa-font-bold cqa-text-[#111827] cqa-m-0 cqa-font-[600]\">\n Element\n </h2>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <!-- Need help? with custom tooltip (works inside overlay) -->\n <div class=\"cqa-relative cqa-inline-flex\"\n (mouseenter)=\"showHelpTooltip = true\" (mouseleave)=\"showHelpTooltip = false\">\n <a *ngIf=\"helpUrl\" href=\"#\" (click)=\"onHelp($event)\"\n class=\"cqa-flex cqa-items-center cqa-gap-1 cqa-text-[#3F43EE] cqa-text-[12px] cqa-leading-[21px] cqa-no-underline cqa-cursor-pointer\">\n <svg width=\"17\" height=\"16\" viewBox=\"0 0 17 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" class=\"cqa-flex-shrink-0\" aria-hidden=\"true\">\n <g clip-path=\"url(#help-icon-clip)\">\n <path d=\"M8.50033 14.6663C12.4123 14.6663 15.5837 11.6816 15.5837 7.99967C15.5837 4.31778 12.4123 1.33301 8.50033 1.33301C4.58831 1.33301 1.41699 4.31778 1.41699 7.99967C1.41699 11.6816 4.58831 14.6663 8.50033 14.6663Z\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6.43848 6.00038C6.60501 5.55483 6.93371 5.17912 7.36636 4.9398C7.79901 4.70049 8.30769 4.61301 8.80231 4.69285C9.29693 4.7727 9.74556 5.01473 10.0687 5.37607C10.3919 5.7374 10.5688 6.19473 10.5681 6.66705C10.5681 8.00038 8.44306 8.66705 8.44306 8.66705\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M8.5 11.333H8.50966\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </g>\n <defs>\n <clipPath id=\"help-icon-clip\">\n <rect width=\"17\" height=\"16\" fill=\"white\"/>\n </clipPath>\n </defs>\n </svg>\n Need help ?\n </a>\n <span *ngIf=\"!helpUrl\" class=\"cqa-flex cqa-items-center cqa-gap-1.5 cqa-font-[500] cqa-text-[10px] cqa-cursor-default\">\n <svg width=\"17\" height=\"16\" viewBox=\"0 0 17 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" class=\"cqa-flex-shrink-0 cqa-text-[#3F43EE]\" aria-hidden=\"true\">\n <g clip-path=\"url(#help-icon-clip-nolink)\">\n <path d=\"M8.50033 14.6663C12.4123 14.6663 15.5837 11.6816 15.5837 7.99967C15.5837 4.31778 12.4123 1.33301 8.50033 1.33301C4.58831 1.33301 1.41699 4.31778 1.41699 7.99967C1.41699 11.6816 4.58831 14.6663 8.50033 14.6663Z\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6.43848 6.00038C6.60501 5.55483 6.93371 5.17912 7.36636 4.9398C7.79901 4.70049 8.30769 4.61301 8.80231 4.69285C9.29693 4.7727 9.74556 5.01473 10.0687 5.37607C10.3919 5.7374 10.5688 6.19473 10.5681 6.66705C10.5681 8.00038 8.44306 8.66705 8.44306 8.66705\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M8.5 11.333H8.50966\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </g>\n <defs>\n <clipPath id=\"help-icon-clip-nolink\">\n <rect width=\"17\" height=\"16\" fill=\"white\"/>\n </clipPath>\n </defs>\n </svg>\n Need help ?\n </span>\n <!-- Custom tooltip (exact spec: 306\u00D720 content, 6px radius, #0A0A0A, no arrow) -->\n <div *ngIf=\"showHelpTooltip\" class=\"cqa-absolute cqa-pointer-events-none cqa-z-[100]\"\n style=\"top: -24px; left: -125px;\"\n role=\"tooltip\">\n <div class=\"cqa-text-white cqa-text-center cqa-whitespace-nowrap\"\n style=\"width: 306px; min-height: 20px; border-radius: 6px; opacity: 1; padding: 4px 8px; background-color: #0A0A0A; line-height: 20px; font-size: 8px;\">\n {{ helpTooltipText }}\n </div>\n </div>\n </div>\n <button type=\"button\" (click)=\"onClose()\"\n class=\"cqa-p-1 cqa-rounded cqa-text-[#6B7280] hover:cqa-bg-[#F3F4F6] cqa-flex cqa-items-center cqa-justify-center\"\n title=\"Close\" aria-label=\"Close\">\n <mat-icon class=\"!cqa-w-5 !cqa-h-5 !cqa-text-[20px]\">close</mat-icon>\n </button>\n </div>\n </div>\n\n <!-- Line below header (full width of modal, no side margin) -->\n <div class=\"cqa--mx-2 cqa-w-[calc(100%+1rem)] cqa-flex-shrink-0\">\n <div class=\"cqa-h-px cqa-w-full cqa-bg-[#E5E7EB]\" role=\"presentation\"></div>\n </div>\n\n <ng-container *ngIf=\"enableForm && !isOnRecord\">\n <cqa-element-form\n #elementForm\n [elementId]=\"elementId\"\n [element]=\"element\"\n [screenNameOptions]=\"screenNameOptions\"\n [hasMoreScreenNames]=\"hasMoreScreenNames\"\n [isLoadingScreenNames]=\"isLoadingScreenNames\"\n [isElementLoading]=\"isElementLoading\"\n [isEditMode]=\"isEditMode\"\n [isCreateMode]=\"isCreateMode\"\n (createElement)=\"onElementFormCreate($event)\"\n (updateElement)=\"onElementFormUpdate($event)\"\n (createScreenNameRequest)=\"createScreenNameRequest.emit($event)\"\n (searchScreenName)=\"searchScreenName.emit($event)\"\n (loadMoreScreenNames)=\"loadMoreScreenNames.emit($event)\"\n (cancel)=\"onElementFormCancel()\"\n (editInDepth)=\"onEditInDepth()\">\n </cqa-element-form>\n </ng-container>\n\n<ng-container *ngIf=\"isOnRecord && !enableForm\">\n <div\n class=\"cqa-flex cqa-flex-col cqa-items-center cqa-justify-center cqa-text-center cqa-gap-3 cqa-pt-10\">\n\n <!-- Video Icon -->\n <div\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-[64px] cqa-h-[64px] cqa-rounded-full cqa-bg-[#FEE2E2]\">\n <svg width=\"32\" height=\"32\" viewBox=\"0 0 32 32\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M21.333 17.3333L28.297 21.9759C28.3974 22.0428 28.514 22.0811 28.6345 22.0868C28.7549 22.0926 28.8747 22.0656 28.981 22.0087C29.0873 21.9517 29.1762 21.8671 29.2382 21.7636C29.3002 21.6602 29.3329 21.5419 29.333 21.4213V10.4933C29.333 10.376 29.3021 10.2607 29.2434 10.1592C29.1846 10.0577 29.1001 9.97344 28.9984 9.91501C28.8967 9.85658 28.7814 9.82602 28.6641 9.82642C28.5468 9.82682 28.4317 9.85816 28.3303 9.91728L21.333 13.9999\" stroke=\"#E7000B\" stroke-width=\"2.66667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M18.667 8H5.33366C3.8609 8 2.66699 9.19391 2.66699 10.6667V21.3333C2.66699 22.8061 3.8609 24 5.33366 24H18.667C20.1398 24 21.3337 22.8061 21.3337 21.3333V10.6667C21.3337 9.19391 20.1398 8 18.667 8Z\" stroke=\"#E7000B\" stroke-width=\"2.66667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n \n </div>\n\n <!-- Title -->\n <h4 class=\"cqa-m-0 cqa-text-[16px] cqa-leading-[24px] cqa-font-[600] cqa-text-[#0A0A0A]\">\n Recording Mode Active\n </h4>\n\n <!-- Subtitle -->\n <p class=\"cqa-m-0 cqa-text-[12px] cqa-leading-[18px] cqa-text-[#6B7280]\">\n Click on any element in the browser to capture it\n </p>\n </div>\n\n <!-- Footer -->\n <div class=\"cqa-flex cqa-justify-center cqa-pb-4\">\n <cqa-button\n variant=\"outlined\"\n btnSize=\"lg\"\n [text]=\"'Cancel Recording'\"\n (clicked)=\"onToggleRecordClick()\"\n [customClass]=\"'cqa-text-[14px] cqa-px-16 cqa-py-[9px] cqa-border-[#414146]'\">\n </cqa-button>\n </div>\n</ng-container>\n\n\n <ng-container *ngIf=\"!enableForm && !isOnRecord\">\n<div class=\"cqa-flex cqa-flex-col cqa-gap-4 cqa-px-1 cqa-pt-3\">\n\n <!-- Selected -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-2\">\n <span class=\"cqa-text-[12px] cqa-text-[#6B7280]\">Selected</span>\n\n <div\n class=\"cqa-flex cqa-items-center cqa-justify-between\n cqa-bg-[#FFFBEB] cqa-border cqa-border-[#fadfba]\n cqa-rounded-lg cqa-p-3 cqa-border-solid cqa-gap-3\">\n\n <div class=\"cqa-flex cqa-px-3 cqa-py-2 cqa-rounded-lg cqa-flex-col cqa-gap-0.5 cqa-bg-[#f5f5f5] cqa-flex-1\">\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-gap-2\">\n <span class=\"cqa-text-[14px] cqa-font-[600] cqa-text-[#111827]\">\n {{element.title}}\n </span>\n\n <div class=\"cqa-flex cqa-gap-2\">\n <span *ngFor=\"let l of element.labels\"\n class=\"cqa-text-[10px] cqa-px-1.5 cqa-py-0.5\n cqa-rounded cqa-bg-[#EEF2FF] cqa-text-[#3F43EE] cqa-rounded-full cqa-px-2 cqa-bg-[#eff6ff] cqa-border cqa-border-solid cqa-border-[#c8e0ff]\">\n {{l}}\n </span>\n </div>\n </div>\n\n <span class=\"cqa-text-[11px] cqa-text-[#6B7280]\">\n {{element.selector}}\n </span>\n </div>\n <cqa-button variant=\"outlined\" icon=\"edit\" btnSize=\"lg\" [text]=\"'Edit'\" [fullWidth]=\"true\" (clicked)=\"toggleForm()\"\n [customClass]=\"'cqa-text-[14px] cqa-py-[9px] cqa-border-[#414146]'\"></cqa-button>\n </div>\n </div>\n\n <!-- Recent -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-2\" *ngIf=\"recentSearchedItems.length > 0\">\n <span class=\"cqa-text-[12px] cqa-text-[#6B7280]\">Recent</span>\n\n <div class=\"cqa-flex cqa-gap-2 cqa-overflow-x-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\n <div *ngFor=\"let item of recentSearchedItems\" \n class=\"cqa-cursor-pointer cqa-inline-block\"\n (click)=\"onRecentItemClick(item)\">\n <cqa-badge \n class=\"cqa-element-badge cqa-mb-2 cqa-chip !cqa-bg-white !cqa-text-[12px] cqa-whitespace-nowrap\" \n [label]=\"item\"></cqa-badge>\n </div>\n </div>\n </div>\n\n <!-- Element Library -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-2\">\n <span class=\"cqa-text-[12px] cqa-text-[#6B7280]\">Element Library</span>\n <cqa-search-bar [fullWidth]=\"true\" [value]=\"searchValue\" placeholder=\"Search library\" (valueChange)=\"search($event)\"></cqa-search-bar> \n </div>\n\n <cqa-element-list \n [items]=\"elements\"\n [titleKey]=\"'title'\"\n [selectorKey]=\"'selector'\"\n [labelsKey]=\"'labels'\"\n [maxHeight]=\"'200px'\"\n [hasMore]=\"hasMoreElements\"\n (itemClick)=\"onElementClick($event)\"\n (loadMore)=\"onLoadMoreElements()\">\n </cqa-element-list>\n</div>\n\n\n <!-- Footer: Cancel, Apply (full width in one row) -->\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\" icon=\"radio_button_checked\" btnSize=\"lg\" [text]=\"'Record'\" [fullWidth]=\"true\" (clicked)=\"onToggleRecordClick()\"\n [customClass]=\"'cqa-text-[14px] cqa-py-[9px] cqa-border-[#414146]'\"></cqa-button>\n </div>\n <div class=\"cqa-flex-1 cqa-min-w-0\">\n <cqa-button variant=\"outlined\" icon=\"add\" btnSize=\"lg\" [text]=\"'Create New'\" [fullWidth]=\"true\" (clicked)=\"openCreateForm()\"\n [customClass]=\"'cqa-text-[14px] cqa-py-[9px] cqa-border-[#414146]'\"></cqa-button>\n </div>\n </div>\n </div>\n </ng-container>\n\n</div>\n", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { type: ElementFormComponent, selector: "cqa-element-form", inputs: ["elementId", "element", "screenNameOptions", "hasMoreScreenNames", "isLoadingScreenNames", "isElementLoading", "isEditMode", "isCreateMode", "isEditInDepthAvailable"], outputs: ["createElement", "updateElement", "createScreenNameRequest", "searchScreenName", "loadMoreScreenNames", "cancel", "editInDepth"] }, { type: ButtonComponent, selector: "cqa-button", inputs: ["variant", "btnSize", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass", "inlineStyles", "tooltip", "tooltipPosition"], outputs: ["clicked"] }, { 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: SearchBarComponent, selector: "cqa-search-bar", inputs: ["placeholder", "value", "disabled", "showClear", "ariaLabel", "autoFocus", "size", "fullWidth"], outputs: ["valueChange", "search", "cleared"] }, { type: ElementListComponent, selector: "cqa-element-list", inputs: ["items", "titleKey", "selectorKey", "labelsKey", "maxHeight", "hasMore"], outputs: ["itemClick", "loadMore"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
18954
19063
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: ElementPopupComponent, decorators: [{
|
|
18955
19064
|
type: Component,
|
|
18956
|
-
args: [{ selector: 'cqa-element-popup', host: { class: 'cqa-ui-root' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"cqa-bg-white cqa-rounded-[12px] cqa-shadow-lg cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-w-[500px] cqa-flex cqa-flex-col cqa-gap-[12px] cqa-p-2 cqa-box-border\">\n <!-- Header: title left; Need help? + close icon right -->\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-gap-2 cqa-px-4\">\n <h2 class=\"cqa-text-[16px] cqa-leading-[24px] cqa-font-bold cqa-text-[#111827] cqa-m-0 cqa-font-[600]\">\n Element\n </h2>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <!-- Need help? with custom tooltip (works inside overlay) -->\n <div class=\"cqa-relative cqa-inline-flex\"\n (mouseenter)=\"showHelpTooltip = true\" (mouseleave)=\"showHelpTooltip = false\">\n <a *ngIf=\"helpUrl\" href=\"#\" (click)=\"onHelp($event)\"\n class=\"cqa-flex cqa-items-center cqa-gap-1 cqa-text-[#3F43EE] cqa-text-[12px] cqa-leading-[21px] cqa-no-underline cqa-cursor-pointer\">\n <svg width=\"17\" height=\"16\" viewBox=\"0 0 17 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" class=\"cqa-flex-shrink-0\" aria-hidden=\"true\">\n <g clip-path=\"url(#help-icon-clip)\">\n <path d=\"M8.50033 14.6663C12.4123 14.6663 15.5837 11.6816 15.5837 7.99967C15.5837 4.31778 12.4123 1.33301 8.50033 1.33301C4.58831 1.33301 1.41699 4.31778 1.41699 7.99967C1.41699 11.6816 4.58831 14.6663 8.50033 14.6663Z\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6.43848 6.00038C6.60501 5.55483 6.93371 5.17912 7.36636 4.9398C7.79901 4.70049 8.30769 4.61301 8.80231 4.69285C9.29693 4.7727 9.74556 5.01473 10.0687 5.37607C10.3919 5.7374 10.5688 6.19473 10.5681 6.66705C10.5681 8.00038 8.44306 8.66705 8.44306 8.66705\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M8.5 11.333H8.50966\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </g>\n <defs>\n <clipPath id=\"help-icon-clip\">\n <rect width=\"17\" height=\"16\" fill=\"white\"/>\n </clipPath>\n </defs>\n </svg>\n Need help ?\n </a>\n <span *ngIf=\"!helpUrl\" class=\"cqa-flex cqa-items-center cqa-gap-1.5 cqa-font-[500] cqa-text-[10px] cqa-cursor-default\">\n <svg width=\"17\" height=\"16\" viewBox=\"0 0 17 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" class=\"cqa-flex-shrink-0 cqa-text-[#3F43EE]\" aria-hidden=\"true\">\n <g clip-path=\"url(#help-icon-clip-nolink)\">\n <path d=\"M8.50033 14.6663C12.4123 14.6663 15.5837 11.6816 15.5837 7.99967C15.5837 4.31778 12.4123 1.33301 8.50033 1.33301C4.58831 1.33301 1.41699 4.31778 1.41699 7.99967C1.41699 11.6816 4.58831 14.6663 8.50033 14.6663Z\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6.43848 6.00038C6.60501 5.55483 6.93371 5.17912 7.36636 4.9398C7.79901 4.70049 8.30769 4.61301 8.80231 4.69285C9.29693 4.7727 9.74556 5.01473 10.0687 5.37607C10.3919 5.7374 10.5688 6.19473 10.5681 6.66705C10.5681 8.00038 8.44306 8.66705 8.44306 8.66705\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M8.5 11.333H8.50966\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </g>\n <defs>\n <clipPath id=\"help-icon-clip-nolink\">\n <rect width=\"17\" height=\"16\" fill=\"white\"/>\n </clipPath>\n </defs>\n </svg>\n Need help ?\n </span>\n <!-- Custom tooltip (exact spec: 306\u00D720 content, 6px radius, #0A0A0A, no arrow) -->\n <div *ngIf=\"showHelpTooltip\" class=\"cqa-absolute cqa-pointer-events-none cqa-z-[100]\"\n style=\"top: -24px; left: -125px;\"\n role=\"tooltip\">\n <div class=\"cqa-text-white cqa-text-center cqa-whitespace-nowrap\"\n style=\"width: 306px; min-height: 20px; border-radius: 6px; opacity: 1; padding: 4px 8px; background-color: #0A0A0A; line-height: 20px; font-size: 8px;\">\n {{ helpTooltipText }}\n </div>\n </div>\n </div>\n <button type=\"button\" (click)=\"onClose()\"\n class=\"cqa-p-1 cqa-rounded cqa-text-[#6B7280] hover:cqa-bg-[#F3F4F6] cqa-flex cqa-items-center cqa-justify-center\"\n title=\"Close\" aria-label=\"Close\">\n <mat-icon class=\"!cqa-w-5 !cqa-h-5 !cqa-text-[20px]\">close</mat-icon>\n </button>\n </div>\n </div>\n\n <!-- Line below header (full width of modal, no side margin) -->\n <div class=\"cqa--mx-2 cqa-w-[calc(100%+1rem)] cqa-flex-shrink-0\">\n <div class=\"cqa-h-px cqa-w-full cqa-bg-[#E5E7EB]\" role=\"presentation\"></div>\n </div>\n\n <ng-container *ngIf=\"enableForm && !isOnRecord\">\n <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 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 <span *ngFor=\"let tag of formLabels\"\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-full cqa-text-[12px] cqa-text-[#3F43EE]\">\n {{ tag }}\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 </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)=\"toggleForm()\"\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=\"#\" (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 </ng-container>\n\n<ng-container *ngIf=\"isOnRecord && !enableForm\">\n <div\n class=\"cqa-flex cqa-flex-col cqa-items-center cqa-justify-center cqa-text-center cqa-gap-3 cqa-pt-10\">\n\n <!-- Video Icon -->\n <div\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-[64px] cqa-h-[64px] cqa-rounded-full cqa-bg-[#FEE2E2]\">\n <svg width=\"32\" height=\"32\" viewBox=\"0 0 32 32\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M21.333 17.3333L28.297 21.9759C28.3974 22.0428 28.514 22.0811 28.6345 22.0868C28.7549 22.0926 28.8747 22.0656 28.981 22.0087C29.0873 21.9517 29.1762 21.8671 29.2382 21.7636C29.3002 21.6602 29.3329 21.5419 29.333 21.4213V10.4933C29.333 10.376 29.3021 10.2607 29.2434 10.1592C29.1846 10.0577 29.1001 9.97344 28.9984 9.91501C28.8967 9.85658 28.7814 9.82602 28.6641 9.82642C28.5468 9.82682 28.4317 9.85816 28.3303 9.91728L21.333 13.9999\" stroke=\"#E7000B\" stroke-width=\"2.66667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M18.667 8H5.33366C3.8609 8 2.66699 9.19391 2.66699 10.6667V21.3333C2.66699 22.8061 3.8609 24 5.33366 24H18.667C20.1398 24 21.3337 22.8061 21.3337 21.3333V10.6667C21.3337 9.19391 20.1398 8 18.667 8Z\" stroke=\"#E7000B\" stroke-width=\"2.66667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n \n </div>\n\n <!-- Title -->\n <h4 class=\"cqa-m-0 cqa-text-[16px] cqa-leading-[24px] cqa-font-[600] cqa-text-[#0A0A0A]\">\n Recording Mode Active\n </h4>\n\n <!-- Subtitle -->\n <p class=\"cqa-m-0 cqa-text-[12px] cqa-leading-[18px] cqa-text-[#6B7280]\">\n Click on any element in the browser to capture it\n </p>\n </div>\n\n <!-- Footer -->\n <div class=\"cqa-flex cqa-justify-center cqa-pb-4\">\n <cqa-button\n variant=\"outlined\"\n btnSize=\"lg\"\n [text]=\"'Cancel Recording'\"\n (clicked)=\"onToggleRecordClick()\"\n [customClass]=\"'cqa-text-[14px] cqa-px-16 cqa-py-[9px] cqa-border-[#414146]'\">\n </cqa-button>\n </div>\n</ng-container>\n\n\n <ng-container *ngIf=\"!enableForm && !isOnRecord\">\n<div class=\"cqa-flex cqa-flex-col cqa-gap-4 cqa-px-1 cqa-pt-3\">\n\n <!-- Selected -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-2\">\n <span class=\"cqa-text-[12px] cqa-text-[#6B7280]\">Selected</span>\n\n <div\n class=\"cqa-flex cqa-items-center cqa-justify-between\n cqa-bg-[#FFFBEB] cqa-border cqa-border-[#fadfba]\n cqa-rounded-lg cqa-p-3 cqa-border-solid cqa-gap-3\">\n\n <div class=\"cqa-flex cqa-px-3 cqa-py-2 cqa-rounded-lg cqa-flex-col cqa-gap-0.5 cqa-bg-[#f5f5f5] cqa-flex-1\">\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-gap-2\">\n <span class=\"cqa-text-[14px] cqa-font-[600] cqa-text-[#111827]\">\n {{element.title}}\n </span>\n\n <div class=\"cqa-flex cqa-gap-2\">\n <span *ngFor=\"let l of element.labels\"\n class=\"cqa-text-[10px] cqa-px-1.5 cqa-py-0.5\n cqa-rounded cqa-bg-[#EEF2FF] cqa-text-[#3F43EE] cqa-rounded-full cqa-px-2 cqa-bg-[#eff6ff] cqa-border cqa-border-solid cqa-border-[#c8e0ff]\">\n {{l}}\n </span>\n </div>\n </div>\n\n <span class=\"cqa-text-[11px] cqa-text-[#6B7280]\">\n {{element.selector}}\n </span>\n </div>\n <cqa-button variant=\"outlined\" icon=\"edit\" btnSize=\"lg\" [text]=\"'Edit'\" [fullWidth]=\"true\" (clicked)=\"toggleForm()\"\n [customClass]=\"'cqa-text-[14px] cqa-py-[9px] cqa-border-[#414146]'\"></cqa-button>\n </div>\n </div>\n\n <!-- Recent -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-2\" *ngIf=\"recentSearchedItems.length > 0\">\n <span class=\"cqa-text-[12px] cqa-text-[#6B7280]\">Recent</span>\n\n <div class=\"cqa-flex cqa-gap-2 cqa-overflow-x-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\n <div *ngFor=\"let item of recentSearchedItems\" \n class=\"cqa-cursor-pointer cqa-inline-block\"\n (click)=\"onRecentItemClick(item)\">\n <cqa-badge \n class=\"cqa-element-badge cqa-mb-2 cqa-chip !cqa-bg-white !cqa-text-[12px] cqa-whitespace-nowrap\" \n [label]=\"item\"></cqa-badge>\n </div>\n </div>\n </div>\n\n <!-- Element Library -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-2\">\n <span class=\"cqa-text-[12px] cqa-text-[#6B7280]\">Element Library</span>\n <cqa-search-bar [fullWidth]=\"true\" [value]=\"searchValue\" placeholder=\"Search library\" (valueChange)=\"search($event)\"></cqa-search-bar> \n </div>\n\n <cqa-element-list \n [items]=\"elements\"\n [titleKey]=\"'title'\"\n [selectorKey]=\"'selector'\"\n [labelsKey]=\"'labels'\"\n [maxHeight]=\"'200px'\"\n [hasMore]=\"hasMoreElements\"\n (itemClick)=\"onElementClick($event)\"\n (loadMore)=\"onLoadMoreElements()\">\n </cqa-element-list>\n</div>\n\n\n <!-- Footer: Cancel, Apply (full width in one row) -->\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\" icon=\"radio_button_checked\" btnSize=\"lg\" [text]=\"'Record'\" [fullWidth]=\"true\" (clicked)=\"onToggleRecordClick()\"\n [customClass]=\"'cqa-text-[14px] cqa-py-[9px] cqa-border-[#414146]'\"></cqa-button>\n </div>\n <div class=\"cqa-flex-1 cqa-min-w-0\">\n <cqa-button variant=\"outlined\" icon=\"add\" btnSize=\"lg\" [text]=\"'Create New'\" [fullWidth]=\"true\" (clicked)=\"openCreateForm()\"\n [customClass]=\"'cqa-text-[14px] cqa-py-[9px] cqa-border-[#414146]'\"></cqa-button>\n </div>\n </div>\n </div>\n </ng-container>\n\n</div>\n" }]
|
|
19065
|
+
args: [{ selector: 'cqa-element-popup', host: { class: 'cqa-ui-root' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"cqa-bg-white cqa-rounded-[12px] cqa-shadow-lg cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-w-[500px] cqa-flex cqa-flex-col cqa-gap-[12px] cqa-p-2 cqa-box-border\">\n <!-- Header: title left; Need help? + close icon right -->\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-gap-2 cqa-px-4\">\n <h2 class=\"cqa-text-[16px] cqa-leading-[24px] cqa-font-bold cqa-text-[#111827] cqa-m-0 cqa-font-[600]\">\n Element\n </h2>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <!-- Need help? with custom tooltip (works inside overlay) -->\n <div class=\"cqa-relative cqa-inline-flex\"\n (mouseenter)=\"showHelpTooltip = true\" (mouseleave)=\"showHelpTooltip = false\">\n <a *ngIf=\"helpUrl\" href=\"#\" (click)=\"onHelp($event)\"\n class=\"cqa-flex cqa-items-center cqa-gap-1 cqa-text-[#3F43EE] cqa-text-[12px] cqa-leading-[21px] cqa-no-underline cqa-cursor-pointer\">\n <svg width=\"17\" height=\"16\" viewBox=\"0 0 17 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" class=\"cqa-flex-shrink-0\" aria-hidden=\"true\">\n <g clip-path=\"url(#help-icon-clip)\">\n <path d=\"M8.50033 14.6663C12.4123 14.6663 15.5837 11.6816 15.5837 7.99967C15.5837 4.31778 12.4123 1.33301 8.50033 1.33301C4.58831 1.33301 1.41699 4.31778 1.41699 7.99967C1.41699 11.6816 4.58831 14.6663 8.50033 14.6663Z\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6.43848 6.00038C6.60501 5.55483 6.93371 5.17912 7.36636 4.9398C7.79901 4.70049 8.30769 4.61301 8.80231 4.69285C9.29693 4.7727 9.74556 5.01473 10.0687 5.37607C10.3919 5.7374 10.5688 6.19473 10.5681 6.66705C10.5681 8.00038 8.44306 8.66705 8.44306 8.66705\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M8.5 11.333H8.50966\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </g>\n <defs>\n <clipPath id=\"help-icon-clip\">\n <rect width=\"17\" height=\"16\" fill=\"white\"/>\n </clipPath>\n </defs>\n </svg>\n Need help ?\n </a>\n <span *ngIf=\"!helpUrl\" class=\"cqa-flex cqa-items-center cqa-gap-1.5 cqa-font-[500] cqa-text-[10px] cqa-cursor-default\">\n <svg width=\"17\" height=\"16\" viewBox=\"0 0 17 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" class=\"cqa-flex-shrink-0 cqa-text-[#3F43EE]\" aria-hidden=\"true\">\n <g clip-path=\"url(#help-icon-clip-nolink)\">\n <path d=\"M8.50033 14.6663C12.4123 14.6663 15.5837 11.6816 15.5837 7.99967C15.5837 4.31778 12.4123 1.33301 8.50033 1.33301C4.58831 1.33301 1.41699 4.31778 1.41699 7.99967C1.41699 11.6816 4.58831 14.6663 8.50033 14.6663Z\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6.43848 6.00038C6.60501 5.55483 6.93371 5.17912 7.36636 4.9398C7.79901 4.70049 8.30769 4.61301 8.80231 4.69285C9.29693 4.7727 9.74556 5.01473 10.0687 5.37607C10.3919 5.7374 10.5688 6.19473 10.5681 6.66705C10.5681 8.00038 8.44306 8.66705 8.44306 8.66705\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M8.5 11.333H8.50966\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </g>\n <defs>\n <clipPath id=\"help-icon-clip-nolink\">\n <rect width=\"17\" height=\"16\" fill=\"white\"/>\n </clipPath>\n </defs>\n </svg>\n Need help ?\n </span>\n <!-- Custom tooltip (exact spec: 306\u00D720 content, 6px radius, #0A0A0A, no arrow) -->\n <div *ngIf=\"showHelpTooltip\" class=\"cqa-absolute cqa-pointer-events-none cqa-z-[100]\"\n style=\"top: -24px; left: -125px;\"\n role=\"tooltip\">\n <div class=\"cqa-text-white cqa-text-center cqa-whitespace-nowrap\"\n style=\"width: 306px; min-height: 20px; border-radius: 6px; opacity: 1; padding: 4px 8px; background-color: #0A0A0A; line-height: 20px; font-size: 8px;\">\n {{ helpTooltipText }}\n </div>\n </div>\n </div>\n <button type=\"button\" (click)=\"onClose()\"\n class=\"cqa-p-1 cqa-rounded cqa-text-[#6B7280] hover:cqa-bg-[#F3F4F6] cqa-flex cqa-items-center cqa-justify-center\"\n title=\"Close\" aria-label=\"Close\">\n <mat-icon class=\"!cqa-w-5 !cqa-h-5 !cqa-text-[20px]\">close</mat-icon>\n </button>\n </div>\n </div>\n\n <!-- Line below header (full width of modal, no side margin) -->\n <div class=\"cqa--mx-2 cqa-w-[calc(100%+1rem)] cqa-flex-shrink-0\">\n <div class=\"cqa-h-px cqa-w-full cqa-bg-[#E5E7EB]\" role=\"presentation\"></div>\n </div>\n\n <ng-container *ngIf=\"enableForm && !isOnRecord\">\n <cqa-element-form\n #elementForm\n [elementId]=\"elementId\"\n [element]=\"element\"\n [screenNameOptions]=\"screenNameOptions\"\n [hasMoreScreenNames]=\"hasMoreScreenNames\"\n [isLoadingScreenNames]=\"isLoadingScreenNames\"\n [isElementLoading]=\"isElementLoading\"\n [isEditMode]=\"isEditMode\"\n [isCreateMode]=\"isCreateMode\"\n (createElement)=\"onElementFormCreate($event)\"\n (updateElement)=\"onElementFormUpdate($event)\"\n (createScreenNameRequest)=\"createScreenNameRequest.emit($event)\"\n (searchScreenName)=\"searchScreenName.emit($event)\"\n (loadMoreScreenNames)=\"loadMoreScreenNames.emit($event)\"\n (cancel)=\"onElementFormCancel()\"\n (editInDepth)=\"onEditInDepth()\">\n </cqa-element-form>\n </ng-container>\n\n<ng-container *ngIf=\"isOnRecord && !enableForm\">\n <div\n class=\"cqa-flex cqa-flex-col cqa-items-center cqa-justify-center cqa-text-center cqa-gap-3 cqa-pt-10\">\n\n <!-- Video Icon -->\n <div\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-[64px] cqa-h-[64px] cqa-rounded-full cqa-bg-[#FEE2E2]\">\n <svg width=\"32\" height=\"32\" viewBox=\"0 0 32 32\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M21.333 17.3333L28.297 21.9759C28.3974 22.0428 28.514 22.0811 28.6345 22.0868C28.7549 22.0926 28.8747 22.0656 28.981 22.0087C29.0873 21.9517 29.1762 21.8671 29.2382 21.7636C29.3002 21.6602 29.3329 21.5419 29.333 21.4213V10.4933C29.333 10.376 29.3021 10.2607 29.2434 10.1592C29.1846 10.0577 29.1001 9.97344 28.9984 9.91501C28.8967 9.85658 28.7814 9.82602 28.6641 9.82642C28.5468 9.82682 28.4317 9.85816 28.3303 9.91728L21.333 13.9999\" stroke=\"#E7000B\" stroke-width=\"2.66667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M18.667 8H5.33366C3.8609 8 2.66699 9.19391 2.66699 10.6667V21.3333C2.66699 22.8061 3.8609 24 5.33366 24H18.667C20.1398 24 21.3337 22.8061 21.3337 21.3333V10.6667C21.3337 9.19391 20.1398 8 18.667 8Z\" stroke=\"#E7000B\" stroke-width=\"2.66667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n \n </div>\n\n <!-- Title -->\n <h4 class=\"cqa-m-0 cqa-text-[16px] cqa-leading-[24px] cqa-font-[600] cqa-text-[#0A0A0A]\">\n Recording Mode Active\n </h4>\n\n <!-- Subtitle -->\n <p class=\"cqa-m-0 cqa-text-[12px] cqa-leading-[18px] cqa-text-[#6B7280]\">\n Click on any element in the browser to capture it\n </p>\n </div>\n\n <!-- Footer -->\n <div class=\"cqa-flex cqa-justify-center cqa-pb-4\">\n <cqa-button\n variant=\"outlined\"\n btnSize=\"lg\"\n [text]=\"'Cancel Recording'\"\n (clicked)=\"onToggleRecordClick()\"\n [customClass]=\"'cqa-text-[14px] cqa-px-16 cqa-py-[9px] cqa-border-[#414146]'\">\n </cqa-button>\n </div>\n</ng-container>\n\n\n <ng-container *ngIf=\"!enableForm && !isOnRecord\">\n<div class=\"cqa-flex cqa-flex-col cqa-gap-4 cqa-px-1 cqa-pt-3\">\n\n <!-- Selected -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-2\">\n <span class=\"cqa-text-[12px] cqa-text-[#6B7280]\">Selected</span>\n\n <div\n class=\"cqa-flex cqa-items-center cqa-justify-between\n cqa-bg-[#FFFBEB] cqa-border cqa-border-[#fadfba]\n cqa-rounded-lg cqa-p-3 cqa-border-solid cqa-gap-3\">\n\n <div class=\"cqa-flex cqa-px-3 cqa-py-2 cqa-rounded-lg cqa-flex-col cqa-gap-0.5 cqa-bg-[#f5f5f5] cqa-flex-1\">\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-gap-2\">\n <span class=\"cqa-text-[14px] cqa-font-[600] cqa-text-[#111827]\">\n {{element.title}}\n </span>\n\n <div class=\"cqa-flex cqa-gap-2\">\n <span *ngFor=\"let l of element.labels\"\n class=\"cqa-text-[10px] cqa-px-1.5 cqa-py-0.5\n cqa-rounded cqa-bg-[#EEF2FF] cqa-text-[#3F43EE] cqa-rounded-full cqa-px-2 cqa-bg-[#eff6ff] cqa-border cqa-border-solid cqa-border-[#c8e0ff]\">\n {{l}}\n </span>\n </div>\n </div>\n\n <span class=\"cqa-text-[11px] cqa-text-[#6B7280]\">\n {{element.selector}}\n </span>\n </div>\n <cqa-button variant=\"outlined\" icon=\"edit\" btnSize=\"lg\" [text]=\"'Edit'\" [fullWidth]=\"true\" (clicked)=\"toggleForm()\"\n [customClass]=\"'cqa-text-[14px] cqa-py-[9px] cqa-border-[#414146]'\"></cqa-button>\n </div>\n </div>\n\n <!-- Recent -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-2\" *ngIf=\"recentSearchedItems.length > 0\">\n <span class=\"cqa-text-[12px] cqa-text-[#6B7280]\">Recent</span>\n\n <div class=\"cqa-flex cqa-gap-2 cqa-overflow-x-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\n <div *ngFor=\"let item of recentSearchedItems\" \n class=\"cqa-cursor-pointer cqa-inline-block\"\n (click)=\"onRecentItemClick(item)\">\n <cqa-badge \n class=\"cqa-element-badge cqa-mb-2 cqa-chip !cqa-bg-white !cqa-text-[12px] cqa-whitespace-nowrap\" \n [label]=\"item\"></cqa-badge>\n </div>\n </div>\n </div>\n\n <!-- Element Library -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-2\">\n <span class=\"cqa-text-[12px] cqa-text-[#6B7280]\">Element Library</span>\n <cqa-search-bar [fullWidth]=\"true\" [value]=\"searchValue\" placeholder=\"Search library\" (valueChange)=\"search($event)\"></cqa-search-bar> \n </div>\n\n <cqa-element-list \n [items]=\"elements\"\n [titleKey]=\"'title'\"\n [selectorKey]=\"'selector'\"\n [labelsKey]=\"'labels'\"\n [maxHeight]=\"'200px'\"\n [hasMore]=\"hasMoreElements\"\n (itemClick)=\"onElementClick($event)\"\n (loadMore)=\"onLoadMoreElements()\">\n </cqa-element-list>\n</div>\n\n\n <!-- Footer: Cancel, Apply (full width in one row) -->\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\" icon=\"radio_button_checked\" btnSize=\"lg\" [text]=\"'Record'\" [fullWidth]=\"true\" (clicked)=\"onToggleRecordClick()\"\n [customClass]=\"'cqa-text-[14px] cqa-py-[9px] cqa-border-[#414146]'\"></cqa-button>\n </div>\n <div class=\"cqa-flex-1 cqa-min-w-0\">\n <cqa-button variant=\"outlined\" icon=\"add\" btnSize=\"lg\" [text]=\"'Create New'\" [fullWidth]=\"true\" (clicked)=\"openCreateForm()\"\n [customClass]=\"'cqa-text-[14px] cqa-py-[9px] cqa-border-[#414146]'\"></cqa-button>\n </div>\n </div>\n </div>\n </ng-container>\n\n</div>\n" }]
|
|
18957
19066
|
}], ctorParameters: function () { return [{ type: ElementPopupRef, decorators: [{
|
|
18958
19067
|
type: Optional
|
|
18959
19068
|
}, {
|
|
@@ -18964,8 +19073,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
|
|
|
18964
19073
|
}, {
|
|
18965
19074
|
type: Inject,
|
|
18966
19075
|
args: [ELEMENT_POPUP_DATA]
|
|
18967
|
-
}] }, { type: i1$1.FormBuilder, decorators: [{
|
|
18968
|
-
type: Optional
|
|
18969
19076
|
}] }, { type: i0.ChangeDetectorRef, decorators: [{
|
|
18970
19077
|
type: Optional
|
|
18971
19078
|
}] }]; }, propDecorators: { value: [{
|
|
@@ -19026,6 +19133,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
|
|
|
19026
19133
|
type: Output
|
|
19027
19134
|
}], toggleRecord: [{
|
|
19028
19135
|
type: Output
|
|
19136
|
+
}], elementFormComponent: [{
|
|
19137
|
+
type: ViewChild,
|
|
19138
|
+
args: [ElementFormComponent]
|
|
19029
19139
|
}] } });
|
|
19030
19140
|
|
|
19031
19141
|
class ElementPopupService {
|
|
@@ -25297,13 +25407,30 @@ class TemplateVariablesFormComponent {
|
|
|
25297
25407
|
constructor(cdr) {
|
|
25298
25408
|
this.cdr = cdr;
|
|
25299
25409
|
this.templateVariables = [];
|
|
25300
|
-
this.variablesForm = new
|
|
25410
|
+
this.variablesForm = new FormArray([]);
|
|
25301
25411
|
this.metadata = '';
|
|
25302
25412
|
this.description = '';
|
|
25413
|
+
this.elementOptions = []; // Element objects for element dropdown
|
|
25414
|
+
this.hasMoreElements = false; // Whether more elements are available
|
|
25415
|
+
this.isLoadingElements = false; // Loading state for elements
|
|
25416
|
+
/** Screen name options for element form autocomplete (from API) */
|
|
25417
|
+
this.screenNameOptions = [];
|
|
25418
|
+
/** Whether more screen names are available for infinite scroll */
|
|
25419
|
+
this.hasMoreScreenNames = false;
|
|
25420
|
+
/** True while parent is loading screen names (search or load more) */
|
|
25421
|
+
this.isLoadingScreenNames = false;
|
|
25303
25422
|
this.variableValueChange = new EventEmitter();
|
|
25304
25423
|
this.variableBooleanChange = new EventEmitter();
|
|
25305
25424
|
this.metadataChange = new EventEmitter();
|
|
25306
25425
|
this.descriptionChange = new EventEmitter();
|
|
25426
|
+
this.loadMoreElements = new EventEmitter(); // Emit when load more is requested
|
|
25427
|
+
this.searchElements = new EventEmitter(); // Emit when user searches for elements
|
|
25428
|
+
this.createElement = new EventEmitter(); // Emit when element is created with payload
|
|
25429
|
+
this.searchScreenName = new EventEmitter(); // Emit when user searches screen names
|
|
25430
|
+
this.loadMoreScreenNames = new EventEmitter(); // Emit when user scrolls to load more screen names
|
|
25431
|
+
this.createScreenNameRequest = new EventEmitter(); // Emit when user requests to create a new screen name
|
|
25432
|
+
this.cancelElementForm = new EventEmitter(); // Emit when element form is cancelled
|
|
25433
|
+
this.elementFormVisibilityChange = new EventEmitter(); // Emit when element form visibility changes
|
|
25307
25434
|
// Cache for select configs to avoid recalculating on every change detection
|
|
25308
25435
|
this.selectConfigCache = new Map();
|
|
25309
25436
|
// Cache for data type select configs
|
|
@@ -25322,9 +25449,29 @@ class TemplateVariablesFormComponent {
|
|
|
25322
25449
|
{ id: 'runtime', value: 'runtime', name: '$|Runtime|', label: '$|Runtime|' },
|
|
25323
25450
|
{ id: 'environment', value: 'environment', name: '*|Environment|', label: '*|Environment|' }
|
|
25324
25451
|
];
|
|
25452
|
+
this.createElementVisible = false;
|
|
25453
|
+
}
|
|
25454
|
+
onCreateElement(payload) {
|
|
25455
|
+
console.log('onCreateElement', payload);
|
|
25456
|
+
this.createElement.emit(payload);
|
|
25457
|
+
this.createElementVisible = false;
|
|
25458
|
+
this.elementFormVisibilityChange.emit(false);
|
|
25459
|
+
this.cdr.markForCheck();
|
|
25460
|
+
}
|
|
25461
|
+
onCancelElementForm() {
|
|
25462
|
+
this.createElementVisible = false;
|
|
25463
|
+
this.elementFormVisibilityChange.emit(false);
|
|
25464
|
+
this.cancelElementForm.emit();
|
|
25465
|
+
this.cdr.markForCheck();
|
|
25466
|
+
}
|
|
25467
|
+
onShowElementForm() {
|
|
25468
|
+
this.createElementVisible = true;
|
|
25469
|
+
this.elementFormVisibilityChange.emit(true);
|
|
25470
|
+
this.cdr.markForCheck();
|
|
25325
25471
|
}
|
|
25326
25472
|
ngOnChanges(changes) {
|
|
25327
|
-
if (changes['templateVariables'] || changes['variablesForm']
|
|
25473
|
+
if (changes['templateVariables'] || changes['variablesForm'] || changes['elementOptions'] ||
|
|
25474
|
+
changes['hasMoreElements'] || changes['isLoadingElements']) {
|
|
25328
25475
|
// Clear all caches when inputs change
|
|
25329
25476
|
this.selectConfigCache.clear();
|
|
25330
25477
|
this.dataTypeSelectConfigCache.clear();
|
|
@@ -25341,34 +25488,51 @@ class TemplateVariablesFormComponent {
|
|
|
25341
25488
|
}
|
|
25342
25489
|
}
|
|
25343
25490
|
initializeTestDataVariables() {
|
|
25344
|
-
this.templateVariables.forEach(variable => {
|
|
25491
|
+
this.templateVariables.forEach((variable, index) => {
|
|
25345
25492
|
if (this.needsDataTypeDropdown(variable)) {
|
|
25346
25493
|
const { dataType, rawValue } = this.parseTestDataValue(variable.value || '');
|
|
25347
25494
|
this.variableDataTypes.set(variable.name, dataType);
|
|
25348
25495
|
this.variableRawValues.set(variable.name, rawValue);
|
|
25349
|
-
// Ensure form control exists for data type
|
|
25350
|
-
const
|
|
25351
|
-
if (
|
|
25352
|
-
|
|
25353
|
-
|
|
25354
|
-
|
|
25355
|
-
|
|
25496
|
+
// Ensure form control exists for data type in the FormArray
|
|
25497
|
+
const variableGroup = this.getVariableFormGroup(variable.name);
|
|
25498
|
+
if (variableGroup) {
|
|
25499
|
+
if (!variableGroup.get('dataType')) {
|
|
25500
|
+
variableGroup.addControl('dataType', new FormControl(dataType));
|
|
25501
|
+
}
|
|
25502
|
+
else {
|
|
25503
|
+
variableGroup.get('dataType')?.setValue(dataType, { emitEvent: false });
|
|
25504
|
+
}
|
|
25356
25505
|
}
|
|
25357
25506
|
}
|
|
25358
25507
|
});
|
|
25359
25508
|
}
|
|
25509
|
+
/** Get form group for a variable by name from FormArray */
|
|
25510
|
+
getVariableFormGroup(variableName) {
|
|
25511
|
+
const variableIndex = this.variablesForm.controls.findIndex(control => control.get('name')?.value === variableName);
|
|
25512
|
+
if (variableIndex !== -1) {
|
|
25513
|
+
return this.variablesForm.at(variableIndex);
|
|
25514
|
+
}
|
|
25515
|
+
return null;
|
|
25516
|
+
}
|
|
25517
|
+
/** Get form group at a specific index from FormArray (for template use) */
|
|
25518
|
+
getFormGroupAt(index) {
|
|
25519
|
+
if (index >= 0 && index < this.variablesForm.length) {
|
|
25520
|
+
return this.variablesForm.at(index);
|
|
25521
|
+
}
|
|
25522
|
+
return null;
|
|
25523
|
+
}
|
|
25360
25524
|
precomputeConfigs() {
|
|
25361
25525
|
if (!this.templateVariables)
|
|
25362
25526
|
return;
|
|
25363
25527
|
// Pre-compute all select configs
|
|
25364
|
-
this.templateVariables.forEach(variable => {
|
|
25528
|
+
this.templateVariables.forEach((variable, index) => {
|
|
25365
25529
|
// Pre-compute regular select configs
|
|
25366
25530
|
if (this.shouldShowDropdown(variable)) {
|
|
25367
|
-
this.getSelectConfig(variable);
|
|
25531
|
+
this.getSelectConfig(variable, index);
|
|
25368
25532
|
}
|
|
25369
25533
|
// Pre-compute data type select configs
|
|
25370
25534
|
if (this.needsDataTypeDropdown(variable)) {
|
|
25371
|
-
this.getDataTypeSelectConfig(variable);
|
|
25535
|
+
this.getDataTypeSelectConfig(variable, index);
|
|
25372
25536
|
}
|
|
25373
25537
|
});
|
|
25374
25538
|
}
|
|
@@ -25412,32 +25576,70 @@ class TemplateVariablesFormComponent {
|
|
|
25412
25576
|
trackByVariable(index, variable) {
|
|
25413
25577
|
return variable.name || index;
|
|
25414
25578
|
}
|
|
25415
|
-
getSelectConfig(variable) {
|
|
25579
|
+
getSelectConfig(variable, index) {
|
|
25416
25580
|
// Use cache to avoid recalculating on every change detection
|
|
25417
|
-
|
|
25581
|
+
// For element variables, include elementOptions, hasMoreElements, and isLoadingElements in cache key
|
|
25582
|
+
const optionsKey = variable.dataKey === 'element' || variable.dataKey === 'label'
|
|
25583
|
+
? this.elementOptions.map(el => String(el.name || '')).join(',')
|
|
25584
|
+
: (variable.options?.join(',') || '');
|
|
25585
|
+
// Include hasMoreElements and isLoadingElements in cache key for selector variables
|
|
25586
|
+
const cacheKey = variable.dataKey === 'element' || variable.dataKey === 'label'
|
|
25587
|
+
? `${variable.name}_${optionsKey}_${this.hasMoreElements}_${this.isLoadingElements}`
|
|
25588
|
+
: `${variable.name}_${optionsKey}`;
|
|
25418
25589
|
if (this.selectConfigCache.has(cacheKey)) {
|
|
25419
25590
|
return this.selectConfigCache.get(cacheKey);
|
|
25420
25591
|
}
|
|
25421
|
-
|
|
25422
|
-
|
|
25423
|
-
|
|
25424
|
-
|
|
25425
|
-
|
|
25426
|
-
|
|
25592
|
+
// Use elementOptions if variable name is 'selector', otherwise use variable.options
|
|
25593
|
+
// Extract element names from Element objects
|
|
25594
|
+
let optionsArray = [];
|
|
25595
|
+
if (variable.dataKey === 'element' || variable.dataKey === 'label') {
|
|
25596
|
+
// For element options, use locatorValue as both id and value so the component returns locatorValue
|
|
25597
|
+
// This ensures the selected value is the locatorValue (not the element id)
|
|
25598
|
+
optionsArray = this.elementOptions
|
|
25599
|
+
.map(el => {
|
|
25600
|
+
const locatorValue = el.locatorValue || '';
|
|
25601
|
+
return {
|
|
25602
|
+
id: locatorValue,
|
|
25603
|
+
elementId: el.id?.toString() || '',
|
|
25604
|
+
value: locatorValue,
|
|
25605
|
+
name: el.name,
|
|
25606
|
+
label: el.name
|
|
25607
|
+
};
|
|
25608
|
+
});
|
|
25609
|
+
}
|
|
25610
|
+
else {
|
|
25611
|
+
optionsArray = variable.options?.map(opt => { return { id: opt, value: opt, name: opt, label: opt }; }) || [];
|
|
25612
|
+
}
|
|
25613
|
+
console.log('optionsArray', optionsArray);
|
|
25427
25614
|
const config = {
|
|
25428
|
-
key:
|
|
25615
|
+
key: 'value',
|
|
25429
25616
|
placeholder: `Select ${variable.label}`,
|
|
25430
25617
|
multiple: false,
|
|
25431
25618
|
searchable: false,
|
|
25432
|
-
options:
|
|
25619
|
+
options: optionsArray,
|
|
25433
25620
|
onChange: (value) => {
|
|
25434
25621
|
this.onVariableValueChange(variable.name, value);
|
|
25435
25622
|
}
|
|
25436
25623
|
};
|
|
25624
|
+
// Add load more and search support for selector variables
|
|
25625
|
+
if (variable.dataKey === 'element' || variable.dataKey === 'label') {
|
|
25626
|
+
config.searchable = true; // Enable search for selector dropdown
|
|
25627
|
+
config.serverSearch = true; // Enable server-side search
|
|
25628
|
+
config.hasMore = this.hasMoreElements;
|
|
25629
|
+
config.isLoading = this.isLoadingElements;
|
|
25630
|
+
config.onLoadMore = () => {
|
|
25631
|
+
this.loadMoreElements.emit();
|
|
25632
|
+
};
|
|
25633
|
+
config.onSearch = (query) => {
|
|
25634
|
+
// Emit search event when user types in the search box
|
|
25635
|
+
this.searchElements.emit(query);
|
|
25636
|
+
};
|
|
25637
|
+
}
|
|
25437
25638
|
this.selectConfigCache.set(cacheKey, config);
|
|
25438
25639
|
return config;
|
|
25439
25640
|
}
|
|
25440
25641
|
onVariableValueChange(variableName, value) {
|
|
25642
|
+
console.log("onVariableValueChange", variableName, value);
|
|
25441
25643
|
const variable = this.templateVariables.find(v => v.name === variableName);
|
|
25442
25644
|
if (!variable)
|
|
25443
25645
|
return;
|
|
@@ -25446,17 +25648,18 @@ class TemplateVariablesFormComponent {
|
|
|
25446
25648
|
const { dataType, rawValue } = this.parseTestDataValue(value || '');
|
|
25447
25649
|
this.variableDataTypes.set(variableName, dataType);
|
|
25448
25650
|
this.variableRawValues.set(variableName, rawValue);
|
|
25449
|
-
// Update data type form control
|
|
25450
|
-
const
|
|
25451
|
-
if (
|
|
25452
|
-
|
|
25651
|
+
// Update data type form control in FormArray
|
|
25652
|
+
const variableGroup = this.getVariableFormGroup(variableName);
|
|
25653
|
+
if (variableGroup && variableGroup.get('dataType')) {
|
|
25654
|
+
variableGroup.get('dataType')?.setValue(dataType, { emitEvent: false });
|
|
25453
25655
|
}
|
|
25454
25656
|
}
|
|
25455
25657
|
// Update the variable in templateVariables array
|
|
25456
25658
|
variable.value = value;
|
|
25457
|
-
// Also update form control (use emitEvent: false to prevent triggering valueChanges)
|
|
25458
|
-
|
|
25459
|
-
|
|
25659
|
+
// Also update form control in FormArray (use emitEvent: false to prevent triggering valueChanges)
|
|
25660
|
+
const variableGroup = this.getVariableFormGroup(variableName);
|
|
25661
|
+
if (variableGroup && variableGroup.get('value')) {
|
|
25662
|
+
variableGroup.get('value')?.setValue(value, { emitEvent: false });
|
|
25460
25663
|
}
|
|
25461
25664
|
// Mark for check since we're using OnPush
|
|
25462
25665
|
this.cdr.markForCheck();
|
|
@@ -25469,14 +25672,12 @@ class TemplateVariablesFormComponent {
|
|
|
25469
25672
|
if (variable) {
|
|
25470
25673
|
variable.value = value;
|
|
25471
25674
|
}
|
|
25472
|
-
// Also update form control (use emitEvent: false to prevent triggering valueChanges)
|
|
25473
|
-
|
|
25474
|
-
|
|
25475
|
-
|
|
25476
|
-
else {
|
|
25477
|
-
// Create form control if it doesn't exist
|
|
25478
|
-
this.variablesForm.addControl(variableName, new FormControl(value));
|
|
25675
|
+
// Also update form control in FormArray (use emitEvent: false to prevent triggering valueChanges)
|
|
25676
|
+
const variableGroup = this.getVariableFormGroup(variableName);
|
|
25677
|
+
if (variableGroup && variableGroup.get('value')) {
|
|
25678
|
+
variableGroup.get('value')?.setValue(value, { emitEvent: false });
|
|
25479
25679
|
}
|
|
25680
|
+
// Note: If variable doesn't exist in FormArray, it should be added by parent component
|
|
25480
25681
|
// Mark for check since we're using OnPush
|
|
25481
25682
|
this.cdr.markForCheck();
|
|
25482
25683
|
// Emit the change event
|
|
@@ -25487,7 +25688,7 @@ class TemplateVariablesFormComponent {
|
|
|
25487
25688
|
if (this.shouldShowDropdownCache.has(variable.name)) {
|
|
25488
25689
|
return this.shouldShowDropdownCache.get(variable.name);
|
|
25489
25690
|
}
|
|
25490
|
-
const result = variable.name === 'type' || variable.name === 'scrollTo';
|
|
25691
|
+
const result = variable.name === 'type' || variable.name === 'scrollTo' || variable.dataKey === 'element' || variable.dataKey === 'label';
|
|
25491
25692
|
this.shouldShowDropdownCache.set(variable.name, result);
|
|
25492
25693
|
return result;
|
|
25493
25694
|
}
|
|
@@ -25496,8 +25697,8 @@ class TemplateVariablesFormComponent {
|
|
|
25496
25697
|
if (this.needsDataTypeDropdownCache.has(variable.name)) {
|
|
25497
25698
|
return this.needsDataTypeDropdownCache.get(variable.name);
|
|
25498
25699
|
}
|
|
25499
|
-
const
|
|
25500
|
-
const result =
|
|
25700
|
+
const dataKey = variable.dataKey?.toLowerCase() || '';
|
|
25701
|
+
const result = dataKey === 'test-data' || dataKey === 'source_value' || dataKey === 'target_value';
|
|
25501
25702
|
this.needsDataTypeDropdownCache.set(variable.name, result);
|
|
25502
25703
|
return result;
|
|
25503
25704
|
}
|
|
@@ -25505,20 +25706,20 @@ class TemplateVariablesFormComponent {
|
|
|
25505
25706
|
// Return cached static array
|
|
25506
25707
|
return this.dataTypeOptions;
|
|
25507
25708
|
}
|
|
25508
|
-
getDataTypeSelectConfig(variable) {
|
|
25709
|
+
getDataTypeSelectConfig(variable, index) {
|
|
25509
25710
|
// Use cache to avoid recalculating on every change detection
|
|
25510
25711
|
const cacheKey = `${variable.name}_dataType`;
|
|
25511
25712
|
if (this.dataTypeSelectConfigCache.has(cacheKey)) {
|
|
25512
25713
|
return this.dataTypeSelectConfigCache.get(cacheKey);
|
|
25513
25714
|
}
|
|
25514
|
-
|
|
25515
|
-
|
|
25516
|
-
if (!
|
|
25715
|
+
// Ensure form control exists in FormArray
|
|
25716
|
+
const variableGroup = this.getVariableFormGroup(variable.name);
|
|
25717
|
+
if (variableGroup && !variableGroup.get('dataType')) {
|
|
25517
25718
|
const currentDataType = this.variableDataTypes.get(variable.name) || 'plain-text';
|
|
25518
|
-
|
|
25719
|
+
variableGroup.addControl('dataType', new FormControl(currentDataType));
|
|
25519
25720
|
}
|
|
25520
25721
|
const config = {
|
|
25521
|
-
key:
|
|
25722
|
+
key: 'dataType',
|
|
25522
25723
|
placeholder: 'Select Type',
|
|
25523
25724
|
multiple: false,
|
|
25524
25725
|
searchable: false,
|
|
@@ -25538,6 +25739,38 @@ class TemplateVariablesFormComponent {
|
|
|
25538
25739
|
// Simple getter - already cached in Map, no computation needed
|
|
25539
25740
|
return this.variableRawValues.get(variable.name) || '';
|
|
25540
25741
|
}
|
|
25742
|
+
/**
|
|
25743
|
+
* Check if selector variable is available in templateVariables
|
|
25744
|
+
*/
|
|
25745
|
+
get selectorVariableAvailable() {
|
|
25746
|
+
return this.templateVariables.some(v => v.dataKey === 'element' || v.dataKey === 'label');
|
|
25747
|
+
}
|
|
25748
|
+
/**
|
|
25749
|
+
* Check if parameter variable is available (testData with parameter type)
|
|
25750
|
+
*/
|
|
25751
|
+
get parameterVariableAvailable() {
|
|
25752
|
+
return this.templateVariables.some(v => {
|
|
25753
|
+
const dataKey = v.dataKey?.toLowerCase() || '';
|
|
25754
|
+
if (dataKey === 'test-data' || dataKey === 'source_value' || dataKey === 'target_value') {
|
|
25755
|
+
const dataType = this.variableDataTypes.get(v.name) || 'plain-text';
|
|
25756
|
+
return dataType === 'parameter';
|
|
25757
|
+
}
|
|
25758
|
+
return false;
|
|
25759
|
+
});
|
|
25760
|
+
}
|
|
25761
|
+
/**
|
|
25762
|
+
* Check if environment variable is available (testData with environment type)
|
|
25763
|
+
*/
|
|
25764
|
+
get environmentVariableAvailable() {
|
|
25765
|
+
return this.templateVariables.some(v => {
|
|
25766
|
+
const dataKey = v.name?.toLowerCase() || '';
|
|
25767
|
+
if (dataKey === 'test-data' || dataKey === 'source_value' || dataKey === 'target_value') {
|
|
25768
|
+
const dataType = this.variableDataTypes.get(v.name) || 'plain-text';
|
|
25769
|
+
return dataType === 'environment';
|
|
25770
|
+
}
|
|
25771
|
+
return false;
|
|
25772
|
+
});
|
|
25773
|
+
}
|
|
25541
25774
|
onDataTypeChange(variableName, dataType) {
|
|
25542
25775
|
// Update stored data type
|
|
25543
25776
|
this.variableDataTypes.set(variableName, dataType);
|
|
@@ -25550,9 +25783,10 @@ class TemplateVariablesFormComponent {
|
|
|
25550
25783
|
if (variable) {
|
|
25551
25784
|
variable.value = formattedValue;
|
|
25552
25785
|
}
|
|
25553
|
-
// Update form control
|
|
25554
|
-
|
|
25555
|
-
|
|
25786
|
+
// Update form control in FormArray
|
|
25787
|
+
const variableGroup = this.getVariableFormGroup(variableName);
|
|
25788
|
+
if (variableGroup && variableGroup.get('value')) {
|
|
25789
|
+
variableGroup.get('value')?.setValue(formattedValue, { emitEvent: false });
|
|
25556
25790
|
}
|
|
25557
25791
|
// Mark for check since we're using OnPush
|
|
25558
25792
|
this.cdr.markForCheck();
|
|
@@ -25560,6 +25794,12 @@ class TemplateVariablesFormComponent {
|
|
|
25560
25794
|
// Emit the change event
|
|
25561
25795
|
this.variableValueChange.emit({ name: variableName, value: formattedValue });
|
|
25562
25796
|
}
|
|
25797
|
+
onElementSearch(event) {
|
|
25798
|
+
// Only handle search for selector variables
|
|
25799
|
+
// The key will be 'value' since that's what we set in the config
|
|
25800
|
+
// Emit the search query to parent component
|
|
25801
|
+
this.searchElements.emit(event.query);
|
|
25802
|
+
}
|
|
25563
25803
|
onTestDataValueChange(variableName, rawValue) {
|
|
25564
25804
|
// Update stored raw value
|
|
25565
25805
|
this.variableRawValues.set(variableName, rawValue);
|
|
@@ -25572,9 +25812,10 @@ class TemplateVariablesFormComponent {
|
|
|
25572
25812
|
if (variable) {
|
|
25573
25813
|
variable.value = formattedValue;
|
|
25574
25814
|
}
|
|
25575
|
-
// Update form control
|
|
25576
|
-
|
|
25577
|
-
|
|
25815
|
+
// Update form control in FormArray
|
|
25816
|
+
const variableGroup = this.getVariableFormGroup(variableName);
|
|
25817
|
+
if (variableGroup && variableGroup.get('value')) {
|
|
25818
|
+
variableGroup.get('value')?.setValue(formattedValue, { emitEvent: false });
|
|
25578
25819
|
}
|
|
25579
25820
|
// Mark for check since we're using OnPush
|
|
25580
25821
|
this.cdr.markForCheck();
|
|
@@ -25583,10 +25824,10 @@ class TemplateVariablesFormComponent {
|
|
|
25583
25824
|
}
|
|
25584
25825
|
}
|
|
25585
25826
|
TemplateVariablesFormComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TemplateVariablesFormComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
25586
|
-
TemplateVariablesFormComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TemplateVariablesFormComponent, selector: "cqa-template-variables-form", inputs: { templateVariables: "templateVariables", variablesForm: "variablesForm", metadata: "metadata", description: "description" }, outputs: { variableValueChange: "variableValueChange", variableBooleanChange: "variableBooleanChange", metadataChange: "metadataChange", descriptionChange: "descriptionChange" }, host: { classAttribute: "cqa-ui-root" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-flex cqa-gap-x-6 cqa-flex-wrap\">\n <ng-container *ngFor=\"let variable of templateVariables; trackBy: trackByVariable\">\n <!-- Boolean variables with mat-slide-toggle -->\n <ng-container *ngIf=\"variable.type === 'boolean'\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" style=\"width: calc(50% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700\">\n {{ variable.label }}\n </label>\n <mat-slide-toggle
|
|
25827
|
+
TemplateVariablesFormComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TemplateVariablesFormComponent, selector: "cqa-template-variables-form", inputs: { templateVariables: "templateVariables", variablesForm: "variablesForm", metadata: "metadata", description: "description", elementOptions: "elementOptions", hasMoreElements: "hasMoreElements", isLoadingElements: "isLoadingElements", screenNameOptions: "screenNameOptions", hasMoreScreenNames: "hasMoreScreenNames", isLoadingScreenNames: "isLoadingScreenNames" }, outputs: { variableValueChange: "variableValueChange", variableBooleanChange: "variableBooleanChange", metadataChange: "metadataChange", descriptionChange: "descriptionChange", loadMoreElements: "loadMoreElements", searchElements: "searchElements", createElement: "createElement", searchScreenName: "searchScreenName", loadMoreScreenNames: "loadMoreScreenNames", createScreenNameRequest: "createScreenNameRequest", cancelElementForm: "cancelElementForm", elementFormVisibilityChange: "elementFormVisibilityChange" }, host: { classAttribute: "cqa-ui-root" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-flex cqa-gap-x-6 cqa-gap-y-4 cqa-flex-wrap\" *ngIf=\"!createElementVisible\">\n <ng-container *ngFor=\"let variable of templateVariables; let i = index; trackBy: trackByVariable\">\n <!-- Boolean variables with mat-slide-toggle -->\n <ng-container *ngIf=\"variable.type === 'boolean'\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" style=\"width: calc(50% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700\">\n {{ variable.label }}\n </label>\n <mat-slide-toggle [checked]=\"variablesForm.at(i)?.get('value')?.value || variable.value || false\"\n (change)=\"onVariableBooleanChange(variable.name, $event.checked)\" color=\"primary\">\n </mat-slide-toggle>\n </div>\n </ng-container>\n\n <!-- Non-boolean, non-custom_code variables -->\n <ng-container *ngIf=\"variable.name !== 'custom_code' && variable.type !== 'boolean'\">\n <ng-container *ngIf=\"shouldShowDropdown(variable); else defaultInput\">\n <div class=\"cqa-flex cqa-flex-col\" style=\"width: calc(50% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n {{ variable.label }}\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n </ng-container>\n <ng-template #defaultInput>\n <!-- Test-data, source-value, or target-value with data type dropdown -->\n <ng-container *ngIf=\"needsDataTypeDropdown(variable); else regularInput\">\n <div class=\"cqa-flex cqa-flex-col\" style=\"width: calc(50% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n {{ variable.label }} Type\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getDataTypeSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n <div class=\"cqa-flex cqa-flex-col\" style=\"width: calc(50% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n {{ variable.label }}\n </label>\n <cqa-custom-input [placeholder]=\"'Text Input'\" [value]=\"getRawValue(variable)\" [fullWidth]=\"true\"\n (valueChange)=\"onTestDataValueChange(variable.name, $event)\">\n </cqa-custom-input>\n </div>\n </ng-container>\n <ng-template #regularInput>\n <div class=\"cqa-flex cqa-flex-col\" style=\"width: calc(50% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n {{ variable.label }}\n </label>\n <cqa-custom-input [placeholder]=\"'Text Input'\" [value]=\"variable.value\" [fullWidth]=\"true\"\n (valueChange)=\"onVariableValueChange(variable.name, $event)\">\n </cqa-custom-input>\n </div>\n </ng-template>\n </ng-template>\n </ng-container>\n </ng-container>\n\n <!-- Metadata -->\n <div class=\"cqa-flex cqa-flex-col\" style=\"width: calc(50% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n Metadata\n </label>\n <cqa-custom-input [placeholder]=\"'Text Input'\" [value]=\"metadata\" [fullWidth]=\"true\"\n (valueChange)=\"metadataChange.emit($event)\">\n </cqa-custom-input>\n </div>\n\n <!-- Description -->\n <div class=\"cqa-flex cqa-flex-col\" style=\"width: calc(50% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n Description\n </label>\n <cqa-custom-input [placeholder]=\"'Text Input'\" [value]=\"description\" [fullWidth]=\"true\"\n (valueChange)=\"descriptionChange.emit($event)\">\n </cqa-custom-input>\n </div>\n</div>\n\n<div *ngIf=\"createElementVisible\">\n <cqa-element-form\n [isCreateMode]=\"true\"\n [screenNameOptions]=\"screenNameOptions\"\n [hasMoreScreenNames]=\"hasMoreScreenNames\"\n [isLoadingScreenNames]=\"isLoadingScreenNames\"\n [isEditInDepthAvailable]=\"false\"\n (createElement)=\"onCreateElement($event)\"\n (cancel)=\"onCancelElementForm()\"\n (searchScreenName)=\"searchScreenName.emit($event)\"\n (loadMoreScreenNames)=\"loadMoreScreenNames.emit($event)\"\n (createScreenNameRequest)=\"createScreenNameRequest.emit($event)\">\n </cqa-element-form>\n</div>\n<div class=\"cqa-flex cqa-justify-end cqa-pt-2\" *ngIf=\"!createElementVisible\">\n <cqa-button \n *ngIf=\"selectorVariableAvailable\"\n variant=\"text\" \n size=\"sm\"\n text=\"Create Element\"\n (clicked)=\"onShowElementForm()\">\n </cqa-button>\n <!-- <cqa-button \n *ngIf=\"parameterVariableAvailable\"\n variant=\"filled\" \n text=\"Create Parameter\"\n (clicked)=\"onCreateParameter()\">\n </cqa-button>\n <cqa-button \n *ngIf=\"environmentVariableAvailable\"\n variant=\"filled\" \n text=\"Create Environment\"\n (clicked)=\"onCreateEnvironment()\">\n </cqa-button> -->\n</div>", components: [{ type: i5$1.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["disabled", "disableRipple", "color", "tabIndex", "name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "checked"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { type: DynamicSelectFieldComponent, selector: "cqa-dynamic-select", inputs: ["form", "config"], outputs: ["selectionChange", "selectClick", "searchChange", "loadMore", "addCustomValue"] }, { 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: ElementFormComponent, selector: "cqa-element-form", inputs: ["elementId", "element", "screenNameOptions", "hasMoreScreenNames", "isLoadingScreenNames", "isElementLoading", "isEditMode", "isCreateMode", "isEditInDepthAvailable"], outputs: ["createElement", "updateElement", "createScreenNameRequest", "searchScreenName", "loadMoreScreenNames", "cancel", "editInDepth"] }, { type: ButtonComponent, selector: "cqa-button", inputs: ["variant", "btnSize", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass", "inlineStyles", "tooltip", "tooltipPosition"], outputs: ["clicked"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
25587
25828
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TemplateVariablesFormComponent, decorators: [{
|
|
25588
25829
|
type: Component,
|
|
25589
|
-
args: [{ selector: 'cqa-template-variables-form', host: { class: 'cqa-ui-root' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"cqa-flex cqa-gap-x-6 cqa-flex-wrap\">\n <ng-container *ngFor=\"let variable of templateVariables; trackBy: trackByVariable\">\n <!-- Boolean variables with mat-slide-toggle -->\n <ng-container *ngIf=\"variable.type === 'boolean'\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" style=\"width: calc(50% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700\">\n {{ variable.label }}\n </label>\n <mat-slide-toggle
|
|
25830
|
+
args: [{ selector: 'cqa-template-variables-form', host: { class: 'cqa-ui-root' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"cqa-flex cqa-gap-x-6 cqa-gap-y-4 cqa-flex-wrap\" *ngIf=\"!createElementVisible\">\n <ng-container *ngFor=\"let variable of templateVariables; let i = index; trackBy: trackByVariable\">\n <!-- Boolean variables with mat-slide-toggle -->\n <ng-container *ngIf=\"variable.type === 'boolean'\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" style=\"width: calc(50% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700\">\n {{ variable.label }}\n </label>\n <mat-slide-toggle [checked]=\"variablesForm.at(i)?.get('value')?.value || variable.value || false\"\n (change)=\"onVariableBooleanChange(variable.name, $event.checked)\" color=\"primary\">\n </mat-slide-toggle>\n </div>\n </ng-container>\n\n <!-- Non-boolean, non-custom_code variables -->\n <ng-container *ngIf=\"variable.name !== 'custom_code' && variable.type !== 'boolean'\">\n <ng-container *ngIf=\"shouldShowDropdown(variable); else defaultInput\">\n <div class=\"cqa-flex cqa-flex-col\" style=\"width: calc(50% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n {{ variable.label }}\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n </ng-container>\n <ng-template #defaultInput>\n <!-- Test-data, source-value, or target-value with data type dropdown -->\n <ng-container *ngIf=\"needsDataTypeDropdown(variable); else regularInput\">\n <div class=\"cqa-flex cqa-flex-col\" style=\"width: calc(50% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n {{ variable.label }} Type\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getDataTypeSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n <div class=\"cqa-flex cqa-flex-col\" style=\"width: calc(50% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n {{ variable.label }}\n </label>\n <cqa-custom-input [placeholder]=\"'Text Input'\" [value]=\"getRawValue(variable)\" [fullWidth]=\"true\"\n (valueChange)=\"onTestDataValueChange(variable.name, $event)\">\n </cqa-custom-input>\n </div>\n </ng-container>\n <ng-template #regularInput>\n <div class=\"cqa-flex cqa-flex-col\" style=\"width: calc(50% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n {{ variable.label }}\n </label>\n <cqa-custom-input [placeholder]=\"'Text Input'\" [value]=\"variable.value\" [fullWidth]=\"true\"\n (valueChange)=\"onVariableValueChange(variable.name, $event)\">\n </cqa-custom-input>\n </div>\n </ng-template>\n </ng-template>\n </ng-container>\n </ng-container>\n\n <!-- Metadata -->\n <div class=\"cqa-flex cqa-flex-col\" style=\"width: calc(50% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n Metadata\n </label>\n <cqa-custom-input [placeholder]=\"'Text Input'\" [value]=\"metadata\" [fullWidth]=\"true\"\n (valueChange)=\"metadataChange.emit($event)\">\n </cqa-custom-input>\n </div>\n\n <!-- Description -->\n <div class=\"cqa-flex cqa-flex-col\" style=\"width: calc(50% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n Description\n </label>\n <cqa-custom-input [placeholder]=\"'Text Input'\" [value]=\"description\" [fullWidth]=\"true\"\n (valueChange)=\"descriptionChange.emit($event)\">\n </cqa-custom-input>\n </div>\n</div>\n\n<div *ngIf=\"createElementVisible\">\n <cqa-element-form\n [isCreateMode]=\"true\"\n [screenNameOptions]=\"screenNameOptions\"\n [hasMoreScreenNames]=\"hasMoreScreenNames\"\n [isLoadingScreenNames]=\"isLoadingScreenNames\"\n [isEditInDepthAvailable]=\"false\"\n (createElement)=\"onCreateElement($event)\"\n (cancel)=\"onCancelElementForm()\"\n (searchScreenName)=\"searchScreenName.emit($event)\"\n (loadMoreScreenNames)=\"loadMoreScreenNames.emit($event)\"\n (createScreenNameRequest)=\"createScreenNameRequest.emit($event)\">\n </cqa-element-form>\n</div>\n<div class=\"cqa-flex cqa-justify-end cqa-pt-2\" *ngIf=\"!createElementVisible\">\n <cqa-button \n *ngIf=\"selectorVariableAvailable\"\n variant=\"text\" \n size=\"sm\"\n text=\"Create Element\"\n (clicked)=\"onShowElementForm()\">\n </cqa-button>\n <!-- <cqa-button \n *ngIf=\"parameterVariableAvailable\"\n variant=\"filled\" \n text=\"Create Parameter\"\n (clicked)=\"onCreateParameter()\">\n </cqa-button>\n <cqa-button \n *ngIf=\"environmentVariableAvailable\"\n variant=\"filled\" \n text=\"Create Environment\"\n (clicked)=\"onCreateEnvironment()\">\n </cqa-button> -->\n</div>", styles: [] }]
|
|
25590
25831
|
}], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }]; }, propDecorators: { templateVariables: [{
|
|
25591
25832
|
type: Input
|
|
25592
25833
|
}], variablesForm: [{
|
|
@@ -25595,6 +25836,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
|
|
|
25595
25836
|
type: Input
|
|
25596
25837
|
}], description: [{
|
|
25597
25838
|
type: Input
|
|
25839
|
+
}], elementOptions: [{
|
|
25840
|
+
type: Input
|
|
25841
|
+
}], hasMoreElements: [{
|
|
25842
|
+
type: Input
|
|
25843
|
+
}], isLoadingElements: [{
|
|
25844
|
+
type: Input
|
|
25845
|
+
}], screenNameOptions: [{
|
|
25846
|
+
type: Input
|
|
25847
|
+
}], hasMoreScreenNames: [{
|
|
25848
|
+
type: Input
|
|
25849
|
+
}], isLoadingScreenNames: [{
|
|
25850
|
+
type: Input
|
|
25598
25851
|
}], variableValueChange: [{
|
|
25599
25852
|
type: Output
|
|
25600
25853
|
}], variableBooleanChange: [{
|
|
@@ -25603,6 +25856,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
|
|
|
25603
25856
|
type: Output
|
|
25604
25857
|
}], descriptionChange: [{
|
|
25605
25858
|
type: Output
|
|
25859
|
+
}], loadMoreElements: [{
|
|
25860
|
+
type: Output
|
|
25861
|
+
}], searchElements: [{
|
|
25862
|
+
type: Output
|
|
25863
|
+
}], createElement: [{
|
|
25864
|
+
type: Output
|
|
25865
|
+
}], searchScreenName: [{
|
|
25866
|
+
type: Output
|
|
25867
|
+
}], loadMoreScreenNames: [{
|
|
25868
|
+
type: Output
|
|
25869
|
+
}], createScreenNameRequest: [{
|
|
25870
|
+
type: Output
|
|
25871
|
+
}], cancelElementForm: [{
|
|
25872
|
+
type: Output
|
|
25873
|
+
}], elementFormVisibilityChange: [{
|
|
25874
|
+
type: Output
|
|
25606
25875
|
}] } });
|
|
25607
25876
|
|
|
25608
25877
|
class StepBuilderActionComponent {
|
|
@@ -25616,7 +25885,22 @@ class StepBuilderActionComponent {
|
|
|
25616
25885
|
/** Function to handle variable processing or custom logic. Can be passed from parent component. */
|
|
25617
25886
|
this.setTemplateVariables = () => { return []; };
|
|
25618
25887
|
this.preventSelectTemplate = ['databaseverification'];
|
|
25888
|
+
this.elementOptions = []; // Element objects for element dropdown
|
|
25889
|
+
this.hasMoreElements = false; // Whether more elements are available
|
|
25890
|
+
this.isLoadingElements = false; // Loading state for elements
|
|
25891
|
+
/** Screen name options for element form autocomplete (from API) */
|
|
25892
|
+
this.screenNameOptions = [];
|
|
25893
|
+
/** Whether more screen names are available for infinite scroll */
|
|
25894
|
+
this.hasMoreScreenNames = false;
|
|
25895
|
+
/** True while parent is loading screen names (search or load more) */
|
|
25896
|
+
this.isLoadingScreenNames = false;
|
|
25619
25897
|
this.templateChanged = new EventEmitter();
|
|
25898
|
+
this.loadMoreElements = new EventEmitter(); // Emit when load more is requested
|
|
25899
|
+
this.searchElements = new EventEmitter(); // Emit when user searches for elements
|
|
25900
|
+
this.createElement = new EventEmitter(); // Emit when element is created
|
|
25901
|
+
this.searchScreenName = new EventEmitter(); // Emit when user searches screen names
|
|
25902
|
+
this.loadMoreScreenNames = new EventEmitter(); // Emit when user scrolls to load more screen names
|
|
25903
|
+
this.createScreenNameRequest = new EventEmitter(); // Emit when user requests to create a new screen name
|
|
25620
25904
|
/** Emit when step is created */
|
|
25621
25905
|
this.createStep = new EventEmitter();
|
|
25622
25906
|
/** Emit when cancelled */
|
|
@@ -25628,12 +25912,21 @@ class StepBuilderActionComponent {
|
|
|
25628
25912
|
this.description = '';
|
|
25629
25913
|
this.advancedExpanded = false;
|
|
25630
25914
|
this.templateVariables = [];
|
|
25915
|
+
this.updatedHtmlGrammar = ''; // Updated HTML grammar with variable values
|
|
25916
|
+
// Track element form visibility
|
|
25917
|
+
this.isElementFormVisible = false;
|
|
25631
25918
|
// Cache for select configs to avoid recalculating on every change detection
|
|
25632
25919
|
this.selectConfigCache = new Map();
|
|
25633
25920
|
this.formValidCache = false;
|
|
25634
25921
|
this.lastFormValidationTime = 0;
|
|
25635
25922
|
this.FORM_VALIDATION_CACHE_MS = 100; // Cache for 100ms
|
|
25636
|
-
this.variablesForm = this.fb.
|
|
25923
|
+
this.variablesForm = this.fb.array([]);
|
|
25924
|
+
}
|
|
25925
|
+
/**
|
|
25926
|
+
* Handle element form visibility change
|
|
25927
|
+
*/
|
|
25928
|
+
onElementFormVisibilityChange(visible) {
|
|
25929
|
+
this.isElementFormVisible = visible;
|
|
25637
25930
|
}
|
|
25638
25931
|
ngOnInit() {
|
|
25639
25932
|
this.filteredTemplates = [...this.templates];
|
|
@@ -25663,14 +25956,38 @@ class StepBuilderActionComponent {
|
|
|
25663
25956
|
const searchTerm = this.searchValue.toLowerCase().trim();
|
|
25664
25957
|
this.filteredTemplates = this.templates.filter(template => {
|
|
25665
25958
|
const naturalText = template.naturalText?.toLowerCase() || '';
|
|
25666
|
-
|
|
25959
|
+
// Strip HTML tags from htmlGrammar for searching (only search text content, not HTML markup)
|
|
25960
|
+
const htmlGrammarText = this.stripHtmlTags(template.htmlGrammar || '').toLowerCase();
|
|
25667
25961
|
const searchableGrammar = template.searchableGrammar?.toLowerCase() || '';
|
|
25668
25962
|
return naturalText.includes(searchTerm) ||
|
|
25669
|
-
|
|
25963
|
+
htmlGrammarText.includes(searchTerm) ||
|
|
25670
25964
|
searchableGrammar.includes(searchTerm);
|
|
25671
25965
|
});
|
|
25672
25966
|
console.log("filteredTemplates", this.filteredTemplates);
|
|
25673
25967
|
}
|
|
25968
|
+
/**
|
|
25969
|
+
* Strip HTML tags from a string, returning only the text content
|
|
25970
|
+
* @param htmlString - HTML string to strip tags from
|
|
25971
|
+
* @returns Plain text without HTML tags
|
|
25972
|
+
*/
|
|
25973
|
+
stripHtmlTags(htmlString) {
|
|
25974
|
+
if (!htmlString)
|
|
25975
|
+
return '';
|
|
25976
|
+
// Use browser's DOMParser if available
|
|
25977
|
+
if (typeof document !== 'undefined' && document.createElement) {
|
|
25978
|
+
try {
|
|
25979
|
+
const tempDiv = document.createElement('div');
|
|
25980
|
+
tempDiv.innerHTML = htmlString;
|
|
25981
|
+
return tempDiv.textContent || tempDiv.innerText || '';
|
|
25982
|
+
}
|
|
25983
|
+
catch (error) {
|
|
25984
|
+
// Fallback to regex if DOM parsing fails
|
|
25985
|
+
return htmlString.replace(/<[^>]*>/g, '');
|
|
25986
|
+
}
|
|
25987
|
+
}
|
|
25988
|
+
// Fallback: regex-based tag removal for server-side rendering
|
|
25989
|
+
return htmlString.replace(/<[^>]*>/g, '');
|
|
25990
|
+
}
|
|
25674
25991
|
selectTemplate(template) {
|
|
25675
25992
|
if (this.preventSelectTemplate.includes(template.displayName || '')) {
|
|
25676
25993
|
this.templateChanged.emit(template);
|
|
@@ -25687,20 +26004,26 @@ class StepBuilderActionComponent {
|
|
|
25687
26004
|
setTimeout(() => {
|
|
25688
26005
|
try {
|
|
25689
26006
|
this.templateVariables = this.setTemplateVariables(template);
|
|
26007
|
+
console.log("templateVariables", this.templateVariables);
|
|
25690
26008
|
this.buildVariablesForm();
|
|
26009
|
+
// Initialize updated HTML grammar
|
|
26010
|
+
this.updateHtmlGrammar();
|
|
25691
26011
|
}
|
|
25692
26012
|
catch (error) {
|
|
25693
26013
|
console.error('Error processing template variables:', error);
|
|
25694
26014
|
}
|
|
25695
26015
|
}, 0);
|
|
25696
26016
|
}
|
|
26017
|
+
else {
|
|
26018
|
+
// Initialize with template's HTML grammar if no variables
|
|
26019
|
+
this.updatedHtmlGrammar = template.htmlGrammar || template.naturalText || '';
|
|
26020
|
+
}
|
|
25697
26021
|
}
|
|
25698
26022
|
buildVariablesForm() {
|
|
25699
|
-
// Clear existing form
|
|
25700
|
-
|
|
25701
|
-
|
|
25702
|
-
|
|
25703
|
-
});
|
|
26023
|
+
// Clear existing form array
|
|
26024
|
+
while (this.variablesForm.length !== 0) {
|
|
26025
|
+
this.variablesForm.removeAt(0);
|
|
26026
|
+
}
|
|
25704
26027
|
// Clear cache when form is rebuilt
|
|
25705
26028
|
this.selectConfigCache.clear();
|
|
25706
26029
|
this.formValidCache = false;
|
|
@@ -25708,13 +26031,39 @@ class StepBuilderActionComponent {
|
|
|
25708
26031
|
if (this.formValueChangesSubscription) {
|
|
25709
26032
|
this.formValueChangesSubscription.unsubscribe();
|
|
25710
26033
|
}
|
|
25711
|
-
// Add form
|
|
26034
|
+
// Add form groups for each variable
|
|
25712
26035
|
this.templateVariables.forEach(variable => {
|
|
25713
26036
|
// Handle boolean variables - use boolean value, others use string
|
|
25714
26037
|
const defaultValue = variable.type === 'boolean'
|
|
25715
26038
|
? (variable.value === true || variable.value === 'true' || variable.value === 1)
|
|
25716
26039
|
: (variable.value || '');
|
|
25717
|
-
|
|
26040
|
+
// Create a FormGroup for each variable with name and value
|
|
26041
|
+
const variableGroup = this.fb.group({
|
|
26042
|
+
name: [variable.name],
|
|
26043
|
+
value: [defaultValue],
|
|
26044
|
+
type: [variable.type || 'string'],
|
|
26045
|
+
label: [variable.label || ''],
|
|
26046
|
+
options: [variable.options || []]
|
|
26047
|
+
});
|
|
26048
|
+
// Add dataType control for test-data variables if needed
|
|
26049
|
+
const label = variable.label?.toLowerCase() || '';
|
|
26050
|
+
if (label === 'test-data' || label === 'source-value' || label === 'target-value' ||
|
|
26051
|
+
label === 'source_value' || label === 'target_value') {
|
|
26052
|
+
// Parse the value to determine data type
|
|
26053
|
+
const valueStr = String(defaultValue || '');
|
|
26054
|
+
let dataType = 'plain-text';
|
|
26055
|
+
if (valueStr.startsWith('@|') && valueStr.endsWith('|')) {
|
|
26056
|
+
dataType = 'parameter';
|
|
26057
|
+
}
|
|
26058
|
+
else if (valueStr.startsWith('$|') && valueStr.endsWith('|')) {
|
|
26059
|
+
dataType = 'runtime';
|
|
26060
|
+
}
|
|
26061
|
+
else if (valueStr.startsWith('*|') && valueStr.endsWith('|')) {
|
|
26062
|
+
dataType = 'environment';
|
|
26063
|
+
}
|
|
26064
|
+
variableGroup.addControl('dataType', new FormControl(dataType));
|
|
26065
|
+
}
|
|
26066
|
+
this.variablesForm.push(variableGroup);
|
|
25718
26067
|
});
|
|
25719
26068
|
// Subscribe to form value changes to invalidate cache (only when user actually changes values)
|
|
25720
26069
|
// Note: We use emitEvent: false when programmatically setting values, so this won't fire unnecessarily
|
|
@@ -25728,7 +26077,7 @@ class StepBuilderActionComponent {
|
|
|
25728
26077
|
this.formValueChangesSubscription.unsubscribe();
|
|
25729
26078
|
}
|
|
25730
26079
|
}
|
|
25731
|
-
getSelectConfig(variable) {
|
|
26080
|
+
getSelectConfig(variable, index) {
|
|
25732
26081
|
// Use cache to avoid recalculating on every change detection
|
|
25733
26082
|
const cacheKey = `${variable.name}_${variable.options?.join(',') || ''}`;
|
|
25734
26083
|
if (this.selectConfigCache.has(cacheKey)) {
|
|
@@ -25741,7 +26090,7 @@ class StepBuilderActionComponent {
|
|
|
25741
26090
|
label: opt
|
|
25742
26091
|
}));
|
|
25743
26092
|
const config = {
|
|
25744
|
-
key:
|
|
26093
|
+
key: `value`,
|
|
25745
26094
|
placeholder: `Select ${variable.label}`,
|
|
25746
26095
|
multiple: false,
|
|
25747
26096
|
searchable: false,
|
|
@@ -25753,18 +26102,62 @@ class StepBuilderActionComponent {
|
|
|
25753
26102
|
this.selectConfigCache.set(cacheKey, config);
|
|
25754
26103
|
return config;
|
|
25755
26104
|
}
|
|
26105
|
+
/** Get form group for a variable by name */
|
|
26106
|
+
getVariableFormGroup(variableName) {
|
|
26107
|
+
const variableIndex = this.variablesForm.controls.findIndex(control => control.get('name')?.value === variableName);
|
|
26108
|
+
if (variableIndex !== -1) {
|
|
26109
|
+
return this.variablesForm.at(variableIndex);
|
|
26110
|
+
}
|
|
26111
|
+
return null;
|
|
26112
|
+
}
|
|
26113
|
+
/** Add a new variable to the form array dynamically */
|
|
26114
|
+
addVariable(variable) {
|
|
26115
|
+
const defaultValue = variable.type === 'boolean'
|
|
26116
|
+
? (variable.value === true || variable.value === 'true' || variable.value === 1)
|
|
26117
|
+
: (variable.value || '');
|
|
26118
|
+
const variableGroup = this.fb.group({
|
|
26119
|
+
name: [variable.name],
|
|
26120
|
+
value: [defaultValue],
|
|
26121
|
+
type: [variable.type || 'string'],
|
|
26122
|
+
label: [variable.label || ''],
|
|
26123
|
+
options: [variable.options || []]
|
|
26124
|
+
});
|
|
26125
|
+
// Add dataType control for test-data variables if needed
|
|
26126
|
+
const label = variable.label?.toLowerCase() || '';
|
|
26127
|
+
if (label === 'test-data' || label === 'source-value' || label === 'target-value' ||
|
|
26128
|
+
label === 'source_value' || label === 'target_value') {
|
|
26129
|
+
const valueStr = String(defaultValue || '');
|
|
26130
|
+
let dataType = 'plain-text';
|
|
26131
|
+
if (valueStr.startsWith('@|') && valueStr.endsWith('|')) {
|
|
26132
|
+
dataType = 'parameter';
|
|
26133
|
+
}
|
|
26134
|
+
else if (valueStr.startsWith('$|') && valueStr.endsWith('|')) {
|
|
26135
|
+
dataType = 'runtime';
|
|
26136
|
+
}
|
|
26137
|
+
else if (valueStr.startsWith('*|') && valueStr.endsWith('|')) {
|
|
26138
|
+
dataType = 'environment';
|
|
26139
|
+
}
|
|
26140
|
+
variableGroup.addControl('dataType', new FormControl(dataType));
|
|
26141
|
+
}
|
|
26142
|
+
this.variablesForm.push(variableGroup);
|
|
26143
|
+
this.formValidCache = false;
|
|
26144
|
+
}
|
|
25756
26145
|
onVariableValueChange(variableName, value) {
|
|
26146
|
+
console.log("onVariableValueChange", variableName, value);
|
|
25757
26147
|
// Update the variable in templateVariables array
|
|
25758
26148
|
const variable = this.templateVariables.find(v => v.name === variableName);
|
|
25759
26149
|
if (variable) {
|
|
25760
26150
|
variable.value = value;
|
|
25761
26151
|
}
|
|
25762
|
-
// Also update form
|
|
25763
|
-
|
|
25764
|
-
|
|
26152
|
+
// Also update form array (use emitEvent: false to prevent triggering valueChanges)
|
|
26153
|
+
const variableIndex = this.variablesForm.controls.findIndex(control => control.get('name')?.value === variableName);
|
|
26154
|
+
if (variableIndex !== -1) {
|
|
26155
|
+
this.variablesForm.at(variableIndex).get('value')?.setValue(value, { emitEvent: false });
|
|
25765
26156
|
}
|
|
25766
26157
|
// Invalidate form validation cache
|
|
25767
26158
|
this.formValidCache = false;
|
|
26159
|
+
// Update HTML grammar with new value
|
|
26160
|
+
this.updateHtmlGrammar();
|
|
25768
26161
|
}
|
|
25769
26162
|
onVariableBooleanChange(variableName, value) {
|
|
25770
26163
|
// Update the variable in templateVariables array
|
|
@@ -25772,16 +26165,26 @@ class StepBuilderActionComponent {
|
|
|
25772
26165
|
if (variable) {
|
|
25773
26166
|
variable.value = value;
|
|
25774
26167
|
}
|
|
25775
|
-
// Also update form
|
|
25776
|
-
|
|
25777
|
-
|
|
26168
|
+
// Also update form array (use emitEvent: false to prevent triggering valueChanges)
|
|
26169
|
+
const variableIndex = this.variablesForm.controls.findIndex(control => control.get('name')?.value === variableName);
|
|
26170
|
+
if (variableIndex !== -1) {
|
|
26171
|
+
this.variablesForm.at(variableIndex).get('value')?.setValue(value, { emitEvent: false });
|
|
25778
26172
|
}
|
|
25779
26173
|
else {
|
|
25780
|
-
// Create form
|
|
25781
|
-
this.
|
|
26174
|
+
// Create new form group if it doesn't exist
|
|
26175
|
+
const variableGroup = this.fb.group({
|
|
26176
|
+
name: [variableName],
|
|
26177
|
+
value: [value],
|
|
26178
|
+
type: ['boolean'],
|
|
26179
|
+
label: [variable?.label || ''],
|
|
26180
|
+
options: [variable?.options || []]
|
|
26181
|
+
});
|
|
26182
|
+
this.variablesForm.push(variableGroup);
|
|
25782
26183
|
}
|
|
25783
26184
|
// Invalidate form validation cache
|
|
25784
26185
|
this.formValidCache = false;
|
|
26186
|
+
// Update HTML grammar with new value
|
|
26187
|
+
this.updateHtmlGrammar();
|
|
25785
26188
|
}
|
|
25786
26189
|
onBack() {
|
|
25787
26190
|
this.selectedTemplate = null;
|
|
@@ -25789,10 +26192,11 @@ class StepBuilderActionComponent {
|
|
|
25789
26192
|
this.description = '';
|
|
25790
26193
|
this.advancedExpanded = false;
|
|
25791
26194
|
this.templateVariables = [];
|
|
25792
|
-
|
|
25793
|
-
|
|
25794
|
-
|
|
25795
|
-
|
|
26195
|
+
this.updatedHtmlGrammar = '';
|
|
26196
|
+
// Clear form array
|
|
26197
|
+
while (this.variablesForm.length !== 0) {
|
|
26198
|
+
this.variablesForm.removeAt(0);
|
|
26199
|
+
}
|
|
25796
26200
|
// Reapply filter to maintain search state
|
|
25797
26201
|
this.applyFilter();
|
|
25798
26202
|
}
|
|
@@ -25810,22 +26214,22 @@ class StepBuilderActionComponent {
|
|
|
25810
26214
|
return this.formValidCache;
|
|
25811
26215
|
}
|
|
25812
26216
|
// Check if all required variables are filled
|
|
25813
|
-
let isValid = true;
|
|
25814
|
-
if (this.templateVariables && this.templateVariables.length > 0) {
|
|
25815
|
-
|
|
25816
|
-
|
|
25817
|
-
|
|
25818
|
-
|
|
25819
|
-
|
|
25820
|
-
|
|
25821
|
-
|
|
25822
|
-
|
|
25823
|
-
|
|
25824
|
-
}
|
|
26217
|
+
// let isValid = true;
|
|
26218
|
+
// if (this.templateVariables && this.templateVariables.length > 0) {
|
|
26219
|
+
// isValid = this.templateVariables.every(variable => {
|
|
26220
|
+
// // Boolean variables are always valid (they have a default value)
|
|
26221
|
+
// if (variable.type === 'boolean') {
|
|
26222
|
+
// return true;
|
|
26223
|
+
// }
|
|
26224
|
+
// // Check if variable has a value
|
|
26225
|
+
// const value = variable.value;
|
|
26226
|
+
// return value !== null && value !== undefined && value !== '';
|
|
26227
|
+
// });
|
|
26228
|
+
// }
|
|
25825
26229
|
// Cache the result
|
|
25826
|
-
this.formValidCache =
|
|
26230
|
+
this.formValidCache = this.variablesForm.valid;
|
|
25827
26231
|
this.lastFormValidationTime = now;
|
|
25828
|
-
return
|
|
26232
|
+
return this.variablesForm.valid;
|
|
25829
26233
|
}
|
|
25830
26234
|
trackByTemplate(index, template) {
|
|
25831
26235
|
return template.id || template.displayName || index;
|
|
@@ -25843,6 +26247,8 @@ class StepBuilderActionComponent {
|
|
|
25843
26247
|
description: this.description,
|
|
25844
26248
|
templateVariables: this.templateVariables
|
|
25845
26249
|
};
|
|
26250
|
+
console.log("stepData", stepData);
|
|
26251
|
+
console.log("variablesForm", this.variablesForm.value);
|
|
25846
26252
|
this.createStep.emit(stepData);
|
|
25847
26253
|
}
|
|
25848
26254
|
toggleAdvanced() {
|
|
@@ -25858,12 +26264,75 @@ class StepBuilderActionComponent {
|
|
|
25858
26264
|
onTestDataValueChange(key, value) {
|
|
25859
26265
|
console.log(key, value);
|
|
25860
26266
|
}
|
|
26267
|
+
/**
|
|
26268
|
+
* Update HTML grammar by replacing placeholder spans with actual variable values
|
|
26269
|
+
*/
|
|
26270
|
+
updateHtmlGrammar() {
|
|
26271
|
+
if (!this.selectedTemplate) {
|
|
26272
|
+
this.updatedHtmlGrammar = '';
|
|
26273
|
+
return;
|
|
26274
|
+
}
|
|
26275
|
+
const htmlGrammar = this.selectedTemplate.htmlGrammar || this.selectedTemplate.naturalText || '';
|
|
26276
|
+
if (!htmlGrammar) {
|
|
26277
|
+
this.updatedHtmlGrammar = '';
|
|
26278
|
+
return;
|
|
26279
|
+
}
|
|
26280
|
+
// Create a map of variable values by name for quick lookup
|
|
26281
|
+
const valueMap = new Map();
|
|
26282
|
+
if (this.templateVariables && Array.isArray(this.templateVariables)) {
|
|
26283
|
+
this.templateVariables.forEach((variable) => {
|
|
26284
|
+
if (variable.name && variable.value !== undefined && variable.value !== null) {
|
|
26285
|
+
// Convert value to string, handling boolean values
|
|
26286
|
+
const valueStr = typeof variable.value === 'boolean'
|
|
26287
|
+
? (variable.value ? 'true' : 'false')
|
|
26288
|
+
: String(variable.value || '');
|
|
26289
|
+
valueMap.set(variable.name, valueStr);
|
|
26290
|
+
}
|
|
26291
|
+
});
|
|
26292
|
+
}
|
|
26293
|
+
// Use browser's DOMParser if available, otherwise fallback to string replacement
|
|
26294
|
+
if (typeof document !== 'undefined' && document.createElement) {
|
|
26295
|
+
try {
|
|
26296
|
+
const tempDiv = document.createElement('div');
|
|
26297
|
+
tempDiv.innerHTML = String(htmlGrammar);
|
|
26298
|
+
// Find all spans with data-event-key attribute
|
|
26299
|
+
const spans = tempDiv.querySelectorAll('span[data-event-key]');
|
|
26300
|
+
spans.forEach((span) => {
|
|
26301
|
+
const eventKey = span.getAttribute('data-event-key');
|
|
26302
|
+
if (eventKey && valueMap.has(eventKey)) {
|
|
26303
|
+
const value = valueMap.get(eventKey);
|
|
26304
|
+
// Preserve the span structure but update the content
|
|
26305
|
+
span.innerHTML = value || '';
|
|
26306
|
+
}
|
|
26307
|
+
});
|
|
26308
|
+
this.updatedHtmlGrammar = tempDiv.innerHTML;
|
|
26309
|
+
}
|
|
26310
|
+
catch (error) {
|
|
26311
|
+
console.error('Error updating HTML grammar:', error);
|
|
26312
|
+
// Fallback to original HTML grammar
|
|
26313
|
+
this.updatedHtmlGrammar = String(htmlGrammar);
|
|
26314
|
+
}
|
|
26315
|
+
}
|
|
26316
|
+
else {
|
|
26317
|
+
// Fallback: simple string replacement for server-side rendering
|
|
26318
|
+
let updatedHtml = String(htmlGrammar);
|
|
26319
|
+
valueMap.forEach((value, key) => {
|
|
26320
|
+
// Replace spans with data-event-key matching the variable name
|
|
26321
|
+
const regex = new RegExp(`<span[^>]*data-event-key="${key}"[^>]*>.*?</span>`, 'gi');
|
|
26322
|
+
updatedHtml = updatedHtml.replace(regex, (match) => {
|
|
26323
|
+
// Replace the content inside the span
|
|
26324
|
+
return match.replace(/>.*?</, `>${value}<`);
|
|
26325
|
+
});
|
|
26326
|
+
});
|
|
26327
|
+
this.updatedHtmlGrammar = updatedHtml;
|
|
26328
|
+
}
|
|
26329
|
+
}
|
|
25861
26330
|
}
|
|
25862
26331
|
StepBuilderActionComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StepBuilderActionComponent, deps: [{ token: i1$1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
|
|
25863
|
-
StepBuilderActionComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: StepBuilderActionComponent, selector: "cqa-step-builder-action", inputs: { showHeader: "showHeader", templates: "templates", searchPlaceholder: "searchPlaceholder", setTemplateVariables: "setTemplateVariables", preventSelectTemplate: "preventSelectTemplate" }, outputs: { templateChanged: "templateChanged", createStep: "createStep", cancelled: "cancelled" }, host: { classAttribute: "cqa-ui-root" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white\" [ngClass]=\"{'cqa-px-4 cqa-py-2': showHeader}\">\n <!-- Header -->\n <h2 *ngIf=\"showHeader\" class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-1\">\n Create an action step\n </h2>\n <div *ngIf=\"!selectedTemplate\" class=\"cqa-flex cqa-flex-col cqa-h-full cqa-flex-1\"\n [ngClass]=\"{'cqa-px-3': showHeader}\">\n\n <!-- Search Bar -->\n <div class=\"cqa-pb-1\">\n <div class=\"cqa-pb-1\" *ngIf=\"showHeader\">\n <p class=\"cqa-text-[12px] cqa-text-gray-500\">\n Template library\n </p>\n </div>\n <cqa-search-bar [placeholder]=\"searchPlaceholder\" [fullWidth]=\"true\" [value]=\"searchValue\"\n (valueChange)=\"onSearchChange($event)\" (search)=\"onSearchSubmit($event)\" (cleared)=\"onSearchCleared()\">\n </cqa-search-bar>\n </div>\n\n <!-- Template List -->\n <div class=\"cqa-flex-1 cqa-overflow-y-auto cqa-px-2\">\n <div class=\"cqa-py-2\">\n <div *ngFor=\"let template of filteredTemplates; trackBy: trackByTemplate\"\n class=\"cqa-action-format cqa-bg-white cqa-cursor-pointer cqa-transition-all hover:cqa-border-blue-500 hover:cqa-shadow-sm mb-6\"\n (click)=\"selectTemplate(template)\">\n <div class=\"cqa-text-[12px] cqa-leading-[23px] cqa-text-black-100\"\n [innerHTML]=\"template.htmlGrammar || template.naturalText || ''\">\n </div>\n </div>\n\n <div *ngIf=\"filteredTemplates.length === 0\" class=\"cqa-text-center cqa-py-8 cqa-text-gray-400 cqa-text-[12px]\">\n No templates found\n </div>\n </div>\n </div>\n </div>\n\n <div *ngIf=\"selectedTemplate\" class=\"cqa-flex cqa-flex-col cqa-
|
|
26332
|
+
StepBuilderActionComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: StepBuilderActionComponent, selector: "cqa-step-builder-action", inputs: { showHeader: "showHeader", templates: "templates", searchPlaceholder: "searchPlaceholder", setTemplateVariables: "setTemplateVariables", preventSelectTemplate: "preventSelectTemplate", elementOptions: "elementOptions", hasMoreElements: "hasMoreElements", isLoadingElements: "isLoadingElements", screenNameOptions: "screenNameOptions", hasMoreScreenNames: "hasMoreScreenNames", isLoadingScreenNames: "isLoadingScreenNames" }, outputs: { templateChanged: "templateChanged", loadMoreElements: "loadMoreElements", searchElements: "searchElements", createElement: "createElement", searchScreenName: "searchScreenName", loadMoreScreenNames: "loadMoreScreenNames", createScreenNameRequest: "createScreenNameRequest", createStep: "createStep", cancelled: "cancelled" }, host: { styleAttribute: "display: block;height: 100%;width: 100%;", classAttribute: "cqa-ui-root" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white\" [ngClass]=\"{'cqa-px-4': showHeader, 'cqa-py-2': showHeader && !selectedTemplate}\">\n <!-- Header -->\n <h2 *ngIf=\"showHeader\" class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-1\">\n Create an action step\n </h2>\n <div *ngIf=\"!selectedTemplate\" class=\"cqa-flex cqa-flex-col cqa-h-full cqa-flex-1\"\n [ngClass]=\"{'cqa-px-3': showHeader}\">\n\n <!-- Search Bar -->\n <div class=\"cqa-pb-1\">\n <div class=\"cqa-pb-1\" *ngIf=\"showHeader\">\n <p class=\"cqa-text-[12px] cqa-text-gray-500\">\n Template library\n </p>\n </div>\n <cqa-search-bar [placeholder]=\"searchPlaceholder\" [fullWidth]=\"true\" [value]=\"searchValue\"\n (valueChange)=\"onSearchChange($event)\" (search)=\"onSearchSubmit($event)\" (cleared)=\"onSearchCleared()\">\n </cqa-search-bar>\n </div>\n\n <!-- Template List -->\n <div class=\"cqa-flex-1 cqa-overflow-y-auto cqa-px-2\">\n <div class=\"cqa-py-2\">\n <div *ngFor=\"let template of filteredTemplates; trackBy: trackByTemplate\"\n class=\"cqa-action-format cqa-bg-white cqa-cursor-pointer cqa-transition-all hover:cqa-border-blue-500 hover:cqa-shadow-sm mb-6\"\n (click)=\"selectTemplate(template)\">\n <div class=\"cqa-text-[12px] cqa-leading-[23px] cqa-text-black-100\"\n [innerHTML]=\"template.htmlGrammar || template.naturalText || ''\">\n </div>\n </div>\n\n <div *ngIf=\"filteredTemplates.length === 0\" class=\"cqa-text-center cqa-py-8 cqa-text-gray-400 cqa-text-[12px]\">\n No templates found\n </div>\n </div>\n </div>\n </div>\n\n <div *ngIf=\"selectedTemplate\" class=\"cqa-flex cqa-flex-col cqa-overflow-y-auto\" style=\"flex: 1 1 0 !important;\">\n <!-- Instruction Text with Element Buttons -->\n <div class=\"cqa-mb-4 cqa-flex cqa-items-center cqa-flex-wrap cqa-gap-1 cqa-text-sm cqa-text-gray-700\">\n <div class=\"cqa-action-format cqa-text-[12px] cqa-leading-[23px] cqa-text-black-100\"\n [innerHTML]=\"updatedHtmlGrammar || selectedTemplate.htmlGrammar || selectedTemplate.naturalText || ''\">\n </div>\n </div>\n\n <!-- Form Fields in Two Columns -->\n <div class=\"cqa-flex cqa-overflow-y-auto cqa-flex-1 cqa-pb-2\">\n <div class=\"cqa-flex-1 cqa-flex cqa-flex-col cqa-gap-1\">\n <div class=\"cqa-flex cqa-gap-x-6 cqa-flex-wrap cqa-pb-4\">\n <!-- Template Variables Form Component -->\n <cqa-template-variables-form\n style=\"width: 100%;\"\n [templateVariables]=\"templateVariables\"\n [variablesForm]=\"variablesForm\"\n [metadata]=\"metadata\"\n [description]=\"description\"\n [elementOptions]=\"elementOptions\"\n [hasMoreElements]=\"hasMoreElements\"\n [isLoadingElements]=\"isLoadingElements\"\n [screenNameOptions]=\"screenNameOptions\"\n [hasMoreScreenNames]=\"hasMoreScreenNames\"\n [isLoadingScreenNames]=\"isLoadingScreenNames\"\n (variableValueChange)=\"onVariableValueChange($event.name, $event.value)\"\n (variableBooleanChange)=\"onVariableBooleanChange($event.name, $event.value)\"\n (metadataChange)=\"metadata = $event\"\n (descriptionChange)=\"description = $event\"\n (loadMoreElements)=\"loadMoreElements.emit()\"\n (searchElements)=\"searchElements.emit($event)\"\n (createElement)=\"createElement.emit($event)\"\n (searchScreenName)=\"searchScreenName.emit($event)\"\n (loadMoreScreenNames)=\"loadMoreScreenNames.emit($event)\"\n (createScreenNameRequest)=\"createScreenNameRequest.emit($event)\"\n (elementFormVisibilityChange)=\"onElementFormVisibilityChange($event)\">\n </cqa-template-variables-form>\n </div>\n\n <!-- Advanced (Expandable) -->\n <!-- <div class=\"cqa-flex cqa-flex-col cqa-w-full\">\n <button type=\"button\"\n class=\"cqa-flex cqa-w-full cqa-items-center cqa-justify-between cqa-gap-2 cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-bg-transparent cqa-border-none cqa-cursor-pointer cqa-p-0 cqa-mb-1.5\"\n (click)=\"toggleAdvanced()\">\n <span class=\"cqa-text-[10px]\">Advanced</span>\n <mat-icon class=\"cqa-text-base\" [class.cqa-rotate-180]=\"advancedExpanded\">\n expand_more\n </mat-icon>\n </button>\n <div *ngIf=\"advancedExpanded\" class=\"cqa-mt-2\">\n </div>\n </div> -->\n <div>\n \n </div>\n </div>\n\n\n </div>\n\n <!-- Action Buttons -->\n <div *ngIf=\"!isElementFormVisible\" class=\"cqa-flex cqa-w-full cqa-gap-2 cqa-border-t cqa-border-gray-200 cqa-pb-2\">\n <cqa-button class=\"cqa-w-1/2\" variant=\"outlined\" text=\"Cancel\" [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onCancel()\">\n </cqa-button>\n <cqa-button class=\"cqa-w-1/2\" variant=\"filled\" text=\"Create Step\" [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n [disabled]=\"!isFormValid()\"\n (clicked)=\"onCreateStep()\">\n </cqa-button>\n </div>\n </div>\n</div>", components: [{ type: SearchBarComponent, selector: "cqa-search-bar", inputs: ["placeholder", "value", "disabled", "showClear", "ariaLabel", "autoFocus", "size", "fullWidth"], outputs: ["valueChange", "search", "cleared"] }, { type: TemplateVariablesFormComponent, selector: "cqa-template-variables-form", inputs: ["templateVariables", "variablesForm", "metadata", "description", "elementOptions", "hasMoreElements", "isLoadingElements", "screenNameOptions", "hasMoreScreenNames", "isLoadingScreenNames"], outputs: ["variableValueChange", "variableBooleanChange", "metadataChange", "descriptionChange", "loadMoreElements", "searchElements", "createElement", "searchScreenName", "loadMoreScreenNames", "createScreenNameRequest", "cancelElementForm", "elementFormVisibilityChange"] }, { type: ButtonComponent, selector: "cqa-button", inputs: ["variant", "btnSize", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass", "inlineStyles", "tooltip", "tooltipPosition"], outputs: ["clicked"] }], directives: [{ type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
|
|
25864
26333
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StepBuilderActionComponent, decorators: [{
|
|
25865
26334
|
type: Component,
|
|
25866
|
-
args: [{ selector: 'cqa-step-builder-action', host: { class: 'cqa-ui-root' }, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white\" [ngClass]=\"{'cqa-px-4 cqa-py-2': showHeader}\">\n <!-- Header -->\n <h2 *ngIf=\"showHeader\" class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-1\">\n Create an action step\n </h2>\n <div *ngIf=\"!selectedTemplate\" class=\"cqa-flex cqa-flex-col cqa-h-full cqa-flex-1\"\n [ngClass]=\"{'cqa-px-3': showHeader}\">\n\n <!-- Search Bar -->\n <div class=\"cqa-pb-1\">\n <div class=\"cqa-pb-1\" *ngIf=\"showHeader\">\n <p class=\"cqa-text-[12px] cqa-text-gray-500\">\n Template library\n </p>\n </div>\n <cqa-search-bar [placeholder]=\"searchPlaceholder\" [fullWidth]=\"true\" [value]=\"searchValue\"\n (valueChange)=\"onSearchChange($event)\" (search)=\"onSearchSubmit($event)\" (cleared)=\"onSearchCleared()\">\n </cqa-search-bar>\n </div>\n\n <!-- Template List -->\n <div class=\"cqa-flex-1 cqa-overflow-y-auto cqa-px-2\">\n <div class=\"cqa-py-2\">\n <div *ngFor=\"let template of filteredTemplates; trackBy: trackByTemplate\"\n class=\"cqa-action-format cqa-bg-white cqa-cursor-pointer cqa-transition-all hover:cqa-border-blue-500 hover:cqa-shadow-sm mb-6\"\n (click)=\"selectTemplate(template)\">\n <div class=\"cqa-text-[12px] cqa-leading-[23px] cqa-text-black-100\"\n [innerHTML]=\"template.htmlGrammar || template.naturalText || ''\">\n </div>\n </div>\n\n <div *ngIf=\"filteredTemplates.length === 0\" class=\"cqa-text-center cqa-py-8 cqa-text-gray-400 cqa-text-[12px]\">\n No templates found\n </div>\n </div>\n </div>\n </div>\n\n <div *ngIf=\"selectedTemplate\" class=\"cqa-flex cqa-flex-col cqa-
|
|
26335
|
+
args: [{ selector: 'cqa-step-builder-action', host: { class: 'cqa-ui-root', style: 'display: block;height: 100%;width: 100%;' }, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white\" [ngClass]=\"{'cqa-px-4': showHeader, 'cqa-py-2': showHeader && !selectedTemplate}\">\n <!-- Header -->\n <h2 *ngIf=\"showHeader\" class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-1\">\n Create an action step\n </h2>\n <div *ngIf=\"!selectedTemplate\" class=\"cqa-flex cqa-flex-col cqa-h-full cqa-flex-1\"\n [ngClass]=\"{'cqa-px-3': showHeader}\">\n\n <!-- Search Bar -->\n <div class=\"cqa-pb-1\">\n <div class=\"cqa-pb-1\" *ngIf=\"showHeader\">\n <p class=\"cqa-text-[12px] cqa-text-gray-500\">\n Template library\n </p>\n </div>\n <cqa-search-bar [placeholder]=\"searchPlaceholder\" [fullWidth]=\"true\" [value]=\"searchValue\"\n (valueChange)=\"onSearchChange($event)\" (search)=\"onSearchSubmit($event)\" (cleared)=\"onSearchCleared()\">\n </cqa-search-bar>\n </div>\n\n <!-- Template List -->\n <div class=\"cqa-flex-1 cqa-overflow-y-auto cqa-px-2\">\n <div class=\"cqa-py-2\">\n <div *ngFor=\"let template of filteredTemplates; trackBy: trackByTemplate\"\n class=\"cqa-action-format cqa-bg-white cqa-cursor-pointer cqa-transition-all hover:cqa-border-blue-500 hover:cqa-shadow-sm mb-6\"\n (click)=\"selectTemplate(template)\">\n <div class=\"cqa-text-[12px] cqa-leading-[23px] cqa-text-black-100\"\n [innerHTML]=\"template.htmlGrammar || template.naturalText || ''\">\n </div>\n </div>\n\n <div *ngIf=\"filteredTemplates.length === 0\" class=\"cqa-text-center cqa-py-8 cqa-text-gray-400 cqa-text-[12px]\">\n No templates found\n </div>\n </div>\n </div>\n </div>\n\n <div *ngIf=\"selectedTemplate\" class=\"cqa-flex cqa-flex-col cqa-overflow-y-auto\" style=\"flex: 1 1 0 !important;\">\n <!-- Instruction Text with Element Buttons -->\n <div class=\"cqa-mb-4 cqa-flex cqa-items-center cqa-flex-wrap cqa-gap-1 cqa-text-sm cqa-text-gray-700\">\n <div class=\"cqa-action-format cqa-text-[12px] cqa-leading-[23px] cqa-text-black-100\"\n [innerHTML]=\"updatedHtmlGrammar || selectedTemplate.htmlGrammar || selectedTemplate.naturalText || ''\">\n </div>\n </div>\n\n <!-- Form Fields in Two Columns -->\n <div class=\"cqa-flex cqa-overflow-y-auto cqa-flex-1 cqa-pb-2\">\n <div class=\"cqa-flex-1 cqa-flex cqa-flex-col cqa-gap-1\">\n <div class=\"cqa-flex cqa-gap-x-6 cqa-flex-wrap cqa-pb-4\">\n <!-- Template Variables Form Component -->\n <cqa-template-variables-form\n style=\"width: 100%;\"\n [templateVariables]=\"templateVariables\"\n [variablesForm]=\"variablesForm\"\n [metadata]=\"metadata\"\n [description]=\"description\"\n [elementOptions]=\"elementOptions\"\n [hasMoreElements]=\"hasMoreElements\"\n [isLoadingElements]=\"isLoadingElements\"\n [screenNameOptions]=\"screenNameOptions\"\n [hasMoreScreenNames]=\"hasMoreScreenNames\"\n [isLoadingScreenNames]=\"isLoadingScreenNames\"\n (variableValueChange)=\"onVariableValueChange($event.name, $event.value)\"\n (variableBooleanChange)=\"onVariableBooleanChange($event.name, $event.value)\"\n (metadataChange)=\"metadata = $event\"\n (descriptionChange)=\"description = $event\"\n (loadMoreElements)=\"loadMoreElements.emit()\"\n (searchElements)=\"searchElements.emit($event)\"\n (createElement)=\"createElement.emit($event)\"\n (searchScreenName)=\"searchScreenName.emit($event)\"\n (loadMoreScreenNames)=\"loadMoreScreenNames.emit($event)\"\n (createScreenNameRequest)=\"createScreenNameRequest.emit($event)\"\n (elementFormVisibilityChange)=\"onElementFormVisibilityChange($event)\">\n </cqa-template-variables-form>\n </div>\n\n <!-- Advanced (Expandable) -->\n <!-- <div class=\"cqa-flex cqa-flex-col cqa-w-full\">\n <button type=\"button\"\n class=\"cqa-flex cqa-w-full cqa-items-center cqa-justify-between cqa-gap-2 cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-bg-transparent cqa-border-none cqa-cursor-pointer cqa-p-0 cqa-mb-1.5\"\n (click)=\"toggleAdvanced()\">\n <span class=\"cqa-text-[10px]\">Advanced</span>\n <mat-icon class=\"cqa-text-base\" [class.cqa-rotate-180]=\"advancedExpanded\">\n expand_more\n </mat-icon>\n </button>\n <div *ngIf=\"advancedExpanded\" class=\"cqa-mt-2\">\n </div>\n </div> -->\n <div>\n \n </div>\n </div>\n\n\n </div>\n\n <!-- Action Buttons -->\n <div *ngIf=\"!isElementFormVisible\" class=\"cqa-flex cqa-w-full cqa-gap-2 cqa-border-t cqa-border-gray-200 cqa-pb-2\">\n <cqa-button class=\"cqa-w-1/2\" variant=\"outlined\" text=\"Cancel\" [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onCancel()\">\n </cqa-button>\n <cqa-button class=\"cqa-w-1/2\" variant=\"filled\" text=\"Create Step\" [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n [disabled]=\"!isFormValid()\"\n (clicked)=\"onCreateStep()\">\n </cqa-button>\n </div>\n </div>\n</div>", styles: [] }]
|
|
25867
26336
|
}], ctorParameters: function () { return [{ type: i1$1.FormBuilder }]; }, propDecorators: { showHeader: [{
|
|
25868
26337
|
type: Input
|
|
25869
26338
|
}], templates: [{
|
|
@@ -25874,8 +26343,32 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
|
|
|
25874
26343
|
type: Input
|
|
25875
26344
|
}], preventSelectTemplate: [{
|
|
25876
26345
|
type: Input
|
|
26346
|
+
}], elementOptions: [{
|
|
26347
|
+
type: Input
|
|
26348
|
+
}], hasMoreElements: [{
|
|
26349
|
+
type: Input
|
|
26350
|
+
}], isLoadingElements: [{
|
|
26351
|
+
type: Input
|
|
26352
|
+
}], screenNameOptions: [{
|
|
26353
|
+
type: Input
|
|
26354
|
+
}], hasMoreScreenNames: [{
|
|
26355
|
+
type: Input
|
|
26356
|
+
}], isLoadingScreenNames: [{
|
|
26357
|
+
type: Input
|
|
25877
26358
|
}], templateChanged: [{
|
|
25878
26359
|
type: Output
|
|
26360
|
+
}], loadMoreElements: [{
|
|
26361
|
+
type: Output
|
|
26362
|
+
}], searchElements: [{
|
|
26363
|
+
type: Output
|
|
26364
|
+
}], createElement: [{
|
|
26365
|
+
type: Output
|
|
26366
|
+
}], searchScreenName: [{
|
|
26367
|
+
type: Output
|
|
26368
|
+
}], loadMoreScreenNames: [{
|
|
26369
|
+
type: Output
|
|
26370
|
+
}], createScreenNameRequest: [{
|
|
26371
|
+
type: Output
|
|
25879
26372
|
}], createStep: [{
|
|
25880
26373
|
type: Output
|
|
25881
26374
|
}], cancelled: [{
|
|
@@ -25912,6 +26405,21 @@ class StepBuilderLoopComponent {
|
|
|
25912
26405
|
this.whileTemplates = [];
|
|
25913
26406
|
this.whileSearchPlaceholder = 'Search While';
|
|
25914
26407
|
this.whileSearchValue = '';
|
|
26408
|
+
// Element fetching properties
|
|
26409
|
+
this.elementOptions = [];
|
|
26410
|
+
this.hasMoreElements = false;
|
|
26411
|
+
this.isLoadingElements = false;
|
|
26412
|
+
// Screen name fetching properties
|
|
26413
|
+
this.screenNameOptions = [];
|
|
26414
|
+
this.hasMoreScreenNames = false;
|
|
26415
|
+
this.isLoadingScreenNames = false;
|
|
26416
|
+
this.loadMoreElements = new EventEmitter();
|
|
26417
|
+
this.searchElements = new EventEmitter();
|
|
26418
|
+
this.createElement = new EventEmitter();
|
|
26419
|
+
this.searchScreenName = new EventEmitter();
|
|
26420
|
+
this.loadMoreScreenNames = new EventEmitter();
|
|
26421
|
+
this.createScreenNameRequest = new EventEmitter();
|
|
26422
|
+
this.cancelElementForm = new EventEmitter();
|
|
25915
26423
|
this.selectedWhileTemplate = null;
|
|
25916
26424
|
this.selectedLoopType = 'for';
|
|
25917
26425
|
// Internal state for managing loop indices
|
|
@@ -26255,10 +26763,10 @@ class StepBuilderLoopComponent {
|
|
|
26255
26763
|
}
|
|
26256
26764
|
}
|
|
26257
26765
|
StepBuilderLoopComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StepBuilderLoopComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
26258
|
-
StepBuilderLoopComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: StepBuilderLoopComponent, selector: "cqa-step-builder-loop", inputs: { loopType: "loopType", selectOptions: "selectOptions", dataProfileOptions: "dataProfileOptions", hasMoreDataProfiles: "hasMoreDataProfiles", isLoadingDataProfiles: "isLoadingDataProfiles", setWhileTemplateVariables: "setWhileTemplateVariables", whileTemplates: "whileTemplates", whileSearchPlaceholder: "whileSearchPlaceholder", whileSearchValue: "whileSearchValue" }, outputs: { createStep: "createStep", cancelled: "cancelled", loopTypeChange: "loopTypeChange", loadMoreDataProfiles: "loadMoreDataProfiles", searchDataProfiles: "searchDataProfiles" }, host: { classAttribute: "cqa-ui-root" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white cqa-px-4 cqa-py-2\">\n <!-- Header -->\n <h2 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n Create Loop Test Step\n </h2>\n\n <!-- Loop Type Selection -->\n <div class=\"cqa-mb-4 cqa-w-full\">\n <div class=\"cqa-w-full cqa-inline-flex cqa-items-center cqa-bg-gray-100 cqa-rounded-lg cqa-p-1 cqa-gap-0\" style=\"height: 30px; background-color: #F3F4F6;\">\n <!-- For Button -->\n <button\n type=\"button\"\n class=\"cqa-w-1/2 cqa-text-[12px] cqa-rounded-md cqa-font-medium cqa-transition-all cqa-duration-200 cqa-ease-in-out cqa-min-w-[80px] cqa-text-center cqa-cursor-pointer\"\n [style.background-color]=\"selectedLoopType === 'for' ? '#3F43EE' : 'transparent'\"\n [style.color]=\"selectedLoopType === 'for' ? '#FFFFFF' : '#6B7280'\"\n [style.border-radius]=\"'8px'\"\n [style.height]=\"'22px'\"\n (click)=\"onLoopTypeChange('for')\">\n For\n </button>\n <!-- While Button -->\n <button\n type=\"button\"\n class=\"cqa-w-1/2 cqa-text-[12px] cqa-rounded-md cqa-font-medium cqa-transition-all cqa-duration-200 cqa-ease-in-out cqa-min-w-[80px] cqa-text-center cqa-cursor-pointer\"\n [style.background-color]=\"selectedLoopType === 'while' ? '#3F43EE' : 'transparent'\"\n [style.color]=\"selectedLoopType === 'while' ? '#FFFFFF' : '#6B7280'\"\n [style.border-radius]=\"'8px'\"\n [style.height]=\"'22px'\"\n (click)=\"onLoopTypeChange('while')\">\n While\n </button>\n </div>\n </div>\n\n <!-- Form Fields -->\n <ng-container *ngIf=\"selectedLoopType === 'for'\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-4 cqa-flex-1 cqa-overflow-y-auto\">\n <!-- Dropdown Fields Row -->\n <div class=\"cqa-flex cqa-gap-4 cqa-flex-wrap\">\n <!-- Select Option -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1\" style=\"min-width: calc(25% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5\">\n Select Option\n </label>\n <cqa-dynamic-select\n [form]=\"loopForm\"\n [config]=\"selectOptionConfig\">\n </cqa-dynamic-select>\n </div>\n\n <ng-container *ngIf=\"loopForm.get('selectOption')?.value === 'dataProfile'\">\n <!-- Data Profile -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1\" style=\"min-width: calc(25% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5\">\n Data Profile\n </label>\n <cqa-dynamic-select\n [form]=\"loopForm\"\n [config]=\"dataProfileConfig\"\n (searchChange)=\"onSearchDataProfiles($event.query)\"\n (loadMore)=\"onLoadMoreDataProfiles($event)\">\n </cqa-dynamic-select>\n </div>\n\n <!-- Loop Start -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1\" style=\"min-width: calc(25% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5\">\n Loop Start\n </label>\n <cqa-dynamic-select\n [form]=\"loopForm\"\n [config]=\"loopStartConfig\">\n </cqa-dynamic-select>\n </div>\n\n <!-- Loop End -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1\" style=\"min-width: calc(25% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5\">\n Loop End\n </label>\n <cqa-dynamic-select\n [form]=\"loopForm\"\n [config]=\"loopEndConfig\">\n </cqa-dynamic-select>\n </div>\n </ng-container>\n <ng-container *ngIf=\"loopForm.get('selectOption')?.value === 'runTime'\">\n <!-- Run Time Input Field -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1\" style=\"min-width: calc(25% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5\">\n Run Time\n </label>\n <cqa-custom-input\n [placeholder]=\"'Enter Run Time'\"\n [value]=\"loopForm.get('runTime')?.value\"\n [fullWidth]=\"true\"\n (valueChange)=\"loopForm.get('runTime')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n </ng-container>\n </div>\n </div>\n</ng-container>\n <ng-container *ngIf=\"selectedLoopType === 'while'\">\n <cqa-step-builder-action [showHeader]=\"false\" [templates]=\"whileTemplates\" [setTemplateVariables]=\"setWhileTemplateVariables\" [searchPlaceholder]=\"whileSearchPlaceholder\"
|
|
26766
|
+
StepBuilderLoopComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: StepBuilderLoopComponent, selector: "cqa-step-builder-loop", inputs: { loopType: "loopType", selectOptions: "selectOptions", dataProfileOptions: "dataProfileOptions", hasMoreDataProfiles: "hasMoreDataProfiles", isLoadingDataProfiles: "isLoadingDataProfiles", setWhileTemplateVariables: "setWhileTemplateVariables", whileTemplates: "whileTemplates", whileSearchPlaceholder: "whileSearchPlaceholder", whileSearchValue: "whileSearchValue", elementOptions: "elementOptions", hasMoreElements: "hasMoreElements", isLoadingElements: "isLoadingElements", screenNameOptions: "screenNameOptions", hasMoreScreenNames: "hasMoreScreenNames", isLoadingScreenNames: "isLoadingScreenNames" }, outputs: { createStep: "createStep", cancelled: "cancelled", loopTypeChange: "loopTypeChange", loadMoreDataProfiles: "loadMoreDataProfiles", searchDataProfiles: "searchDataProfiles", loadMoreElements: "loadMoreElements", searchElements: "searchElements", createElement: "createElement", searchScreenName: "searchScreenName", loadMoreScreenNames: "loadMoreScreenNames", createScreenNameRequest: "createScreenNameRequest", cancelElementForm: "cancelElementForm" }, host: { classAttribute: "cqa-ui-root" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white cqa-px-4 cqa-py-2\">\n <!-- Header -->\n <h2 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n Create Loop Test Step\n </h2>\n\n <!-- Loop Type Selection -->\n <div class=\"cqa-mb-4 cqa-w-full\">\n <div class=\"cqa-w-full cqa-inline-flex cqa-items-center cqa-bg-gray-100 cqa-rounded-lg cqa-p-1 cqa-gap-0\" style=\"height: 30px; background-color: #F3F4F6;\">\n <!-- For Button -->\n <button\n type=\"button\"\n class=\"cqa-w-1/2 cqa-text-[12px] cqa-rounded-md cqa-font-medium cqa-transition-all cqa-duration-200 cqa-ease-in-out cqa-min-w-[80px] cqa-text-center cqa-cursor-pointer\"\n [style.background-color]=\"selectedLoopType === 'for' ? '#3F43EE' : 'transparent'\"\n [style.color]=\"selectedLoopType === 'for' ? '#FFFFFF' : '#6B7280'\"\n [style.border-radius]=\"'8px'\"\n [style.height]=\"'22px'\"\n (click)=\"onLoopTypeChange('for')\">\n For\n </button>\n <!-- While Button -->\n <button\n type=\"button\"\n class=\"cqa-w-1/2 cqa-text-[12px] cqa-rounded-md cqa-font-medium cqa-transition-all cqa-duration-200 cqa-ease-in-out cqa-min-w-[80px] cqa-text-center cqa-cursor-pointer\"\n [style.background-color]=\"selectedLoopType === 'while' ? '#3F43EE' : 'transparent'\"\n [style.color]=\"selectedLoopType === 'while' ? '#FFFFFF' : '#6B7280'\"\n [style.border-radius]=\"'8px'\"\n [style.height]=\"'22px'\"\n (click)=\"onLoopTypeChange('while')\">\n While\n </button>\n </div>\n </div>\n\n <!-- Form Fields -->\n <ng-container *ngIf=\"selectedLoopType === 'for'\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-4 cqa-flex-1 cqa-overflow-y-auto\">\n <!-- Dropdown Fields Row -->\n <div class=\"cqa-flex cqa-gap-4 cqa-flex-wrap\">\n <!-- Select Option -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1\" style=\"min-width: calc(25% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5\">\n Select Option\n </label>\n <cqa-dynamic-select\n [form]=\"loopForm\"\n [config]=\"selectOptionConfig\">\n </cqa-dynamic-select>\n </div>\n\n <ng-container *ngIf=\"loopForm.get('selectOption')?.value === 'dataProfile'\">\n <!-- Data Profile -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1\" style=\"min-width: calc(25% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5\">\n Data Profile\n </label>\n <cqa-dynamic-select\n [form]=\"loopForm\"\n [config]=\"dataProfileConfig\"\n (searchChange)=\"onSearchDataProfiles($event.query)\"\n (loadMore)=\"onLoadMoreDataProfiles($event)\">\n </cqa-dynamic-select>\n </div>\n\n <!-- Loop Start -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1\" style=\"min-width: calc(25% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5\">\n Loop Start\n </label>\n <cqa-dynamic-select\n [form]=\"loopForm\"\n [config]=\"loopStartConfig\">\n </cqa-dynamic-select>\n </div>\n\n <!-- Loop End -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1\" style=\"min-width: calc(25% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5\">\n Loop End\n </label>\n <cqa-dynamic-select\n [form]=\"loopForm\"\n [config]=\"loopEndConfig\">\n </cqa-dynamic-select>\n </div>\n </ng-container>\n <ng-container *ngIf=\"loopForm.get('selectOption')?.value === 'runTime'\">\n <!-- Run Time Input Field -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1\" style=\"min-width: calc(25% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5\">\n Run Time\n </label>\n <cqa-custom-input\n [placeholder]=\"'Enter Run Time'\"\n [value]=\"loopForm.get('runTime')?.value\"\n [fullWidth]=\"true\"\n (valueChange)=\"loopForm.get('runTime')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n </ng-container>\n </div>\n </div>\n</ng-container>\n <ng-container *ngIf=\"selectedLoopType === 'while'\">\n <cqa-step-builder-action \n [showHeader]=\"false\" \n [templates]=\"whileTemplates\" \n [setTemplateVariables]=\"setWhileTemplateVariables\" \n [searchPlaceholder]=\"whileSearchPlaceholder\"\n [elementOptions]=\"elementOptions\"\n [hasMoreElements]=\"hasMoreElements\"\n [isLoadingElements]=\"isLoadingElements\"\n [screenNameOptions]=\"screenNameOptions\"\n [hasMoreScreenNames]=\"hasMoreScreenNames\"\n [isLoadingScreenNames]=\"isLoadingScreenNames\"\n (templateChanged)=\"selectWhileTemplate($event)\" \n (createStep)=\"createWhileStep($event)\"\n (loadMoreElements)=\"loadMoreElements.emit()\"\n (searchElements)=\"searchElements.emit($event)\"\n (createElement)=\"createElement.emit($event)\"\n (searchScreenName)=\"searchScreenName.emit($event)\"\n (loadMoreScreenNames)=\"loadMoreScreenNames.emit($event)\"\n (createScreenNameRequest)=\"createScreenNameRequest.emit($event)\"\n (cancelElementForm)=\"cancelElementForm.emit()\">\n </cqa-step-builder-action>\n </ng-container>\n\n <!-- Action Buttons -->\n <div *ngIf=\"selectedLoopType === 'for'\" class=\"cqa-flex cqa-w-full cqa-gap-2 cqa-mt-6 cqa-pt-4 cqa-border-t cqa-border-gray-200\">\n <cqa-button\n class=\"cqa-w-1/2\"\n variant=\"outlined\"\n text=\"Cancel\"\n [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onCancel()\">\n </cqa-button>\n <cqa-button\n class=\"cqa-w-1/2\"\n variant=\"filled\"\n text=\"Create Step\"\n [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n [disabled]=\"!isFormValid()\"\n (clicked)=\"onCreateStep()\">\n </cqa-button>\n </div>\n</div>\n\n", components: [{ type: DynamicSelectFieldComponent, selector: "cqa-dynamic-select", inputs: ["form", "config"], outputs: ["selectionChange", "selectClick", "searchChange", "loadMore", "addCustomValue"] }, { 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: StepBuilderActionComponent, selector: "cqa-step-builder-action", inputs: ["showHeader", "templates", "searchPlaceholder", "setTemplateVariables", "preventSelectTemplate", "elementOptions", "hasMoreElements", "isLoadingElements", "screenNameOptions", "hasMoreScreenNames", "isLoadingScreenNames"], outputs: ["templateChanged", "loadMoreElements", "searchElements", "createElement", "searchScreenName", "loadMoreScreenNames", "createScreenNameRequest", "createStep", "cancelled"] }, { 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"] }] });
|
|
26259
26767
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StepBuilderLoopComponent, decorators: [{
|
|
26260
26768
|
type: Component,
|
|
26261
|
-
args: [{ selector: 'cqa-step-builder-loop', host: { class: 'cqa-ui-root' }, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white cqa-px-4 cqa-py-2\">\n <!-- Header -->\n <h2 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n Create Loop Test Step\n </h2>\n\n <!-- Loop Type Selection -->\n <div class=\"cqa-mb-4 cqa-w-full\">\n <div class=\"cqa-w-full cqa-inline-flex cqa-items-center cqa-bg-gray-100 cqa-rounded-lg cqa-p-1 cqa-gap-0\" style=\"height: 30px; background-color: #F3F4F6;\">\n <!-- For Button -->\n <button\n type=\"button\"\n class=\"cqa-w-1/2 cqa-text-[12px] cqa-rounded-md cqa-font-medium cqa-transition-all cqa-duration-200 cqa-ease-in-out cqa-min-w-[80px] cqa-text-center cqa-cursor-pointer\"\n [style.background-color]=\"selectedLoopType === 'for' ? '#3F43EE' : 'transparent'\"\n [style.color]=\"selectedLoopType === 'for' ? '#FFFFFF' : '#6B7280'\"\n [style.border-radius]=\"'8px'\"\n [style.height]=\"'22px'\"\n (click)=\"onLoopTypeChange('for')\">\n For\n </button>\n <!-- While Button -->\n <button\n type=\"button\"\n class=\"cqa-w-1/2 cqa-text-[12px] cqa-rounded-md cqa-font-medium cqa-transition-all cqa-duration-200 cqa-ease-in-out cqa-min-w-[80px] cqa-text-center cqa-cursor-pointer\"\n [style.background-color]=\"selectedLoopType === 'while' ? '#3F43EE' : 'transparent'\"\n [style.color]=\"selectedLoopType === 'while' ? '#FFFFFF' : '#6B7280'\"\n [style.border-radius]=\"'8px'\"\n [style.height]=\"'22px'\"\n (click)=\"onLoopTypeChange('while')\">\n While\n </button>\n </div>\n </div>\n\n <!-- Form Fields -->\n <ng-container *ngIf=\"selectedLoopType === 'for'\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-4 cqa-flex-1 cqa-overflow-y-auto\">\n <!-- Dropdown Fields Row -->\n <div class=\"cqa-flex cqa-gap-4 cqa-flex-wrap\">\n <!-- Select Option -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1\" style=\"min-width: calc(25% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5\">\n Select Option\n </label>\n <cqa-dynamic-select\n [form]=\"loopForm\"\n [config]=\"selectOptionConfig\">\n </cqa-dynamic-select>\n </div>\n\n <ng-container *ngIf=\"loopForm.get('selectOption')?.value === 'dataProfile'\">\n <!-- Data Profile -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1\" style=\"min-width: calc(25% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5\">\n Data Profile\n </label>\n <cqa-dynamic-select\n [form]=\"loopForm\"\n [config]=\"dataProfileConfig\"\n (searchChange)=\"onSearchDataProfiles($event.query)\"\n (loadMore)=\"onLoadMoreDataProfiles($event)\">\n </cqa-dynamic-select>\n </div>\n\n <!-- Loop Start -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1\" style=\"min-width: calc(25% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5\">\n Loop Start\n </label>\n <cqa-dynamic-select\n [form]=\"loopForm\"\n [config]=\"loopStartConfig\">\n </cqa-dynamic-select>\n </div>\n\n <!-- Loop End -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1\" style=\"min-width: calc(25% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5\">\n Loop End\n </label>\n <cqa-dynamic-select\n [form]=\"loopForm\"\n [config]=\"loopEndConfig\">\n </cqa-dynamic-select>\n </div>\n </ng-container>\n <ng-container *ngIf=\"loopForm.get('selectOption')?.value === 'runTime'\">\n <!-- Run Time Input Field -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1\" style=\"min-width: calc(25% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5\">\n Run Time\n </label>\n <cqa-custom-input\n [placeholder]=\"'Enter Run Time'\"\n [value]=\"loopForm.get('runTime')?.value\"\n [fullWidth]=\"true\"\n (valueChange)=\"loopForm.get('runTime')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n </ng-container>\n </div>\n </div>\n</ng-container>\n <ng-container *ngIf=\"selectedLoopType === 'while'\">\n <cqa-step-builder-action [showHeader]=\"false\" [templates]=\"whileTemplates\" [setTemplateVariables]=\"setWhileTemplateVariables\" [searchPlaceholder]=\"whileSearchPlaceholder\"
|
|
26769
|
+
args: [{ selector: 'cqa-step-builder-loop', host: { class: 'cqa-ui-root' }, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white cqa-px-4 cqa-py-2\">\n <!-- Header -->\n <h2 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n Create Loop Test Step\n </h2>\n\n <!-- Loop Type Selection -->\n <div class=\"cqa-mb-4 cqa-w-full\">\n <div class=\"cqa-w-full cqa-inline-flex cqa-items-center cqa-bg-gray-100 cqa-rounded-lg cqa-p-1 cqa-gap-0\" style=\"height: 30px; background-color: #F3F4F6;\">\n <!-- For Button -->\n <button\n type=\"button\"\n class=\"cqa-w-1/2 cqa-text-[12px] cqa-rounded-md cqa-font-medium cqa-transition-all cqa-duration-200 cqa-ease-in-out cqa-min-w-[80px] cqa-text-center cqa-cursor-pointer\"\n [style.background-color]=\"selectedLoopType === 'for' ? '#3F43EE' : 'transparent'\"\n [style.color]=\"selectedLoopType === 'for' ? '#FFFFFF' : '#6B7280'\"\n [style.border-radius]=\"'8px'\"\n [style.height]=\"'22px'\"\n (click)=\"onLoopTypeChange('for')\">\n For\n </button>\n <!-- While Button -->\n <button\n type=\"button\"\n class=\"cqa-w-1/2 cqa-text-[12px] cqa-rounded-md cqa-font-medium cqa-transition-all cqa-duration-200 cqa-ease-in-out cqa-min-w-[80px] cqa-text-center cqa-cursor-pointer\"\n [style.background-color]=\"selectedLoopType === 'while' ? '#3F43EE' : 'transparent'\"\n [style.color]=\"selectedLoopType === 'while' ? '#FFFFFF' : '#6B7280'\"\n [style.border-radius]=\"'8px'\"\n [style.height]=\"'22px'\"\n (click)=\"onLoopTypeChange('while')\">\n While\n </button>\n </div>\n </div>\n\n <!-- Form Fields -->\n <ng-container *ngIf=\"selectedLoopType === 'for'\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-4 cqa-flex-1 cqa-overflow-y-auto\">\n <!-- Dropdown Fields Row -->\n <div class=\"cqa-flex cqa-gap-4 cqa-flex-wrap\">\n <!-- Select Option -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1\" style=\"min-width: calc(25% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5\">\n Select Option\n </label>\n <cqa-dynamic-select\n [form]=\"loopForm\"\n [config]=\"selectOptionConfig\">\n </cqa-dynamic-select>\n </div>\n\n <ng-container *ngIf=\"loopForm.get('selectOption')?.value === 'dataProfile'\">\n <!-- Data Profile -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1\" style=\"min-width: calc(25% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5\">\n Data Profile\n </label>\n <cqa-dynamic-select\n [form]=\"loopForm\"\n [config]=\"dataProfileConfig\"\n (searchChange)=\"onSearchDataProfiles($event.query)\"\n (loadMore)=\"onLoadMoreDataProfiles($event)\">\n </cqa-dynamic-select>\n </div>\n\n <!-- Loop Start -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1\" style=\"min-width: calc(25% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5\">\n Loop Start\n </label>\n <cqa-dynamic-select\n [form]=\"loopForm\"\n [config]=\"loopStartConfig\">\n </cqa-dynamic-select>\n </div>\n\n <!-- Loop End -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1\" style=\"min-width: calc(25% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5\">\n Loop End\n </label>\n <cqa-dynamic-select\n [form]=\"loopForm\"\n [config]=\"loopEndConfig\">\n </cqa-dynamic-select>\n </div>\n </ng-container>\n <ng-container *ngIf=\"loopForm.get('selectOption')?.value === 'runTime'\">\n <!-- Run Time Input Field -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1\" style=\"min-width: calc(25% - 12px);\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5\">\n Run Time\n </label>\n <cqa-custom-input\n [placeholder]=\"'Enter Run Time'\"\n [value]=\"loopForm.get('runTime')?.value\"\n [fullWidth]=\"true\"\n (valueChange)=\"loopForm.get('runTime')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n </ng-container>\n </div>\n </div>\n</ng-container>\n <ng-container *ngIf=\"selectedLoopType === 'while'\">\n <cqa-step-builder-action \n [showHeader]=\"false\" \n [templates]=\"whileTemplates\" \n [setTemplateVariables]=\"setWhileTemplateVariables\" \n [searchPlaceholder]=\"whileSearchPlaceholder\"\n [elementOptions]=\"elementOptions\"\n [hasMoreElements]=\"hasMoreElements\"\n [isLoadingElements]=\"isLoadingElements\"\n [screenNameOptions]=\"screenNameOptions\"\n [hasMoreScreenNames]=\"hasMoreScreenNames\"\n [isLoadingScreenNames]=\"isLoadingScreenNames\"\n (templateChanged)=\"selectWhileTemplate($event)\" \n (createStep)=\"createWhileStep($event)\"\n (loadMoreElements)=\"loadMoreElements.emit()\"\n (searchElements)=\"searchElements.emit($event)\"\n (createElement)=\"createElement.emit($event)\"\n (searchScreenName)=\"searchScreenName.emit($event)\"\n (loadMoreScreenNames)=\"loadMoreScreenNames.emit($event)\"\n (createScreenNameRequest)=\"createScreenNameRequest.emit($event)\"\n (cancelElementForm)=\"cancelElementForm.emit()\">\n </cqa-step-builder-action>\n </ng-container>\n\n <!-- Action Buttons -->\n <div *ngIf=\"selectedLoopType === 'for'\" class=\"cqa-flex cqa-w-full cqa-gap-2 cqa-mt-6 cqa-pt-4 cqa-border-t cqa-border-gray-200\">\n <cqa-button\n class=\"cqa-w-1/2\"\n variant=\"outlined\"\n text=\"Cancel\"\n [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onCancel()\">\n </cqa-button>\n <cqa-button\n class=\"cqa-w-1/2\"\n variant=\"filled\"\n text=\"Create Step\"\n [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n [disabled]=\"!isFormValid()\"\n (clicked)=\"onCreateStep()\">\n </cqa-button>\n </div>\n</div>\n\n", styles: [] }]
|
|
26262
26770
|
}], ctorParameters: function () { return []; }, propDecorators: { loopType: [{
|
|
26263
26771
|
type: Input
|
|
26264
26772
|
}], selectOptions: [{
|
|
@@ -26287,6 +26795,32 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
|
|
|
26287
26795
|
type: Input
|
|
26288
26796
|
}], whileSearchValue: [{
|
|
26289
26797
|
type: Input
|
|
26798
|
+
}], elementOptions: [{
|
|
26799
|
+
type: Input
|
|
26800
|
+
}], hasMoreElements: [{
|
|
26801
|
+
type: Input
|
|
26802
|
+
}], isLoadingElements: [{
|
|
26803
|
+
type: Input
|
|
26804
|
+
}], screenNameOptions: [{
|
|
26805
|
+
type: Input
|
|
26806
|
+
}], hasMoreScreenNames: [{
|
|
26807
|
+
type: Input
|
|
26808
|
+
}], isLoadingScreenNames: [{
|
|
26809
|
+
type: Input
|
|
26810
|
+
}], loadMoreElements: [{
|
|
26811
|
+
type: Output
|
|
26812
|
+
}], searchElements: [{
|
|
26813
|
+
type: Output
|
|
26814
|
+
}], createElement: [{
|
|
26815
|
+
type: Output
|
|
26816
|
+
}], searchScreenName: [{
|
|
26817
|
+
type: Output
|
|
26818
|
+
}], loadMoreScreenNames: [{
|
|
26819
|
+
type: Output
|
|
26820
|
+
}], createScreenNameRequest: [{
|
|
26821
|
+
type: Output
|
|
26822
|
+
}], cancelElementForm: [{
|
|
26823
|
+
type: Output
|
|
26290
26824
|
}] } });
|
|
26291
26825
|
|
|
26292
26826
|
class StepBuilderConditionComponent {
|
|
@@ -26306,10 +26840,25 @@ class StepBuilderConditionComponent {
|
|
|
26306
26840
|
this.conditionTemplates = [];
|
|
26307
26841
|
/** Function to handle variable processing or custom logic. Can be passed from parent component. */
|
|
26308
26842
|
this.setConditionTemplateVariables = () => { return []; };
|
|
26843
|
+
this.elementOptions = []; // Element objects for element dropdown
|
|
26844
|
+
this.hasMoreElements = false; // Whether more elements are available
|
|
26845
|
+
this.isLoadingElements = false; // Loading state for elements
|
|
26846
|
+
/** Screen name options for element form autocomplete (from API) */
|
|
26847
|
+
this.screenNameOptions = [];
|
|
26848
|
+
/** Whether more screen names are available for infinite scroll */
|
|
26849
|
+
this.hasMoreScreenNames = false;
|
|
26850
|
+
/** True while parent is loading screen names (search or load more) */
|
|
26851
|
+
this.isLoadingScreenNames = false;
|
|
26309
26852
|
/** Emit when step is created */
|
|
26310
26853
|
this.createStep = new EventEmitter();
|
|
26311
26854
|
/** Emit when cancelled */
|
|
26312
26855
|
this.cancelled = new EventEmitter();
|
|
26856
|
+
this.loadMoreElements = new EventEmitter(); // Emit when load more is requested
|
|
26857
|
+
this.searchElements = new EventEmitter(); // Emit when user searches for elements
|
|
26858
|
+
this.createElement = new EventEmitter(); // Emit when element is created
|
|
26859
|
+
this.searchScreenName = new EventEmitter(); // Emit when user searches screen names
|
|
26860
|
+
this.loadMoreScreenNames = new EventEmitter(); // Emit when user scrolls to load more screen names
|
|
26861
|
+
this.createScreenNameRequest = new EventEmitter(); // Emit when user requests to create a new screen name
|
|
26313
26862
|
this.includeElse = false;
|
|
26314
26863
|
// Cache for value configs to avoid recreating on every change detection
|
|
26315
26864
|
this.valueConfigCache = null;
|
|
@@ -26321,6 +26870,7 @@ class StepBuilderConditionComponent {
|
|
|
26321
26870
|
this.selectedTemplates = new Map();
|
|
26322
26871
|
this.conditionTemplateVariables = new Map();
|
|
26323
26872
|
this.conditionVariablesForms = new Map();
|
|
26873
|
+
this.conditionUpdatedHtmlGrammar = new Map(); // Updated HTML grammar per condition
|
|
26324
26874
|
// Cache for condition form groups to avoid repeated lookups
|
|
26325
26875
|
this.conditionFormGroupCache = new Map();
|
|
26326
26876
|
this.conditionForm = this.fb.group({
|
|
@@ -26369,8 +26919,8 @@ class StepBuilderConditionComponent {
|
|
|
26369
26919
|
});
|
|
26370
26920
|
const index = this.conditionsFormArray.length;
|
|
26371
26921
|
this.conditionsFormArray.push(conditionGroup);
|
|
26372
|
-
// Initialize variables form for this condition
|
|
26373
|
-
this.conditionVariablesForms.set(index, this.fb.
|
|
26922
|
+
// Initialize variables form for this condition (FormArray)
|
|
26923
|
+
this.conditionVariablesForms.set(index, this.fb.array([]));
|
|
26374
26924
|
// Cache the form group
|
|
26375
26925
|
this.conditionFormGroupCache.set(index, conditionGroup);
|
|
26376
26926
|
// Mark for check since we're using OnPush
|
|
@@ -26398,6 +26948,7 @@ class StepBuilderConditionComponent {
|
|
|
26398
26948
|
const newVariablesForms = new Map();
|
|
26399
26949
|
const newFormGroupCache = new Map();
|
|
26400
26950
|
const newValueConfigs = new Map();
|
|
26951
|
+
const newUpdatedHtmlGrammar = new Map();
|
|
26401
26952
|
this.selectedTemplates.forEach((template, oldIndex) => {
|
|
26402
26953
|
if (oldIndex < removedIndex) {
|
|
26403
26954
|
newSelectedTemplates.set(oldIndex, template);
|
|
@@ -26445,11 +26996,20 @@ class StepBuilderConditionComponent {
|
|
|
26445
26996
|
newValueConfigs.set(oldIndex - 1, newConfig);
|
|
26446
26997
|
}
|
|
26447
26998
|
});
|
|
26999
|
+
this.conditionUpdatedHtmlGrammar.forEach((grammar, oldIndex) => {
|
|
27000
|
+
if (oldIndex < removedIndex) {
|
|
27001
|
+
newUpdatedHtmlGrammar.set(oldIndex, grammar);
|
|
27002
|
+
}
|
|
27003
|
+
else if (oldIndex > removedIndex) {
|
|
27004
|
+
newUpdatedHtmlGrammar.set(oldIndex - 1, grammar);
|
|
27005
|
+
}
|
|
27006
|
+
});
|
|
26448
27007
|
this.selectedTemplates = newSelectedTemplates;
|
|
26449
27008
|
this.conditionTemplateVariables = newTemplateVariables;
|
|
26450
27009
|
this.conditionVariablesForms = newVariablesForms;
|
|
26451
27010
|
this.conditionFormGroupCache = newFormGroupCache;
|
|
26452
27011
|
this.valueConfigsWithHandlers = newValueConfigs;
|
|
27012
|
+
this.conditionUpdatedHtmlGrammar = newUpdatedHtmlGrammar;
|
|
26453
27013
|
}
|
|
26454
27014
|
getOperatorConfig(index) {
|
|
26455
27015
|
// Return cached config (static, same for all conditions)
|
|
@@ -26505,54 +27065,98 @@ class StepBuilderConditionComponent {
|
|
|
26505
27065
|
this.conditionTemplateVariables.set(index, variables);
|
|
26506
27066
|
// Build form for template variables
|
|
26507
27067
|
this.buildConditionVariablesForm(index, variables);
|
|
27068
|
+
// Initialize updated HTML grammar
|
|
27069
|
+
this.updateConditionHtmlGrammar(index);
|
|
26508
27070
|
}
|
|
26509
27071
|
else {
|
|
26510
27072
|
// Clear template and variables if no template selected
|
|
26511
27073
|
this.selectedTemplates.delete(index);
|
|
26512
27074
|
this.conditionTemplateVariables.delete(index);
|
|
26513
|
-
|
|
26514
|
-
|
|
26515
|
-
|
|
26516
|
-
|
|
26517
|
-
|
|
27075
|
+
this.conditionUpdatedHtmlGrammar.delete(index);
|
|
27076
|
+
const formArray = this.conditionVariablesForms.get(index);
|
|
27077
|
+
if (formArray) {
|
|
27078
|
+
while (formArray.length !== 0) {
|
|
27079
|
+
formArray.removeAt(0);
|
|
27080
|
+
}
|
|
26518
27081
|
}
|
|
26519
27082
|
}
|
|
26520
27083
|
// Mark for check since we're using OnPush
|
|
26521
27084
|
this.cdr.markForCheck();
|
|
26522
27085
|
}
|
|
26523
27086
|
buildConditionVariablesForm(index, variables) {
|
|
26524
|
-
let
|
|
26525
|
-
if (!
|
|
26526
|
-
|
|
26527
|
-
this.conditionVariablesForms.set(index,
|
|
27087
|
+
let formArray = this.conditionVariablesForms.get(index);
|
|
27088
|
+
if (!formArray) {
|
|
27089
|
+
formArray = this.fb.array([]);
|
|
27090
|
+
this.conditionVariablesForms.set(index, formArray);
|
|
26528
27091
|
}
|
|
26529
|
-
// Ensure
|
|
26530
|
-
if (!
|
|
27092
|
+
// Ensure formArray is not undefined (TypeScript guard)
|
|
27093
|
+
if (!formArray) {
|
|
26531
27094
|
return;
|
|
26532
27095
|
}
|
|
26533
|
-
//
|
|
26534
|
-
|
|
26535
|
-
|
|
26536
|
-
|
|
26537
|
-
|
|
27096
|
+
// Store reference to avoid TypeScript issues in forEach callback
|
|
27097
|
+
// TypeScript knows formArray is defined here due to the early return above
|
|
27098
|
+
const formArrayRef = formArray;
|
|
27099
|
+
// Clear existing form array
|
|
27100
|
+
while (formArrayRef.length !== 0) {
|
|
27101
|
+
formArrayRef.removeAt(0);
|
|
27102
|
+
}
|
|
27103
|
+
// Add form groups for each variable
|
|
26538
27104
|
variables.forEach(variable => {
|
|
26539
27105
|
// Handle boolean variables - use boolean value, others use string
|
|
26540
27106
|
const defaultValue = variable.type === 'boolean'
|
|
26541
27107
|
? (variable.value === true || variable.value === 'true' || variable.value === 1)
|
|
26542
27108
|
: (variable.value || '');
|
|
26543
|
-
|
|
27109
|
+
// Create a FormGroup for each variable with name and value
|
|
27110
|
+
const variableGroup = this.fb.group({
|
|
27111
|
+
name: [variable.name],
|
|
27112
|
+
value: [defaultValue],
|
|
27113
|
+
type: [variable.type || 'string'],
|
|
27114
|
+
label: [variable.label || ''],
|
|
27115
|
+
options: [variable.options || []]
|
|
27116
|
+
});
|
|
27117
|
+
// Add dataType control for test-data variables if needed
|
|
27118
|
+
const label = variable.label?.toLowerCase() || '';
|
|
27119
|
+
if (label === 'test-data' || label === 'source-value' || label === 'target-value' ||
|
|
27120
|
+
label === 'source_value' || label === 'target_value') {
|
|
27121
|
+
// Parse the value to determine data type
|
|
27122
|
+
const valueStr = String(defaultValue || '');
|
|
27123
|
+
let dataType = 'plain-text';
|
|
27124
|
+
if (valueStr.startsWith('@|') && valueStr.endsWith('|')) {
|
|
27125
|
+
dataType = 'parameter';
|
|
27126
|
+
}
|
|
27127
|
+
else if (valueStr.startsWith('$|') && valueStr.endsWith('|')) {
|
|
27128
|
+
dataType = 'runtime';
|
|
27129
|
+
}
|
|
27130
|
+
else if (valueStr.startsWith('*|') && valueStr.endsWith('|')) {
|
|
27131
|
+
dataType = 'environment';
|
|
27132
|
+
}
|
|
27133
|
+
variableGroup.addControl('dataType', new FormControl(dataType));
|
|
27134
|
+
}
|
|
27135
|
+
formArrayRef.push(variableGroup);
|
|
26544
27136
|
});
|
|
27137
|
+
// Initialize updated HTML grammar for this condition
|
|
27138
|
+
this.updateConditionHtmlGrammar(index);
|
|
26545
27139
|
}
|
|
26546
27140
|
getConditionTemplateVariables(index) {
|
|
26547
27141
|
return this.conditionTemplateVariables.get(index) || [];
|
|
26548
27142
|
}
|
|
26549
27143
|
getConditionVariablesForm(index) {
|
|
26550
|
-
let
|
|
26551
|
-
if (!
|
|
26552
|
-
|
|
26553
|
-
this.conditionVariablesForms.set(index,
|
|
27144
|
+
let formArray = this.conditionVariablesForms.get(index);
|
|
27145
|
+
if (!formArray) {
|
|
27146
|
+
formArray = this.fb.array([]);
|
|
27147
|
+
this.conditionVariablesForms.set(index, formArray);
|
|
26554
27148
|
}
|
|
26555
|
-
return
|
|
27149
|
+
return formArray;
|
|
27150
|
+
}
|
|
27151
|
+
getConditionFormGroupAt(index, variableIndex) {
|
|
27152
|
+
const formArray = this.getConditionVariablesForm(index);
|
|
27153
|
+
return formArray.at(variableIndex);
|
|
27154
|
+
}
|
|
27155
|
+
getConditionUpdatedHtmlGrammar(index) {
|
|
27156
|
+
const template = this.selectedTemplates.get(index);
|
|
27157
|
+
if (!template)
|
|
27158
|
+
return '';
|
|
27159
|
+
return this.conditionUpdatedHtmlGrammar.get(index) || template.htmlGrammar || template.naturalText || '';
|
|
26556
27160
|
}
|
|
26557
27161
|
getSelectedTemplate(index) {
|
|
26558
27162
|
return this.selectedTemplates.get(index) || null;
|
|
@@ -26582,11 +27186,16 @@ class StepBuilderConditionComponent {
|
|
|
26582
27186
|
if (variable) {
|
|
26583
27187
|
variable.value = value;
|
|
26584
27188
|
}
|
|
26585
|
-
// Also update form
|
|
26586
|
-
const
|
|
26587
|
-
if (
|
|
26588
|
-
|
|
27189
|
+
// Also update form array
|
|
27190
|
+
const formArray = this.conditionVariablesForms.get(conditionIndex);
|
|
27191
|
+
if (formArray) {
|
|
27192
|
+
const variableIndex = formArray.controls.findIndex(control => control.get('name')?.value === variableName);
|
|
27193
|
+
if (variableIndex !== -1) {
|
|
27194
|
+
formArray.at(variableIndex).get('value')?.setValue(value, { emitEvent: false });
|
|
27195
|
+
}
|
|
26589
27196
|
}
|
|
27197
|
+
// Update HTML grammar for this condition
|
|
27198
|
+
this.updateConditionHtmlGrammar(conditionIndex);
|
|
26590
27199
|
// Mark for check since we're using OnPush
|
|
26591
27200
|
this.cdr.markForCheck();
|
|
26592
27201
|
}
|
|
@@ -26610,20 +27219,63 @@ class StepBuilderConditionComponent {
|
|
|
26610
27219
|
if (variable) {
|
|
26611
27220
|
variable.value = value;
|
|
26612
27221
|
}
|
|
26613
|
-
// Also update form
|
|
26614
|
-
const
|
|
26615
|
-
if (
|
|
26616
|
-
|
|
26617
|
-
|
|
26618
|
-
|
|
26619
|
-
|
|
26620
|
-
|
|
26621
|
-
form.addControl(variableName, new FormControl(value));
|
|
26622
|
-
}
|
|
27222
|
+
// Also update form array
|
|
27223
|
+
const formArray = this.conditionVariablesForms.get(conditionIndex);
|
|
27224
|
+
if (!formArray) {
|
|
27225
|
+
return;
|
|
27226
|
+
}
|
|
27227
|
+
const variableIndex = formArray.controls.findIndex(control => control.get('name')?.value === variableName);
|
|
27228
|
+
if (variableIndex !== -1) {
|
|
27229
|
+
formArray.at(variableIndex).get('value')?.setValue(value, { emitEvent: false });
|
|
26623
27230
|
}
|
|
27231
|
+
else {
|
|
27232
|
+
// Create new form group if it doesn't exist
|
|
27233
|
+
const variableGroup = this.fb.group({
|
|
27234
|
+
name: [variableName],
|
|
27235
|
+
value: [value],
|
|
27236
|
+
type: ['boolean'],
|
|
27237
|
+
label: [variable?.label || ''],
|
|
27238
|
+
options: [variable?.options || []]
|
|
27239
|
+
});
|
|
27240
|
+
// formArray is guaranteed to be defined here due to the early return above
|
|
27241
|
+
formArray.push(variableGroup);
|
|
27242
|
+
}
|
|
27243
|
+
// Update HTML grammar for this condition
|
|
27244
|
+
this.updateConditionHtmlGrammar(conditionIndex);
|
|
26624
27245
|
// Mark for check since we're using OnPush
|
|
26625
27246
|
this.cdr.markForCheck();
|
|
26626
27247
|
}
|
|
27248
|
+
/**
|
|
27249
|
+
* Strip HTML tags from a string for search functionality
|
|
27250
|
+
*/
|
|
27251
|
+
stripHtmlTags(htmlString) {
|
|
27252
|
+
if (!htmlString)
|
|
27253
|
+
return '';
|
|
27254
|
+
// Create a temporary div element to parse HTML
|
|
27255
|
+
const tmp = document.createElement('DIV');
|
|
27256
|
+
tmp.innerHTML = htmlString;
|
|
27257
|
+
return tmp.textContent || tmp.innerText || '';
|
|
27258
|
+
}
|
|
27259
|
+
/**
|
|
27260
|
+
* Update HTML grammar for a specific condition with actual variable values
|
|
27261
|
+
*/
|
|
27262
|
+
updateConditionHtmlGrammar(conditionIndex) {
|
|
27263
|
+
const template = this.selectedTemplates.get(conditionIndex);
|
|
27264
|
+
if (!template || !template.htmlGrammar) {
|
|
27265
|
+
return;
|
|
27266
|
+
}
|
|
27267
|
+
let updatedGrammar = template.htmlGrammar;
|
|
27268
|
+
const variables = this.conditionTemplateVariables.get(conditionIndex) || [];
|
|
27269
|
+
// Replace placeholders with actual values
|
|
27270
|
+
variables.forEach(variable => {
|
|
27271
|
+
const placeholder = new RegExp(`<span[^>]*data-event-key="${variable.name}"[^>]*>.*?</span>`, 'gi');
|
|
27272
|
+
const value = variable.value || '';
|
|
27273
|
+
// Escape HTML in value to prevent XSS
|
|
27274
|
+
const escapedValue = String(value).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
27275
|
+
updatedGrammar = updatedGrammar.replace(placeholder, escapedValue);
|
|
27276
|
+
});
|
|
27277
|
+
this.conditionUpdatedHtmlGrammar.set(conditionIndex, updatedGrammar);
|
|
27278
|
+
}
|
|
26627
27279
|
getConditionFormGroup(index) {
|
|
26628
27280
|
// Use cache to avoid repeated lookups
|
|
26629
27281
|
if (this.conditionFormGroupCache.has(index)) {
|
|
@@ -26692,20 +27344,44 @@ class StepBuilderConditionComponent {
|
|
|
26692
27344
|
}
|
|
26693
27345
|
}
|
|
26694
27346
|
StepBuilderConditionComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StepBuilderConditionComponent, deps: [{ token: i1$1.FormBuilder }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
26695
|
-
StepBuilderConditionComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: StepBuilderConditionComponent, selector: "cqa-step-builder-condition", inputs: { operatorOptions: "operatorOptions", conditionTemplates: "conditionTemplates", setConditionTemplateVariables: "setConditionTemplateVariables" }, outputs: { createStep: "createStep", cancelled: "cancelled" }, host: { classAttribute: "cqa-ui-root" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white cqa-px-4 cqa-py-2\">\n <!-- Header -->\n <h2 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n Create Condition Step\n </h2>\n\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1 cqa-overflow-y-auto\">\n <!-- Condition Builder Section -->\n <div class=\"cqa-mb-6\">\n <h3 class=\"cqa-text-sm cqa-text-[12px] cqa-font-semibold cqa-text-gray-900 cqa-mb-3\">\n Condition Builder\n </h3>\n\n <!-- Condition Rows -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-3 cqa-mb-3\">\n <ng-container *ngFor=\"let condition of conditionsFormArray.controls; let i = index; trackBy: trackByConditionIndex\">\n <div\n *ngIf=\"isConditionIf(i) || isConditionElseIf(i)\"\n class=\"cqa-flex cqa-flex-col cqa-gap-2\">\n <!-- Condition Row -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <!-- Condition Label -->\n <div class=\"cqa-text-[12px] cqa-font-semibold\">\n {{ getConditionLabel(i) }}\n </div>\n\n <!-- Operator Dropdown -->\n <!-- <div class=\"cqa-flex-1 cqa-max-w-[100px] cqa-text-[10px]\">\n <cqa-dynamic-select [form]=\"getConditionFormGroup(i)\" [config]=\"getOperatorConfig(i)\">\n </cqa-dynamic-select>\n </div> -->\n\n <!-- Value Template Dropdown -->\n <div class=\"cqa-flex-1 cqa-min-w-[150px] cqa-text-[10px]\">\n <cqa-dynamic-select [form]=\"getConditionFormGroup(i)\" [config]=\"getValueConfig(i)\">\n </cqa-dynamic-select>\n </div>\n\n <!-- Remove Button -->\n <cqa-button\n *ngIf=\"i >= 1\"\n variant=\"text\"\n icon=\"close\"\n iconPosition=\"start\"\n [customClass]=\"'cqa-w-full cqa-flex cqa-items-center cqa-justify-center'\"\n (click)=\"removeCondition(i)\"\n [attr.aria-label]=\"'Remove condition'\">\n </cqa-button>\n <!-- <button type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-8 cqa-h-8 cqa-rounded cqa-text-gray-500 hover:cqa-text-gray-700 hover:cqa-bg-gray-100 cqa-transition-colors\"\n (click)=\"removeCondition(i)\" *ngIf=\"i >= 1\"\n [attr.aria-label]=\"'Remove condition'\">\n <mat-icon class=\"cqa-text-lg cqa-text-[24px]\">close</mat-icon>\n </button> -->\n </div>\n\n <!-- Template Variables Section (shown when template is selected) -->\n <div *ngIf=\"getSelectedTemplate(i)\">\n <!-- Template Grammar Display -->\n
|
|
27347
|
+
StepBuilderConditionComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: StepBuilderConditionComponent, selector: "cqa-step-builder-condition", inputs: { operatorOptions: "operatorOptions", conditionTemplates: "conditionTemplates", setConditionTemplateVariables: "setConditionTemplateVariables", elementOptions: "elementOptions", hasMoreElements: "hasMoreElements", isLoadingElements: "isLoadingElements", screenNameOptions: "screenNameOptions", hasMoreScreenNames: "hasMoreScreenNames", isLoadingScreenNames: "isLoadingScreenNames" }, outputs: { createStep: "createStep", cancelled: "cancelled", loadMoreElements: "loadMoreElements", searchElements: "searchElements", createElement: "createElement", searchScreenName: "searchScreenName", loadMoreScreenNames: "loadMoreScreenNames", createScreenNameRequest: "createScreenNameRequest" }, host: { classAttribute: "cqa-ui-root" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white cqa-px-4 cqa-py-2\">\n <!-- Header -->\n <h2 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n Create Condition Step\n </h2>\n\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1 cqa-overflow-y-auto\">\n <!-- Condition Builder Section -->\n <div class=\"cqa-mb-6\">\n <h3 class=\"cqa-text-sm cqa-text-[12px] cqa-font-semibold cqa-text-gray-900 cqa-mb-3\">\n Condition Builder\n </h3>\n\n <!-- Condition Rows -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-3 cqa-mb-3\">\n <ng-container *ngFor=\"let condition of conditionsFormArray.controls; let i = index; trackBy: trackByConditionIndex\">\n <div\n *ngIf=\"isConditionIf(i) || isConditionElseIf(i)\"\n class=\"cqa-flex cqa-flex-col cqa-gap-2\">\n <!-- Condition Row -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <!-- Condition Label -->\n <div class=\"cqa-text-[12px] cqa-font-semibold\">\n {{ getConditionLabel(i) }}\n </div>\n\n <!-- Operator Dropdown -->\n <!-- <div class=\"cqa-flex-1 cqa-max-w-[100px] cqa-text-[10px]\">\n <cqa-dynamic-select [form]=\"getConditionFormGroup(i)\" [config]=\"getOperatorConfig(i)\">\n </cqa-dynamic-select>\n </div> -->\n\n <!-- Value Template Dropdown -->\n <div class=\"cqa-flex-1 cqa-min-w-[150px] cqa-text-[10px]\">\n <cqa-dynamic-select [form]=\"getConditionFormGroup(i)\" [config]=\"getValueConfig(i)\">\n </cqa-dynamic-select>\n </div>\n\n <!-- Remove Button -->\n <cqa-button\n *ngIf=\"i >= 1\"\n variant=\"text\"\n icon=\"close\"\n iconPosition=\"start\"\n [customClass]=\"'cqa-w-full cqa-flex cqa-items-center cqa-justify-center'\"\n (click)=\"removeCondition(i)\"\n [attr.aria-label]=\"'Remove condition'\">\n </cqa-button>\n <!-- <button type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-8 cqa-h-8 cqa-rounded cqa-text-gray-500 hover:cqa-text-gray-700 hover:cqa-bg-gray-100 cqa-transition-colors\"\n (click)=\"removeCondition(i)\" *ngIf=\"i >= 1\"\n [attr.aria-label]=\"'Remove condition'\">\n <mat-icon class=\"cqa-text-lg cqa-text-[24px]\">close</mat-icon>\n </button> -->\n </div>\n\n <!-- Template Variables Section (shown when template is selected) -->\n <div *ngIf=\"getSelectedTemplate(i)\" class=\"cqa-mt-2\">\n <!-- Template Grammar Display -->\n <div class=\"cqa-mb-4 cqa-flex cqa-items-center cqa-flex-wrap cqa-gap-1 cqa-text-sm cqa-text-gray-700\">\n <div class=\"cqa-action-format cqa-text-[12px] cqa-leading-[23px] cqa-text-black-100\"\n [innerHTML]=\"getConditionUpdatedHtmlGrammar(i) || getSelectedTemplate(i)?.htmlGrammar || getSelectedTemplate(i)?.naturalText || ''\">\n </div>\n </div>\n \n <!-- Template Variables Form Component (includes Description and Metadata) -->\n <cqa-template-variables-form\n style=\"width: 100%;\"\n [templateVariables]=\"getConditionTemplateVariables(i)\"\n [variablesForm]=\"getConditionVariablesForm(i)\"\n [metadata]=\"getConditionFormGroup(i).get('metadata')?.value || ''\"\n [description]=\"getConditionFormGroup(i).get('description')?.value || ''\"\n [elementOptions]=\"elementOptions\"\n [hasMoreElements]=\"hasMoreElements\"\n [isLoadingElements]=\"isLoadingElements\"\n [screenNameOptions]=\"screenNameOptions\"\n [hasMoreScreenNames]=\"hasMoreScreenNames\"\n [isLoadingScreenNames]=\"isLoadingScreenNames\"\n (variableValueChange)=\"onConditionVariableValueChange(i, $event.name, $event.value)\"\n (variableBooleanChange)=\"onConditionVariableBooleanChange(i, $event.name, $event.value)\"\n (metadataChange)=\"getConditionFormGroup(i).get('metadata')?.setValue($event)\"\n (descriptionChange)=\"getConditionFormGroup(i).get('description')?.setValue($event)\"\n (loadMoreElements)=\"loadMoreElements.emit()\"\n (searchElements)=\"searchElements.emit($event)\"\n (createElement)=\"createElement.emit($event)\"\n (searchScreenName)=\"searchScreenName.emit($event)\"\n (loadMoreScreenNames)=\"loadMoreScreenNames.emit($event)\"\n (createScreenNameRequest)=\"createScreenNameRequest.emit($event)\">\n </cqa-template-variables-form>\n </div>\n </div>\n </ng-container>\n </div>\n\n <!-- Add Condition Button -->\n <div class=\"cqa-border-2 cqa-border-dashed cqa-border-gray-300 cqa-rounded-lg cqa-p-1 cqa-mt-3\">\n <cqa-button\n variant=\"text\"\n icon=\"add\"\n iconPosition=\"start\"\n [customClass]=\"'cqa-w-full cqa-flex cqa-items-center cqa-justify-center'\"\n [text]=\"'Add Condition'\"\n (clicked)=\"addCondition('CONDITION_ELSE_IF')\">\n </cqa-button>\n </div>\n </div>\n\n <!-- Include ELSE Branch Section -->\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-mb-6 cqa-p-3 cqa-bg-gray-50 cqa-rounded-lg\">\n <div class=\"cqa-flex cqa-flex-col\">\n <h3 class=\"cqa-text-[14px] cqa-font-semibold cqa-text-gray-900 cqa-mb-1\">\n Include ELSE branch\n </h3>\n <p class=\"cqa-text-[12px] cqa-text-gray-600\">\n Execute alternative steps when condition is not met.\n </p>\n </div>\n <mat-slide-toggle [checked]=\"includeElse\" (change)=\"onIncludeElseChange($event.checked)\" color=\"primary\">\n </mat-slide-toggle>\n </div>\n </div>\n <!-- Action Buttons -->\n <div class=\"cqa-flex cqa-w-full cqa-gap-2 cqa-mt-auto cqa-pt-4 cqa-border-t cqa-border-gray-200\">\n <cqa-button class=\"cqa-w-1/2\" variant=\"outlined\" text=\"Cancel\" [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onCancel()\">\n </cqa-button>\n <cqa-button class=\"cqa-w-1/2\" variant=\"filled\" text=\"Create Step\" [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n [disabled]=\"!conditionForm.valid\"\n (clicked)=\"onCreateStep()\">\n </cqa-button>\n </div>\n</div>", components: [{ type: DynamicSelectFieldComponent, selector: "cqa-dynamic-select", inputs: ["form", "config"], outputs: ["selectionChange", "selectClick", "searchChange", "loadMore", "addCustomValue"] }, { type: ButtonComponent, selector: "cqa-button", inputs: ["variant", "btnSize", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass", "inlineStyles", "tooltip", "tooltipPosition"], outputs: ["clicked"] }, { type: TemplateVariablesFormComponent, selector: "cqa-template-variables-form", inputs: ["templateVariables", "variablesForm", "metadata", "description", "elementOptions", "hasMoreElements", "isLoadingElements", "screenNameOptions", "hasMoreScreenNames", "isLoadingScreenNames"], outputs: ["variableValueChange", "variableBooleanChange", "metadataChange", "descriptionChange", "loadMoreElements", "searchElements", "createElement", "searchScreenName", "loadMoreScreenNames", "createScreenNameRequest", "cancelElementForm", "elementFormVisibilityChange"] }, { type: i5$1.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["disabled", "disableRipple", "color", "tabIndex", "name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "checked"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }], directives: [{ type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
26696
27348
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StepBuilderConditionComponent, decorators: [{
|
|
26697
27349
|
type: Component,
|
|
26698
|
-
args: [{ selector: 'cqa-step-builder-condition', host: { class: 'cqa-ui-root' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white cqa-px-4 cqa-py-2\">\n <!-- Header -->\n <h2 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n Create Condition Step\n </h2>\n\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1 cqa-overflow-y-auto\">\n <!-- Condition Builder Section -->\n <div class=\"cqa-mb-6\">\n <h3 class=\"cqa-text-sm cqa-text-[12px] cqa-font-semibold cqa-text-gray-900 cqa-mb-3\">\n Condition Builder\n </h3>\n\n <!-- Condition Rows -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-3 cqa-mb-3\">\n <ng-container *ngFor=\"let condition of conditionsFormArray.controls; let i = index; trackBy: trackByConditionIndex\">\n <div\n *ngIf=\"isConditionIf(i) || isConditionElseIf(i)\"\n class=\"cqa-flex cqa-flex-col cqa-gap-2\">\n <!-- Condition Row -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <!-- Condition Label -->\n <div class=\"cqa-text-[12px] cqa-font-semibold\">\n {{ getConditionLabel(i) }}\n </div>\n\n <!-- Operator Dropdown -->\n <!-- <div class=\"cqa-flex-1 cqa-max-w-[100px] cqa-text-[10px]\">\n <cqa-dynamic-select [form]=\"getConditionFormGroup(i)\" [config]=\"getOperatorConfig(i)\">\n </cqa-dynamic-select>\n </div> -->\n\n <!-- Value Template Dropdown -->\n <div class=\"cqa-flex-1 cqa-min-w-[150px] cqa-text-[10px]\">\n <cqa-dynamic-select [form]=\"getConditionFormGroup(i)\" [config]=\"getValueConfig(i)\">\n </cqa-dynamic-select>\n </div>\n\n <!-- Remove Button -->\n <cqa-button\n *ngIf=\"i >= 1\"\n variant=\"text\"\n icon=\"close\"\n iconPosition=\"start\"\n [customClass]=\"'cqa-w-full cqa-flex cqa-items-center cqa-justify-center'\"\n (click)=\"removeCondition(i)\"\n [attr.aria-label]=\"'Remove condition'\">\n </cqa-button>\n <!-- <button type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-8 cqa-h-8 cqa-rounded cqa-text-gray-500 hover:cqa-text-gray-700 hover:cqa-bg-gray-100 cqa-transition-colors\"\n (click)=\"removeCondition(i)\" *ngIf=\"i >= 1\"\n [attr.aria-label]=\"'Remove condition'\">\n <mat-icon class=\"cqa-text-lg cqa-text-[24px]\">close</mat-icon>\n </button> -->\n </div>\n\n <!-- Template Variables Section (shown when template is selected) -->\n <div *ngIf=\"getSelectedTemplate(i)\">\n <!-- Template Grammar Display -->\n
|
|
27350
|
+
args: [{ selector: 'cqa-step-builder-condition', host: { class: 'cqa-ui-root' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white cqa-px-4 cqa-py-2\">\n <!-- Header -->\n <h2 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n Create Condition Step\n </h2>\n\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1 cqa-overflow-y-auto\">\n <!-- Condition Builder Section -->\n <div class=\"cqa-mb-6\">\n <h3 class=\"cqa-text-sm cqa-text-[12px] cqa-font-semibold cqa-text-gray-900 cqa-mb-3\">\n Condition Builder\n </h3>\n\n <!-- Condition Rows -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-3 cqa-mb-3\">\n <ng-container *ngFor=\"let condition of conditionsFormArray.controls; let i = index; trackBy: trackByConditionIndex\">\n <div\n *ngIf=\"isConditionIf(i) || isConditionElseIf(i)\"\n class=\"cqa-flex cqa-flex-col cqa-gap-2\">\n <!-- Condition Row -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <!-- Condition Label -->\n <div class=\"cqa-text-[12px] cqa-font-semibold\">\n {{ getConditionLabel(i) }}\n </div>\n\n <!-- Operator Dropdown -->\n <!-- <div class=\"cqa-flex-1 cqa-max-w-[100px] cqa-text-[10px]\">\n <cqa-dynamic-select [form]=\"getConditionFormGroup(i)\" [config]=\"getOperatorConfig(i)\">\n </cqa-dynamic-select>\n </div> -->\n\n <!-- Value Template Dropdown -->\n <div class=\"cqa-flex-1 cqa-min-w-[150px] cqa-text-[10px]\">\n <cqa-dynamic-select [form]=\"getConditionFormGroup(i)\" [config]=\"getValueConfig(i)\">\n </cqa-dynamic-select>\n </div>\n\n <!-- Remove Button -->\n <cqa-button\n *ngIf=\"i >= 1\"\n variant=\"text\"\n icon=\"close\"\n iconPosition=\"start\"\n [customClass]=\"'cqa-w-full cqa-flex cqa-items-center cqa-justify-center'\"\n (click)=\"removeCondition(i)\"\n [attr.aria-label]=\"'Remove condition'\">\n </cqa-button>\n <!-- <button type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-8 cqa-h-8 cqa-rounded cqa-text-gray-500 hover:cqa-text-gray-700 hover:cqa-bg-gray-100 cqa-transition-colors\"\n (click)=\"removeCondition(i)\" *ngIf=\"i >= 1\"\n [attr.aria-label]=\"'Remove condition'\">\n <mat-icon class=\"cqa-text-lg cqa-text-[24px]\">close</mat-icon>\n </button> -->\n </div>\n\n <!-- Template Variables Section (shown when template is selected) -->\n <div *ngIf=\"getSelectedTemplate(i)\" class=\"cqa-mt-2\">\n <!-- Template Grammar Display -->\n <div class=\"cqa-mb-4 cqa-flex cqa-items-center cqa-flex-wrap cqa-gap-1 cqa-text-sm cqa-text-gray-700\">\n <div class=\"cqa-action-format cqa-text-[12px] cqa-leading-[23px] cqa-text-black-100\"\n [innerHTML]=\"getConditionUpdatedHtmlGrammar(i) || getSelectedTemplate(i)?.htmlGrammar || getSelectedTemplate(i)?.naturalText || ''\">\n </div>\n </div>\n \n <!-- Template Variables Form Component (includes Description and Metadata) -->\n <cqa-template-variables-form\n style=\"width: 100%;\"\n [templateVariables]=\"getConditionTemplateVariables(i)\"\n [variablesForm]=\"getConditionVariablesForm(i)\"\n [metadata]=\"getConditionFormGroup(i).get('metadata')?.value || ''\"\n [description]=\"getConditionFormGroup(i).get('description')?.value || ''\"\n [elementOptions]=\"elementOptions\"\n [hasMoreElements]=\"hasMoreElements\"\n [isLoadingElements]=\"isLoadingElements\"\n [screenNameOptions]=\"screenNameOptions\"\n [hasMoreScreenNames]=\"hasMoreScreenNames\"\n [isLoadingScreenNames]=\"isLoadingScreenNames\"\n (variableValueChange)=\"onConditionVariableValueChange(i, $event.name, $event.value)\"\n (variableBooleanChange)=\"onConditionVariableBooleanChange(i, $event.name, $event.value)\"\n (metadataChange)=\"getConditionFormGroup(i).get('metadata')?.setValue($event)\"\n (descriptionChange)=\"getConditionFormGroup(i).get('description')?.setValue($event)\"\n (loadMoreElements)=\"loadMoreElements.emit()\"\n (searchElements)=\"searchElements.emit($event)\"\n (createElement)=\"createElement.emit($event)\"\n (searchScreenName)=\"searchScreenName.emit($event)\"\n (loadMoreScreenNames)=\"loadMoreScreenNames.emit($event)\"\n (createScreenNameRequest)=\"createScreenNameRequest.emit($event)\">\n </cqa-template-variables-form>\n </div>\n </div>\n </ng-container>\n </div>\n\n <!-- Add Condition Button -->\n <div class=\"cqa-border-2 cqa-border-dashed cqa-border-gray-300 cqa-rounded-lg cqa-p-1 cqa-mt-3\">\n <cqa-button\n variant=\"text\"\n icon=\"add\"\n iconPosition=\"start\"\n [customClass]=\"'cqa-w-full cqa-flex cqa-items-center cqa-justify-center'\"\n [text]=\"'Add Condition'\"\n (clicked)=\"addCondition('CONDITION_ELSE_IF')\">\n </cqa-button>\n </div>\n </div>\n\n <!-- Include ELSE Branch Section -->\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-mb-6 cqa-p-3 cqa-bg-gray-50 cqa-rounded-lg\">\n <div class=\"cqa-flex cqa-flex-col\">\n <h3 class=\"cqa-text-[14px] cqa-font-semibold cqa-text-gray-900 cqa-mb-1\">\n Include ELSE branch\n </h3>\n <p class=\"cqa-text-[12px] cqa-text-gray-600\">\n Execute alternative steps when condition is not met.\n </p>\n </div>\n <mat-slide-toggle [checked]=\"includeElse\" (change)=\"onIncludeElseChange($event.checked)\" color=\"primary\">\n </mat-slide-toggle>\n </div>\n </div>\n <!-- Action Buttons -->\n <div class=\"cqa-flex cqa-w-full cqa-gap-2 cqa-mt-auto cqa-pt-4 cqa-border-t cqa-border-gray-200\">\n <cqa-button class=\"cqa-w-1/2\" variant=\"outlined\" text=\"Cancel\" [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onCancel()\">\n </cqa-button>\n <cqa-button class=\"cqa-w-1/2\" variant=\"filled\" text=\"Create Step\" [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n [disabled]=\"!conditionForm.valid\"\n (clicked)=\"onCreateStep()\">\n </cqa-button>\n </div>\n</div>", styles: [] }]
|
|
26699
27351
|
}], ctorParameters: function () { return [{ type: i1$1.FormBuilder }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { operatorOptions: [{
|
|
26700
27352
|
type: Input
|
|
26701
27353
|
}], conditionTemplates: [{
|
|
26702
27354
|
type: Input
|
|
26703
27355
|
}], setConditionTemplateVariables: [{
|
|
26704
27356
|
type: Input
|
|
27357
|
+
}], elementOptions: [{
|
|
27358
|
+
type: Input
|
|
27359
|
+
}], hasMoreElements: [{
|
|
27360
|
+
type: Input
|
|
27361
|
+
}], isLoadingElements: [{
|
|
27362
|
+
type: Input
|
|
27363
|
+
}], screenNameOptions: [{
|
|
27364
|
+
type: Input
|
|
27365
|
+
}], hasMoreScreenNames: [{
|
|
27366
|
+
type: Input
|
|
27367
|
+
}], isLoadingScreenNames: [{
|
|
27368
|
+
type: Input
|
|
26705
27369
|
}], createStep: [{
|
|
26706
27370
|
type: Output
|
|
26707
27371
|
}], cancelled: [{
|
|
26708
27372
|
type: Output
|
|
27373
|
+
}], loadMoreElements: [{
|
|
27374
|
+
type: Output
|
|
27375
|
+
}], searchElements: [{
|
|
27376
|
+
type: Output
|
|
27377
|
+
}], createElement: [{
|
|
27378
|
+
type: Output
|
|
27379
|
+
}], searchScreenName: [{
|
|
27380
|
+
type: Output
|
|
27381
|
+
}], loadMoreScreenNames: [{
|
|
27382
|
+
type: Output
|
|
27383
|
+
}], createScreenNameRequest: [{
|
|
27384
|
+
type: Output
|
|
26709
27385
|
}] } });
|
|
26710
27386
|
|
|
26711
27387
|
class StepBuilderDatabaseComponent {
|
|
@@ -30407,6 +31083,7 @@ UiKitModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "1
|
|
|
30407
31083
|
StepBuilderActionComponent,
|
|
30408
31084
|
StepBuilderLoopComponent,
|
|
30409
31085
|
ElementPopupComponent,
|
|
31086
|
+
ElementFormComponent,
|
|
30410
31087
|
StepBuilderConditionComponent,
|
|
30411
31088
|
StepBuilderDatabaseComponent,
|
|
30412
31089
|
StepBuilderAiAgentComponent,
|
|
@@ -30550,6 +31227,7 @@ UiKitModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "1
|
|
|
30550
31227
|
StepBuilderActionComponent,
|
|
30551
31228
|
StepBuilderLoopComponent,
|
|
30552
31229
|
ElementPopupComponent,
|
|
31230
|
+
ElementFormComponent,
|
|
30553
31231
|
StepBuilderConditionComponent,
|
|
30554
31232
|
StepBuilderDatabaseComponent,
|
|
30555
31233
|
StepBuilderAiAgentComponent,
|
|
@@ -30742,6 +31420,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
|
|
|
30742
31420
|
StepBuilderActionComponent,
|
|
30743
31421
|
StepBuilderLoopComponent,
|
|
30744
31422
|
ElementPopupComponent,
|
|
31423
|
+
ElementFormComponent,
|
|
30745
31424
|
StepBuilderConditionComponent,
|
|
30746
31425
|
StepBuilderDatabaseComponent,
|
|
30747
31426
|
StepBuilderAiAgentComponent,
|
|
@@ -30891,6 +31570,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
|
|
|
30891
31570
|
StepBuilderActionComponent,
|
|
30892
31571
|
StepBuilderLoopComponent,
|
|
30893
31572
|
ElementPopupComponent,
|
|
31573
|
+
ElementFormComponent,
|
|
30894
31574
|
StepBuilderConditionComponent,
|
|
30895
31575
|
StepBuilderDatabaseComponent,
|
|
30896
31576
|
StepBuilderAiAgentComponent,
|
|
@@ -31580,5 +32260,5 @@ function buildTestCaseDetailsFromApi(data, options) {
|
|
|
31580
32260
|
* Generated bundle index. Do not edit.
|
|
31581
32261
|
*/
|
|
31582
32262
|
|
|
31583
|
-
export { ADVANCED_SUBFIELDS_BY_TYPE, ADVANCED_TOGGLE_KEYS, AIActionStepComponent, AIAgentStepComponent, API_EDIT_STEP_LABELS, ActionMenuButtonComponent, AddPrerequisiteCasesSectionComponent, AiDebugAlertComponent, AiLogsWithReasoningComponent, AiReasoningComponent, ApiEditStepComponent, ApiStepComponent, AutocompleteComponent, BadgeComponent, BasicStepComponent, BreakpointsModalComponent, ButtonComponent, CUSTOM_EDIT_STEP_DATA, CUSTOM_EDIT_STEP_EDIT_IN_DEPTH, CUSTOM_EDIT_STEP_REF, CUSTOM_ELEMENT_POPUP_REF, ChartCardComponent, ColumnVisibilityComponent, CompareRunsComponent, ConditionStepComponent, ConfigurationCardComponent, ConsoleAlertComponent, CoverageModuleCardComponent, CreateStepGroupComponent, CustomEditStepComponent, CustomEditStepRef, CustomEditStepService, CustomInputComponent, CustomTextareaComponent, CustomToggleComponent, DEFAULT_METADATA_COLOR, DEFAULT_PRIORITY_COLOR_CONFIG, DEFAULT_STATUS_COLOR_CONFIG, DIALOG_DATA, DIALOG_REF, DashboardHeaderComponent, DaterangepickerComponent, DaterangepickerDirective, DbQueryExecutionItemComponent, DbVerificationStepComponent, DeleteStepsComponent, DetailDrawerComponent, DetailDrawerTabComponent, DetailDrawerTabContentDirective, DetailSidePanelComponent, DialogComponent, DialogRef, DialogService, DocumentVerificationStepComponent, DropdownButtonComponent, DynamicCellContainerDirective, DynamicCellTemplateDirective, DynamicFilterComponent, DynamicHeaderTemplateDirective, DynamicSelectFieldComponent, DynamicTableComponent, ELEMENT_POPUP_DATA, ELEMENT_POPUP_EDIT_IN_DEPTH, EMPTY_STATE_IMAGES, EMPTY_STATE_PRESETS, ElementListComponent, ElementPopupComponent, ElementPopupRef, ElementPopupService, EmptyStateComponent, ErrorModalComponent, ExecutionResultModalComponent, ExportCodeModalComponent, FailedStepCardComponent, FailedStepComponent, FailedTestCasesCardComponent, FileDownloadStepComponent, FileUploadComponent, FullTableLoaderComponent, HeatErrorMapCellComponent, InsightCardComponent, ItemListComponent, IterationsLoopComponent, JumpToStepModalComponent, LiveConversationComponent, LiveExecutionStepComponent, LoopStepComponent, MainStepCollapseComponent, MetricsCardComponent, NetworkRequestComponent, OtherButtonComponent, PRIORITY_COLORS, PaginationComponent, ProgressIndicatorComponent, ProgressTextCardComponent, RESULT_COLORS, RunHistoryCardComponent, STATUS_COLORS, STEP_DETAILS_DRAWER_DATA, STEP_DETAILS_DRAWER_REF, STEP_DETAILS_FIELDS_BY_TYPE, STEP_DETAILS_FIELD_META, SearchBarComponent, SegmentControlComponent, SelectedFiltersComponent, SelfHealAnalysisComponent, SessionChangesModalComponent, SimulatorComponent, StepBuilderActionComponent, StepBuilderAiAgentComponent, StepBuilderConditionComponent, StepBuilderCustomCodeComponent, StepBuilderDatabaseComponent, StepBuilderDocumentComponent, StepBuilderDocumentGenerationTemplateStepComponent, StepBuilderGroupComponent, StepBuilderLoopComponent, StepBuilderRecordStepComponent, StepDetailsDrawerComponent, StepDetailsDrawerRef, StepDetailsDrawerService, StepGroupComponent, StepProgressCardComponent, StepRendererComponent, StepStatusCardComponent, StepTypes, TEST_CASE_DETAILS_FIELD_MAP, TEST_CASE_DETAILS_SELECT_KEYS, TEST_DATA_MODAL_DATA, TEST_DATA_MODAL_EDIT_IN_DEPTH, TEST_DATA_MODAL_REF, TableActionToolbarComponent, TableDataLoaderComponent, TableTemplateComponent, TailwindOverlayContainer, TemplateVariablesFormComponent, TestCaseAiAgentStepComponent, TestCaseAiVerifyStepComponent, TestCaseApiStepComponent, TestCaseConditionStepComponent, TestCaseCustomCodeStepComponent, TestCaseDatabaseStepComponent, TestCaseDetailsComponent, TestCaseDetailsEditComponent, TestCaseDetailsRendererComponent, TestCaseLoopStepComponent, TestCaseNormalStepComponent, TestCaseRestoreSessionStepComponent, TestCaseScreenshotStepComponent, TestCaseScrollStepComponent, TestCaseStepGroupComponent, TestCaseUploadStepComponent, TestCaseVerifyUrlStepComponent, TestDataModalComponent, TestDataModalRef, TestDataModalService, TestDistributionCardComponent, UiKitModule, UpdatedFailedStepComponent, ViewMoreFailedStepButtonComponent, VisualComparisonComponent, VisualDifferenceModalComponent, buildTestCaseDetailsFromApi, getDynamicFieldsFromLegacyConfig, getEmptyStatePreset, getMetadataColor, getMetadataValueStyle, getStepDetailsStepType, humanizeVariableKey, isAiAgentStepConfig, isAiVerifyStepConfig, isApiStepConfig, isConditionStepConfig, isCustomCodeStepConfig, isDatabaseStepConfig, isLoopStepConfig, isNormalStepConfig, isRestoreSessionStepConfig, isScreenshotStepConfig, isScrollStepConfig, isStepGroupConfig, isUploadStepConfig, isVerifyUrlStepConfig, mapApiVariablesToDynamicFields };
|
|
32263
|
+
export { ADVANCED_SUBFIELDS_BY_TYPE, ADVANCED_TOGGLE_KEYS, AIActionStepComponent, AIAgentStepComponent, API_EDIT_STEP_LABELS, ActionMenuButtonComponent, AddPrerequisiteCasesSectionComponent, AiDebugAlertComponent, AiLogsWithReasoningComponent, AiReasoningComponent, ApiEditStepComponent, ApiStepComponent, AutocompleteComponent, BadgeComponent, BasicStepComponent, BreakpointsModalComponent, ButtonComponent, CUSTOM_EDIT_STEP_DATA, CUSTOM_EDIT_STEP_EDIT_IN_DEPTH, CUSTOM_EDIT_STEP_REF, CUSTOM_ELEMENT_POPUP_REF, ChartCardComponent, ColumnVisibilityComponent, CompareRunsComponent, ConditionStepComponent, ConfigurationCardComponent, ConsoleAlertComponent, CoverageModuleCardComponent, CreateStepGroupComponent, CustomEditStepComponent, CustomEditStepRef, CustomEditStepService, CustomInputComponent, CustomTextareaComponent, CustomToggleComponent, DEFAULT_METADATA_COLOR, DEFAULT_PRIORITY_COLOR_CONFIG, DEFAULT_STATUS_COLOR_CONFIG, DIALOG_DATA, DIALOG_REF, DashboardHeaderComponent, DaterangepickerComponent, DaterangepickerDirective, DbQueryExecutionItemComponent, DbVerificationStepComponent, DeleteStepsComponent, DetailDrawerComponent, DetailDrawerTabComponent, DetailDrawerTabContentDirective, DetailSidePanelComponent, DialogComponent, DialogRef, DialogService, DocumentVerificationStepComponent, DropdownButtonComponent, DynamicCellContainerDirective, DynamicCellTemplateDirective, DynamicFilterComponent, DynamicHeaderTemplateDirective, DynamicSelectFieldComponent, DynamicTableComponent, ELEMENT_POPUP_DATA, ELEMENT_POPUP_EDIT_IN_DEPTH, EMPTY_STATE_IMAGES, EMPTY_STATE_PRESETS, ElementFormComponent, ElementListComponent, ElementPopupComponent, ElementPopupRef, ElementPopupService, EmptyStateComponent, ErrorModalComponent, ExecutionResultModalComponent, ExportCodeModalComponent, FailedStepCardComponent, FailedStepComponent, FailedTestCasesCardComponent, FileDownloadStepComponent, FileUploadComponent, FullTableLoaderComponent, HeatErrorMapCellComponent, InsightCardComponent, ItemListComponent, IterationsLoopComponent, JumpToStepModalComponent, LiveConversationComponent, LiveExecutionStepComponent, LoopStepComponent, MainStepCollapseComponent, MetricsCardComponent, NetworkRequestComponent, OtherButtonComponent, PRIORITY_COLORS, PaginationComponent, ProgressIndicatorComponent, ProgressTextCardComponent, RESULT_COLORS, RunHistoryCardComponent, STATUS_COLORS, STEP_DETAILS_DRAWER_DATA, STEP_DETAILS_DRAWER_REF, STEP_DETAILS_FIELDS_BY_TYPE, STEP_DETAILS_FIELD_META, SearchBarComponent, SegmentControlComponent, SelectedFiltersComponent, SelfHealAnalysisComponent, SessionChangesModalComponent, SimulatorComponent, StepBuilderActionComponent, StepBuilderAiAgentComponent, StepBuilderConditionComponent, StepBuilderCustomCodeComponent, StepBuilderDatabaseComponent, StepBuilderDocumentComponent, StepBuilderDocumentGenerationTemplateStepComponent, StepBuilderGroupComponent, StepBuilderLoopComponent, StepBuilderRecordStepComponent, StepDetailsDrawerComponent, StepDetailsDrawerRef, StepDetailsDrawerService, StepGroupComponent, StepProgressCardComponent, StepRendererComponent, StepStatusCardComponent, StepTypes, TEST_CASE_DETAILS_FIELD_MAP, TEST_CASE_DETAILS_SELECT_KEYS, TEST_DATA_MODAL_DATA, TEST_DATA_MODAL_EDIT_IN_DEPTH, TEST_DATA_MODAL_REF, TableActionToolbarComponent, TableDataLoaderComponent, TableTemplateComponent, TailwindOverlayContainer, TemplateVariablesFormComponent, TestCaseAiAgentStepComponent, TestCaseAiVerifyStepComponent, TestCaseApiStepComponent, TestCaseConditionStepComponent, TestCaseCustomCodeStepComponent, TestCaseDatabaseStepComponent, TestCaseDetailsComponent, TestCaseDetailsEditComponent, TestCaseDetailsRendererComponent, TestCaseLoopStepComponent, TestCaseNormalStepComponent, TestCaseRestoreSessionStepComponent, TestCaseScreenshotStepComponent, TestCaseScrollStepComponent, TestCaseStepGroupComponent, TestCaseUploadStepComponent, TestCaseVerifyUrlStepComponent, TestDataModalComponent, TestDataModalRef, TestDataModalService, TestDistributionCardComponent, UiKitModule, UpdatedFailedStepComponent, ViewMoreFailedStepButtonComponent, VisualComparisonComponent, VisualDifferenceModalComponent, buildTestCaseDetailsFromApi, getDynamicFieldsFromLegacyConfig, getEmptyStatePreset, getMetadataColor, getMetadataValueStyle, getStepDetailsStepType, humanizeVariableKey, isAiAgentStepConfig, isAiVerifyStepConfig, isApiStepConfig, isConditionStepConfig, isCustomCodeStepConfig, isDatabaseStepConfig, isLoopStepConfig, isNormalStepConfig, isRestoreSessionStepConfig, isScreenshotStepConfig, isScrollStepConfig, isStepGroupConfig, isUploadStepConfig, isVerifyUrlStepConfig, mapApiVariablesToDynamicFields };
|
|
31584
32264
|
//# sourceMappingURL=cqa-lib-cqa-ui.mjs.map
|