Skip to content

Commit 1e1fd38

Browse files
committed
TT-70 fix: fix bug when update two entries
1 parent 0cb1516 commit 1e1fd38

File tree

11 files changed

+107
-23
lines changed

11 files changed

+107
-23
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
@@ -132,7 +132,7 @@ export class DetailsFieldsComponent implements OnChanges, OnInit {
132132
project_id: this.entryToEdit.project_id,
133133
activity_id: this.entryToEdit.activity_id,
134134
description: this.entryToEdit.description,
135-
start_date: formatDate(get(this.entryToEdit, 'start_date', '') ,DATE_FORMAT, 'en'),
135+
start_date: formatDate(get(this.entryToEdit, 'start_date', ''), DATE_FORMAT, 'en'),
136136
end_date: formatDate(get(this.entryToEdit, 'end_date'), DATE_FORMAT, 'en'),
137137
start_hour: formatDate(get(this.entryToEdit, 'start_date', '00:00'), 'HH:mm', 'en'),
138138
end_hour: formatDate(get(this.entryToEdit, 'end_date', '00:00'), 'HH:mm', 'en'),

src/app/modules/time-clock/components/entry-fields/entry-fields.component.spec.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -262,19 +262,16 @@ describe('EntryFieldsComponent', () => {
262262
expect(component.lastEntry).toBe(state.entries.timeEntriesDataSource.data[1]);
263263
}));
264264

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

274272
component.onUpdateStartHour();
275273

276-
expect(store.dispatch).toHaveBeenCalledTimes(2);
277-
expect(store.dispatch).toHaveBeenCalledWith(new UpdateEntry({id: lastEntry.id, end_date: lastStartHourEntryEnteredTest}));
274+
expect(store.dispatch).toHaveBeenCalledTimes(1);
278275
});
279276

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

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

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

382379
actionSubject.next(action);
383380

384-
expect(store.dispatch).toHaveBeenCalledTimes(0);
381+
expect(store.dispatch).toHaveBeenCalledTimes(3);
385382
});
386383

387384
it('activeEntry is populated using the payload of LOAD_ACTIVE_ENTRY_SUCCESS', () => {

src/app/modules/time-clock/components/entry-fields/entry-fields.component.ts

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ export class EntryFieldsComponent implements OnInit {
7070
if (!action.payload.end_date) {
7171
this.store.dispatch(new LoadActiveEntry());
7272
this.store.dispatch(new entryActions.LoadEntriesSummary());
73+
} else {
74+
this.store.dispatch(new entryActions.UpdateEntryRunning({ ...this.newData, ...this.entryForm.value }));
75+
this.store.dispatch(new LoadActiveEntry());
76+
this.store.dispatch(new entryActions.LoadEntriesSummary());
7377
}
7478
});
7579

@@ -143,31 +147,22 @@ export class EntryFieldsComponent implements OnInit {
143147
return;
144148
}
145149
this.entryForm.patchValue({ start_date: newHourEntered });
146-
this.dispatchEntries(newHourEntered);
150+
this.store.dispatch(new entryActions.UpdateTwoEntries({ ...this.newData, ...this.entryForm.value }));
147151
this.showTimeInbuttons = false;
148152
}
149153

150-
private dispatchEntries(newHourEntered) {
151-
const lastEntryEndDate = get(this.lastEntry, 'end_date', moment().subtract(1, 'hours'));
152-
const isInLastEntry = moment(newHourEntered).isBefore(lastEntryEndDate);
153-
if (isInLastEntry) {
154-
this.store.dispatch(new entryActions.UpdateEntry({ id: this.lastEntry.id, end_date: newHourEntered }));
155-
}
156-
this.store.dispatch(new entryActions.UpdateEntryRunning({ ...this.newData, ...this.entryForm.value }));
157-
}
158-
159154
private getLastEntry() {
160155
const lastEntry$ = this.store.pipe(select(getTimeEntriesDataSource));
161156
lastEntry$.subscribe((entry) => {
162157
this.lastEntry = entry.data[1];
163158
});
164159
}
165160

