import { EventEmitter, OnInit, OnChanges, ChangeDetectorRef, ElementRef } from '@angular/core'; import { FormBuilder, FormGroup } from '@angular/forms'; import { DndDropEvent } from 'ngx-drag-drop'; import { ConditionStepConfig, ConditionBranch, TestCaseStepConfig, NormalStepConfig, LoopStepConfig, StepGroupConfig } from '../test-case-step.models'; import { DynamicSelectFieldConfig } from '../../dynamic-select/dynamic-select-field.component'; import { CqaAutocompleteOption } from '../../autocomplete/autocomplete.model'; import { ViewDetailsPayload } from '../step-details-modal/step-details-modal-data'; import * as i0 from "@angular/core"; export declare class TestCaseConditionStepComponent implements OnInit, OnChanges { private fb; private cdr; config: ConditionStepConfig; id: string; stepNumber: number | string; /** Array index from parent renderer - use this for editInDepth instead of stepNumber (stepNumber "10.3" parses to 10) */ index?: number; condition: string; branches: ConditionBranch[]; expanded: boolean; isNested: boolean; isInsideLoop: boolean; isInsideForLoop: boolean; testCaseTestDataId?: number | string; isInsideStepGroup: boolean; isReorder: boolean; /** True when any ancestor step is skipped; used to cascade skipped styling to nested rows. */ isParentSkipped: boolean; editable: boolean; /** Visual indentation level for nested structures (passed down from renderer). */ nestingLevel: number; selected: boolean; /** Options for the data profile dropdown */ dataProfileOptions: any[]; /** Indicates if more data profiles are available for loading */ hasMoreDataProfiles: boolean; /** Loading state for data profiles */ isLoadingDataProfiles: boolean; /** Natural text actions options for while loop condition */ naturalTextActionsOptions: any[]; /** Passed to nested renderers (e.g. reusable step group hint). */ currentTestCaseId?: number | string; /** Function to process template variables (similar to step-builder-condition) */ setConditionTemplateVariables: (template: any) => any[]; /** Show "Add Step Between" button above nested steps */ addStepBetweenAbove: boolean; /** Show "Add Step Between" button below nested steps */ addStepBetweenBelow: boolean; /** @deprecated Use addStepBetweenAbove and addStepBetweenBelow instead. If set, applies to both buttons. */ addStepBetween: boolean; /** When non-null, edit mode is open: 'stepRow' = edit UI in step row only, 'branchRow' = edit UI in branch row only */ editContext: 'stepRow' | 'branchRow' | null; /** Base left padding for step rows (matches px-4 = 16px) plus 24px per nesting level (matches pl-10 = 40px at level 1). */ getRowPaddingLeftPx(): number; /** Which branch index is being edited when editContext === 'branchRow' (0 = IF TRUE, 1+ = ELSE IF) */ editingBranchIndex: number; /** True when editContext is set (either step row or branch row edit). */ get isEditing(): boolean; /** Array of ELSE IF branches in edit mode */ elseIfBranches: Array<{ id: string; form: FormGroup; selectedTemplate: any; templateVariables: any[]; templateVariablesForm: FormGroup; snapshot: { conditionLeft?: string; conditionOperator?: string; conditionRight?: string; }; /** Index of the branch row that triggered this "Add ELSE IF" (0 = IF TRUE) */ triggerBranchIndex: number; /** Branch ID after which this new ELSE IF should be inserted */ insertAfterBranchId?: string; }>; /** Form for edit mode; bound to cqa-dynamic-select and cqa-custom-input */ editForm: FormGroup; /** Operator dropdown config (IS, IS NOT, CONTAINS, etc.) */ operatorSelectConfig: DynamicSelectFieldConfig; /** Condition left operand dropdown config (natural text actions with IF_CONDITION) */ conditionLeftSelectConfig: DynamicSelectFieldConfig; /** Snapshot for Cancel revert */ private editSnapshot; /** Selected template for IF condition */ selectedTemplate: any; /** Template variables for IF condition */ templateVariables: any[]; /** Form group for template variables */ templateVariablesForm: FormGroup; viewDetailsTrigger?: ElementRef; toggleExpanded: EventEmitter<{ config: ConditionStepConfig; expanded: boolean; }>; conditionChange: EventEmitter; branchStepChange: EventEmitter<{ branch: ConditionBranch; step: TestCaseStepConfig; stepIndex: number; }>; addStep: EventEmitter<{ branch: ConditionBranch; }>; /** Emitted when a nested loop-step emits addStepForLoop (empty state plus button). */ addStepForLoop: EventEmitter<{ loopStepConfig: LoopStepConfig; }>; deleteStep: EventEmitter<{ branch: ConditionBranch; stepIndex: number; }>; addBranch: EventEmitter; /** Emitted when user clicks "Add Else" so the parent can call POST test_steps with conditionType CONDITION_ELSE */ addElse: EventEmitter<{ conditionStepConfig: ConditionStepConfig; }>; /** Payload can be branch only (legacy) or { branch, stepNumber } for delete modal label e.g. "Step 5 ELSE". */ deleteBranch: EventEmitter; duplicate: EventEmitter; delete: EventEmitter; edit: EventEmitter<{ step: TestCaseStepConfig; index: number; }>; moreOptions: EventEmitter; viewDetails: EventEmitter; editInDepth: EventEmitter<{ step: TestCaseStepConfig; index?: number; templateOverride?: any; isCreateMode?: boolean; createModeBranchData?: any; }>; dndDropInZone: EventEmitter<{ event: DndDropEvent; targetList: TestCaseStepConfig[]; }>; /** Emit when more data profiles need to be loaded */ loadMoreDataProfiles: EventEmitter; /** Emit when data profile search query changes */ searchDataProfiles: EventEmitter; /** Emit when a nested step is updated (e.g., Apply button clicked in loop-step edit mode) */ stepUpdate: EventEmitter; /** Re-emit when a nested step (e.g. normal-step) emits clickAction (e.g. element/label click for popup) */ clickAction: EventEmitter<{ event: MouseEvent; step: TestCaseStepConfig; }>; /** Re-emit addStepBetweenClick from nested renderers */ addStepBetweenClick: EventEmitter<{ step: TestCaseStepConfig; index: number; position: 'ABOVE' | 'BELOW'; }>; selectionChange: EventEmitter; /** Re-emit when nested step group emits openExternal (redirect to step group in new tab) */ openExternal: EventEmitter<{ step: TestCaseStepConfig; }>; onDndDrop(event: DndDropEvent, branch: ConditionBranch): void; /** * Toggle skip state for the whole condition step. * Uses the same payload shape as other step types (emits `stepUpdate` with `shouldSkip` flipped). */ onSkipToggle(): void; /** Emit clickAction when user clicks on condition/branch action badges (element, test_data, etc.) so parent can open edit modals */ onConditionActionClick(event: MouseEvent, branch?: ConditionBranch): void; /** Forward clickAction from nested steps only when not inside a step-group (Element/Test Data modals disabled there). */ onNestedClickAction(payload: { event: MouseEvent; step: TestCaseStepConfig; }): void; constructor(fb: FormBuilder, cdr: ChangeDetectorRef); ngOnInit(): void; ngOnChanges(changes: any): void; /** Rebuild edit form when naturalTextActionsOptions are loaded to populate from naturalTextActionId */ private rebuildEditFormWithNaturalTextAction; private buildEditForm; private buildElseIfBranch; private buildOperatorSelectConfig; /** Update condition left select config with filtered natural text actions (IF_CONDITION only) */ private updateConditionLeftSelectConfig; /** Options for the condition left autocomplete (IF_CONDITION natural text actions) */ get conditionLeftAutocompleteOptions(): CqaAutocompleteOption[]; /** * Display value for IF/ELSE IF condition autocomplete. * - For IF (step row / IF branch edit), show naturalText from option matching naturalTextActionId when form is empty. * - For ELSE IF branch edit, always use the form value (so clearing leaves the field empty instead of reverting to IF). */ get conditionLeftDisplayValue(): string; onConditionLeftSelect(option: CqaAutocompleteOption & { template?: any; }): void; private buildTemplateVariablesForm; onElseConditionLeftSelect(option: CqaAutocompleteOption & { template?: any; }, branchId: string): void; private buildElseTemplateVariablesForm; onAddElse(triggerBranchIndex?: number): void; /** Returns the pending ELSE IF add-forms that belong after a specific branch row. */ getElseIfBranchesForBranchIndex(branchIndex: number): Array<{ id: string; form: FormGroup; selectedTemplate: any; templateVariables: any[]; templateVariablesForm: FormGroup; snapshot: { conditionLeft?: string; conditionOperator?: string; conditionRight?: string; }; triggerBranchIndex: number; insertAfterBranchId?: string; }>; /** True when the given elseIfBranch is the last pending one (determines where Cancel/Apply are shown). */ isLastElseIfBranch(branchId: string): boolean; onAddElseBranch(): void; onRemoveElse(branchId: string): void; /** Strip HTML tags from a string to get plain text */ private stripHtmlTags; /** Parse condition string into left, operator, right (e.g. "Usertype is Premium") * Strips HTML tags before parsing to handle formatted conditions */ private parseCondition; /** Build condition string from form values */ private buildConditionFromForm; onEditFormFieldChange(controlName: string, value: string): void; /** Count and summarize condition branches using their display step numbers. * Example: IF + 2x ELSE IF + ELSE → "Steps 6-9 (4 steps)". */ /** * Returns a flat list of all branches including those chained via nextBranch. * Used for counting, badge display, and summary when the condition uses a chained structure. */ getAllBranchesFlat(): ConditionBranch[]; getStepsSummary(): string; /** Branch type badges for step row: IF, ELSE IF (with count if multiple), ELSE */ getBranchTypeBadges(): { label: string; count?: number; type: 'if' | 'else-if' | 'else'; badgeClass: string; }[]; /** Condition text as plain text (strips HTML), truncated with "..." if long */ getConditionPlainText(maxLength?: number): string; /** Event key-value pairs for display, excluding customEvent */ getEventDetailsForDisplay(): { key: string; value: string; }[]; /** Event key-value pairs for a branch (e.g. selector, element) - for IF uses config.event, for ELSE IF/ELSE uses branch.event */ getBranchEventDetailsForDisplay(branch: ConditionBranch): { key: string; value: string; }[]; onToggleExpanded(): void; onConditionChange(value: string): void; onBranchStepChange(branch: ConditionBranch, step: TestCaseStepConfig, stepIndex: number): void; /** Re-emit openExternal from nested step group so redirect works for step groups inside condition branches. */ onNestedOpenExternal(payload: { step: TestCaseStepConfig; }): void; onNestedToggleExpanded(event: boolean | { config: TestCaseStepConfig; expanded: boolean; }, branch: ConditionBranch, step: TestCaseStepConfig, index: number): void; onAddStep(branch: ConditionBranch): void; /** Handle addStepForLoop event from nested loop-step (empty state plus button). */ onAddStepForLoop(event: { loopStepConfig: LoopStepConfig; }, branch: ConditionBranch): void; onDeleteStep(branch: ConditionBranch, stepIndex: number): void; /** Re-emit edit from nested step in a branch so the portal can open edit modal (same as root level). */ onNestedEdit(event: { step: TestCaseStepConfig; index: number; }): void; /** Re-emit duplicate from nested step in a branch so the portal can duplicate (same as root level). */ onNestedDuplicate(event: any, step: TestCaseStepConfig): void; onAddBranch(): void; onDeleteBranch(branch: ConditionBranch): void; onNestedConditionAddBranch(nestedStep: ConditionStepConfig): void; onNestedConditionDeleteBranch(nestedStep: ConditionStepConfig, payload: ConditionBranch | { branch: ConditionBranch; stepNumber?: number | string; }): void; /** Forward nested step's delete event upward (e.g. a step inside a loop inside a branch). */ onNestedStepDelete(payload: { step: TestCaseStepConfig; } | void): void; isNormalStep(step: TestCaseStepConfig): step is NormalStepConfig; isLoopStep(step: TestCaseStepConfig): step is LoopStepConfig; isConditionStep(step: TestCaseStepConfig): step is ConditionStepConfig; isStepGroup(step: TestCaseStepConfig): step is StepGroupConfig; getBranchLabel(branch: ConditionBranch): string; /** Condition text for branch header display: IF uses main condition, ELSE IF/ELSE use branch.action */ getBranchConditionDisplay(branch: ConditionBranch): string; /** Start marker label for each branch: START IF, START ELSE IF, or START ELSE */ getStartBranchLabel(branch: ConditionBranch): string; /** End marker label for each branch: END IF, END ELSE IF, or END ELSE */ getEndBranchLabel(branch: ConditionBranch): string; /** START branch marker: first nested step's step number in this branch. */ getBranchMarkerStartStep(branch: ConditionBranch): string; /** END branch marker: last nested step's step number in this branch. */ getBranchMarkerEndStep(branch: ConditionBranch): string; /** END CONDITION marker: this condition step's display number. */ getEndConditionMarkerStepDisplay(): string; /** Branch display number: full hierarchical number. IF = stepNumber (e.g. 2.1.50), ELSE IF = 2.1.51, ELSE = 2.1.52. */ getBranchDisplayNumber(branchIndex: number): number | string; /** Return the branch id after which a new ELSE IF should be inserted, based on the current edit context. */ getInsertAfterBranchId(): string | undefined; /** Find branch in branches by id (for elseIfBranches which use same id). */ getBranchById(branchId?: string | number): ConditionBranch | undefined; /** Get branch index in branches by id. */ getBranchIndexById(branchId?: string | number): number; getBranchColorClass(branch: ConditionBranch): string; getBranchTextColor(branch: ConditionBranch): string; /** Created date for branch header display: branch-specific or fallback to config. */ getBranchCreatedDate(branch: ConditionBranch): number | undefined; /** True when condition already has an ELSE branch (disables Add ELSE IF / Add ELSE). */ get hasElseBranch(): boolean; onOpenExternal(): void; /** Shared init for edit mode; then call onEditFromStepRow or onEditFromBranchRow to set context. */ private initEditForm; /** Edit from step row: edit UI appears in the step row only (first branch stays read-only). */ onEditFromStepRow(): void; /** Edit from branch row: edit UI appears in that branch row (IF TRUE or ELSE IF). */ onEditFromBranchRow(branchIndex?: number): void; /** @deprecated Use onEditFromStepRow or onEditFromBranchRow. Kept for compatibility. */ onEdit(): void; onEditCancel(): void; /** * Build payload for one ELSE IF branch (action, naturalTextActionId, templateVariablesData, testDataList) * so the parent can create the step via POST then PUT when Apply is clicked. */ private buildElseIfBranchPayload; onEditApply(): void; /** * Local helper to substitute #{variable} placeholders in the condition text with HTML badge spans. * Mirrors the portal renderer's substituteTemplateVariablesToHtml so inline edit mode never shows raw #{label}. */ private substituteTemplateVariablesToHtmlForCondition; /** * Emit editInDepth. When branch is provided (ELSE IF/ELSE branch row), use branch's nested condition step * and branch display number for correct "Edit Step N" title. When isCreateMode (new ELSE IF), modal shows "Create In depth" and calls create API on save. */ onEditInDepth(templateOverride?: any, branch?: ConditionBranch, branchIndex?: number, isCreateMode?: boolean, elseIfBranch?: any, insertAfterBranchId?: string): void; onLink(): void; onDuplicate(): void; onDelete(): void; onSelectionChange(checked: boolean): void; onMoreOptions(): void; onViewDetails(event?: MouseEvent): void; /** Get select config for a template variable */ getSelectConfigForVariable(variable: any, branchIdOrIsElse?: string | boolean): DynamicSelectFieldConfig; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵcmp: i0.ɵɵComponentDeclaration; }