Skip to content

Commit 6a8cc0c

Browse files
committed
fix: ioet#89 get last changes and solve conflict
2 parents cba828e + 742b487 commit 6a8cc0c

File tree

48 files changed

+951
-169
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+951
-169
lines changed

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "time-tracker",
3-
"version": "1.0.20",
3+
"version": "1.0.23",
44
"scripts": {
55
"ng": "ng",
66
"start": "ng serve",

src/app/app.module.ts

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@ import { ActivitiesManagementComponent } from './modules/activities-management/p
2828
import { ActivityListComponent } from './modules/activities-management/components/activity-list/activity-list.component';
2929
import { CreateActivityComponent } from './modules/activities-management/components/create-activity/create-activity.component';
3030
import { FilterProjectPipe } from './modules/shared/pipes/filter-project/filter-project.pipe';
31-
import { SearchProjectComponent } from './modules/shared/components/search-project/search-project.component';
31+
import { SearchComponent } from './modules/shared/components/search/search.component';
3232
import { HomeComponent } from './modules/home/home.component';
3333
import { LoginComponent } from './modules/login/login.component';
3434
import { ActivityEffects } from './modules/activities-management/store/activity-management.effects';
35-
import { ProjectEffects } from './modules/project-management/store/project.effects';
35+
import { ProjectEffects } from './modules/customer-management/components/projects/components/store/project.effects';
3636
import { TechnologyEffects } from './modules/shared/store/technology.effects';
3737
import { ProjectTypeEffects } from './modules/customer-management/components/projects-type/store/project-type.effects';
3838
import { reducers, metaReducers } from './reducers';
@@ -51,6 +51,7 @@ import { ProjectTypeListComponent } from './modules/customer-management/componen
5151
// tslint:disable-next-line: max-line-length
5252
import { CreateProjectTypeComponent } from './modules/customer-management/components/projects-type/components/create-project-type/create-project-type.component';
5353
import { CustomerEffects } from './modules/customer-management/store/customer-management.effects';
54+
import { EntryEffects } from './modules/time-clock/store/entry.effects';
5455
import { InjectTokenInterceptor } from './modules/shared/interceptors/inject.token.interceptor';
5556

5657
@NgModule({
@@ -76,7 +77,7 @@ import { InjectTokenInterceptor } from './modules/shared/interceptors/inject.tok
7677
HomeComponent,
7778
LoginComponent,
7879
FilterProjectPipe,
79-
SearchProjectComponent,
80+
SearchComponent,
8081
CustomerComponent,
8182
CustomerListComponent,
8283
ManagementCustomerProjectsComponent,
@@ -103,13 +104,22 @@ import { InjectTokenInterceptor } from './modules/shared/interceptors/inject.tok
103104
maxAge: 15, // Retains last 15 states
104105
})
105106
: [],
106-
EffectsModule.forRoot([ProjectEffects, ActivityEffects, CustomerEffects, TechnologyEffects, ProjectTypeEffects]),
107+
EffectsModule.forRoot([
108+
ProjectEffects,
109+
ActivityEffects,
110+
CustomerEffects,
111+
TechnologyEffects,
112+
ProjectTypeEffects,
113+
EntryEffects,
114+
]),
115+
],
116+
providers: [
117+
{
118+
provide: HTTP_INTERCEPTORS,
119+
useClass: InjectTokenInterceptor,
120+
multi: true,
121+
},
107122
],
108-
providers: [{
109-
provide: HTTP_INTERCEPTORS,
110-
useClass: InjectTokenInterceptor,
111-
multi: true,
112-
}],
113123
bootstrap: [AppComponent],
114124
})
115125
export class AppModule {}

src/app/modules/activities-management/services/activity.service.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,9 @@ describe('Activity Service', () => {
6060
service.deleteActivity(activities[0].id).subscribe((activitiesInResponse) => {
6161
expect(activitiesInResponse.filter((activity) => activity.id !== activities[0].id)).toEqual([activities[1]]);
6262
});
63-
const getActivitiesRequest = httpMock.expectOne(url);
64-
expect(getActivitiesRequest.request.method).toBe('DELETE');
65-
getActivitiesRequest.flush(activities);
63+
const deleteActivitiesRequest = httpMock.expectOne(url);
64+
expect(deleteActivitiesRequest.request.method).toBe('DELETE');
65+
deleteActivitiesRequest.flush(activities);
6666
});
6767

