From b7b627d9ce3fa5b6732543e93029415e3d6e9474 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Mon, 27 Jan 2025 10:30:47 +0100 Subject: [PATCH] refactor action plan --- .../action-plan/action-plan.component.html | 38 ++-- .../action-plan/action-plan.component.spec.ts | 2 +- .../action-plan/action-plan.component.ts | 176 ++++++++---------- .../check-in-form.component.html | 4 +- .../check-in-form/check-in-form.component.ts | 47 +++-- .../key-result-dialog.component.ts | 31 ++- .../key-result-form.component.html | 5 +- .../key-result-form.component.ts | 52 ++---- .../objective/objective-menu-actions.ts | 36 ++-- .../objective-menu-actions.service.ts | 8 +- frontend/src/app/shared/common.ts | 23 +++ frontend/src/app/shared/constant-library.ts | 13 +- frontend/src/app/shared/test-data.ts | 2 +- .../src/app/shared/types/model/key-result.ts | 2 +- 14 files changed, 218 insertions(+), 221 deletions(-) diff --git a/frontend/src/app/components/action-plan/action-plan.component.html b/frontend/src/app/components/action-plan/action-plan.component.html index 55c2b3579b..698a0081e3 100644 --- a/frontend/src/app/components/action-plan/action-plan.component.html +++ b/frontend/src/app/components/action-plan/action-plan.component.html @@ -2,8 +2,7 @@
Drag indicator
- Delete bin + class="btn btn-link" + + >Delete bin +
@@ -52,11 +52,11 @@ class="fw-bold col-auto" id="add-action-button" [attr.data-testId]="'add-action-plan-line'" - (click)="addNewAction()" + (click)="addNewItem()" > Add action icon { it('should add new action with empty text into array', () => { component.control = new BehaviorSubject([]); component.keyResultId = addedAction.keyResultId; - component.addNewAction(); + component.addNewItem(); expect(component.control.getValue()) .toHaveLength(1); expect(component.control.getValue()![0]) diff --git a/frontend/src/app/components/action-plan/action-plan.component.ts b/frontend/src/app/components/action-plan/action-plan.component.ts index ea2e0d0e3c..43f12524ee 100644 --- a/frontend/src/app/components/action-plan/action-plan.component.ts +++ b/frontend/src/app/components/action-plan/action-plan.component.ts @@ -1,138 +1,102 @@ -import { Component, ElementRef, Input, QueryList, ViewChildren } from '@angular/core'; -import { CdkDragDrop, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop'; +import { AfterContentInit, Component, ElementRef, Input, QueryList, ViewChildren } from '@angular/core'; +import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop'; import { Action } from '../../shared/types/model/action'; import { ActionService } from '../../services/action.service'; -import { BehaviorSubject } from 'rxjs'; import { trackByFn } from '../../shared/common'; import { DialogService } from '../../services/dialog.service'; +import { + AbstractControl, + ControlContainer, + FormArray, + FormArrayName, + FormControl, + FormGroup, + FormGroupDirective +} from '@angular/forms'; +import { Observable } from 'rxjs'; + +export type FormControlsOf = { + [P in keyof T]: AbstractControl; +}; + +export interface Item { + id: number | undefined; + item: string; + isChecked: boolean; +} @Component({ selector: 'app-action-plan', templateUrl: './action-plan.component.html', styleUrls: ['./action-plan.component.scss'], - standalone: false + standalone: false, + viewProviders: [{ provide: ControlContainer, + useExisting: FormArrayName }] }) -export class ActionPlanComponent { - @Input() control: BehaviorSubject = new BehaviorSubject([]); - - @Input() keyResultId?: number; +export class ActionPlanComponent implements AfterContentInit { + form?: FormGroup; - activeItem = 0; + @Input() onDelete: (index: number) => Observable = () => new Observable(); @ViewChildren('listItem') listItems!: QueryList; - constructor(private actionService: ActionService, - public dialogService: DialogService) { - } - - handleKeyDown(event: Event, currentIndex: number) { - let newIndex = currentIndex; - if ((event as KeyboardEvent).key === 'ArrowDown') { - if (newIndex + 1 <= this.control.getValue()!.length - 1) { - newIndex += 1; - } - } else if ((event as KeyboardEvent).key === 'ArrowUp') { - if (newIndex - 1 >= 0) { - newIndex -= 1; - } - } - this.changeItemPosition(newIndex, currentIndex); - this.listItems.get(this.activeItem)?.nativeElement.focus(); - } - - changeItemPosition(newIndex: number, currentIndex: number) { - this.activeItem = newIndex; - const currentActionPlan: Action[] = this.control.getValue()!; - this.updateActionTexts(currentActionPlan); - moveItemInArray(currentActionPlan, currentIndex, newIndex); - currentActionPlan.forEach((action: Action, index: number) => action.priority = index); - this.control.next(currentActionPlan); - } - - updateActionTexts(currentActionPlan: Action[]) { - const texts = Array.from(this.listItems) - .map((input: any) => input.nativeElement.value); - currentActionPlan.forEach((action: Action, index: number) => action.action = texts[index]); - } - - increaseActiveItemWithTab() { - if (this.activeItem <= this.control.getValue()!.length - 2) { - this.activeItem++; - } + constructor( + private actionService: ActionService, + public dialogService: DialogService, private parentF: FormGroupDirective, private formArrayNameF: FormArrayName + ) { } - decreaseActiveItemWithShiftTab() { - if (this.activeItem > 0) { - this.activeItem--; - } + changeItemPosition(currentIndex: number, newIndex: number) { + const value = this.getFormControlArray().value as Item[]; + moveItemInArray(value, currentIndex, newIndex); + this.getFormControlArray() + .setValue(value); + this.focusItem(newIndex); } drop(event: CdkDragDrop) { - const value: string = (event.container.element.nativeElement.children[event.previousIndex].children[1] as HTMLInputElement).value; - const actions: Action[] = this.control.getValue()!; - if (actions[event.previousIndex].action == '' && value != '') { - actions[event.previousIndex] = { - ...actions[event.previousIndex], - action: value - }; - this.control.next(actions); - } - if (event.previousContainer === event.container) { - moveItemInArray(event.container.data!, event.previousIndex, event.currentIndex); - } else { - transferArrayItem( - event.previousContainer.data!, event.container.data!, event.previousIndex, event.currentIndex - ); - } - this.adjustPriorities(); - this.activeItem = event.currentIndex; + this.changeItemPosition(event.previousIndex, event.currentIndex); } - adjustPriorities() { - const actions: Action[] = this.control.getValue()!; - actions.forEach(function(action: Action, index: number) { - action.priority = index; - }); - this.control.next(actions); + focusItem(index: number) { + this.listItems.get(index)?.nativeElement.focus(); + this.listItems.get(index)?.nativeElement.scrollIntoView(); } removeAction(index: number) { - const actions: Action[] = this.control.getValue()!; - if (this.activeItem == index && this.activeItem > 0) { - this.activeItem--; - } - if (actions[index].action !== '' || actions[index].id) { + const itemGroup = this.getFormControlArray() + .at(index) as FormGroup; + const itemValue = itemGroup.get('item')?.value; + const itemId = itemGroup.get('id')?.value; + + if (itemValue !== '' || itemId) { this.dialogService .openConfirmDialog('CONFIRMATION.DELETE.ACTION') .afterClosed() .subscribe((result) => { if (result) { - if (actions[index].id) { - this.actionService.deleteAction(actions[index].id) - .subscribe(); - } - actions.splice(index, 1); - this.control.next(actions); - this.adjustPriorities(); + this.getFormControlArray() + .removeAt(index); + + this.onDelete(itemId) + .subscribe(); } }); } else { - actions.splice(index, 1); - this.control.next(actions); - this.adjustPriorities(); + this.getFormControlArray() + .removeAt(index); } } - addNewAction() { - const actions: Action[] = this.control.getValue()!; - actions.push({ - action: '', - priority: actions.length, - keyResultId: this.keyResultId - } as Action); - this.control.next(actions); - this.activeItem = actions.length - 1; + addNewItem() { + const newFormGroup = new FormGroup({ + item: new FormControl(''), + id: new FormControl(undefined), + isChecked: new FormControl(false) + } as FormControlsOf); + this.getFormControlArray() + ?.push(newFormGroup); } /* @@ -144,4 +108,18 @@ export class ActionPlanComponent { } protected readonly trackByFn = trackByFn; + + getFormControlArray() { + return this.form?.get(`${this.formArrayNameF.name}`) as FormArray>>; + } + + ngAfterContentInit(): void { + this.form = this.parentF.form; + if (this.getFormControlArray() + ?.getRawValue().length === 0) { + this.addNewItem(); + this.addNewItem(); + this.addNewItem(); + } + } } diff --git a/frontend/src/app/components/checkin/check-in-form/check-in-form.component.html b/frontend/src/app/components/checkin/check-in-form/check-in-form.component.html index 01f91d9e59..e485f4f412 100644 --- a/frontend/src/app/components/checkin/check-in-form/check-in-form.component.html +++ b/frontend/src/app/components/checkin/check-in-form/check-in-form.component.html @@ -48,7 +48,9 @@ - +
+ +