Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
fix: #572 allow manual editing in time in when switch project
  • Loading branch information
PaulRC-ioet committed Nov 26, 2020
commit 4500127893d461f694cf3406c27a8be59aa36f62
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ describe('EntryFieldsComponent', () => {
error: (message?: string, title?: string, override?: Partial<IndividualConfig>) => { },
warning: (message?: string, title?: string, override?: Partial<IndividualConfig>) => { }
};
const lastDate = moment().format('YYYY-MM-DD');
const startHourTest = moment().add(-5, 'hours').format('HH:mm:ss');
const endHourTest = moment().add(-3, 'hours').format('HH:mm:ss');
const lastStartHourEntryEntered = new Date(`${lastDate}T${startHourTest.trim()}`).toISOString();
const lastEndHourEntryEntered = new Date(`${lastDate}T${endHourTest.trim()}`).toISOString();

const state = {
projects: {
Expand Down Expand Up @@ -57,6 +62,28 @@ describe('EntryFieldsComponent', () => {
},
entryList: [],
message: '',
timeEntriesDataSource: { data: [
{
activity_id: 'xyz',
activity_name: 'abc',
id: 'id-15',
project_id: 'project-id-15',
description: 'description for an entry',
uri: 'abc',
start_date : moment().toISOString(),
end_date : moment().toISOString(),
},
{
activity_id: 'xyz',
activity_name: 'abc',
id: 'id-15',
project_id: 'project-id-15',
description: 'description for an entry',
uri: 'abc',
start_date : lastStartHourEntryEntered,
end_date : lastEndHourEntryEntered,
}
]}
},
};

Expand Down Expand Up @@ -134,6 +161,37 @@ describe('EntryFieldsComponent', () => {
expect(toastrServiceStub.error).toHaveBeenCalled();
});

it('displays error message when new hour entered is in the past of other entry', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not quite sure about what are you testing here. Correct me if I am wrong please:

Displays an error message when new entry has start_time before (start time/end time???) of active entry

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, it's the same, the name could be:
Displays an error message when new entry has start_time before end time of last entry

component.newData = entry;
component.activeEntry = entry ;
component.setDataToUpdate(entry);
spyOn(toastrServiceStub, 'error');

const hourInTheFuture = moment().add(-6, 'hour').format('HH:mm:ss');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how the time can be in the future if you're actually subtracting hours. BTW, you can use the function subtract instead of add in this case

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, I already change it

component.entryForm.patchValue({ start_hour : hourInTheFuture});
component.onUpdateStartHour();

expect(toastrServiceStub.error).toHaveBeenCalled();
});

it('If start hour is in the past of other entry, reset to initial start_date in form', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't get what are you testing here. Feel free to send me a DM

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is to restart to the previous time when you enter a wrong time.
I corrected the name to:
should reset to current start_date of form when start_date is before the current entrie’s start_date

component.newData = entry;
component.activeEntry = entry ;
component.setDataToUpdate(entry);

const newHour = moment().add(-6, 'hours').format('HH:mm:ss');
component.entryForm.patchValue({ start_hour : newHour});

spyOn(component.entryForm, 'patchValue');
component.onUpdateStartHour();

expect(component.entryForm.patchValue).toHaveBeenCalledWith(
{
start_hour: component.newData.start_hour
}
);
});