6868
it('update activity using PUT from baseUrl', () => {

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,10 @@
4949
></app-create-customer>
5050
</div>
5151
<div class="tab-pane fade mt-3" id="projects" role="tabpanel" aria-labelledby="projects-tab">
52-
<app-create-project></app-create-project>
52+
<div class="container mb-1">
53+
<app-create-project></app-create-project>
54+
<app-project-list></app-project-list>
55+
</div>
5356
</div>
5457
<div class="tab-pane fade mt-3" id="projectsType" role="tabpanel" aria-labelledby="projects-type-tab">
5558
<div class="container">

src/app/modules/customer-management/components/projects-type/store/project-type.selectors.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,14 @@ export const projectTypeIdToEdit = createSelector(getProjectTypeState, (state: P
1212
return state.projectTypeIdToEdit;
1313
});
1414

15-
export const getProjectTypeById = createSelector(allProjectTypes, projectTypeIdToEdit, (projectType, projectTypeId) => {
16-
if (projectType && projectTypeId) {
17-
return projectType.find((activity) => {
18-
return activity.id === projectTypeId;
19-
});
15+
export const getProjectTypeById = createSelector(
16+
allProjectTypes,
17+
projectTypeIdToEdit,
18+
(projectTypes, projectTypeId) => {
19+
if (projectTypes && projectTypeId) {
20+
return projectTypes.find((projectType) => {
21+
return projectType.id === projectTypeId;
22+
});
23+
}
2024
}
21-
});
25+
);
Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,36 @@
1-
<div class="container mb-1">
2-
<form style="width: 600px;">
3-
<div class="form-group">
4-
<input type="text" class="form-control form-control-sm" id="projectName" placeholder="Project name" />
5-
<textarea
6-
class="form-control form-control-sm mt-2"
7-
id="exampleFormControlTextarea1"
8-
rows="3"
9-
placeholder="Description"
10-
></textarea>
11-
<select class="form-group custom-select custom-select-sm mt-2">
12-
<option selected>Select project type</option>
13-
<option value="1">a..</option>
14-
<option value="2">b..</option>
15-
</select>
16-
<button type="submit" class="btn btn-sm btn-primary">Save</button>
17-
<button type="submit" class="btn btn-sm btn-secondary mb-2 ml-2 mt-2">Cancel</button>
18-
</div>
19-
</form>
20-
<hr />
21-
<div class="row text-right">
22-
<hr />
23-
<div class="col-5 text-right">
24-
<app-search-project></app-search-project>
1+
<form style="width: 600px;" [formGroup]="projectForm" (ngSubmit)="onSubmit(projectForm.value)">
2+
<div class="form-group">
3+
<input
4+
type="text"
5+
class="form-control form-control-sm"
6+
placeholder="Project name"
7+
formControlName="name"
8+
[class.is-invalid]="name.invalid && name.touched"
9+
/>
10+
<div class="text-danger" *ngIf="(name.dirty || name.touched) && name.invalid && name.errors.required">
11+
Project name is required.
2512
</div>
2613
</div>
27-
<app-project-list></app-project-list>
28-
</div>
14+
<textarea
15+
class="form-control form-control-sm mt-2"
16+
rows="3"
17+
formControlName="description"
18+
placeholder="Description"
19+
></textarea>
20+
<div class="form-group">
21+
<select class="custom-select custom-select-sm mt-2" formControlName="project_type_id">
22+
<option [value]="" disabled selected>Select project type</option>
23+
<option *ngFor="let type of projectsTypes" [value]="type.id">{{ type.name }}</option>
24+
</select>
25+
</div>
26+
<button type="submit" [disabled]="!projectForm.valid" class="btn btn-sm btn-primary">Save</button>
27+
<button
28+
type="reset"
29+
[hidden]="!projectToEdit"
30+
(click)="cancelButton()"
31+
class="btn btn-sm btn-secondary mb-2 ml-2 mt-2"
32+
>
33+
Cancel
34+
</button>
35+
</form>
36+
<hr />
Lines changed: 128 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,151 @@
11
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2-
2+
import { MockStore, provideMockStore } from '@ngrx/store/testing';
3+
import { FormBuilder } from '@angular/forms';
4+
import { Subscription } from 'rxjs';
35
import { CreateProjectComponent } from './create-project.component';
6+
import { ProjectState } from '../store/project.reducer';
7+
import { Project } from 'src/app/modules/shared/models';
8+
import { getProjectToEdit } from '../store/project.selectors';
9+
import { UpdateProject, CreateProject, ResetProjectToEdit } from '../store/project.actions';
410

511
describe('InputProjectComponent', () => {
612
let component: CreateProjectComponent;
713
let fixture: ComponentFixture<CreateProjectComponent>;
14+
let store: MockStore<ProjectState>;
15+
let getProjectToEditMock;
16+
17+
const state = {
18+
projectList: [{ id: '', name: '', project_type_id: '' }],
19+
isLoading: false,
20+
message: '',
21+
projectToEdit: undefined,
22+
};
23+
24+
const project: Project = {
25+
id: '1',
26+
name: 'Test',
27+
description: 'xxx',
28+
project_type_id: '123',
29+
};
30+
31+
const projectForm = {
32+
name: 'Test',
33+
description: 'xxx',
34+
project_type_id: '123',
35+
};
836

937
beforeEach(async(() => {
1038
TestBed.configureTestingModule({
1139
declarations: [CreateProjectComponent],
40+
providers: [FormBuilder, provideMockStore({ initialState: state })],
1241
}).compileComponents();
1342
}));
1443

1544
beforeEach(() => {
1645
fixture = TestBed.createComponent(CreateProjectComponent);
1746
component = fixture.componentInstance;
1847
fixture.detectChanges();
48+
49+
store = TestBed.inject(MockStore);
50+
store.setState(state);
51+
52+
component.projectToEditSubscription = new Subscription();
53+
component.projectTypesSubscription = new Subscription();
54+
});
55+
56+
afterEach(() => {
57+
fixture.destroy();
1958
});
2059

2160
it('component should be created', () => {
2261
expect(component).toBeTruthy();
2362
});
63+
64+
it('should destroy the subscriptions', () => {
65+
component.projectToEditSubscription = new Subscription();
66+
component.projectTypesSubscription = new Subscription();
67+
const subscription = spyOn(component.projectToEditSubscription, 'unsubscribe');
68+
const projectTypeSubscription = spyOn(component.projectTypesSubscription, 'unsubscribe');
69+
70+
component.ngOnDestroy();
71+
72+
expect(subscription).toHaveBeenCalledTimes(1);
73+
expect(projectTypeSubscription).toHaveBeenCalledTimes(1);
74+
});
75+
76+
it('should reset form #onSubmit and dispatch UpdateProject action', () => {
77+
const currentState = {
78+
data: [project],
79+
isLoading: false,
80+
message: '',
81+
projectToEdit: project,
82+
};
83+
84+
getProjectToEditMock = store.overrideSelector(getProjectToEdit, currentState.projectToEdit);
85+
component.projectToEdit = getProjectToEditMock;
86+
87+
const projectUpdated = {
88+
id: component.projectToEdit.id,
89+
name: 'Test',
90+
description: 'xxx',
91+
project_type_id: '123',
92+
};
93+
94+
component.projectToEditSubscription = new Subscription();
95+
component.projectTypesSubscription = new Subscription();
96+
spyOn(component.projectForm, 'reset');
97+
spyOn(store, 'dispatch');
98+
const subscription = spyOn(component.projectToEditSubscription, 'unsubscribe');
99+
const projectTypeSubscription = spyOn(component.projectTypesSubscription, 'unsubscribe');
100+
101+
component.onSubmit(projectForm);
102+
component.ngOnDestroy();
103+
104+
expect(subscription).toHaveBeenCalledTimes(1);
105+
expect(projectTypeSubscription).toHaveBeenCalledTimes(1);
106+
107+
expect(component.projectForm.reset).toHaveBeenCalled();
108+
expect(store.dispatch).toHaveBeenCalledTimes(1);
109+
expect(store.dispatch).toHaveBeenCalledWith(new UpdateProject(projectUpdated));
110+
});
111+
112+
it('should reset form onSubmit and dispatch CreateProject action', () => {
113+
component.projectToEdit = undefined;
114+
115+
spyOn(component.projectForm, 'reset');
116+
spyOn(store, 'dispatch');
117+
118+
component.onSubmit(project);
119+
120+
expect(component.projectForm.reset).toHaveBeenCalled();
121+
expect(store.dispatch).toHaveBeenCalledTimes(1);
122+
expect(store.dispatch).toHaveBeenCalledWith(new CreateProject(project));
123+
});
124+
125+
it('should set data in projectForm', () => {
126+
component.projectToEditSubscription = new Subscription();
127+
component.projectTypesSubscription = new Subscription();
128+
component.projectToEdit = project;
129+
130+
const subscription = spyOn(component.projectToEditSubscription, 'unsubscribe');
131+
const projectTypeSubscription = spyOn(component.projectTypesSubscription, 'unsubscribe');
132+
spyOn(component.projectForm, 'setValue');
133+
134+
component.setDataToUpdate(project);
135+
component.ngOnDestroy();
136+
137+
expect(subscription).toHaveBeenCalledTimes(1);
138+
expect(projectTypeSubscription).toHaveBeenCalledTimes(1);
139+
expect(component.projectForm.setValue).toHaveBeenCalledTimes(1);
140+
expect(component.projectForm.setValue).toHaveBeenCalledWith(projectForm);
141+
});
142+
143+
it('should dispatch a ResetActivityToEdit action', () => {
144+
spyOn(store, 'dispatch');
145+
146+
component.cancelButton();
147+
148+
expect(store.dispatch).toHaveBeenCalledTimes(1);
149+
expect(store.dispatch).toHaveBeenCalledWith(new ResetProjectToEdit());
150+
});
24151
});

0 commit comments

Comments
 (0)