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
TT-70 fix: fix bug when update two entries
  • Loading branch information
PaulRC-ioet committed Dec 16, 2020
commit 27da07b9acec0522a84b9a3fd7fa155e885ab5c8
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ export class DetailsFieldsComponent implements OnChanges, OnInit {
project_id: this.entryToEdit.project_id,
activity_id: this.entryToEdit.activity_id,
description: this.entryToEdit.description,
start_date: formatDate(get(this.entryToEdit, 'start_date', '') ,DATE_FORMAT, 'en'),
start_date: formatDate(get(this.entryToEdit, 'start_date', ''), DATE_FORMAT, 'en'),
end_date: formatDate(get(this.entryToEdit, 'end_date'), DATE_FORMAT, 'en'),
start_hour: formatDate(get(this.entryToEdit, 'start_date', '00:00'), 'HH:mm', 'en'),
end_hour: formatDate(get(this.entryToEdit, 'end_date', '00:00'), 'HH:mm', 'en'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,19 +262,16 @@ describe('EntryFieldsComponent', () => {
expect(component.lastEntry).toBe(state.entries.timeEntriesDataSource.data[1]);
}));

it('When start_time is updated for a time entry. UpdateEntry and UpdateEntryRuning actions are dispatched', () => {
it('When start_time is updated for a time entry. UpdateTwoEntry action is dispatched', () => {
component.activeEntry = entry ;
component.setDataToUpdate(entry);
const lastEntry = state.entries.timeEntriesDataSource.data[1];
const updatedTime = moment().subtract(4, 'hours').format('HH:mm');
const lastStartHourEntryEnteredTest = new Date(`${lastDate}T${updatedTime.trim()}`).toISOString();
component.entryForm.patchValue({ start_hour : updatedTime});
spyOn(store, 'dispatch');

component.onUpdateStartHour();

expect(store.dispatch).toHaveBeenCalledTimes(2);
expect(store.dispatch).toHaveBeenCalledWith(new UpdateEntry({id: lastEntry.id, end_date: lastStartHourEntryEnteredTest}));
expect(store.dispatch).toHaveBeenCalledTimes(1);
});

it('when a technology is added, then dispatch UpdateActiveEntry', () => {
Expand Down Expand Up @@ -370,7 +367,7 @@ describe('EntryFieldsComponent', () => {
expect(store.dispatch).toHaveBeenCalledWith(new LoadActiveEntry());
});

it('when entry has an end_date then nothing is dispatched', () => {
it('when entry has an end_date then update time entry running and load entries', () => {
spyOn(store, 'dispatch');

const actionSubject = TestBed.inject(ActionsSubject) as ActionsSubject;
Expand All @@ -381,7 +378,7 @@ describe('EntryFieldsComponent', () => {

actionSubject.next(action);

expect(store.dispatch).toHaveBeenCalledTimes(0);
expect(store.dispatch).toHaveBeenCalledTimes(3);
});

it('activeEntry is populated using the payload of LOAD_ACTIVE_ENTRY_SUCCESS', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ export class EntryFieldsComponent implements OnInit {
if (!action.payload.end_date) {
this.store.dispatch(new LoadActiveEntry());
this.store.dispatch(new entryActions.LoadEntriesSummary());
} else {
this.store.dispatch(new entryActions.UpdateEntryRunning({ ...this.newData, ...this.entryForm.value }));
this.store.dispatch(new LoadActiveEntry());
this.store.dispatch(new entryActions.LoadEntriesSummary());
}
});

Expand Down Expand Up @@ -143,31 +147,22 @@ export class EntryFieldsComponent implements OnInit {
return;
}
this.entryForm.patchValue({ start_date: newHourEntered });
this.dispatchEntries(newHourEntered);
this.store.dispatch(new entryActions.UpdateTwoEntries({ ...this.newData, ...this.entryForm.value }));
this.showTimeInbuttons = false;
}

private dispatchEntries(newHourEntered) {
const lastEntryEndDate = get(this.lastEntry, 'end_date', moment().subtract(1, 'hours'));
const isInLastEntry = moment(newHourEntered).isBefore(lastEntryEndDate);
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];
});
}

activeTimeInButtons(){
activeTimeInButtons() {
this.showTimeInbuttons = true;
}

cancelTimeInUpdate(){
cancelTimeInUpdate() {
this.entryForm.patchValue({ start_hour: this.newData.start_hour });
this.showTimeInbuttons = false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ export class ProjectListHoverComponent implements OnInit, OnDestroy {
).subscribe((action) => {
this.activeEntry = action.payload;
this.setSelectedProject();
this.store.dispatch(new entryActions.LoadEntries(new Date().getMonth() + 1));
this.store.dispatch(new entryActions.LoadActiveEntry());
});

}
Expand Down Expand Up @@ -105,7 +107,6 @@ 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
10 changes: 10 additions & 0 deletions src/app/modules/time-clock/store/entry.actions.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,14 @@ describe('Actions for Entries', () => {
const action = new actions.RestartEntryFail('error');
expect(action.type).toEqual(actions.EntryActionTypes.RESTART_ENTRY_FAIL);
});

it('UpdateTwoEntries type is EntryActionTypes.UPDATE_TWO_ENTRIES', () => {
const action = new actions.UpdateTwoEntries(entry);
expect(action.type).toEqual(actions.EntryActionTypes.UPDATE_TWO_ENTRIES);
});

it('UpdateTwoEntriesFail type is EntryActionTypes.UPDATE_TWO_ENTRIES_FAIL', () => {
const action = new actions.UpdateTwoEntriesFail('error');
expect(action.type).toEqual(actions.EntryActionTypes.UPDATE_TWO_ENTRIES_FAIL);
});
});
18 changes: 17 additions & 1 deletion src/app/modules/time-clock/store/entry.actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ export enum EntryActionTypes {
UPDATE_ENTRY_RUNNING = '[Entry] UPDATE_ENTRY_RUNNING',
UPDATE_ENTRY = '[Entry] UPDATE_ENTRY',
UPDATE_ENTRY_SUCCESS = '[Entry] UPDATE_ENTRY_SUCCESS',
UPDATE_TWO_ENTRIES = '[Entry] UPDATE_TWO_ENTRIES',
UPDATE_TWO_ENTRIES_FAIL = '[Entry] UPDATE_TWO_ENTRIES_FAIL',
UPDATE_ENTRY_FAIL = '[Entry] UPDATE_ENTRY_FAIL',
DELETE_ENTRY = '[Entry] DELETE_ENTRY',
DELETE_ENTRY_SUCCESS = '[Entry] DELETE_ENTRY_SUCCESS',
Expand Down Expand Up @@ -183,6 +185,18 @@ export class UpdateEntryFail implements Action {
}
}

export class UpdateTwoEntries implements Action {
public readonly type = EntryActionTypes.UPDATE_TWO_ENTRIES;

constructor(public payload) {
}
}
export class UpdateTwoEntriesFail implements Action {
public readonly type = EntryActionTypes.UPDATE_TWO_ENTRIES_FAIL;

constructor(public error: string) {
}
}
export class StopTimeEntryRunning implements Action {
public readonly type = EntryActionTypes.STOP_TIME_ENTRY_RUNNING;

Expand Down Expand Up @@ -296,4 +310,6 @@ export type EntryActions =
| SwitchTimeEntryFail
| RestartEntry
| RestartEntrySuccess
| RestartEntryFail;
| RestartEntryFail
| UpdateTwoEntries
| UpdateTwoEntriesFail;
18 changes: 18 additions & 0 deletions src/app/modules/time-clock/store/entry.effects.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -339,4 +339,22 @@ describe('TimeEntryActionEffects', () => {
expect(action.type).toEqual(EntryActionTypes.STOP_TIME_ENTRY_RUNNING_FAILED);
});
});

it('action type is UPDATE_ENTRY when UPDATE_TWO_ENTRIES executed', async () => {
actions$ = of({ type: EntryActionTypes.UPDATE_TWO_ENTRIES, payload: entry });
spyOn(service, 'loadEntries').and.returnValue(of([entry, entry]));

effects.updateLastEntryAndNew$.subscribe(action => {
expect(action.type).toEqual(EntryActionTypes.UPDATE_ENTRY);
});
});

it('action type is UPDATE_TWO_ENTRIES_FAIL when service fail in execution', async () => {
actions$ = of({ type: EntryActionTypes.UPDATE_TWO_ENTRIES, payload: entry });
spyOn(service, 'loadEntries').and.returnValue(throwError({ error: { message: 'fail!' } }));

effects.updateLastEntryAndNew$.subscribe((action) => {
expect(action.type).toEqual(EntryActionTypes.UPDATE_TWO_ENTRIES_FAIL);
});
});
});
25 changes: 25 additions & 0 deletions src/app/modules/time-clock/store/entry.effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Observable, of } from 'rxjs';
import { catchError, map, mergeMap, switchMap } from 'rxjs/operators';
import { EntryService } from '../services/entry.service';
import * as actions from './entry.actions';
import * as moment from 'moment';

@Injectable()
export class EntryEffects {
Expand Down Expand Up @@ -219,6 +220,30 @@ export class EntryEffects {
)
);

@Effect()
updateLastEntryAndNew$: Observable<Action> = this.actions$.pipe(
ofType(actions.EntryActionTypes.UPDATE_TWO_ENTRIES),
map((action: actions.UpdateTwoEntries) => action.payload),
switchMap((entry) =>
this.entryService.loadEntries(new Date().getMonth() + 1).pipe(
map((entries) => {
const lastEntry = entries[1];
const isInLastEntry = moment(entry.start_date).isBefore(lastEntry.end_date);
if (isInLastEntry) {
return new actions.UpdateEntry({ id: lastEntry.id, end_date: entry.start_date });
} else {
this.toastrService.success('You change the time in successfully');
return new actions.UpdateEntryRunning(entry);
}
}),
catchError((error) => {
this.toastrService.error(error.error.message);
return of(new actions.UpdateTwoEntriesFail('error'));
})
)
)
);

@Effect()
loadEntriesByTimeRange$: Observable<Action> = this.actions$.pipe(
ofType(actions.EntryActionTypes.LOAD_ENTRIES_BY_TIME_RANGE),
Expand Down
7 changes: 7 additions & 0 deletions src/app/modules/time-clock/store/entry.reducer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,13 @@ describe('entryReducer', () => {
expect(state.isLoading).toEqual(true);
});

it('on UpdateTwoEntries, isLoading is true', () => {
const action = new actions.UpdateTwoEntries(newEntry);
const state = entryReducer(initialState, action);

expect(state.isLoading).toEqual(true);
});

it('on UpdateActiveEntrySuccess, loading is false', () => {
const action = new actions.UpdateEntrySuccess(entry);

Expand Down
15 changes: 15 additions & 0 deletions src/app/modules/time-clock/store/entry.reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,21 @@ export const entryReducer = (state: EntryState = initialState, action: EntryActi
};
}

case EntryActionTypes.UPDATE_TWO_ENTRIES: {
return {
...state,
isLoading: true,
};
}

case EntryActionTypes.UPDATE_TWO_ENTRIES_FAIL: {
return {
...state,
isLoading: false,
message: 'Update Two Entries Fail',
};
}

case EntryActionTypes.STOP_TIME_ENTRY_RUNNING: {
return {
...state,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export class TimeEntriesComponent implements OnInit, OnDestroy {
const isEditingEntryEqualToActiveEntry = this.entryId === this.activeTimeEntry.id;
const isStartDateGreaterThanActiveEntry = startDateAsLocalDate > activeEntryAsLocalDate;
const isEndDateGreaterThanActiveEntry = endDateAsLocalDate > activeEntryAsLocalDate;
if(!isEditingEntryEqualToActiveEntry && (isStartDateGreaterThanActiveEntry || isEndDateGreaterThanActiveEntry)){
if (!isEditingEntryEqualToActiveEntry && (isStartDateGreaterThanActiveEntry || isEndDateGreaterThanActiveEntry)) {
this.toastrService.error('You are on the clock and this entry overlaps it, try with earlier times.');
} else {
this.doSave(event);
Expand Down