166-
activeTimeInButtons(){
161+
activeTimeInButtons() {
167162
this.showTimeInbuttons = true;
168163
}
169164

170-
cancelTimeInUpdate(){
165+
cancelTimeInUpdate() {
171166
this.entryForm.patchValue({ start_hour: this.newData.start_hour });
172167
this.showTimeInbuttons = false;
173168
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ export class ProjectListHoverComponent implements OnInit, OnDestroy {
5454
).subscribe((action) => {
5555
this.activeEntry = action.payload;
5656
this.setSelectedProject();
57+
this.store.dispatch(new entryActions.LoadEntries(new Date().getMonth() + 1));
58+
this.store.dispatch(new entryActions.LoadActiveEntry());
5759
});
5860

5961
}
@@ -105,7 +107,6 @@ export class ProjectListHoverComponent implements OnInit, OnDestroy {
105107
} else {
106108
this.store.dispatch(new entryActions.SwitchTimeEntry(this.activeEntry.id, selectedProject));
107109
this.projectsForm.setValue( { project_id: `${customerName} - ${name}`, } );
108-
this.store.dispatch(new entryActions.LoadEntries(new Date().getMonth() + 1));
109110
}
110111
}
111112

src/app/modules/time-clock/store/entry.actions.spec.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,4 +126,14 @@ describe('Actions for Entries', () => {
126126
const action = new actions.RestartEntryFail('error');
127127
expect(action.type).toEqual(actions.EntryActionTypes.RESTART_ENTRY_FAIL);
128128
});
129+
130+
it('UpdateTwoEntries type is EntryActionTypes.UPDATE_TWO_ENTRIES', () => {
131+
const action = new actions.UpdateTwoEntries(entry);
132+
expect(action.type).toEqual(actions.EntryActionTypes.UPDATE_TWO_ENTRIES);
133+
});
134+
135+
it('UpdateTwoEntriesFail type is EntryActionTypes.UPDATE_TWO_ENTRIES_FAIL', () => {
136+
const action = new actions.UpdateTwoEntriesFail('error');
137+
expect(action.type).toEqual(actions.EntryActionTypes.UPDATE_TWO_ENTRIES_FAIL);
138+
});
129139
});

src/app/modules/time-clock/store/entry.actions.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ export enum EntryActionTypes {
2121
UPDATE_ENTRY_RUNNING = '[Entry] UPDATE_ENTRY_RUNNING',
2222
UPDATE_ENTRY = '[Entry] UPDATE_ENTRY',
2323
UPDATE_ENTRY_SUCCESS = '[Entry] UPDATE_ENTRY_SUCCESS',
24+
UPDATE_TWO_ENTRIES = '[Entry] UPDATE_TWO_ENTRIES',
25+
UPDATE_TWO_ENTRIES_FAIL = '[Entry] UPDATE_TWO_ENTRIES_FAIL',
2426
UPDATE_ENTRY_FAIL = '[Entry] UPDATE_ENTRY_FAIL',
2527
DELETE_ENTRY = '[Entry] DELETE_ENTRY',
2628
DELETE_ENTRY_SUCCESS = '[Entry] DELETE_ENTRY_SUCCESS',
@@ -183,6 +185,18 @@ export class UpdateEntryFail implements Action {
183185
}
184186
}
185187

188+
export class UpdateTwoEntries implements Action {
189+
public readonly type = EntryActionTypes.UPDATE_TWO_ENTRIES;
190+
191+
constructor(public payload) {
192+
}
193+
}
194+
export class UpdateTwoEntriesFail implements Action {
195+
public readonly type = EntryActionTypes.UPDATE_TWO_ENTRIES_FAIL;
196+
197+
constructor(public error: string) {
198+
}
199+
}
186200
export class StopTimeEntryRunning implements Action {
187201
public readonly type = EntryActionTypes.STOP_TIME_ENTRY_RUNNING;
188202

@@ -296,4 +310,6 @@ export type EntryActions =
296310
| SwitchTimeEntryFail
297311
| RestartEntry
298312
| RestartEntrySuccess
299-
| RestartEntryFail;
313+
| RestartEntryFail
314+
| UpdateTwoEntries
315+
| UpdateTwoEntriesFail;

src/app/modules/time-clock/store/entry.effects.spec.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,4 +339,22 @@ describe('TimeEntryActionEffects', () => {
339339
expect(action.type).toEqual(EntryActionTypes.STOP_TIME_ENTRY_RUNNING_FAILED);
340340
});
341341
});
342+
343+
it('action type is UPDATE_ENTRY when UPDATE_TWO_ENTRIES executed', async () => {
344+
actions$ = of({ type: EntryActionTypes.UPDATE_TWO_ENTRIES, payload: entry });
345+
spyOn(service, 'loadEntries').and.returnValue(of([entry, entry]));
346+
347+
effects.updateLastEntryAndNew$.subscribe(action => {
348+
expect(action.type).toEqual(EntryActionTypes.UPDATE_ENTRY);
349+
});
350+
});
351+
352+
it('action type is UPDATE_TWO_ENTRIES_FAIL when service fail in execution', async () => {
353+
actions$ = of({ type: EntryActionTypes.UPDATE_TWO_ENTRIES, payload: entry });
354+
spyOn(service, 'loadEntries').and.returnValue(throwError({ error: { message: 'fail!' } }));
355+
356+
effects.updateLastEntryAndNew$.subscribe((action) => {
357+
expect(action.type).toEqual(EntryActionTypes.UPDATE_TWO_ENTRIES_FAIL);
358+
});
359+
});
342360
});

