Skip to content

Commit 1aa27dc

Browse files
committed
fix: Updated Component & Form
Fix bugs and complete functionality
1 parent 3d95918 commit 1aa27dc

File tree

16 files changed

+329
-191
lines changed

16 files changed

+329
-191
lines changed
Lines changed: 12 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,19 @@
1-
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, inject, OnDestroy, OnInit } from '@angular/core';
1+
import { ChangeDetectionStrategy, Component, inject, Input, OnDestroy, OnInit } from '@angular/core';
22
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
33

4-
import { forkJoin, Subscription, switchMap } from 'rxjs';
5-
64
import {
7-
User,
85
TaskService,
96
UserService,
10-
ModalService,
117
InputComponent,
12-
TaskRepository,
13-
UserRepository,
148
TaskUserService,
159
SelectComponent,
1610
DatabaseService,
17-
TaskUserRepository,
1811
NotificationService,
19-
Task,
2012
TextareaComponent,
13+
ModalComponent,
2114
} from 'src/app/shared';
2215
import { TASK_REPOSITORY_TOKEN, TASK_USER_REPOSITORY_TOKEN, USER_REPOSITORY_TOKEN } from 'src/app/injection-tokens';
23-
import { NewTaskFormService } from '../../services';
16+
import { TaskFormService } from '../../services';
2417

