Skip to content

Commit b2f3cd0

Browse files
authored
Merge pull request #72 from ioet/3-filter-project
#3 Time Clock - find project
2 parents e592d21 + 90d93a5 commit b2f3cd0

19 files changed

+323
-146
lines changed

src/app/app.module.ts

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ import { GroupByDatePipe } from './modules/shared/pipes/group-by-date/group-by-d
2424
import { ActivitiesManagementComponent } from './modules/activities-management/pages/activities-management.component';
2525
import { ActivityListComponent } from './modules/activities-management/components/activity-list/activity-list.component';
2626
import { CreateActivityComponent } from './modules/activities-management/components/create-activity/create-activity.component';
27-
27+
import { FilterProjectPipe } from './modules/shared/pipes/filter-project/filter-project.pipe';
28+
import { SearchProjectComponent } from './modules/shared/components/search-project/search-project.component';
2829
import { HomeComponent } from './modules/home/home.component';
2930
import { LoginComponent } from './modules/login/login.component';
3031

@@ -51,17 +52,12 @@ import { LoginComponent } from './modules/login/login.component';
5152
CreateActivityComponent,
5253
ActivityListComponent,
5354
HomeComponent,
54-
LoginComponent
55-
],
56-
imports: [
57-
CommonModule,
58-
BrowserModule,
59-
AppRoutingModule,
60-
FormsModule,
61-
ReactiveFormsModule,
62-
HttpClientModule
55+
LoginComponent,
56+
FilterProjectPipe,
57+
SearchProjectComponent,
6358
],
59+
imports: [CommonModule, BrowserModule, AppRoutingModule, FormsModule, ReactiveFormsModule, HttpClientModule],
6460
providers: [],
65-
bootstrap: [AppComponent]
61+
bootstrap: [AppComponent],
6662
})
67-
export class AppModule { }
63+
export class AppModule {}
Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,40 @@
11
<div class="card-body">
2+
<app-search-project (changeFilterProject)="filterProjects = $event"></app-search-project>
3+
<hr />
24
<div class="scroll">
35
<div class="accordion" id="accordionProject">
46
<div *ngIf="projects?.length > 0; else notShow">
5-
<div class="card" *ngFor="let project of projects; let rowIndex = index">
7+
<div class="card" *ngFor="let project of projects | filterProject: filterProjects; let rowIndex = index">
68
<div class="card-header">
79
<h2 class="mb-0">
8-
<a type="button" data-toggle="collapse" [attr.data-target]="'#row'+rowIndex" [attr.aria-controls]="'row'+rowIndex">
9-
{{project.name}}
10+
<a
11+
type="button"
12+
data-toggle="collapse"
13+
[attr.data-target]="'#row' + rowIndex"
14+
[attr.aria-controls]="'row' + rowIndex"
15+
>
16+
{{ project.name }}
1017
</a>
11-
<div class="btn-group float-right" role="group" >
18+
<div class="btn-group float-right" role="group">
1219
<i (click)="editProject.emit(project.id)" class="far fa-edit btn btn-link"></i>
13-
<i (click)="openModal(project)" data-toggle="modal" data-target="#deleteModal" class="far fa-trash-alt btn btn-link"></i>
20+
<i
21+
(click)="openModal(project)"
22+
data-toggle="modal"
23+
data-target="#deleteModal"
24+
class="far fa-trash-alt btn btn-link"
25+
></i>
1426
</div>
1527
</h2>
1628
</div>
1729

18-
<div [id]="'row'+rowIndex" class="collapse" data-parent="#accordionProject">
30+
<div [id]="'row' + rowIndex" class="collapse" data-parent="#accordionProject">
1931
<div class="card-body">
2032
<h5>Details:</h5>
21-
<p>{{project.details}}</p>
33+
<p>{{ project.details }}</p>
2234
<h5>Status:</h5>
23-
<p>{{project.status}}</p>
35+
<p>{{ project.status }}</p>
2436
<h5>Completed project:</h5>
25-
<p>{{project.completed ? 'Yes' : 'No'}}</p>
37+
<p>{{ project.completed ? 'Yes' : 'No' }}</p>
2638
</div>
2739
</div>
2840
</div>
@@ -34,8 +46,14 @@ <h5>Completed project:</h5>
3446
</div>
3547
</div>
3648