src/app/modules/time-clock/store/entry.effects.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { Observable, of } from 'rxjs';
77
import { catchError, map, mergeMap, switchMap } from 'rxjs/operators';
88
import { EntryService } from '../services/entry.service';
99
import * as actions from './entry.actions';
10+
import * as moment from 'moment';
1011

1112
@Injectable()
1213
export class EntryEffects {
@@ -219,6 +220,30 @@ export class EntryEffects {
219220
)
220221
);
221222

223+
@Effect()
224+
updateLastEntryAndNew$: Observable<Action> = this.actions$.pipe(
225+
ofType(actions.EntryActionTypes.UPDATE_TWO_ENTRIES),
226+
map((action: actions.UpdateTwoEntries) => action.payload),
227+
switchMap((entry) =>
228+
this.entryService.loadEntries(new Date().getMonth() + 1).pipe(
229+
map((entries) => {
230+
const lastEntry = entries[1];
231+
const isInLastEntry = moment(entry.start_date).isBefore(lastEntry.end_date);
232+
if (isInLastEntry) {
233+
return new actions.UpdateEntry({ id: lastEntry.id, end_date: entry.start_date });
234+
} else {
235+
this.toastrService.success('You change the time in successfully');
236+
return new actions.UpdateEntryRunning(entry);
237+
}
238+
}),
239+
catchError((error) => {
240+
this.toastrService.error(error.error.message);
241+
return of(new actions.UpdateTwoEntriesFail('error'));
242+
})
243+
)
244+
)
245+
);
246+
222247
@Effect()
223248
loadEntriesByTimeRange$: Observable<Action> = this.actions$.pipe(
224249
ofType(actions.EntryActionTypes.LOAD_ENTRIES_BY_TIME_RANGE),

src/app/modules/time-clock/store/entry.reducer.spec.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,13 @@ describe('entryReducer', () => {
199199
expect(state.isLoading).toEqual(true);
200200
});
201201

202+
it('on UpdateTwoEntries, isLoading is true', () => {
203+
const action = new actions.UpdateTwoEntries(newEntry);
204+
const state = entryReducer(initialState, action);
205+
206+
expect(state.isLoading).toEqual(true);
207+
});
208+
202209
it('on UpdateActiveEntrySuccess, loading is false', () => {
203210
const action = new actions.UpdateEntrySuccess(entry);
204211

src/app/modules/time-clock/store/entry.reducer.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,21 @@ export const entryReducer = (state: EntryState = initialState, action: EntryActi
206206
};
207207
}
208208

209+
case EntryActionTypes.UPDATE_TWO_ENTRIES: {
210+
return {
211+
...state,
212+
isLoading: true,
213+
};
214+
}
215+
216+
case EntryActionTypes.UPDATE_TWO_ENTRIES_FAIL: {
217+
return {
218+
...state,
219+
isLoading: false,
220+
message: 'Update Two Entries Fail',
221+
};
222+
}
223+
209224
case EntryActionTypes.STOP_TIME_ENTRY_RUNNING: {
210225
return {
211226
...state,

0 commit comments

Comments
 (0)