Skip to content

Commit 24752fb

Browse files
authored
fix: TT-26 warn of unsaved changes on customer page (#648)
* feat: TT-26 Warn of unsaved changes on customer pag * fix: TT-26 resolve commets
1 parent e82a479 commit 24752fb

18 files changed

+202
-13
lines changed

src/app/modules/customer-management/components/customer-info/components/create-customer/create-customer.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
formControlName="name"
99
placeholder="Customer name"
1010
[class.is-invalid]="customerForm.invalid && customerForm.touched"
11+
(input)="onInputChangeCustomer($event.target.value)"
1112
required
1213
/>
1314
<span
@@ -23,6 +24,7 @@
2324
rows="3"
2425
formControlName="description"
2526
placeholder="Customer description"
27+
(input)="onInputChangeCustomer($event.target.value)"
2628
></textarea>
2729
</div>
2830
<button type="submit" class="btn btn-primary" [disabled]="!customerForm.valid">Save</button>

src/app/modules/customer-management/components/customer-info/components/create-customer/create-customer.spec.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,4 +140,23 @@ describe('CreateCustomerComponent', () => {
140140
expect(component.changeValueAreTabsActives.emit).toHaveBeenCalledWith(component.areTabsActive);
141141
});
142142

143+
it('if detect changes in customer information, it should emit a true', () => {
144+
component.hasChange = true;
145+
spyOn(component.hasChangedEvent, 'emit');
146+
147+
component.onInputChangeCustomer('changes text');
148+
149+
expect(component.hasChange).toBe(true);
150+
expect(component.hasChangedEvent.emit).toHaveBeenCalledWith(component.hasChange);
151+
});
152+
153+
it('if not detect changes in customer information, it should emit a false', () => {
154+
component.hasChange = false;
155+
spyOn(component.hasChangedEvent, 'emit');
156+
157+
component.onInputChangeCustomer('');
158+
159+
expect(component.hasChange).toBe(false);
160+
expect(component.hasChangedEvent.emit).toHaveBeenCalledWith(component.hasChange);
161+
});
143162
});