37-
<app-modal *ngIf = "openDeleteModal" class="modal fade" id="deleteModal" tabindex="-1" role="dialog" aria-hidden="true"
38-
[list] = "projectToDelete"
39-
(removeList) = "removeProject($event)"
49+
<app-modal
50+
*ngIf="openDeleteModal"
51+
class="modal fade"
52+
id="deleteModal"
53+
tabindex="-1"
54+
role="dialog"
55+
aria-hidden="true"
56+
[list]="projectToDelete"
57+
(removeList)="removeProject($event)"
4058
>
4159
</app-modal>

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
22

33
import { ProjectListComponent } from './project-list.component';
4+
import { FilterProjectPipe } from '../../../shared/pipes';
45

56
describe('ProjectListComponent', () => {
67
let component: ProjectListComponent;
78
let fixture: ComponentFixture<ProjectListComponent>;
89

910
beforeEach(async(() => {
1011
TestBed.configureTestingModule({
11-
declarations: [ ProjectListComponent ]
12-
})
13-
.compileComponents();
12+
declarations: [ProjectListComponent, FilterProjectPipe],
13+
}).compileComponents();
1414
}));
1515

1616
beforeEach(() => {
@@ -29,7 +29,7 @@ describe('ProjectListComponent', () => {
2929
name: 'app 4',
3030
details: 'It is a good app',
3131
status: 'inactive',
32-
completed: true
32+
completed: true,
3333
};
3434

3535
component.projectToDelete = project;
@@ -45,7 +45,7 @@ describe('ProjectListComponent', () => {
4545
name: 'app 4',
4646
details: 'It is a good app',
4747
status: 'inactive',
48-
completed: true
48+
completed: true,
4949
};
5050

5151
component.openModal(project);

src/app/modules/project-management/components/project-list/project-list.component.ts

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,23 @@
1-
import {
2-
Component,
3-
OnInit,
4-
Input,
5-
Output,
6-
EventEmitter
7-
} from '@angular/core';
1+
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
82
import { Project } from '../../../shared/models';
93

104
@Component({
115
selector: 'app-project-list',
126
templateUrl: './project-list.component.html',
13-
styleUrls: ['./project-list.component.scss']
7+
styleUrls: ['./project-list.component.scss'],
148
})
159
export class ProjectListComponent implements OnInit {
16-
1710
@Input() projects: Project[] = [];
1811
@Output() editProject = new EventEmitter();
1912
@Output() deleteProject = new EventEmitter();
2013

2114
projectToDelete: Project;
2215
openDeleteModal = false;
16+
filterProjects = '';
2317

24-
constructor() { }
18+
constructor() {}
2519

26-
ngOnInit(): void {
27-
}
20+
ngOnInit(): void {}
2821

2922
openModal(projectData) {
3023
this.projectToDelete = projectData;

src/app/modules/project-management/pages/project-management.component.spec.ts

Lines changed: 36 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -6,52 +6,50 @@ import { CreateProjectComponent, ProjectListComponent } from '../components';
66
import { Project } from '../../shared/models';
77
import { ProjectManagementComponent } from './project-management.component';
88
import { ProjectService } from '../services/project.service';
9+
import { FilterProjectPipe } from '../../shared/pipes';
910

1011
describe('ProjectManagementComponent', () => {
1112
let component: ProjectManagementComponent;
1213
let fixture: ComponentFixture<ProjectManagementComponent>;
1314
let projectService: ProjectService;
1415

15-
const projects: Project[] = [{
16-
id: '1',
17-
name: 'app 1',
18-
details: 'It is a good app',
19-
status: 'inactive',
20-
completed: true
21-
},
22-
{
23-
id: '2',
24-
name: 'app 2',
25-
details: 'It is a good app',
26-
status: 'inactive',
27-
completed: false
28-
},
29-
{
30-
id: '3',
31-
name: 'app 3',
32-
details: 'It is a good app',
33-
status: 'active',
34-
completed: true
35-
}
16+
const projects: Project[] = [
17+
{
18+
id: '1',
19+
name: 'app 1',
20+
details: 'It is a good app',
21+
status: 'inactive',
22+
completed: true,
23+
},
24+
{
25+
id: '2',
26+
name: 'app 2',
27+
details: 'It is a good app',
28+
status: 'inactive',
29+
completed: false,
30+
},
31+
{
32+
id: '3',
33+
name: 'app 3',
34+
details: 'It is a good app',
35+
status: 'active',
36+
completed: true,
37+
},
3638
];
3739

3840
const projectServiceStub = {
3941
getProjects() {
4042
const projectsMock = projects;
4143
return of(projectsMock);
42-
}
44+
},
4345
};
4446

4547
beforeEach(async(() => {
4648
TestBed.configureTestingModule({
47-
declarations: [ ProjectManagementComponent, CreateProjectComponent, ProjectListComponent ],
48-
providers: [ { provide: ProjectService, useValue: projectServiceStub }],
49-
imports: [
50-
FormsModule,
51-
ReactiveFormsModule
52-
]
53-
})
54-
.compileComponents();
49+
declarations: [ProjectManagementComponent, CreateProjectComponent, ProjectListComponent, FilterProjectPipe],
50+
providers: [{ provide: ProjectService, useValue: projectServiceStub }],
51+
imports: [FormsModule, ReactiveFormsModule],
52+
}).compileComponents();
5553
}));
5654

5755
beforeEach(() => {
@@ -63,12 +61,12 @@ describe('ProjectManagementComponent', () => {
6361
component.projects = projects;
6462
});
6563

66-
67-
it('Service injected via inject(...) and TestBed.get(...) should be the same instance',
68-
inject([ProjectService], (injectService: ProjectService) => {
64+
it('Service injected via inject(...) and TestBed.get(...) should be the same instance', inject(
65+
[ProjectService],
66+
(injectService: ProjectService) => {
6967
expect(injectService).toBe(projectService);
70-
})
71-
);
68+
}
69+
));
7270

7371
it('should create', () => {
7472
expect(component).toBeTruthy();
@@ -79,7 +77,7 @@ describe('ProjectManagementComponent', () => {
7977
name: 'app 4',
8078
details: 'It is a good app',
8179
status: 'inactive',
82-
completed: true
80+
completed: true,
8381
};
8482

8583
component.editedProjectId = null;
@@ -93,7 +91,7 @@ describe('ProjectManagementComponent', () => {
9391
name: 'app test',
9492
details: 'It is a excelent app',
9593
status: 'inactive',
96-
completed: true
94+
completed: true,
9795
};
9896

9997
component.editedProjectId = '1';
@@ -117,7 +115,7 @@ describe('ProjectManagementComponent', () => {
117115
name: 'app 1',
118116
details: 'It is a good app',
119117
status: 'inactive',
120-
completed: true
118+
completed: true,
121119
};
122120

123121
component.project = project;
@@ -138,9 +136,7 @@ describe('ProjectManagementComponent', () => {
138136
expect(componentSpy).toHaveBeenCalledTimes(1);
139137
});
140138

141-
142139
it('should call getProjects and return a list of projects', async(() => {
143-
144140
spyOn(projectService, 'getProjects').and.returnValue(of(projects));
145141

146142
component.ngOnInit();
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<div class="form-group">
2+
<input (keyup)="changeFilterValue()" type="text" class="form-control" placeholder="&#xF002; Search projects..." name="filterProject" [(ngModel)]="filterProject" style="font-family:'Segoe UI', Tahoma, Geneva, Verdana, sans-serif, FontAwesome">
3+
</div>

src/app/modules/shared/components/search-project/search-project.component.scss

Whitespace-only changes.
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2+
3+
import { SearchProjectComponent } from './search-project.component';
4+
5+
describe('SearchProjectComponent', () => {
6+
let component: SearchProjectComponent;
7+
let fixture: ComponentFixture<SearchProjectComponent>;
8+
9+
beforeEach(async(() => {
10+
TestBed.configureTestingModule({
11+
declarations: [SearchProjectComponent],
12+
}).compileComponents();
13+
}));
14+
15+
beforeEach(() => {
16+
fixture = TestBed.createComponent(SearchProjectComponent);
17+
component = fixture.componentInstance;
18+
fixture.detectChanges();
19+
});
20+
21+
it('should create', () => {
22+
expect(component).toBeTruthy();
23+
});
24+
25+
it('should emit changeFilterProject event #changeFilterValue', () => {
26+
component.filterProject = 'angular';
27+
spyOn(component.changeFilterProject, 'emit');
28+
component.changeFilterValue();
29+
expect(component.changeFilterProject.emit).toHaveBeenCalled();
30+
});
31+
});
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { Component, OnInit, Output, EventEmitter } from '@angular/core';
2+
3+
@Component({
4+
selector: 'app-search-project',
5+
templateUrl: './search-project.component.html',
6+
styleUrls: ['./search-project.component.scss']
7+
})
8+
export class SearchProjectComponent implements OnInit {
9+
10+
filterProject: string;
11+
@Output() changeFilterProject = new EventEmitter();
12+
13+
constructor() { }
14+
15+
ngOnInit(): void {
16+
}
17+
18+
changeFilterValue() {
19+
this.changeFilterProject.emit(this.filterProject);
20+
}
21+
22+
}

0 commit comments

Comments
 (0)