Skip to content

Commit f0da817

Browse files
authored
Merge pull request #305 from ioet/304-avoid-entries-after-entry-running
fix: #304 avoid creating entries with a date after the one that is ru…
2 parents a77a0f9 + c2bfcfd commit f0da817

File tree

2 files changed

+60
-12
lines changed

2 files changed

+60
-12
lines changed

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

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { ToastrService } from 'ngx-toastr';
12
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
23
import { provideMockStore, MockStore } from '@ngrx/store/testing';
34
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
@@ -23,6 +24,11 @@ describe('TimeEntriesComponent', () => {
2324
let mockTechnologySelector;
2425
let mockProjectsSelector;
2526
let mockEntriesSelector;
27+
let injectedToastrService;
28+
29+
const toastrService = {
30+
error: () => {},
31+
};
2632

2733
const state = {
2834
projects: {
@@ -43,6 +49,10 @@ describe('TimeEntriesComponent', () => {
4349
},
4450
entries: {
4551
entryList: [],
52+
active: {
53+
start_date: new Date('2019-01-01T15:36:15.887Z'),
54+
id: 'active-entry',
55+
}
4656
},
4757
};
4858

@@ -68,13 +78,16 @@ describe('TimeEntriesComponent', () => {
6878
TechnologiesComponent,
6979
TimeEntriesSummaryComponent,
7080
],
71-
providers: [provideMockStore({ initialState: state })],
81+
providers: [provideMockStore({ initialState: state }),
82+
{ provide: ToastrService, useValue: toastrService },
83+
],
7284
imports: [FormsModule, ReactiveFormsModule],
7385
}).compileComponents();
7486
store = TestBed.inject(MockStore);
7587
mockTechnologySelector = store.overrideSelector(allTechnologies, state.technologies);
7688
mockProjectsSelector = store.overrideSelector(getProjects, state.projects.projects);
7789
mockEntriesSelector = store.overrideSelector(allEntries, state.entries.entryList);
90+
injectedToastrService = TestBed.inject(ToastrService);
7891
}));
7992

8093
beforeEach(() => {
@@ -159,30 +172,51 @@ describe('TimeEntriesComponent', () => {
159172
expect(component.entryId).toBe('entry_1');
160173
});
161174

162-
it('should update entry by id', () => {
175+
it('displays an error when start date of entry is > than active entry start date', () => {
163176
const newEntry = {
164-
project_id: 'projectId',
165-
start_date: '',
177+
project_id: 'p-id',
178+
start_date: '2020-05-05T10:04',
179+
description: 'description',
180+
technologies: [],
181+
uri: 'abc',
182+
};
183+
component.entryId = 'new-entry';
184+
spyOn(injectedToastrService, 'error');
185+
186+
component.saveEntry(newEntry);
187+
188+
expect(injectedToastrService.error).toHaveBeenCalled();
189+
});
190+
191+
it('should dispatch an action when entry is going to be saved', () => {
192+
const newEntry = {
193+
project_id: 'p-id',
194+
start_date: '2020-05-05T10:04',
166195
description: 'description',
167196
technologies: [],
168197
uri: 'abc',
169198
};
170-
component.entryId = 'entry_1';
199+
component.entryId = 'active-entry';
171200
spyOn(store, 'dispatch');
201+
172202
component.saveEntry(newEntry);
203+
173204
expect(store.dispatch).toHaveBeenCalled();
174205
});
175206

176207
it('should create new Entry', () => {
177208
const newEntry = {
178209
project_id: 'projectId',
179-
start_date: '',
210+
start_date: '2010-05-05T10:04',
180211
description: 'description',
181212
technologies: [],
182213
uri: 'abc',
183214
};
215+
component.entryId = undefined;
184216
spyOn(store, 'dispatch');
217+
185218
component.saveEntry(newEntry);
219+
186220
expect(store.dispatch).toHaveBeenCalledWith(new entryActions.CreateEntry(newEntry));
187221
});
188222

src/app/modules/time-entries/pages/time-entries.component.ts

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { ToastrService } from 'ngx-toastr';
2+
import { getActiveTimeEntry } from './../../time-clock/store/entry.selectors';
13
import { Component, OnInit } from '@angular/core';
24
import { Entry } from '../../shared/models';
35
import { EntryState } from '../../time-clock/store/entry.reducer';
@@ -14,15 +16,20 @@ export class TimeEntriesComponent implements OnInit {
1416
entryId: string;
1517
entry: Entry;
1618
dataByMonth = [];
19+
activeTimeEntry: Entry;
1720

18-
constructor(private store: Store<EntryState>) {}
21+
constructor(private store: Store<EntryState>, private toastrService: ToastrService) { }
1922

2023
ngOnInit(): void {
2124
this.store.dispatch(new entryActions.LoadEntries(new Date().getMonth() + 1));
2225
const dataByMonth$ = this.store.pipe(select(allEntries));
2326
dataByMonth$.subscribe((response) => {
2427
this.dataByMonth = response;
2528
});
29+
this.store.dispatch(new entryActions.LoadActiveEntry());
30+
this.store.pipe(select(getActiveTimeEntry)).subscribe((activeTimeEntry) => {
31+
this.activeTimeEntry = activeTimeEntry;
32+
});
2633
}
2734

2835
newEntry() {
@@ -31,17 +38,24 @@ export class TimeEntriesComponent implements OnInit {
3138
}
3239

3340
editEntry(entryId: string) {
34-
console.log(this.dataByMonth);
3541
this.entryId = entryId;
3642
this.entry = this.dataByMonth.find((entry) => entry.id === entryId);
3743
}
3844

3945
saveEntry(entry): void {
40-
if (this.entryId) {
41-
entry.id = this.entryId;
42-
this.store.dispatch(new entryActions.UpdateActiveEntry(entry));
46+
const entryDateAsIso = new Date(entry.start_date).toISOString();
47+
const entryDateAsLocalDate = new Date(entryDateAsIso);
48+
const activeEntryAsLocaldate = new Date(this.activeTimeEntry.start_date);
49+
const isEditingActiveEntry = this.entryId === this.activeTimeEntry.id;
50+
if (!isEditingActiveEntry && entryDateAsLocalDate > activeEntryAsLocaldate) {
51+
this.toastrService.error('You are on the clock and this entry overlaps it, try with earlier times.');
4352
} else {
44-
this.store.dispatch(new entryActions.CreateEntry(entry));
53+
if (this.entryId) {
54+
entry.id = this.entryId;
55+
this.store.dispatch(new entryActions.UpdateActiveEntry(entry));
56+
} else {
57+
this.store.dispatch(new entryActions.CreateEntry(entry));
58+
}
4559
}
4660
}
4761

0 commit comments

Comments
 (0)