2518
@Component({
2619
standalone: true,
@@ -30,7 +23,7 @@ import { NewTaskFormService } from '../../services';
3023
changeDetection: ChangeDetectionStrategy.OnPush,
3124
providers: [
3225
DatabaseService,
33-
NewTaskFormService,
26+
TaskFormService,
3427
NotificationService,
3528
{ provide: TASK_REPOSITORY_TOKEN, useClass: TaskService },
3629
{ provide: USER_REPOSITORY_TOKEN, useClass: UserService },
@@ -39,94 +32,28 @@ import { NewTaskFormService } from '../../services';
3932
imports: [FormsModule, ReactiveFormsModule, InputComponent, SelectComponent, TextareaComponent],
4033
})
4134
export class NewTaskModalComponent implements OnInit, OnDestroy {
42-
private readonly modalService: ModalService;
43-
private readonly taskRepository: TaskRepository;
44-
private readonly userRepository: UserRepository;
45-
private readonly changeDetectorRef: ChangeDetectorRef;
46-
private readonly newTaskFormService: NewTaskFormService;
47-
private readonly taskUserRepository: TaskUserRepository;
48-
private readonly notificationService: NotificationService;
49-
50-
private newTaskFormService$?: Subscription;
51-
52-
private taskTitle!: string;
53-
private taskDescription!: string;
54-
private assignationUserId!: string;
55-
private availableUsers?: User[];
35+
@Input() public modalInstance!: ModalComponent;
36+
private readonly taskFormService: TaskFormService;
5637

5738
public constructor() {
58-
this.modalService = inject(ModalService);
59-
this.changeDetectorRef = inject(ChangeDetectorRef);
60-
this.newTaskFormService = inject(NewTaskFormService);
61-
this.notificationService = inject(NotificationService);
62-
this.userRepository = inject<UserRepository>(USER_REPOSITORY_TOKEN);
63-
this.taskRepository = inject<TaskRepository>(TASK_REPOSITORY_TOKEN);
64-
this.taskUserRepository = inject<TaskUserRepository>(TASK_USER_REPOSITORY_TOKEN);
39+
this.taskFormService = inject(TaskFormService);
6540
}
6641

6742
public ngOnInit(): void {
68-
this.newTaskFormService$ = this.newTaskFormService.form.valueChanges.subscribe({
69-
next: (values) => {
70-
this.taskTitle = values.title;
71-
this.taskDescription = values.description;
72-
this.assignationUserId = values.assigned_user;
73-
this.modalService.updateConfig({
74-
okDisabled: !this.newTaskFormService.form.valid,
75-
cancelDisabled: false,
76-
});
77-
this.changeDetectorRef.detectChanges();
78-
},
79-
});
80-
81-
this.userRepository.index().subscribe({
82-
next: (users) => {
83-
this.availableUsers = users;
84-
this.changeDetectorRef.detectChanges();
85-
},
86-
});
87-
88-
this.modalService.componentInstance?.okEvent.subscribe({
89-
next: () =>
90-
this.taskRepository
91-
.save(<Task>{
92-
title: this.taskTitle,
93-
description: this.taskDescription,
94-
})
95-
.pipe(
96-
switchMap((task) =>
97-
this.taskUserRepository.attach(this.assignationUserId, task.id),
98-
),
99-
)
100-
.subscribe({
101-
next: () => {
102-
this.modalService.componentInstance?.onClose();
103-
this.changeDetectorRef.detectChanges();
104-
this.notificationService.success('New task created successfully!');
105-
},
106-
error: (exception) => {
107-
console.error(exception);
108-
this.modalService.componentInstance?.onClose();
109-
this.notificationService.error(
110-
'Error in creating the task, please try later!',
111-
);
112-
},
113-
}),
114-
});
43+
this.modalInstance.title = 'New Task';
11544
}
11645

11746
public get users() {
118-
return this.availableUsers ?? [];
47+
return [];
11948
}
12049

12150
public get form() {
122-
return this.newTaskFormService.form;
51+
return this.taskFormService.form;
12352
}
12453

12554
public get formService() {
126-
return this.newTaskFormService;
55+
return this.taskFormService;
12756
}
12857

129-
public ngOnDestroy(): void {
130-
this.newTaskFormService$?.unsubscribe();
131-
}
58+
public ngOnDestroy(): void {}
13259
}

task-manager/src/app/board/components/task-list-item/task-list-item.component.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
ModalService,
99
StoreDragTaskService,
1010
StoreTaskService,
11+
StoreTaskUpdateService,
1112
StoreTaskUserService,
1213
StoreUserService,
1314
Task,
@@ -49,13 +50,15 @@ export class TaskListItemComponent implements OnInit {
4950
private readonly storeUserService: StoreUserService;
5051
private readonly storeDragTaskService: StoreDragTaskService;
5152
private readonly storeTaskUserService: StoreTaskUserService;
53+
private readonly storeTaskUpdateService: StoreTaskUpdateService;
5254

5355
public constructor() {
5456
this.isHidden = false;
5557
this.modalService = inject(ModalService);
5658
this.storeUserService = inject(StoreUserService);
5759
this.storeDragTaskService = inject(StoreDragTaskService);
5860
this.storeTaskUserService = inject(StoreTaskUserService);
61+
this.storeTaskUpdateService = inject(StoreTaskUpdateService);
5962
}
6063

6164
public ngOnInit(): void {
@@ -98,8 +101,12 @@ export class TaskListItemComponent implements OnInit {
98101
}
99102

100103
public onUpdateTask() {
104+
this.storeTaskUpdateService.value = this.task;
101105
this.modalService.create({
102106
component: UpdateTaskModalComponent,
107+
params: {
108+
task: this.task,
109+
},
103110
title: 'Update task',
104111
width: '60%',
105112
closeDisabled: false,
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
:host {
2+
display: inline-flex;
3+
width: 100%;
4+
height: 100%;
5+
}
6+
7+
.form {
8+
width: 100%;
9+
height: 100%;
10+
display: inline-flex;
11+
flex-direction: column;
12+
justify-content: center;
13+
align-items: flex-start;
14+
box-sizing: border-box;
15+
gap: 1em;
16+
}
17+
18+
.form > * {
19+
width: 100%;
20+
}
Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,41 @@
1-
<p>update-task-modal works!</p>
1+
<form class="form" [formGroup]="form">
2+
<tm-input
3+
label="Title"
4+
type="text"
5+
name="title"
6+
placeholder="Task title here ..."
7+
[formControlName]="formService.titleFormName">
8+
<span [hidden]="!formService.titleFormControl.hasError('required')" class="error-message">
9+
• Il titolo del task è obbligatorio
10+
</span>
11+
<span [hidden]="!formService.titleFormControl.hasError('minlength')" class="error-message">
12+
• Il titolo del task deve essere lungo minimo 2 caratteri
13+
</span>
14+
<span [hidden]="!formService.titleFormControl.hasError('maxlength')" class="error-message">
15+
• Il titolo del task deve essere lungo massimo 255 caratteri
16+
</span></tm-input
17+
>
18+
<tm-textarea
19+
label="Description"
20+
type="text"
21+
name="description"
22+
placeholder="Task's description here ..."
23+
[formControlName]="formService.descriptionFormName">
24+
<span [hidden]="!formService.descriptionFormControl.hasError('required')" class="error-message">
25+
• La descrizione del task è obbligatoria
26+
</span>
27+
<span [hidden]="!formService.descriptionFormControl.hasError('minlength')" class="error-message">
28+
• La descrizione del task deve essere lunga minimo 2 caratteri
29+
</span>
30+
<span [hidden]="!formService.descriptionFormControl.hasError('maxlength')" class="error-message">
31+
• La descrizione del task deve essere lunga massimo 255 caratteri
32+
</span></tm-textarea
33+
>
34+
<tm-select
35+
[key]="'id'"
36+
[values]="databaseUsers"
37+
[displayValues]="['firstName', 'lastName']"
38+
[emptySelectionLabel]="'Assign to someone ...'"
39+
[formControlName]="formService.assignedUserFormName">
40+
</tm-select>
41+
</form>
Lines changed: 145 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,152 @@
1-
import { Component } from '@angular/core';
1+
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, inject, Input } from '@angular/core';
2+
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
3+
4+
import { concatMap, forkJoin, Subscription, switchMap, tap } from 'rxjs';
5+
6+
import {
7+
DatabaseService,
8+
InputComponent,
9+
ModalComponent,
10+
NotificationService,
11+
SelectComponent,
12+
StoreTaskService,
13+
StoreTaskUserService,
14+
Task,
15+
TaskRepository,
16+
TaskService,
17+
TaskUserRepository,
18+
TaskUserService,
19+
TextareaComponent,
20+
User,
21+
UserRepository,
22+
UserService,
23+
} from 'src/app/shared';
24+
25+
import { TaskFormService } from '../../services';
26+
27+
import { TASK_REPOSITORY_TOKEN, TASK_USER_REPOSITORY_TOKEN, USER_REPOSITORY_TOKEN } from 'src/app/injection-tokens';
228

329
@Component({
430
standalone: true,
531
selector: 'tm-update-task-modal',
6-
imports: [],
732
templateUrl: './update-task-modal.component.html',
833
styleUrls: ['./update-task-modal.component.css'],
34+
changeDetection: ChangeDetectionStrategy.OnPush,
35+
providers: [
36+
DatabaseService,
37+
TaskFormService,
38+
NotificationService,
39+
{ provide: TASK_REPOSITORY_TOKEN, useClass: TaskService },
40+
{ provide: USER_REPOSITORY_TOKEN, useClass: UserService },
41+
{ provide: TASK_USER_REPOSITORY_TOKEN, useClass: TaskUserService },
42+
],
43+
imports: [FormsModule, ReactiveFormsModule, InputComponent, SelectComponent, TextareaComponent],
944
})
10-
export class UpdateTaskModalComponent {}
45+
export class UpdateTaskModalComponent {
46+
@Input() public task!: Task;
47+
@Input() public modalInstance!: ModalComponent;
48+
49+
private title!: string;
50+
private description!: string;
51+
private assignedUserId!: string;
52+
private oldAssignedUserId!: string;
53+
54+
private users?: User[];
55+
private assignedUser?: User;
56+
57+
private close$?: Subscription;
58+
private database$?: Subscription;
59+
private taskFormService$?: Subscription;
60+
61+
private readonly taskRepository: TaskRepository;
62+
private readonly userRepository: UserRepository;
63+
private readonly taskFormService: TaskFormService;
64+
private readonly storeTaskService: StoreTaskService;
65+
private readonly changeDetectorRef: ChangeDetectorRef;
66+
private readonly tasksUserRepository: TaskUserRepository;
67+
private readonly notificationService: NotificationService;
68+
private readonly storeTaskUserService: StoreTaskUserService;
69+
70+
public constructor() {
71+
this.taskFormService = inject(TaskFormService);
72+
this.storeTaskService = inject(StoreTaskService);
73+
this.changeDetectorRef = inject(ChangeDetectorRef);
74+
this.notificationService = inject(NotificationService);
75+
this.storeTaskUserService = inject(StoreTaskUserService);
76+
this.taskRepository = inject<TaskRepository>(TASK_REPOSITORY_TOKEN);
77+
this.userRepository = inject<UserRepository>(USER_REPOSITORY_TOKEN);
78+
this.tasksUserRepository = inject<TaskUserRepository>(TASK_USER_REPOSITORY_TOKEN);
79+
}
80+
81+
public ngOnInit(): void {
82+
this.taskFormService$ = this.taskFormService.form.valueChanges.subscribe({
83+
next: (value) => {
84+
this.title = value.title;
85+
this.description = value.description;
86+
this.assignedUserId = value.assigned_user;
87+
this.modalInstance.disableSubmit = !this.taskFormService.form.valid;
88+
89+
this.changeDetectorRef.detectChanges();
90+
},
91+
});
92+
93+
this.database$ = forkJoin([
94+
this.userRepository.index(),
95+
this.tasksUserRepository.findByTaskId(this.task.id),
96+
]).subscribe({
97+
next: ([users, assignations]) => {
98+
const assignedUserId = assignations[0].userId;
99+
100+
this.users = users;
101+
this.assignedUser = users.find((aUser) => aUser.id === assignedUserId);
102+
this.oldAssignedUserId = this.assignedUser!.id;
103+
104+
this.modalInstance.title = 'Update Task';
105+
this.taskFormService.titleFormControl.patchValue(this.task.title);
106+
this.taskFormService.descriptionFormControl.patchValue(this.task.description);
107+
this.taskFormService.assignedUserFormControl.patchValue(this.assignedUser?.id);
108+
109+
this.changeDetectorRef.detectChanges();
110+
},
111+
});
112+
113+
this.close$ = this.modalInstance.okEvent
114+
.pipe(
115+
concatMap(() =>
116+
this.taskRepository.update(this.task.id, {
117+
title: this.title,
118+
description: this.description,
119+
status: this.task.status,
120+
}),
121+
),
122+
switchMap(() => this.tasksUserRepository.detach(this.oldAssignedUserId, this.task.id)),
123+
switchMap(() => this.tasksUserRepository.attach(this.assignedUserId, this.task.id)),
124+
)
125+
.subscribe({
126+
next: () => {
127+
this.storeTaskService.update(this.task, 'id');
128+
this.notificationService.success('Task updated successfully');
129+
this.changeDetectorRef.detectChanges();
130+
this.modalInstance.closeEvent.next();
131+
},
132+
});
133+
}
134+
135+
public get databaseUsers() {
136+
return this.users ?? [];
137+
}
138+
139+
public get form() {
140+
return this.taskFormService.form;
141+
}
142+
143+
public get formService() {
144+
return this.taskFormService;
145+
}
146+
147+
public ngOnDestroy(): void {
148+
this.close$?.unsubscribe();
149+
this.database$?.unsubscribe();
150+
this.taskFormService$?.unsubscribe();
151+
}
152+
}

0 commit comments

Comments
 (0)