src/app/modules/customer-management/components/customer-info/components/create-customer/create-customer.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import { LoadCustomerProjects, CleanCustomerProjects } from '../../../projects/c
2323
export class CreateCustomerComponent implements OnInit, OnDestroy {
2424
customerForm: FormGroup;
2525
@Input() areTabsActive: boolean;
26+
@Input() hasChange: boolean;
27+
@Output() hasChangedEvent = new EventEmitter<boolean>();
2628
@Output() changeValueAreTabsActives = new EventEmitter<boolean>();
2729
@Output() closeCustomerComponent = new EventEmitter<boolean>();
2830
customerToEdit: Customer;
@@ -68,6 +70,7 @@ export class CreateCustomerComponent implements OnInit, OnDestroy {
6870
this.store.dispatch(new LoadProjectTypes(customerData.id));
6971
this.store.dispatch(new LoadCustomerProjects(customerData.id));
7072
this.changeValueAreTabsActives.emit(true);
73+
this.hasChangedEvent.emit(this.hasChange = false);
7174
this.customerForm.setValue({
7275
name: customerData.name,
7376
description: customerData.description,
@@ -94,4 +97,9 @@ export class CreateCustomerComponent implements OnInit, OnDestroy {
9497
this.store.dispatch(new ResetCustomerToEdit());
9598
this.closeCustomerComponent.emit(false);
9699
}
100+
101+
onInputChangeCustomer(searchValue: string): void {
102+
return searchValue ? this.hasChangedEvent.emit(this.hasChange = true) :
103+
this.hasChangedEvent.emit(this.hasChange = false);
104+
}
97105
}

src/app/modules/customer-management/components/customer-info/components/customer-list/customer-list.component.html

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,15 @@
2020
<td class="col-3 text-break">{{ customer.name }}</td>
2121
<td class="col-4 text-center">
2222
<button
23+
data-toggle="modal"
2324
(click)="editCustomer(customer.id)"
2425
type="button"
26+
data-target="#editModal"
2527
class="btn btn-sm btn-primary"
2628
>
27-
<i class="fa fa-pencil fa-xs"></i>
29+
<i class="fa fa-pen fa-xs"></i>
2830
</button>
31+
2932
<button
3033
data-toggle="modal"
3134
data-target="#deleteModal"
@@ -53,3 +56,16 @@
5356
(closeModalEvent)="deleteCustomer()"
5457
>
5558
</app-dialog>
59+
60+
<app-dialog
61+
*ngIf="showModal"
62+
class="modal fade"
63+
id="editModal"
64+
tabindex="-1"
65+
role="dialog"
66+
aria-hidden="true"
67+
[title]="'Edit Customer'"
68+
[body]="message"
69+
(closeModalEvent)="closeModal()"
70+
>
71+
</app-dialog>

src/app/modules/customer-management/components/customer-info/components/customer-list/customer-list.component.spec.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,27 @@ describe('CustomerTableListComponent', () => {
5858
expect(store.dispatch).toHaveBeenCalledWith(new LoadCustomers());
5959
});
6060

61-
it('onClick edit, dispatch SetCustomerToEdit and enable customer form', () => {
61+
62+
it('Onclick Edit, if there are changes, the modal must be presented ', () => {
63+
component.hasChange = true;
64+
const expectMessage = 'Do you have changes in a client, do you want to discard them?';
65+
66+
component.editCustomer('1');
67+
68+
expect(component.message).toEqual(expectMessage);
69+
expect(component.showModal).toBeTrue();
70+
});
71+
72+
it('onClick edit, if there are not have changes dispatch SetCustomerToEdit, enable customer form and hidden modal', () => {
73+
component.hasChange = false;
74+
6275
spyOn(store, 'dispatch');
6376

6477
component.editCustomer('1');
6578

6679
expect(store.dispatch).toHaveBeenCalledWith(new SetCustomerToEdit('1'));
6780
expect(component.showCustomerForm).toBeTruthy();
81+
expect(component.showModal).toBeFalse();
6882
});
6983

7084
it('onClick edit, dispatch clean Forms in project and project type', () => {
@@ -76,6 +90,18 @@ describe('CustomerTableListComponent', () => {
7690
expect(store.dispatch).toHaveBeenCalledWith(new ResetProjectTypeToEdit());
7791
});
7892

93+
it('when you click close modal, you should close the modal, discard the current changes and load a new client for edit', () => {
94+
spyOn(component.changeValueShowCustomerForm, 'emit');
95+
spyOn(store, 'dispatch');
96+
97+
component.editCustomer('1');
98+
component.closeModal();
99+
100+
expect(component.showModal).toBeFalse();
101+
expect(component.changeValueShowCustomerForm.emit).toHaveBeenCalledWith(true);
102+
expect(store.dispatch).toHaveBeenCalledWith(new SetCustomerToEdit('1'));
103+
});
104+
79105
it('onClick delete, dispatch DeleteCustomer', () => {
80106
spyOn(store, 'dispatch');
81107
component.idToDelete = '1';

src/app/modules/customer-management/components/customer-info/components/customer-list/customer-list.component.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { ResetProjectTypeToEdit } from '../../../projects-type/store';
2020
})
2121
export class CustomerListComponent implements OnInit, OnDestroy, AfterViewInit {
2222
@Input() showCustomerForm: boolean;
23+
@Input() hasChange: boolean;
2324
@Output() changeValueShowCustomerForm = new EventEmitter<boolean>();
2425
@Input()
2526
customers: Customer[] = [];
@@ -31,6 +32,7 @@ export class CustomerListComponent implements OnInit, OnDestroy, AfterViewInit {
3132
changeCustomerSubscription: Subscription;
3233
showModal = false;
3334
idToDelete: string;
35+
idToEdit: string;
3436
message: string;
3537
isLoading$: Observable<boolean>;
3638

@@ -77,10 +79,25 @@ export class CustomerListComponent implements OnInit, OnDestroy, AfterViewInit {
7779
}
7880

7981
editCustomer(customerId: string) {
82+
this.idToEdit = customerId;
83+
if (this.hasChange) {
84+
this.message = 'Do you have changes in a client, do you want to discard them?';
85+
this.showModal = true;
86+
} else {
87+
this.showCustomerForm = true;
88+
this.showModal = false;
89+
this.changeValueShowCustomerForm.emit(this.showCustomerForm);
90+
this.resetProjectFieldsToEdit();
91+
this.store.dispatch(new SetCustomerToEdit(customerId));
92+
}
93+
}
94+
95+
closeModal() {
8096
this.showCustomerForm = true;
97+
this.showModal = false;
8198
this.changeValueShowCustomerForm.emit(this.showCustomerForm);
82-
this.store.dispatch(new SetCustomerToEdit(customerId));
8399
this.resetProjectFieldsToEdit();
100+
this.store.dispatch(new SetCustomerToEdit(this.idToEdit));
84101
}
85102

86103
private resetProjectFieldsToEdit() {
@@ -109,5 +126,4 @@ export class CustomerListComponent implements OnInit, OnDestroy, AfterViewInit {
109126
this.message = `Are you sure you want to delete ${item.name}?`;
110127
this.showModal = true;
111128
}
112-
113129
}

src/app/modules/customer-management/components/management-customer-projects/management-customer-projects.component.html

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ <h4 class="navbar-brand nav-title">{{customerName}}</h4>
5555
<app-create-customer
5656
[areTabsActive]="areTabsActive"
5757
(changeValueAreTabsActives)="activeTabs($event)"
58+
(hasChangedEvent)="getChanges($event)"
5859
(closeCustomerComponent)="closeCustomer($event)"
5960
></app-create-customer>
6061
</div>
@@ -66,7 +67,7 @@ <h4 class="navbar-brand nav-title">{{customerName}}</h4>
6667
aria-labelledby="projects-type-tab"
6768
>
6869
<div class="container">
69-
<app-create-project-type></app-create-project-type>
70+
<app-create-project-type (hasChangedEvent)="getChanges($event)"></app-create-project-type>
7071
<app-project-type-list></app-project-type-list>
7172
</div>
7273
</div>
@@ -78,7 +79,7 @@ <h4 class="navbar-brand nav-title">{{customerName}}</h4>
7879
aria-labelledby="projects-tab"
7980
>
8081
<div class="container mb-1">
81-
<app-create-project></app-create-project>
82+
<app-create-project (hasChangedEvent)="getChanges($event)"></app-create-project>
8283
<app-project-list></app-project-list>
8384
</div>
8485
</div>

src/app/modules/customer-management/components/management-customer-projects/management-customer-projects.component.spec.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,18 @@ describe('ManagmentCustomerProjectsComponent', () => {
6464
component.showTab('projects');
6565
expect(component.activeTab).toEqual('projects');
6666
});
67+
6768
it('should call close customer function', () => {
6869
spyOn(component.closeCustemerForm, 'emit');
6970
component.closeCustomer(false);
7071
expect(component.closeCustemerForm.emit).toHaveBeenCalledWith(false);
7172
});
73+
74+
it('with changes should emit a true ', () => {
75+
spyOn(component.sendChanges, 'emit');
76+
77+
component.getChanges(true);
78+
79+
expect(component.sendChanges.emit).toHaveBeenCalledWith(true);
80+
});
7281
});

src/app/modules/customer-management/components/management-customer-projects/management-customer-projects.component.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ import { Component, Output, EventEmitter, OnInit } from '@angular/core';
1010
})
1111
export class ManagementCustomerProjectsComponent implements OnInit {
1212
@Output() closeCustemerForm = new EventEmitter<boolean>();
13+
@Output() sendChanges = new EventEmitter<boolean>();
1314
areTabsActive: boolean;
15+
hasChanged: boolean;
1416
activeTab: string;
1517
customerName: string;
1618

@@ -42,4 +44,8 @@ export class ManagementCustomerProjectsComponent implements OnInit {
4244
this.activeTab = activeTab;
4345
}
4446

47+
getChanges($value: boolean) {
48+
this.hasChanged = $value;
49+
this.sendChanges.emit($value);
50+
}
4551
}

src/app/modules/customer-management/components/projects-type/components/create-project-type/create-project-type.component.html

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,26 @@
11
<form style="width: 600px;" [formGroup]="projectTypeForm" (ngSubmit)="onSubmit(projectTypeForm.value)">
22
<div class="form-group">
3-
<input type="text" class="form-control form-control-sm" id="name" formControlName="name" aria-describedby=""
4-
[class.is-invalid]="name.invalid && name.touched" required placeholder="Name" />
3+
<input type="text"class="form-control form-control-sm"
4+
id="name"
5+
formControlName="name"
6+
aria-describedby=""
7+
[class.is-invalid]="name.invalid && name.touched"
8+
required placeholder="Name"
9+
(input)="onInputChangeProjectType($event.target.value)"
10+
/>
511
<div class="text-danger" *ngIf="(name.dirty || name.touched) && name.invalid && name.errors.required">
612
Name is required.
713
</div>
814
</div>
915
<div class="form-group">
10-
<textarea class="form-control form-control-sm mt-2" id="descriptionTextArea" rows="3" placeholder="Description"
11-
formControlName="description"></textarea>
16+
<textarea class="form-control
17+
form-control-sm mt-2"
18+
id="descriptionTextArea"
19+
rows="3"
20+
placeholder="Description"
21+
formControlName="description"
22+
(input)="onInputChangeProjectType($event.target.value)"
23+
></textarea>
1224
</div>
1325
<button type="submit" class="btn btn-primary" [disabled]="!projectTypeForm.valid">
1426
Save

0 commit comments

Comments
 (0)