From 3ca03419b1de52aefc4048984d3990398e7fb043 Mon Sep 17 00:00:00 2001 From: Zack Lee Date: Wed, 11 Jun 2025 02:24:23 +0900 Subject: [PATCH 1/3] Auto-remove leading/trailing spaces from user-entered payloads --- .../payloads-table/payloads-table.component.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/frontend/projects/upgrade/src/app/features/dashboard/home/components/experiment-design/payloads-table/payloads-table.component.ts b/frontend/projects/upgrade/src/app/features/dashboard/home/components/experiment-design/payloads-table/payloads-table.component.ts index 06d546d222..cb9c4c6ba7 100644 --- a/frontend/projects/upgrade/src/app/features/dashboard/home/components/experiment-design/payloads-table/payloads-table.component.ts +++ b/frontend/projects/upgrade/src/app/features/dashboard/home/components/experiment-design/payloads-table/payloads-table.component.ts @@ -112,13 +112,14 @@ export class PayloadsTableComponent implements OnInit, OnDestroy { handleEditClick(rowData: SimpleExperimentPayloadTableRowData, rowIndex: number) { const payloadTableData = this.experimentDesignStepperService.getSimpleExperimentPayloadTableData(); const rowDataCopy = { ...rowData }; + rowDataCopy.payload = rowDataCopy.payload.trim(); payloadTableData[rowIndex] = rowDataCopy; - if (this.currentPayloadInput$.value !== rowData.payload) { + if (this.currentPayloadInput$.value !== rowDataCopy.payload) { payloadTableData[rowIndex].useCustom = true; } - this.currentPayloadInput$.next(rowData.payload); + this.currentPayloadInput$.next(rowDataCopy.payload); this.experimentDesignStepperService.setUpdatePayloadTableEditModeDetails(rowIndex, false); this.experimentDesignStepperService.setNewSimpleExperimentPayloadTableData(payloadTableData); } From a765a920b6b434bbaba2e7ff1c14ad723f20c28f Mon Sep 17 00:00:00 2001 From: Zack Lee Date: Wed, 11 Jun 2025 22:14:15 +0900 Subject: [PATCH 2/3] Add TrimInputDirective to auto-trim payload input values --- .../payloads-table.component.html | 1 + .../payloads-table.component.ts | 7 ++-- .../conditions-table.component.html | 1 + ...factorial-experiment-design.component.html | 1 + .../shared/directives/trim-input.directive.ts | 37 +++++++++++++++++++ .../upgrade/src/app/shared/shared.module.ts | 3 ++ 6 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 frontend/projects/upgrade/src/app/shared/directives/trim-input.directive.ts diff --git a/frontend/projects/upgrade/src/app/features/dashboard/home/components/experiment-design/payloads-table/payloads-table.component.html b/frontend/projects/upgrade/src/app/features/dashboard/home/components/experiment-design/payloads-table/payloads-table.component.html index 73af470757..a43b3f9611 100644 --- a/frontend/projects/upgrade/src/app/features/dashboard/home/components/experiment-design/payloads-table/payloads-table.component.html +++ b/frontend/projects/upgrade/src/app/features/dashboard/home/components/experiment-design/payloads-table/payloads-table.component.html @@ -62,6 +62,7 @@ required [matAutocomplete]="payloadRowAutoCompleteConditionCodes" (keyup)="handleFilterContextMetaDataConditions(rowData.payload, $event)" + appTrimInput /> diff --git a/frontend/projects/upgrade/src/app/features/dashboard/home/components/factorial-experiment-design/factorial-experiment-design.component.html b/frontend/projects/upgrade/src/app/features/dashboard/home/components/factorial-experiment-design/factorial-experiment-design.component.html index 8d08a6cca6..792cdb7a56 100644 --- a/frontend/projects/upgrade/src/app/features/dashboard/home/components/factorial-experiment-design/factorial-experiment-design.component.html +++ b/frontend/projects/upgrade/src/app/features/dashboard/home/components/factorial-experiment-design/factorial-experiment-design.component.html @@ -539,6 +539,7 @@ formControlName="value" [value]="payload?.value" autocomplete="off" + appTrimInput /> diff --git a/frontend/projects/upgrade/src/app/shared/directives/trim-input.directive.ts b/frontend/projects/upgrade/src/app/shared/directives/trim-input.directive.ts new file mode 100644 index 0000000000..d3e0d05b2e --- /dev/null +++ b/frontend/projects/upgrade/src/app/shared/directives/trim-input.directive.ts @@ -0,0 +1,37 @@ +import { Directive, ElementRef, HostListener } from '@angular/core'; +import { NgControl } from '@angular/forms'; + +/** + * TrimInputDirective automatically trims leading and trailing whitespace + * from form control values when the user finishes editing (on blur). + * + * Usage: + * + * + * This directive will: + * - Trim whitespace on blur (when user finishes editing) + * - Update both the DOM element and the form control + * - Work with any input that has a form control + */ +@Directive({ + selector: '[appTrimInput]', + standalone: false, +}) +export class TrimInputDirective { + constructor(private el: ElementRef, private control: NgControl) {} + + @HostListener('blur') onBlur() { + const value = this.el.nativeElement.value; + if (value != null && typeof value === 'string') { + const trimmedValue = value.trim(); + + // Only update if the value actually changed after trimming + if (trimmedValue !== value) { + this.el.nativeElement.value = trimmedValue; + if (this.control?.control) { + this.control.control.setValue(trimmedValue, { emitEvent: false }); + } + } + } + } +} diff --git a/frontend/projects/upgrade/src/app/shared/shared.module.ts b/frontend/projects/upgrade/src/app/shared/shared.module.ts index ae72779a8f..4fc23947d9 100755 --- a/frontend/projects/upgrade/src/app/shared/shared.module.ts +++ b/frontend/projects/upgrade/src/app/shared/shared.module.ts @@ -34,6 +34,7 @@ import { TruncatePipe } from './pipes/truncate.pipe'; import { ExperimentStatePipe } from './pipes/experiment-state.pipe'; import { FormatDatePipe } from './pipes/format-date.pipe'; import { ScrollDirective } from './directives/scroll.directive'; +import { TrimInputDirective } from './directives/trim-input.directive'; import { OperationPipe } from './pipes/operation.pipe'; import { SegmentStatusPipe } from './pipes/segment-status.pipe'; import { QueryResultComponent } from './components/query-result/query-result.component'; @@ -76,6 +77,7 @@ import { MatConfirmDialogComponent } from './components/mat-confirm-dialog/mat-c TruncatePipe, ExperimentStatePipe, ScrollDirective, + TrimInputDirective, FormatDatePipe, OperationPipe, QueryResultComponent, @@ -118,6 +120,7 @@ import { MatConfirmDialogComponent } from './components/mat-confirm-dialog/mat-c ExperimentStatePipe, FormatDatePipe, ScrollDirective, + TrimInputDirective, OperationPipe, QueryResultComponent, DeleteComponent, From 0a8d139c6c4f12d445a0a94c6debd16087154ffa Mon Sep 17 00:00:00 2001 From: Zack Lee Date: Wed, 11 Jun 2025 23:04:12 +0900 Subject: [PATCH 3/3] Remove redundant null checking --- .../upgrade/src/app/shared/directives/trim-input.directive.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/projects/upgrade/src/app/shared/directives/trim-input.directive.ts b/frontend/projects/upgrade/src/app/shared/directives/trim-input.directive.ts index d3e0d05b2e..c0ee3b8d99 100644 --- a/frontend/projects/upgrade/src/app/shared/directives/trim-input.directive.ts +++ b/frontend/projects/upgrade/src/app/shared/directives/trim-input.directive.ts @@ -22,7 +22,7 @@ export class TrimInputDirective { @HostListener('blur') onBlur() { const value = this.el.nativeElement.value; - if (value != null && typeof value === 'string') { + if (typeof value === 'string') { const trimmedValue = value.trim(); // Only update if the value actually changed after trimming