Skip to content

Commit

Permalink
refactor actionPlan
Browse files Browse the repository at this point in the history
  • Loading branch information
kcinay055679 committed Jan 24, 2025
1 parent 50e5f6a commit 6c0dd25
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 84 deletions.
33 changes: 23 additions & 10 deletions frontend/src/app/components/action-plan/action-plan.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,17 @@ import { Action } from '../../shared/types/model/action';
import { ActionService } from '../../services/action.service';
import { trackByFn } from '../../shared/common';
import { DialogService } from '../../services/dialog.service';
import { ControlContainer, FormArray, FormControl, FormGroup, FormGroupDirective } from '@angular/forms';
import { AbstractControl, ControlContainer, FormArray, FormControl, FormGroup, FormGroupDirective } from '@angular/forms';

export type FormControlsOf<T> = {
[P in keyof T]: AbstractControl<T[P]>;
};

export interface Item {
id: number | undefined;
item: string;
isChecked: boolean;
}

@Component({
selector: 'app-action-plan',
Expand All @@ -27,7 +37,7 @@ export class ActionPlanComponent implements AfterContentInit {
}

changeItemPosition(currentIndex: number, newIndex: number) {
const value = this.getFormControlArray().value;
const value = this.getFormControlArray().value as Item[];
moveItemInArray(value, currentIndex, newIndex);
this.getFormControlArray()
.setValue(value);
Expand Down Expand Up @@ -66,10 +76,11 @@ export class ActionPlanComponent implements AfterContentInit {
}

addNewItem() {
const newItemControl = new FormControl<string>('');
const newIdControl = new FormControl<number | undefined>(undefined);
const newFormGroup = new FormGroup({ item: newItemControl,
id: newIdControl });
const newFormGroup = new FormGroup({
item: new FormControl<string>(''),
id: new FormControl<number | undefined>(undefined),
isChecked: new FormControl<boolean>(false)
} as FormControlsOf<Item>);
this.getFormControlArray()
?.push(newFormGroup);
}
Expand All @@ -85,13 +96,15 @@ export class ActionPlanComponent implements AfterContentInit {
protected readonly trackByFn = trackByFn;

getFormControlArray() {
return this.parentF.form?.get(this.formArrayName) as FormArray;
return this.parentF.form?.get(this.formArrayName) as FormArray<FormGroup<FormControlsOf<Item>>>;
}

ngAfterContentInit(): void {
this.form = this.parentF.form;
this.addNewItem();
this.addNewItem();
this.addNewItem();
if (this.getFormControlArray()?.length === 0) {
this.addNewItem();
this.addNewItem();
this.addNewItem();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
</div>

<ng-template #actionPlanComponent>
<app-action-plan [control]="actionList$" [keyResultId]="keyResult.id"></app-action-plan>
<app-action-plan [formArrayName]="'actionList'"></app-action-plan>
<button
mat-flat-button
color="primary"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
import { ChangeDetectionStrategy, Component, Inject, OnInit } from '@angular/core';
import { KeyResultMetric } from '../../../shared/types/model/key-result-metric';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { FormArray, FormControl, FormGroup, Validators } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { KeyResult } from '../../../shared/types/model/key-result';
import { KeyResultOrdinal } from '../../../shared/types/model/key-result-ordinal';
import { CheckInMin } from '../../../shared/types/model/check-in-min';
import { CheckInService } from '../../../services/check-in.service';
import { Action } from '../../../shared/types/model/action';
import { ActionService } from '../../../services/action.service';
import { formInputCheck, hasFormFieldErrors } from '../../../shared/common';
import { actionListToItemList, formInputCheck, hasFormFieldErrors, itemListToActionList } from '../../../shared/common';
import { TranslateService } from '@ngx-translate/core';
import { CheckIn } from '../../../shared/types/model/check-in';
import { CheckInMetricMin } from '../../../shared/types/model/check-in-metric-min';
import { CheckInOrdinalMin } from '../../../shared/types/model/check-in-ordinal-min';
import { BehaviorSubject } from 'rxjs';

import { FormControlsOf, Item } from '../../action-plan/action-plan.component';
@Component({
selector: 'app-check-in-form',
templateUrl: './check-in-form.component.html',
Expand All @@ -29,8 +28,6 @@ export class CheckInFormComponent implements OnInit {

currentDate: Date;

actionList$: BehaviorSubject<Action[] | null> = new BehaviorSubject<Action[] | null>([] as Action[]);

isAddingAction = false;

dialogForm = new FormGroup({
Expand All @@ -40,7 +37,7 @@ export class CheckInFormComponent implements OnInit {
Validators.max(10)]),
changeInfo: new FormControl<string>('', [Validators.maxLength(4096)]),
initiatives: new FormControl<string>('', [Validators.maxLength(4096)]),
actionList: new FormControl<Action[]>([])
actionList: new FormArray<FormGroup<FormControlsOf<Item>>>([])
});

protected readonly formInputCheck = formInputCheck;
Expand All @@ -61,8 +58,8 @@ export class CheckInFormComponent implements OnInit {

ngOnInit() {
const actionList = this.keyResult.actionList;
this.actionList$.next(actionList);
this.dialogForm.patchValue({ actionList: actionList });
const items = actionListToItemList(actionList);
this.dialogForm.patchValue({ actionList: items });
}

getErrorMessage(error: string, field: string, maxLength: number): string {
Expand All @@ -71,7 +68,8 @@ export class CheckInFormComponent implements OnInit {
}

setDefaultValues() {
this.dialogForm.controls.actionList.setValue(this.keyResult.actionList);
const itemList = actionListToItemList(this.keyResult.actionList);
this.dialogForm.controls.actionList.setValue(itemList);
if (this.data.checkIn != null) {
this.checkIn = this.data.checkIn;
this.dialogForm.controls.value.setValue(this.getCheckInValue());
Expand Down Expand Up @@ -102,8 +100,7 @@ export class CheckInFormComponent implements OnInit {
saveCheckIn() {
this.dialogForm.controls.confidence.setValue(this.checkIn.confidence);

const actionList: Action[] = this.actionList$.value as Action[];
this.dialogForm.patchValue({ actionList: actionList });
const actionList: Action[] = this.getActions();

const baseCheckIn: any = {
id: this.checkIn.id,
Expand All @@ -120,7 +117,7 @@ export class CheckInFormComponent implements OnInit {

this.checkInService.saveCheckIn(checkIn)
.subscribe(() => {
this.actionService.updateActions(this.dialogForm.value.actionList!)
this.actionService.updateActions(actionList)
.subscribe(() => {
this.dialogRef.close();
});
Expand All @@ -144,7 +141,7 @@ export class CheckInFormComponent implements OnInit {
}

getActions(): Action[] {
return this.dialogForm.controls['actionList'].value || [];
return itemListToActionList(this.dialogForm.getRawValue().actionList, this.keyResult.id);
}

changeIsChecked(event: any, index: number) {
Expand All @@ -161,21 +158,10 @@ export class CheckInFormComponent implements OnInit {
}

openActionEdit() {
const actionList: Action[] = this.actionList$.value as Action[];
actionList.push({
action: '',
priority: actionList.length,
keyResultId: this.keyResult.id
} as Action);
this.actionList$.next(actionList);
this.isAddingAction = true;
}

closeActionEdit() {
let actionList: Action[] = this.actionList$.value as Action[];
actionList = actionList.filter((action) => action.action.trim() != '');
this.actionList$.next(actionList);
this.dialogForm.patchValue({ actionList: actionList });
this.isAddingAction = false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { KeyResultService } from '../../services/key-result.service';
import { DialogService } from '../../services/dialog.service';
import { getKeyResultForm } from '../../shared/constant-library';
import { UserService } from '../../services/user.service';
import { KeyResultDto } from '../../shared/types/DTOs/key-result-dto';


@Component({
Expand All @@ -36,28 +37,24 @@ export class KeyResultDialogComponent implements OnInit {
return this.keyResultForm.controls['keyResultType'].value === 'metric';
}

saveActionPoints() {

Check failure on line 40 in frontend/src/app/components/key-result-dialog/key-result-dialog.component.ts

View workflow job for this annotation

GitHub Actions / frontend

Unexpected empty method 'saveActionPoints'

}

saveKeyResult(openNewDialog = false) {
const valueWithType = this.keyResultForm.value;
// Disable to get Value without Type
this.keyResultForm.controls['metric'].disable();
this.keyResultForm.controls['ordinal'].disable();
const valueWithoutType = this.keyResultForm.value;
// reEnable
this.keyResultForm.controls['metric'].enable();
this.keyResultForm.controls['ordinal'].enable();
const keyResult = this.isMetricKeyResult()
? ({
...valueWithoutType,
...valueWithType.metric,
objective: this.data.objective
} as KeyResultMetricDto)
: ({
...valueWithoutType,
...valueWithType.ordinal,
objective: this.data.objective
} as KeyResultOrdinalDto);
let keyResult: KeyResultDto = this.keyResultForm.value;

if (this.isMetricKeyResult()) {
keyResult = keyResult as KeyResultMetricDto;
} else {
keyResult = keyResult as KeyResultOrdinalDto;
}
keyResult.objective = this.data.objective;
keyResult.id = this.data.keyResult?.id;
keyResult.version = this.data.keyResult?.version;

this.keyResultService.saveKeyResult(keyResult)
.subscribe((returnValue) => {
this.dialogRef.close({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ import { getFullNameOfUser, User } from '../../shared/types/model/user';
import { KeyResult } from '../../shared/types/model/key-result';
import { KeyResultMetric } from '../../shared/types/model/key-result-metric';
import { KeyResultOrdinal } from '../../shared/types/model/key-result-ordinal';
import { BehaviorSubject, filter, map, Observable, of, startWith, switchMap } from 'rxjs';
import { filter, map, Observable, of, startWith, switchMap } from 'rxjs';
import { UserService } from '../../services/user.service';
import { Action } from '../../shared/types/model/action';
import { formInputCheck, hasFormFieldErrors } from '../../shared/common';
import { TranslateService } from '@ngx-translate/core';

Expand All @@ -21,7 +20,6 @@ export class KeyResultFormComponent implements OnInit {

filteredUsers$: Observable<User[]> = of([]);

actionList$: BehaviorSubject<Action[] | null> = new BehaviorSubject<Action[] | null>([] as Action[]);

protected readonly formInputCheck = formInputCheck;

Expand All @@ -47,33 +45,7 @@ export class KeyResultFormComponent implements OnInit {
this.isMetricKeyResult()
? this.setMetricValuesInForm(this.keyResult as KeyResultMetric)
: this.setOrdinalValuesInForm(this.keyResult as KeyResultOrdinal);

this.actionList$ = new BehaviorSubject<Action[] | null>(this.keyResult.actionList);
}
if (!this.keyResult) {
this.actionList$ = new BehaviorSubject<Action[] | null>([{ id: null,
version: 1,
action: '',
priority: 0,
keyResultId: undefined,
isChecked: false },
{ id: null,
version: 1,
action: '',
priority: 1,
keyResultId: undefined,
isChecked: false },
{ id: null,
version: 1,
action: '',
priority: 2,
keyResultId: undefined,
isChecked: false }]);
}

this.actionList$.subscribe((value) => {
this.keyResultForm.patchValue({ actionList: value });
});
}

isMetricKeyResult() {
Expand Down
22 changes: 22 additions & 0 deletions frontend/src/app/shared/common.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { FormGroup } from '@angular/forms';
import { KeyResultMetricMin } from './types/model/key-result-metric-min';
import { State } from './types/enums/state';
import { Action } from './types/model/action';
import { Item } from '../components/action-plan/action-plan.component';

export function getNumberOrNull(str: string | null | undefined): number | null {
if (str === null || str === undefined || str.toString()
Expand Down Expand Up @@ -143,3 +145,23 @@ export function getValueOfForm(form: FormGroup, keys: string[]) {
}
return currentControl.value;
}

export function actionListToItemList(actionList: Action[]): Item[] {
return actionList.map((action) => {
return { id: action.id,
item: action.action } as Item;
});
}

export function itemListToActionList(itemList: Item[], keyResultId: number): Action[] {
return itemList.map((item: Item, index) => {
return {
id: item.id,
action: item.item,
priority: index,
keyResultId: keyResultId,
isChecked: false
} as Action;
});
}

3 changes: 2 additions & 1 deletion frontend/src/app/shared/constant-library.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
} from '@angular/forms';
import { Unit } from './types/enums/unit';
import { getFullNameOfUser, User } from './types/model/user';
import { FormControlsOf, Item } from '../components/action-plan/action-plan.component';

type MessageKeyMap = Record<string, MessageEntry>;

Expand Down Expand Up @@ -97,7 +98,7 @@ export function getKeyResultForm(): FormGroup {
owner: new FormControl<User>({} as User, [Validators.required,
Validators.nullValidator,
ownerValidator()]),
actionList: new FormArray([]),
actionList: new FormArray<FormGroup<FormControlsOf<Item>>>([]),
keyResultType: new FormControl('metric'),
metric: new FormGroup({
unit: new FormControl<Unit>(Unit.NUMBER, [Validators.required]),
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/app/shared/types/model/key-result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export interface KeyResult {
objective: KeyResultObjective;
createdOn: Date;
modifiedOn: Date;
actionList: Action[] | null;
actionList: Action[];
lastCheckIn: CheckIn | null;
isWriteable: boolean;
}

0 comments on commit 6c0dd25

Please sign in to comment.