Skip to content

Commit 5747dc3

Browse files
author
Juan Gabriel Guzman
committed
feat: ioet#204 Adding action, reducers, and selectors required for reports
1 parent f531825 commit 5747dc3

File tree

6 files changed

+137
-11
lines changed

6 files changed

+137
-11
lines changed

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,19 @@ describe('Actions for Entries', () => {
7070
const updateActiveEntryFail = new actions.UpdateActiveEntryFail('error');
7171
expect(updateActiveEntryFail.type).toEqual(actions.EntryActionTypes.UPDATE_ACTIVE_ENTRY_FAIL);
7272
});
73+
74+
it('LoadEntriesByTimeRange type is EntryActionTypes.LOAD_ENTRIES_BY_TIME_RANGE', () => {
75+
const action = new actions.LoadEntriesByTimeRange(null);
76+
expect(action.type).toEqual(actions.EntryActionTypes.LOAD_ENTRIES_BY_TIME_RANGE);
77+
});
78+
79+
it('LoadEntriesByTimeRangeSuccess type is EntryActionTypes.LOAD_ENTRIES_BY_TIME_RANGE_SUCCESS', () => {
80+
const action = new actions.LoadEntriesByTimeRangeSuccess(null);
81+
expect(action.type).toEqual(actions.EntryActionTypes.LOAD_ENTRIES_BY_TIME_RANGE_SUCCESS);
82+
});
83+
84+
it('LoadEntriesByTimeRangeFail type is EntryActionTypes.LOAD_ENTRIES_BY_TIME_RANGE_FAIL', () => {
85+
const action = new actions.LoadEntriesByTimeRangeFail();
86+
expect(action.type).toEqual(actions.EntryActionTypes.LOAD_ENTRIES_BY_TIME_RANGE_FAIL);
87+
});
7388
});

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

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { TimeEntriesSummary } from '../models/time.entry.summary';
22
import { Action } from '@ngrx/store';
33
import { NewEntry, Entry } from '../../shared/models';
4+
import {TimeEntriesTimeRange} from '../models/time-entries-time-range';
45

