diff --git a/package-lock.json b/package-lock.json
index a8033c5e0..06a2dbb45 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "time-tracker",
- "version": "1.31.7",
+ "version": "1.31.10",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/package.json b/package.json
index 1ea6a7b0d..f7ce1959a 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "time-tracker",
- "version": "1.31.7",
+ "version": "1.31.10",
"scripts": {
"preinstall": "npx npm-force-resolutions",
"ng": "ng",
diff --git a/src/app/modules/shared/components/details-fields/details-fields.component.spec.ts b/src/app/modules/shared/components/details-fields/details-fields.component.spec.ts
index d41f565a8..60139632f 100644
--- a/src/app/modules/shared/components/details-fields/details-fields.component.spec.ts
+++ b/src/app/modules/shared/components/details-fields/details-fields.component.spec.ts
@@ -128,14 +128,14 @@ describe('DetailsFieldsComponent', () => {
expect(component).toBeTruthy();
});
- it('onClearedComponent project id and name it is set to empty', () => {
+ it('onClearedComponent project id and name are set to empty', () => {
component.onClearedComponent(null);
expect(component.project_id.value).toBe('');
expect(component.project_name.value).toBe('');
});
- it('onSelectedProject project id and name it is set using event data', () => {
+ it('onSelectedProject project id and name are set using event data', () => {
spyOn(component.entryForm, 'patchValue');
component.onSelectedProject( {id: 'id', search_field: 'foo'} );
@@ -143,7 +143,7 @@ describe('DetailsFieldsComponent', () => {
expect(component.entryForm.patchValue).toHaveBeenCalledWith( { project_id: 'id', project_name: 'foo', } );
});
- it('if form is invalid then no save is emited', () => {
+ it('if form is invalid then saveEntry is not emited', () => {
spyOn(component.saveEntry, 'emit');
component.onSubmit();
@@ -172,6 +172,7 @@ describe('DetailsFieldsComponent', () => {
it('should emit ngOnChange without data', () => {
component.entryToEdit = null;
component.ngOnChanges();
+ expect(component.shouldRestartEntry).toBeFalse();
expect(component.entryForm.value).toEqual(initialData);
});
@@ -243,6 +244,7 @@ describe('DetailsFieldsComponent', () => {
},
shouldRestartEntry: false
};
+
expect(component.saveEntry.emit).toHaveBeenCalledWith(data);
});
@@ -298,14 +300,23 @@ describe('DetailsFieldsComponent', () => {
fixture.componentInstance.ngOnChanges();
expect(component.goingToWorkOnThis).toBeFalse();
+ expect(component.shouldRestartEntry).toBeFalse();
});
- it('when editing entry that already finished, then the entry should not be marked as running', () => {
- component.entryToEdit = { ...entryToEdit, running: false };
+ it('when editing entry is running, shouldRestartEntry should be false', () => {
+ component.entryToEdit = { ...entryToEdit, running: true };
fixture.componentInstance.ngOnChanges();
- expect(component.goingToWorkOnThis).toBeFalse();
+ expect(component.goingToWorkOnThis).toBeTrue();
+ expect(component.shouldRestartEntry).toBeFalse();
+ });
+
+ it('when editing entry change to going to work on this shouldRestartEntry should be true', () => {
+ component.onGoingToWorkOnThisChange({ currentTarget: { checked: true } });
+
+ expect(component.goingToWorkOnThis).toBeTrue();
+ expect(component.shouldRestartEntry).toBeTrue();
});
it('when submitting a entry that is currently running, the end date should not be sent ', () => {
@@ -328,6 +339,7 @@ describe('DetailsFieldsComponent', () => {
},
shouldRestartEntry: false
};
+
expect(component.saveEntry.emit).toHaveBeenCalledWith(data);
});
diff --git a/src/app/modules/shared/components/details-fields/details-fields.component.ts b/src/app/modules/shared/components/details-fields/details-fields.component.ts
index 566960acc..5bc62652d 100644
--- a/src/app/modules/shared/components/details-fields/details-fields.component.ts
+++ b/src/app/modules/shared/components/details-fields/details-fields.component.ts
@@ -126,6 +126,7 @@ export class DetailsFieldsComponent implements OnChanges, OnInit {
ngOnChanges(): void {
this.goingToWorkOnThis = this.entryToEdit ? this.entryToEdit.running : false;
+ this.shouldRestartEntry = false;
if (this.entryToEdit) {
this.selectedTechnologies = this.entryToEdit.technologies;
const projectFound = this.listProjects.find((project) => project.id === this.entryToEdit.project_id);
diff --git a/src/app/modules/time-entries/pages/time-entries.component.html b/src/app/modules/time-entries/pages/time-entries.component.html
index 8fabce8a2..9df5c7f0a 100644
--- a/src/app/modules/time-entries/pages/time-entries.component.html
+++ b/src/app/modules/time-entries/pages/time-entries.component.html
@@ -22,6 +22,7 @@
Date |
Time in - out |
Duration |
+ Customer |
Project |
Activity |
|
@@ -33,6 +34,7 @@
{{ entry.start_date | date: 'MM/dd/yyyy' }} |
{{ entry.start_date | date: 'HH:mm' }} - {{ entry.end_date | date: 'HH:mm' }} |
{{ entry.end_date | substractDate: entry.start_date }} |
+ {{ entry.customer_name }} |
{{ entry.project_name }} |
{{ entry.activity_name }} |
diff --git a/src/app/modules/time-entries/pages/time-entries.component.spec.ts b/src/app/modules/time-entries/pages/time-entries.component.spec.ts
index 9781720d0..e64fc92f1 100644
--- a/src/app/modules/time-entries/pages/time-entries.component.spec.ts
+++ b/src/app/modules/time-entries/pages/time-entries.component.spec.ts
@@ -18,6 +18,7 @@ import { TimeEntriesComponent } from './time-entries.component';
import { ActionsSubject } from '@ngrx/store';
import { EntryActionTypes } from './../../time-clock/store/entry.actions';
import { NgxMaterialTimepickerModule } from 'ngx-material-timepicker';
+import { DebugElement } from '@angular/core';
describe('TimeEntriesComponent', () => {
type Merged = TechnologyState & ProjectState & EntryState;
@@ -57,6 +58,7 @@ describe('TimeEntriesComponent', () => {
project_name: 'Time-tracker',
start_date: new Date('2020-02-05T15:36:15.887Z'),
end_date: new Date('2020-02-05T18:36:15.887Z'),
+ customer_name: 'ioet Inc.',
activity_id: 'development',
technologies: ['Angular', 'TypeScript'],
description: 'No comments',
@@ -375,19 +377,54 @@ describe('TimeEntriesComponent', () => {
component.entry = null;
component.entryId = null;
const lastEntry = {
- description : 'testing is fun',
- technologies : [],
- uri : 'http://testing.is.fun',
- activity_id : 'sss',
- project_id : 'id',
- start_date : new Date(new Date().setHours(0, 0, 0, 0)),
- end_date : new Date(new Date().setHours(0, 0, 0, 0))
+ description: 'testing is fun',
+ technologies: [],
+ uri: 'http://testing.is.fun',
+ activity_id: 'sss',
+ project_id: 'id',
+ start_date: new Date(new Date().setHours(0, 0, 0, 0)),
+ end_date: new Date(new Date().setHours(0, 0, 0, 0))
};
- state.timeEntriesDataSource.data = [ lastEntry ];
+ state.timeEntriesDataSource.data = [lastEntry];
mockEntriesSelector = store.overrideSelector(getTimeEntriesDataSource, state.timeEntriesDataSource);
- component.projectSelected({ projectId : 'id'});
+ component.projectSelected({ projectId: 'id' });
expect(component.entry).toEqual(lastEntry);
}));
+ it('when the data source is loaded, the table should to show the appropriated column titles', waitForAsync(() => {
+ component.timeEntriesDataSource$.subscribe(() => {
+
+ fixture.detectChanges();
+
+ const expectedColumnTitles = [
+ 'Date',
+ 'Time in - out',
+ 'Duration',
+ 'Customer',
+ 'Project',
+ 'Activity',
+ '',
+ ];
+
+ const columnTitles: string[] = [];
+
+ const HTMLTimeEntriesDebugElement: DebugElement = fixture.debugElement;
+ const HTMLTimeEntriesElement: HTMLElement = HTMLTimeEntriesDebugElement.nativeElement;
+ const HTMLTimeEntriesTable = HTMLTimeEntriesElement.querySelector('.table') as HTMLTableElement;
+ const HTMLTableHead = HTMLTimeEntriesTable.rows[0];
+
+ Array.from(HTMLTableHead.cells).forEach(columnTitle => {
+ columnTitles.push(columnTitle.innerText);
+ });
+ expect(expectedColumnTitles).toEqual(columnTitles);
+ });
+ }));
+
+ it('when the data source is loaded, the entry should to have customer_name field', waitForAsync(() => {
+ component.timeEntriesDataSource$.subscribe(dataSource => {
+ const entryData = dataSource.data[0];
+ expect(entryData.customer_name).toContain('ioet Inc.');
+ });
+ }));
});
diff --git a/src/app/modules/users/components/users-list/users-list.component.html b/src/app/modules/users/components/users-list/users-list.component.html
index b13c0206f..bab11ae27 100644
--- a/src/app/modules/users/components/users-list/users-list.component.html
+++ b/src/app/modules/users/components/users-list/users-list.component.html
@@ -1,38 +1,40 @@
-
-
-
- User Email |
- Names |
- Roles |
-
-
-
-
-
- {{ user.email }} |
- {{ user.name }} |
-
-
-
- admin
-
- test
-
- |
-
-
-
+
+
+
+
+ User Email |
+ Names |
+ Roles |
+
+
+
+
+
+ {{ user.email }} |
+ {{ user.name }} |
+
+
+
+ admin
+
+ test
+
+ |
+
+
+
+
diff --git a/src/app/modules/users/components/users-list/users-list.component.spec.ts b/src/app/modules/users/components/users-list/users-list.component.spec.ts
index b95e9e4ad..1eff7f73a 100644
--- a/src/app/modules/users/components/users-list/users-list.component.spec.ts
+++ b/src/app/modules/users/components/users-list/users-list.component.spec.ts
@@ -18,7 +18,6 @@ describe('UsersListComponent', () => {
{
name: 'name',
email: 'email',
- role: null,
roles: ['admin', 'test'],
id: 'id',
tenant_id: 'tenant id',
@@ -111,7 +110,7 @@ describe('UsersListComponent', () => {
});
});
- it('on success load users, the data of roles should be an array and role null', () => {
+ it('on success load users, the data of roles should be an array', () => {
const actionSubject = TestBed.inject(ActionsSubject) as ActionsSubject;
const action = {
type: UserActionTypes.LOAD_USERS_SUCCESS,
@@ -121,41 +120,10 @@ describe('UsersListComponent', () => {
actionSubject.next(action);
component.users.map((user) => {
- expect(user.role).toEqual(null);
expect(user.roles).toEqual(['admin', 'test']);
});
});
- it('on success load users, the data of roles should be null and role a string', () => {
- const actionSubject = TestBed.inject(ActionsSubject) as ActionsSubject;
- const mockState: UserState = {
- data: [
- {
- name: 'name',
- email: 'email',
- role: 'admin',
- roles: null,
- id: 'id',
- tenant_id: 'tenant id',
- deleted: 'delete',
- },
- ],
- isLoading: false,
- message: '',
- };
- const action = {
- type: UserActionTypes.LOAD_USERS_SUCCESS,
- payload: mockState.data,
- };
-
- actionSubject.next(action);
-
- component.users.map((user) => {
- expect(user.role).toEqual('admin');
- expect(user.roles).toEqual(null);
- });
- });
-
it('on success load users, the datatable should be reloaded', async () => {
const actionSubject = TestBed.inject(ActionsSubject);
const action = {
diff --git a/src/app/modules/users/models/users.ts b/src/app/modules/users/models/users.ts
index 481fe3d5d..74c8d33df 100644
--- a/src/app/modules/users/models/users.ts
+++ b/src/app/modules/users/models/users.ts
@@ -1,7 +1,6 @@
export interface User {
name: string;
email: string;
- role?: string;
roles?: string[];
id: string;
tenant_id?: string;
diff --git a/src/app/modules/users/store/user.reducer.spec.ts b/src/app/modules/users/store/user.reducer.spec.ts
index 4f89e5d4e..7c9f39c67 100644
--- a/src/app/modules/users/store/user.reducer.spec.ts
+++ b/src/app/modules/users/store/user.reducer.spec.ts
@@ -38,13 +38,13 @@ describe('userReducer', () => {
expect(state.isLoading).toEqual(true);
});
- it('on GrantRoleUserSuccess, user role should change', () => {
+ it('on GrantRoleUserSuccess, user roles should change', () => {
const currentState: UserState = {
- data: [{ id: 'id', name: 'name', email: 'email', role: null }],
+ data: [{ id: 'id', name: 'name', email: 'email', roles: null }],
isLoading: false,
message: '',
};
- const userGranted: User = { id: 'id', name: 'name', email: 'email', role: 'admin' };
+ const userGranted: User = { id: 'id', name: 'name', email: 'email', roles: ['admin'] };
const action = new actions.GrantRoleUserSuccess(userGranted);
const state = userReducer(currentState, action);
@@ -70,13 +70,13 @@ describe('userReducer', () => {
expect(state.isLoading).toEqual(true);
});
- it('on RevokeRoleUserSuccess, user role should change', () => {
+ it('on RevokeRoleUserSuccess, user roles should change', () => {
const currentState: UserState = {
- data: [{ id: 'id', name: 'name', email: 'email', role: 'admin' }],
+ data: [{ id: 'id', name: 'name', email: 'email', roles: ['admin'] }],
isLoading: false,
message: '',
};
- const userRevoked: User = { id: 'id', name: 'name', email: 'email', role: null };
+ const userRevoked: User = { id: 'id', name: 'name', email: 'email', roles: null };
const action = new actions.RevokeRoleUserSuccess(userRevoked);
const state = userReducer(currentState, action);
|