Skip to content

Commit 97780bd

Browse files
authored
Merge pull request #262 from ioet/260-replace-autocomplete-by-select
fix: #260 convert autocomplete into select, removing flaky test on cl…
2 parents da387cd + f5ea0e5 commit 97780bd

File tree

7 files changed

+44
-121
lines changed

7 files changed

+44
-121
lines changed

src/app/modules/shared/components/details-fields/details-fields.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ export class DetailsFieldsComponent implements OnChanges, OnInit {
154154

155155
closeEntryModal() {
156156
this.entryForm.reset();
157-
this.closeModal.nativeElement.click();
157+
this.closeModal?.nativeElement.click();
158158
}
159159

160160
onSubmit() {
Lines changed: 10 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,10 @@
1-
<div class="ng-autocomplete">
2-
<ng-autocomplete
3-
*ngIf="nameActiveProject; else notActiveProject"
4-
class="autocomplete"
5-
(selected)="showButton = ''"
6-
[initialValue]="nameActiveProject"
7-
[data]="listProjects && listProjects"
8-
[searchKeyword]="keyword"
9-
[itemTemplate]="itemTemplate"
10-
[notFoundTemplate]="notFoundTemplate"
11-
>
12-
</ng-autocomplete>
13-
<ng-template #notActiveProject>
14-
<ng-autocomplete
15-
class="autocomplete"
16-
(selected)="showButton = ''"
17-
[data]="listProjects && listProjects"
18-
[searchKeyword]="keyword"
19-
[itemTemplate]="itemTemplate"
20-
[notFoundTemplate]="notFoundTemplate"
21-
>
22-
</ng-autocomplete>
23-
</ng-template>
24-
<ng-template #itemTemplate let-item>
25-
<div class="d-flex">
26-
<div
27-
[innerHTML]="item.name"
28-
(mouseenter)="showButton = item.name"
29-
(mouseleave)="showButton = ''"
30-
(click)="clockIn(item.id)"
31-
class="text-left w-100 py-2 px-3"
32-
></div>
33-
<span *ngIf="showButton === item.name" class="badge badge-light d-flex align-items-center m-2">Clock In</span>
34-
</div>
35-
</ng-template>
36-
<ng-template #notFoundTemplate let-notFound>
37-
<div [innerHTML]="notFound"></div>
38-
</ng-template>
39-
</div>
1+
<form [formGroup]="projectsForm" (ngSubmit)="clockIn()">
2+
<div class="input-group input-group-sm mb-3">
3+
<div class="input-group-prepend">
4+
<span class="input-group-text span-width" id="inputGroup-sizing-sm">Project</span>
5+
</div>
6+
<select (change)="clockIn()" formControlName="project_id" class="form-control">
7+
<option *ngFor="let project of listProjects" value="{{project.id}}">{{ project.name }}</option>
8+
</select>
9+
</div>
10+
</form>
Lines changed: 4 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,7 @@
11
@import '../../../../../styles/colors.scss';
22

3-
.content-projects {
4-
max-height: 10rem;
5-
overflow-x: auto;
6-
7-
li {
8-
display: flex;
9-
cursor: pointer;
10-
font-size: 0.8rem;
11-
padding: 0.5rem 0.8rem;
12-
}
13-
}
14-
15-
.button-clockIn {
16-
font-size: 0.7rem;
17-
padding: 0 0.3rem;
18-
}
19-
20-
.ng-autocomplete {
21-
width: 100%;
22-
}
23-
24-
.autocomplete::ng-deep .autocomplete-container {
25-
border: 1px solid #ced4da;
26-
border-radius: 0 0.25rem 0.25rem 0;
27-
box-shadow: none;
28-
height: 2rem;
29-
30-
.input-container {
31-
height: 100%;
32-
33-
input {
34-
border-radius: 0.25rem;
35-
height: 100%;
36-
}
37-
}
3+
.span-width {
4+
width: 6rem;
5+
background-image: $background-pantone;
6+
color: white;
387
}

src/app/modules/time-clock/components/project-list-hover/project-list-hover.component.spec.ts

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { FormBuilder } from '@angular/forms';
12
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
23
import { provideMockStore, MockStore } from '@ngrx/store/testing';
34
import { HttpClientTestingModule } from '@angular/common/http/testing';
@@ -24,7 +25,7 @@ describe('ProjectListHoverComponent', () => {
2425
},
2526
entries: {
2627
active: {
27-
project_id: '2b87372b-3d0d-4dc0-832b-ae5863cd39e5',
28+
project_id: 'p-1',
2829
start_date: '2020-04-23T16:11:06.455000+00:00',
2930
technologies: ['java', 'typescript'],
3031
},
@@ -37,7 +38,7 @@ describe('ProjectListHoverComponent', () => {
3738
beforeEach(async(() => {
3839
TestBed.configureTestingModule({
3940
declarations: [ProjectListHoverComponent, FilterProjectPipe],
40-
providers: [provideMockStore({ initialState: state })],
41+
providers: [FormBuilder, provideMockStore({ initialState: state })],
4142
imports: [HttpClientTestingModule],
4243
}).compileComponents();
4344
store = TestBed.inject(MockStore);
@@ -54,35 +55,22 @@ describe('ProjectListHoverComponent', () => {
5455
expect(component).toBeTruthy();
5556
});
5657

57-
it('clock-in dispatchs a CreateEntry action', () => {
58-
const entry = {
59-
project_id: '2b87372b-3d0d-4dc0-832b-ae5863cd39e5',
60-
start_date: new Date().toISOString(),
61-
};
62-
58+
it('dispatchs a CreateEntry action when activeEntry is null', () => {
6359
component.activeEntry = null;
6460
spyOn(store, 'dispatch');
6561

66-
component.clockIn('2b87372b-3d0d-4dc0-832b-ae5863cd39e5');
62+
component.clockIn();
6763

68-
expect(store.dispatch).toHaveBeenCalledWith(new CreateEntry(entry));
64+
expect(store.dispatch).toHaveBeenCalledWith(jasmine.any(CreateEntry));
6965
});
7066

71-
it('clock-in dispatchs a UpdateActiveEntry action', () => {
72-
const entry = {
73-
id: '123',
74-
project_id: '2b87372b-3d0d-4dc0-832b-ae5863cd39e5',
75-
start_date: new Date().toISOString(),
76-
};
77-
const updatedEntry = {
78-
id: '123',
79-
project_id: '123372b-3d0d-4dc0-832b-ae5863cd39e5',
80-
};
81-
67+
it('dispatchs a UpdateEntry action when activeEntry is not null', () => {
68+
const entry = { id: '123', project_id: 'p1', start_date: new Date().toISOString() };
69+
const updatedEntry = { id: '123', project_id: 'p-1' };
8270
component.activeEntry = entry;
8371
spyOn(store, 'dispatch');
8472

85-
component.clockIn('123372b-3d0d-4dc0-832b-ae5863cd39e5');
73+
component.clockIn();
8674

8775
expect(store.dispatch).toHaveBeenCalledWith(new UpdateActiveEntry(updatedEntry));
8876
});

src/app/modules/time-clock/components/project-list-hover/project-list-hover.component.ts

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { FormGroup, FormBuilder } from '@angular/forms';
12
import { getProjects } from './../../../customer-management/components/projects/components/store/project.selectors';
23
import { Component, OnInit } from '@angular/core';
34
import { Store, select } from '@ngrx/store';
@@ -14,22 +15,24 @@ import * as entryActions from '../../store/entry.actions';
1415
styleUrls: ['./project-list-hover.component.scss'],
1516
})
1617
export class ProjectListHoverComponent implements OnInit {
18+
1719
listProjects: Project[] = [];
18-
showButton = '';
19-
keyword = 'name';
20-
nameActiveProject: string;
2120
activeEntry;
21+
projectsForm: FormGroup;
2222

23-
constructor(private store: Store<ProjectState>) {}
23+
constructor(private formBuilder: FormBuilder, private store: Store<ProjectState>) {
24+
this.projectsForm = this.formBuilder.group({
25+
project_id: '',
26+
});
27+
}
2428

2529
ngOnInit(): void {
2630
this.store.dispatch(new actions.LoadProjects());
2731
const projects$ = this.store.pipe(select(getProjects));
28-
2932
projects$.subscribe((projects) => {
3033
this.listProjects = projects;
31-
this.loadActiveTimeEntry();
3234
});
35+
this.loadActiveTimeEntry();
3336
}
3437

3538
private loadActiveTimeEntry() {
@@ -38,24 +41,20 @@ export class ProjectListHoverComponent implements OnInit {
3841
activeEntry$.subscribe((activeEntry) => {
3942
this.activeEntry = activeEntry;
4043
if (activeEntry) {
41-
for (const project of this.listProjects) {
42-
if (project.id === activeEntry.project_id) {
43-
this.nameActiveProject = project.name;
44-
break;
45-
}
46-
}
47-
} else {
48-
this.nameActiveProject = null;
44+
this.projectsForm.setValue({
45+
project_id: activeEntry.project_id,
46+
});
4947
}
5048
});
5149
}
5250

53-
clockIn(id: string) {
51+
clockIn() {
52+
const selectedProject = this.projectsForm.get('project_id').value;
5453
if (this.activeEntry) {
55-
const entry = { id: this.activeEntry.id, project_id: id };
54+
const entry = { id: this.activeEntry.id, project_id: selectedProject };
5655
this.store.dispatch(new entryActions.UpdateActiveEntry(entry));
5756
} else {
58-
const newEntry = { project_id: id, start_date: new Date().toISOString() };
57+
const newEntry = { project_id: selectedProject, start_date: new Date().toISOString() };
5958
this.store.dispatch(new entryActions.CreateEntry(newEntry));
6059
}
6160
}

src/app/modules/time-clock/pages/time-clock.component.html

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,8 @@
1212
Hi <strong>{{ username }}</strong>, please select a project to clock-in.
1313
</p>
1414
</div>
15-
16-
</div>
17-
<div class="input-group input-group-sm mb-3 flex-nowrap">
18-
<div class="input-group-prepend">
19-
<span class="input-group-text span-width" id="inputGroup-sizing-sm">Project</span>
20-
</div>
21-
<app-project-list-hover class="w-100"></app-project-list-hover>
2215
</div>
16+
<app-project-list-hover></app-project-list-hover>
2317
<div *ngIf="areFieldsVisible">
2418
<app-entry-fields></app-entry-fields>
2519
</div>

src/app/modules/time-clock/pages/time-clock.component.spec.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { FormBuilder } from '@angular/forms';
12
import { StopTimeEntryRunning } from './../store/entry.actions';
23
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
34
import { HttpClientTestingModule } from '@angular/common/http/testing';
@@ -42,6 +43,7 @@ describe('TimeClockComponent', () => {
4243
imports: [HttpClientTestingModule],
4344
declarations: [TimeClockComponent, ProjectListHoverComponent, FilterProjectPipe],
4445
providers: [
46+
FormBuilder,
4547
AzureAdB2CService,
4648
provideMockStore({ initialState: state }),
4749
],

0 commit comments

Comments
 (0)