it('If start hour is in the future, reset to initial start_date in form', () => {
component.newData = entry;
component.activeEntry = entry ;
Expand All @@ -155,12 +213,37 @@ describe('EntryFieldsComponent', () => {
it('when a start hour is updated, then dispatch UpdateActiveEntry', () => {
component.activeEntry = entry ;
component.setDataToUpdate(entry);
const newHour = moment().format('HH:mm:ss');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's use newTime or updatedTime instead of newHour

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I change to updatedTime

component.entryForm.patchValue({ start_hour : newHour});
spyOn(store, 'dispatch');

component.onUpdateStartHour();
expect(store.dispatch).toHaveBeenCalled();
});

it('when a start hour is update, then select the last time entry', async(() => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct me if I am wrong, I think this is what you are testing here.

When start_time is updated, component.last_entry is equal to...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, another way would be:
When start_time is updated, component.last_entry is equal to last time entry in the state

component.activeEntry = entry ;
component.setDataToUpdate(entry);
const newHour = moment().format('HH:mm:ss');

component.entryForm.patchValue({ start_hour : newHour});
component.onUpdateStartHour();

expect(component.lastEntry).toBe(state.entries.timeEntriesDataSource.data[1]);
}));

it('when a start hour is updated in other time entry, then dispatch UpdateEntry and UpdateEntryRunning', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When start_time is updated for a time entry. UpdateEntry and UpdateEntryRuning actions are dispatched.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course, that phrase is better understood.

component.activeEntry = entry ;
component.setDataToUpdate(entry);

const newHour = moment().add(-4, 'hours').format('HH:mm:ss');
component.entryForm.patchValue({ start_hour : newHour});
spyOn(store, 'dispatch');

component.onUpdateStartHour();
expect(store.dispatch).toHaveBeenCalledTimes(2);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might want to verify here the above-mentioned actions have been dispatched.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, it's tested

});

it('when a technology is added, then dispatch UpdateActiveEntry', () => {
const addedTechnologies = ['react'];
spyOn(store, 'dispatch');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ import { EntryActionTypes, LoadActiveEntry } from './../../store/entry.actions';
import { filter } from 'rxjs/operators';
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { Store, ActionsSubject } from '@ngrx/store';

import { Store, ActionsSubject, select } from '@ngrx/store';
import { Activity, NewEntry } from '../../../shared/models';
import { ProjectState } from '../../../customer-management/components/projects/components/store/project.reducer';
import { TechnologyState } from '../../../shared/store/technology.reducers';
Expand All @@ -15,6 +14,7 @@ import * as entryActions from '../../store/entry.actions';
import * as moment from 'moment';
import { ToastrService } from 'ngx-toastr';
import { formatDate } from '@angular/common';
import { getTimeEntriesDataSource } from '../../store/entry.selectors';

type Merged = TechnologyState & ProjectState & ActivityState;

Expand All @@ -29,13 +29,15 @@ export class EntryFieldsComponent implements OnInit {
activities: Activity[] = [];
activeEntry;
newData;
lastEntry;

constructor(
private formBuilder: FormBuilder,
private store: Store<Merged>,
private actionsSubject$: ActionsSubject,
private toastrService: ToastrService
) {
this.store.dispatch(new entryActions.LoadEntries(new Date().getMonth() + 1));
this.entryForm = this.formBuilder.group({
description: '',
uri: '',
Expand All @@ -57,11 +59,13 @@ export class EntryFieldsComponent implements OnInit {

this.actionsSubject$
.pipe(
filter((action: any) => (
action.type === EntryActionTypes.CREATE_ENTRY_SUCCESS ||
action.type === EntryActionTypes.UPDATE_ENTRY_SUCCESS
))
).subscribe((action) => {
filter(
(action: any) =>
action.type === EntryActionTypes.CREATE_ENTRY_SUCCESS ||
action.type === EntryActionTypes.UPDATE_ENTRY_SUCCESS
)
)
.subscribe((action) => {
if (!action.payload.end_date) {
this.store.dispatch(new LoadActiveEntry());
this.store.dispatch(new entryActions.LoadEntriesSummary());
Expand Down Expand Up @@ -126,10 +130,36 @@ export class EntryFieldsComponent implements OnInit {
this.entryForm.patchValue({ start_hour: this.newData.start_hour });
return;
}

this.getLastEntry();

const isFirstEntry = this.lastEntry !== undefined ? this.lastEntry.start_date : moment().add(-1, 'hours');
const isEntryDateInLastStartDate = moment(newHourEntered).isBefore(isFirstEntry);
if (isEntryDateInLastStartDate) {
this.toastrService.error('You cannot start a time-entry before another time-entry');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is to control that the user does not enter a time equal to or prior to the last time entry.
I have changed the message to:
There is already a time-entry with the time entered. The entry time cannot be the same as another time-entry

this.entryForm.patchValue({ start_hour: this.newData.start_hour });
return;
}
this.entryForm.patchValue({ start_date: newHourEntered });
this.dispatchEntries(newHourEntered);
}

private dispatchEntries(newHourEntered) {
const isFirstEntry = this.lastEntry !== undefined ? this.lastEntry.end_date : moment().add(-1, 'hours');
const isInLastEntry = moment(newHourEntered).isBefore(isFirstEntry);
if (isInLastEntry) {
this.store.dispatch(new entryActions.UpdateEntry({ id: this.lastEntry.id, end_date: newHourEntered }));
}
this.store.dispatch(new entryActions.UpdateEntryRunning({ ...this.newData, ...this.entryForm.value }));
}

private getLastEntry() {
const lastEntry$ = this.store.pipe(select(getTimeEntriesDataSource));
lastEntry$.subscribe((entry) => {
this.lastEntry = entry.data[1];
});
}

onTechnologyAdded($event: string[]) {
this.store.dispatch(new entryActions.UpdateEntryRunning({ ...this.newData, technologies: $event }));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ export class ProjectListHoverComponent implements OnInit, OnDestroy {
} else {
this.store.dispatch(new entryActions.SwitchTimeEntry(this.activeEntry.id, selectedProject));
this.projectsForm.setValue( { project_id: `${customerName} - ${name}`, } );
this.store.dispatch(new entryActions.LoadEntries(new Date().getMonth() + 1));
}
}

Expand Down