56
export enum EntryActionTypes {
67
LOAD_ENTRIES_SUMMARY = '[Entry] LOAD_ENTRIES_SUMMARY',
@@ -27,6 +28,9 @@ export enum EntryActionTypes {
2728
DEFAULT_ENTRY = '[Entry] DEFAULT_ENTRY',
2829
CLEAN_ENTRY_CREATE_ERROR = '[Entry] CLEAN_ENTRY_CREATE_ERROR',
2930
CLEAN_ENTRY_UPDATE_ERROR = '[Entry] CLEAN_ENTRY_UPDATE_ERROR',
31+
LOAD_ENTRIES_BY_TIME_RANGE = '[Entry] LOAD_ENTRIES_BY_TIME_RANGE',
32+
LOAD_ENTRIES_BY_TIME_RANGE_SUCCESS = '[Entry] LOAD_ENTRIES_BY_TIME_RANGE_SUCCESS',
33+
LOAD_ENTRIES_BY_TIME_RANGE_FAIL = '[Entry] LOAD_ENTRIES_BY_TIME_RANGE_FAIL',
3034
}
3135

3236
export class LoadEntriesSummary implements Action {
@@ -154,6 +158,21 @@ export class DefaultEntry implements Action {
154158
public readonly type = EntryActionTypes.DEFAULT_ENTRY;
155159
}
156160

161+
export class LoadEntriesByTimeRange implements Action {
162+
public readonly type = EntryActionTypes.LOAD_ENTRIES_BY_TIME_RANGE;
163+
constructor(readonly timeRange: TimeEntriesTimeRange) {
164+
}
165+
}
166+
167+
export class LoadEntriesByTimeRangeSuccess implements Action {
168+
readonly type = EntryActionTypes.LOAD_ENTRIES_BY_TIME_RANGE_SUCCESS;
169+
constructor(readonly payload: Entry[]) {}
170+
}
171+
172+
export class LoadEntriesByTimeRangeFail implements Action {
173+
readonly type = EntryActionTypes.LOAD_ENTRIES_BY_TIME_RANGE_FAIL;
174+
}
175+
157176
export type EntryActions =
158177
| LoadEntriesSummary
159178
| LoadEntriesSummarySuccess
@@ -178,4 +197,7 @@ export type EntryActions =
178197
| StopTimeEntryRunningFail
179198
| CleanEntryCreateError
180199
| CleanEntryUpdateError
181-
| DefaultEntry;
200+
| DefaultEntry
201+
| LoadEntriesByTimeRange
202+
| LoadEntriesByTimeRangeSuccess
203+
| LoadEntriesByTimeRangeFail

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

Lines changed: 67 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
import { TimeEntriesSummary, TimeDetails } from '../models/time.entry.summary';
2-
import { NewEntry, Entry } from './../../shared/models';
1+
import {TimeEntriesSummary, TimeDetails} from '../models/time.entry.summary';
2+
import {NewEntry, Entry} from './../../shared/models';
33
import * as actions from './entry.actions';
4-
import { entryReducer, EntryState } from './entry.reducer';
4+
import {entryReducer, EntryState} from './entry.reducer';
55

66
describe('entryReducer', () => {
77

8-
const emptyTimeDetails: TimeDetails = { hours: '--:--', minutes: '--:--', seconds: '--:--' };
9-
const emptyTimeEntriesSummary: TimeEntriesSummary = { day: emptyTimeDetails, week: emptyTimeDetails, month: emptyTimeDetails };
8+
const emptyTimeDetails: TimeDetails = {hours: '--:--', minutes: '--:--', seconds: '--:--'};
9+
const emptyTimeEntriesSummary: TimeEntriesSummary = {day: emptyTimeDetails, week: emptyTimeDetails, month: emptyTimeDetails};
10+
1011

1112
const initialState: EntryState = {
1213
active: null,
@@ -15,7 +16,8 @@ describe('entryReducer', () => {
1516
message: '',
1617
createError: null,
1718
updateError: null,
18-
timeEntriesSummary: emptyTimeEntriesSummary
19+
timeEntriesSummary: emptyTimeEntriesSummary,
20+
entriesForReport: []
1921
};
2022

2123
const entry: NewEntry = {
@@ -25,6 +27,19 @@ describe('entryReducer', () => {
2527
technologies: ['angular', 'typescript'],
2628
};
2729

30+
const entryList: Entry[] = [
31+
{
32+
project_id: '123',
33+
comments: 'description',
34+
technologies: ['angular', 'javascript'],
35+
uri: 'uri',
36+
id: 'id',
37+
start_date: new Date(),
38+
end_date: new Date(),
39+
activity_id: 'activity',
40+
}
41+
];
42+
2843
it('sets timeEntriesSummary from action on LOAD_ENTRIES_SUMMARY_SUCCESS', () => {
2944
const payload = null;
3045
const action = new actions.LoadEntriesSummarySuccess(payload);
@@ -64,7 +79,7 @@ describe('entryReducer', () => {
6479

6580
it('on LoadActiveEntrySuccess, activeEntryFound are saved in the store', () => {
6681
const activeEntryFound: NewEntry[] = [
67-
{ project_id: '123', description: 'description', technologies: ['angular', 'javascript'] , activity_id: 'xyz'},
82+
{project_id: '123', description: 'description', technologies: ['angular', 'javascript'], activity_id: 'xyz'},
6883
];
6984
const action = new actions.LoadActiveEntrySuccess(activeEntryFound);
7085
const state = entryReducer(initialState, action);
@@ -109,15 +124,15 @@ describe('entryReducer', () => {
109124
});
110125

111126
it('on CreateEntry, isLoading is true', () => {
112-
const entryToCreate: NewEntry = { project_id: '1', start_date: '2020-04-21T19:51:36.559000+00:00' };
127+
const entryToCreate: NewEntry = {project_id: '1', start_date: '2020-04-21T19:51:36.559000+00:00'};
113128
const action = new actions.CreateEntry(entryToCreate);
114129
const state = entryReducer(initialState, action);
115130

116131
expect(state.isLoading).toEqual(true);
117132
});
118133

119134
it('on CreateEntrySuccess, message is updated', () => {
120-
const entryToCreate: NewEntry = { project_id: '1', start_date: '2020-04-21T19:51:36.559000+00:00' };
135+
const entryToCreate: NewEntry = {project_id: '1', start_date: '2020-04-21T19:51:36.559000+00:00'};
121136
const action = new actions.CreateEntrySuccess(entryToCreate);
122137
const state = entryReducer(initialState, action);
123138

@@ -158,6 +173,8 @@ describe('entryReducer', () => {
158173
message: '',
159174
createError: null,
160175
updateError: null,
176+
entriesForReport: []
177+
161178
};
162179
const action = new actions.DeleteEntrySuccess('id');
163180
const state = entryReducer(currentState, action);
@@ -196,7 +213,8 @@ describe('entryReducer', () => {
196213
message: '',
197214
createError: null,
198215
updateError: null,
199-
timeEntriesSummary: emptyTimeEntriesSummary
216+
timeEntriesSummary: emptyTimeEntriesSummary,
217+
entriesForReport: []
200218
};
201219
const entryUpdated: Entry = {
202220
id: 'id',
@@ -257,4 +275,43 @@ describe('entryReducer', () => {
257275

258276
expect(state.isLoading).toBeFalsy();
259277
});
278+
279+
it('sets timeEntriesSummary from action on LOAD_ENTRIES_SUMMARY_SUCCESS', () => {
280+
const payload = null;
281+
const action = new actions.LoadEntriesSummarySuccess(payload);
282+
const state = entryReducer(initialState, action);
283+
expect(state.timeEntriesSummary).toBe(payload);
284+
});
285+
286+
it('sets message on LOAD_ACTIVE_ENTRY_FAIL', () => {
287+
const action = new actions.LoadActiveEntryFail('');
288+
const state = entryReducer(initialState, action);
289+
expect(state.message).toBe('Something went wrong fetching active entry!');
290+
});
291+
292+
it('on LoadEntriesByTimeRange, the state has isLoading is true', () => {
293+
const action = new actions.LoadEntriesByTimeRange(null);
294+
295+
const state = entryReducer(initialState, action);
296+
297+
expect(state.isLoading).toBeTrue();
298+
});
299+
300+
it('on LoadEntriesByTimeRangeSuccess, the entriesForReport is populated with the payload info from the action', () => {
301+
const payload = entryList;
302+
const action = new actions.LoadEntriesByTimeRangeSuccess(payload);
303+
304+
const state = entryReducer(initialState, action);
305+
306+
expect(state.entriesForReport).toEqual(payload);
307+
});
308+
309+
it('on LoadEntriesByTimeRangeFail, the state has isLoading is false and the entriesForReport is an empty array ', () => {
310+
const action = new actions.LoadEntriesByTimeRangeFail();
311+
312+
const state = entryReducer(initialState, action);
313+
314+
expect(state.isLoading).toBeFalse();
315+
expect(state.entriesForReport).toEqual([]);
316+
});
260317
});

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export interface EntryState {
1010
createError: boolean;
1111
updateError: boolean;
1212
timeEntriesSummary: TimeEntriesSummary;
13+
entriesForReport: Entry[];
1314
}
1415

1516
const emptyTimeDetails: TimeDetails = { hours: '--:--', minutes: '--:--', seconds: '--:--' };
@@ -23,6 +24,7 @@ export const initialState = {
2324
createError: null,
2425
updateError: null,
2526
timeEntriesSummary: emptyTimeEntriesSummary,
27+
entriesForReport: []
2628
};
2729

2830
export const entryReducer = (state: EntryState = initialState, action: EntryActions) => {
@@ -204,6 +206,27 @@ export const entryReducer = (state: EntryState = initialState, action: EntryActi
204206
};
205207
}
206208

209+
case EntryActionTypes.LOAD_ENTRIES_BY_TIME_RANGE: {
210+
return {
211+
...state,
212+
isLoading: true,
213+
};
214+
}
215+
case EntryActionTypes.LOAD_ENTRIES_BY_TIME_RANGE_SUCCESS:
216+
return {
217+
...state,
218+
entriesForReport: action.payload,
219+
isLoading: false,
220+
};
221+
222+
case EntryActionTypes.LOAD_ACTIVE_ENTRY_FAIL: {
223+
return {
224+
...state,
225+
entriesForReport: [],
226+
isLoading: false,
227+
};
228+
}
229+
207230
default: {
208231
return state;
209232
}

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,11 @@ describe('Entry selectors', () => {
1515
expect(selectors.allEntries.projector(entryState)).toBe(entryList);
1616
});
1717

18+
it('should select the entries for report', () => {
19+
const entryList = [];
20+
const entryState = { entriesForReport: entryList };
21+
22+
expect(selectors.entriesForReport.projector(entryState)).toBe(entryList);
23+
});
24+
1825
});

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,5 @@ export const getUpdateError = createSelector(getEntryState, (state: EntryState)
2222
export const getStatusMessage = createSelector(getEntryState, (state: EntryState) => state.message);
2323

2424
export const allEntries = createSelector(getEntryState, (state: EntryState) => state.entryList);
25+
26+
export const entriesForReport = createSelector(getEntryState, (state: EntryState) => state.entriesForReport);

0 commit comments

Comments
 (0)