diff --git a/src/app/modules/activities-management/components/activity-list/activity-list.component.html b/src/app/modules/activities-management/components/activity-list/activity-list.component.html index f9ebe5a7c..be520dee1 100644 --- a/src/app/modules/activities-management/components/activity-list/activity-list.component.html +++ b/src/app/modules/activities-management/components/activity-list/activity-list.component.html @@ -9,7 +9,7 @@

{{ activity.name }}
- +

diff --git a/src/app/modules/activities-management/components/activity-list/activity-list.component.spec.ts b/src/app/modules/activities-management/components/activity-list/activity-list.component.spec.ts index fe4ade315..9ad71df66 100644 --- a/src/app/modules/activities-management/components/activity-list/activity-list.component.spec.ts +++ b/src/app/modules/activities-management/components/activity-list/activity-list.component.spec.ts @@ -8,28 +8,31 @@ import { ActivityListComponent } from './activity-list.component'; describe('ActivityListComponent', () => { let component: ActivityListComponent; let fixture: ComponentFixture; + let store: MockStore; let mockActivitiesSelector; - const state = { data: [{id: 'id', name: 'name', description: 'description'}], isLoading: false, message: '' }; - - let store: MockStore; + const state = { + data: [{ id: 'id', name: 'name', description: 'description' }], + isLoading: false, + message: '', + activityIdToEdit: '', + }; beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [ ActivityListComponent ], - providers: [ provideMockStore({ initialState: state }) ] - }) - .compileComponents(); - - store = TestBed.inject(MockStore); - - mockActivitiesSelector = store.overrideSelector( allActivities, state ); + declarations: [ActivityListComponent], + providers: [provideMockStore({ initialState: state })], + }).compileComponents(); })); beforeEach(() => { fixture = TestBed.createComponent(ActivityListComponent); component = fixture.componentInstance; fixture.detectChanges(); + + store = TestBed.inject(MockStore); + store.setState(state); + mockActivitiesSelector = store.overrideSelector(allActivities, state.data); }); it('should create', () => { @@ -50,6 +53,7 @@ describe('ActivityListComponent', () => { expect(component.activities).toBe(state.data); }); - afterEach(() => { fixture.destroy(); }); - + afterEach(() => { + fixture.destroy(); + }); }); diff --git a/src/app/modules/activities-management/components/activity-list/activity-list.component.ts b/src/app/modules/activities-management/components/activity-list/activity-list.component.ts index 781d5336a..02c24bbc9 100644 --- a/src/app/modules/activities-management/components/activity-list/activity-list.component.ts +++ b/src/app/modules/activities-management/components/activity-list/activity-list.component.ts @@ -2,7 +2,7 @@ import { OnInit } from '@angular/core'; import { Component } from '@angular/core'; import { Store, select } from '@ngrx/store'; -import { LoadActivities, DeleteActivity } from './../../store/activity-management.actions'; +import { LoadActivities, DeleteActivity, SetActivityToEdit } from './../../store/activity-management.actions'; import { ActivityState } from './../../store/activity-management.reducers'; import { allActivities } from '../../store'; import { Activity } from '../../../shared/models'; @@ -14,7 +14,6 @@ import { Activity } from '../../../shared/models'; }) export class ActivityListComponent implements OnInit { activities: Activity[] = []; - public isLoading: boolean; constructor(private store: Store) {} @@ -23,12 +22,15 @@ export class ActivityListComponent implements OnInit { const activities$ = this.store.pipe(select(allActivities)); activities$.subscribe((response) => { - this.isLoading = response.isLoading; - this.activities = response.data; + this.activities = response; }); } deleteActivity(activityId: string) { this.store.dispatch(new DeleteActivity(activityId)); } + + updateActivity(activityId: string) { + this.store.dispatch(new SetActivityToEdit(activityId)); + } } diff --git a/src/app/modules/activities-management/components/create-activity/create-activity.component.html b/src/app/modules/activities-management/components/create-activity/create-activity.component.html index c77cd3ce4..daba7bc68 100644 --- a/src/app/modules/activities-management/components/create-activity/create-activity.component.html +++ b/src/app/modules/activities-management/components/create-activity/create-activity.component.html @@ -3,8 +3,14 @@

Activity

- +
Activity name is required.
@@ -16,7 +22,14 @@

Activity

- \ No newline at end of file + diff --git a/src/app/modules/activities-management/components/create-activity/create-activity.component.spec.ts b/src/app/modules/activities-management/components/create-activity/create-activity.component.spec.ts index f384855df..55670c8c5 100644 --- a/src/app/modules/activities-management/components/create-activity/create-activity.component.spec.ts +++ b/src/app/modules/activities-management/components/create-activity/create-activity.component.spec.ts @@ -3,23 +3,30 @@ import { async, TestBed, ComponentFixture } from '@angular/core/testing'; import { provideMockStore, MockStore } from '@ngrx/store/testing'; import { CreateActivityComponent } from './create-activity.component'; -import { ActivityState, CreateActivity } from '../../store'; +import { + ActivityState, + CreateActivity, + UpdateActivity, + activityIdtoEdit, + allActivities, + ResetActivityToEdit, +} from '../../store'; import { Activity } from 'src/app/modules/shared/models'; describe('CreateActivityComponent', () => { let component: CreateActivityComponent; let fixture: ComponentFixture; let store: MockStore; - - const state = { data: [{ id: 'id', name: 'name', description: 'description' }], isLoading: false, message: '' }; - - const data: Activity[] = [ - { - id: '1', - name: 'Training', - description: 'It is good for learning', - }, - ]; + let activityIdtoEditMock; + let allActivitiesMock; + let getActivityByIdMock; + + const state = { + data: [{ id: '', name: '', description: '' }], + isLoading: false, + message: '', + activityIdToEdit: '', + }; const activity: Activity = { id: '1', @@ -43,16 +50,60 @@ describe('CreateActivityComponent', () => { store.setState(state); }); + afterEach(() => { + fixture.destroy(); + }); + it('should create the component', () => { expect(component).toBeTruthy(); }); - it('should reset form onSubmit', () => { + it('should reset form onSubmit and dispatch UpdateActivity action', () => { + const currentState = { + data: [{ id: '1', name: 'xxx', description: 'xxxx' }], + isLoading: false, + message: '', + activityIdToEdit: '1', + }; + + activityIdtoEditMock = store.overrideSelector(activityIdtoEdit, currentState.activityIdToEdit); + allActivitiesMock = store.overrideSelector(allActivities, currentState.data); + getActivityByIdMock = store.overrideSelector(allActivitiesMock, activityIdtoEditMock); + + component.activityToEdit = getActivityByIdMock; + + const activityForm = { + name: 'Develop', + description: 'xxx', + }; + + const activityUpdated = { + id: component.activityToEdit.id, + name: 'Develop', + description: 'xxx', + }; + spyOn(component.activityForm, 'reset'); + spyOn(store, 'dispatch'); - component.onSubmit(data); + component.onSubmit(activityForm); expect(component.activityForm.reset).toHaveBeenCalled(); + expect(store.dispatch).toHaveBeenCalledTimes(1); + expect(store.dispatch).toHaveBeenCalledWith(new UpdateActivity(activityUpdated)); + }); + + it('should reset form onSubmit and dispatch CreateActivity action', () => { + component.activityToEdit = undefined; + + spyOn(component.activityForm, 'reset'); + spyOn(store, 'dispatch'); + + component.onSubmit(activity); + + expect(component.activityForm.reset).toHaveBeenCalled(); + expect(store.dispatch).toHaveBeenCalledTimes(1); + expect(store.dispatch).toHaveBeenCalledWith(new CreateActivity(activity)); }); it('should get name using activityForm', () => { @@ -71,10 +122,25 @@ describe('CreateActivityComponent', () => { expect(component.activityForm.get).toHaveBeenCalledWith('description'); }); - it('should dispatch createActivity action #onSubmit', () => { + it('should set data in activityForm', () => { + const activityDataForm = { + name: 'Training', + description: 'It is good for learning', + }; + + spyOn(component.activityForm, 'setValue'); + + component.setDataToUpdate(activity); + expect(component.activityForm.setValue).toHaveBeenCalledTimes(1); + expect(component.activityForm.setValue).toHaveBeenCalledWith(activityDataForm); + }); + + it('should dispatch a ResetActivityToEdit action', () => { spyOn(store, 'dispatch'); - component.onSubmit(activity); + + component.cancelButton(); + expect(store.dispatch).toHaveBeenCalledTimes(1); - expect(store.dispatch).toHaveBeenCalledWith(new CreateActivity(activity)); + expect(store.dispatch).toHaveBeenCalledWith(new ResetActivityToEdit()); }); }); diff --git a/src/app/modules/activities-management/components/create-activity/create-activity.component.ts b/src/app/modules/activities-management/components/create-activity/create-activity.component.ts index d5838432b..41bfad980 100644 --- a/src/app/modules/activities-management/components/create-activity/create-activity.component.ts +++ b/src/app/modules/activities-management/components/create-activity/create-activity.component.ts @@ -1,17 +1,19 @@ import { FormBuilder, Validators, FormGroup } from '@angular/forms'; -import { Component } from '@angular/core'; -import { Store } from '@ngrx/store'; +import { Component, OnInit } from '@angular/core'; +import { Store, select } from '@ngrx/store'; + +import { Activity } from '../../../shared/models'; import { ActivityState } from './../../store/activity-management.reducers'; -import { CreateActivity } from '../../store'; +import { CreateActivity, UpdateActivity, getActivityById, ResetActivityToEdit } from '../../store'; @Component({ selector: 'app-create-activity', templateUrl: './create-activity.component.html', styleUrls: ['./create-activity.component.scss'], }) -export class CreateActivityComponent { +export class CreateActivityComponent implements OnInit { activityForm: FormGroup; - isLoading: boolean; + activityToEdit: Activity; constructor(private formBuilder: FormBuilder, private store: Store) { this.activityForm = this.formBuilder.group({ @@ -20,9 +22,12 @@ export class CreateActivityComponent { }); } - onSubmit(activityData) { - this.activityForm.reset(); - this.store.dispatch(new CreateActivity(activityData)); + ngOnInit() { + const activities$ = this.store.pipe(select(getActivityById)); + activities$.subscribe((activity) => { + this.activityToEdit = activity; + this.setDataToUpdate(this.activityToEdit); + }); } get name() { @@ -32,4 +37,31 @@ export class CreateActivityComponent { get description() { return this.activityForm.get('description'); } + + setDataToUpdate(activityData: Activity) { + if (activityData) { + this.activityForm.setValue({ + name: activityData.name, + description: activityData.description, + }); + } + } + + onSubmit(activityData) { + this.activityForm.reset(); + + if (this.activityToEdit) { + const activity = { + ...activityData, + id: this.activityToEdit.id, + }; + this.store.dispatch(new UpdateActivity(activity)); + } else { + this.store.dispatch(new CreateActivity(activityData)); + } + } + + cancelButton() { + this.store.dispatch(new ResetActivityToEdit()); + } } diff --git a/src/app/modules/activities-management/services/activity.service.spec.ts b/src/app/modules/activities-management/services/activity.service.spec.ts index 06e963b91..8906c83de 100644 --- a/src/app/modules/activities-management/services/activity.service.spec.ts +++ b/src/app/modules/activities-management/services/activity.service.spec.ts @@ -64,4 +64,17 @@ describe('Activity Service', () => { expect(getActivitiesRequest.request.method).toBe('DELETE'); getActivitiesRequest.flush(activities); }); + + it('update activity using PUT from baseUrl', () => { + const activity = { id: '1', name: 'aaa', description: 'bbb' }; + + service.baseUrl = 'activities' + '/' + activity.id; + + service.updateActivity(activity).subscribe((response) => { + expect(response.name).toBe('aaa'); + }); + const updateActivitiesRequest = httpMock.expectOne(`${service.baseUrl}/${activity.id}`); + expect(updateActivitiesRequest.request.method).toBe('PUT'); + updateActivitiesRequest.flush(activity); + }); }); diff --git a/src/app/modules/activities-management/services/activity.service.ts b/src/app/modules/activities-management/services/activity.service.ts index 5e7736a65..3f048479d 100644 --- a/src/app/modules/activities-management/services/activity.service.ts +++ b/src/app/modules/activities-management/services/activity.service.ts @@ -30,4 +30,15 @@ export class ActivityService { const url = `${this.baseUrl}/${acitivityId}`; return this.http.delete(url); } + + updateActivity(activityData): Observable { + const url = `${this.baseUrl}/${activityData.id}`; + + const body = { + ...activityData, + tenant_id: '4225ab1e-1033-4a5f-8650-0dd4950f38c8', + }; + + return this.http.put(url, body); + } } diff --git a/src/app/modules/activities-management/store/activity-management.actions.spec.ts b/src/app/modules/activities-management/store/activity-management.actions.spec.ts index 5acecd920..9a0c8a48d 100644 --- a/src/app/modules/activities-management/store/activity-management.actions.spec.ts +++ b/src/app/modules/activities-management/store/activity-management.actions.spec.ts @@ -1,28 +1,51 @@ -import { LoadActivitiesFail, CreateActivitySuccess, CreateActivityFail } from './activity-management.actions'; -import { LoadActivitiesSuccess, ActivityManagementActionTypes } from './activity-management.actions'; +import * as actions from './activity-management.actions'; describe('LoadActivitiesSuccess', () => { it('LoadActivitiesSuccess type is ActivityManagementActionTypes.LOAD_ACTIVITIES_SUCCESS', () => { - const loadActivitiesSuccess = new LoadActivitiesSuccess([]); - expect(loadActivitiesSuccess.type).toEqual(ActivityManagementActionTypes.LOAD_ACTIVITIES_SUCCESS); + const loadActivitiesSuccess = new actions.LoadActivitiesSuccess([]); + expect(loadActivitiesSuccess.type).toEqual(actions.ActivityManagementActionTypes.LOAD_ACTIVITIES_SUCCESS); }); it('LoadActivitiesFail type is ActivityManagementActionTypes.LOAD_ACTIVITIES_FAIL', () => { - const loadActivitiesFail = new LoadActivitiesFail('error'); - expect(loadActivitiesFail.type).toEqual(ActivityManagementActionTypes.LOAD_ACTIVITIES_FAIL); + const loadActivitiesFail = new actions.LoadActivitiesFail('error'); + expect(loadActivitiesFail.type).toEqual(actions.ActivityManagementActionTypes.LOAD_ACTIVITIES_FAIL); }); it('CreateActivitySuccess type is ActivityManagementActionTypes.CREATE_ACTIVITY_SUCCESS', () => { - const createActivitySuccess = new CreateActivitySuccess({ + const createActivitySuccess = new actions.CreateActivitySuccess({ id: '1', name: 'Training', description: 'It is good for learning', }); - expect(createActivitySuccess.type).toEqual(ActivityManagementActionTypes.CREATE_ACTIVITY_SUCCESS); + expect(createActivitySuccess.type).toEqual(actions.ActivityManagementActionTypes.CREATE_ACTIVITY_SUCCESS); }); it('CreateActivityFail type is ActivityManagementActionTypes.CREATE_ACTIVITY_FAIL', () => { - const createActivityFail = new CreateActivityFail('error'); - expect(createActivityFail.type).toEqual(ActivityManagementActionTypes.CREATE_ACTIVITY_FAIL); + const createActivityFail = new actions.CreateActivityFail('error'); + expect(createActivityFail.type).toEqual(actions.ActivityManagementActionTypes.CREATE_ACTIVITY_FAIL); + }); + + it('UpdateActivitySuccess type is ActivityManagementActionTypes.UPDATE_ACTIVITY_SUCCESS', () => { + const updateActivitySuccess = new actions.UpdateActivitySuccess({ + id: '1', + name: 'Training', + description: 'test description', + }); + expect(updateActivitySuccess.type).toEqual(actions.ActivityManagementActionTypes.UPDATE_ACTIVITY_SUCCESS); + }); + + it('UpdateActivityFail type is ActivityManagementActionTypes.UPDATE_ACTIVITY_FAIL', () => { + const updateActivityFail = new actions.UpdateActivityFail('error'); + expect(updateActivityFail.type).toEqual(actions.ActivityManagementActionTypes.UPDATE_ACTIVITY_FAIL); + }); + + it('SetActivityToEdit type is ActivityManagementActionTypes.SET_ACTIVITY_ID_TO_EDIT', () => { + const setActivityToEdit = new actions.SetActivityToEdit('123'); + expect(setActivityToEdit.type).toEqual(actions.ActivityManagementActionTypes.SET_ACTIVITY_ID_TO_EDIT); + }); + + it('ResetActivityToEdit type is ActivityManagementActionTypes.RESET_ACTIVITY_ID_TO_EDIT', () => { + const resetActivityToEdit = new actions.ResetActivityToEdit(); + expect(resetActivityToEdit.type).toEqual(actions.ActivityManagementActionTypes.RESET_ACTIVITY_ID_TO_EDIT); }); }); diff --git a/src/app/modules/activities-management/store/activity-management.actions.ts b/src/app/modules/activities-management/store/activity-management.actions.ts index c467c6998..f07d18efc 100644 --- a/src/app/modules/activities-management/store/activity-management.actions.ts +++ b/src/app/modules/activities-management/store/activity-management.actions.ts @@ -12,6 +12,11 @@ export enum ActivityManagementActionTypes { DELETE_ACTIVITY = '[ActivityManagement] DELETE_ACTIVITY', DELETE_ACTIVITY_SUCCESS = '[ActivityManagement] DELETE_ACTIVITY_SUCESS', DELETE_ACTIVITY_FAIL = '[ActivityManagement] DELETE_ACTIVITY_FAIL', + UPDATE_ACTIVITY = '[ActivityManagement] UPDATE_ACTIVITY', + UPDATE_ACTIVITY_SUCCESS = '[ActivityManagement] UPDATE_ACTIVITY_SUCCESS', + UPDATE_ACTIVITY_FAIL = '[ActivityManagement] UPDATE_ACTIVITY_FAIL', + SET_ACTIVITY_ID_TO_EDIT = '[ActivityManagement] SET_ACTIVITY_ID_TO_EDIT', + RESET_ACTIVITY_ID_TO_EDIT = '[ActivityManagement] RESET_ACTIVITY_ID_TO_EDIT', } export class LoadActivities implements Action { @@ -65,6 +70,33 @@ export class DeleteActivityFail implements Action { constructor(public error: string) {} } +export class UpdateActivity implements Action { + public readonly type = ActivityManagementActionTypes.UPDATE_ACTIVITY; + + constructor(public payload: Activity) {} +} + +export class UpdateActivitySuccess implements Action { + public readonly type = ActivityManagementActionTypes.UPDATE_ACTIVITY_SUCCESS; + + constructor(public payload: Activity) {} +} + +export class UpdateActivityFail implements Action { + public readonly type = ActivityManagementActionTypes.UPDATE_ACTIVITY_FAIL; + + constructor(public error: string) {} +} + +export class SetActivityToEdit implements Action { + public readonly type = ActivityManagementActionTypes.SET_ACTIVITY_ID_TO_EDIT; + + constructor(public payload: string) {} +} + +export class ResetActivityToEdit implements Action { + public readonly type = ActivityManagementActionTypes.RESET_ACTIVITY_ID_TO_EDIT; +} export type ActivityManagementActions = | LoadActivities @@ -75,4 +107,9 @@ export type ActivityManagementActions = | CreateActivityFail | DeleteActivity | DeleteActivitySuccess - | DeleteActivityFail; + | DeleteActivityFail + | UpdateActivity + | UpdateActivitySuccess + | UpdateActivityFail + | SetActivityToEdit + | ResetActivityToEdit; diff --git a/src/app/modules/activities-management/store/activity-management.effects.ts b/src/app/modules/activities-management/store/activity-management.effects.ts index 885511745..8014038cc 100644 --- a/src/app/modules/activities-management/store/activity-management.effects.ts +++ b/src/app/modules/activities-management/store/activity-management.effects.ts @@ -52,4 +52,18 @@ export class ActivityEffects { ) ) ); + + @Effect() + updateActivity$: Observable = this.actions$.pipe( + ofType(actions.ActivityManagementActionTypes.UPDATE_ACTIVITY), + map((action: actions.UpdateActivity) => action.payload), + mergeMap((activity) => + this.activityService.updateActivity(activity).pipe( + map((activityData) => { + return new actions.UpdateActivitySuccess(activityData); + }), + catchError((error) => of(new actions.UpdateActivityFail(error))) + ) + ) + ); } diff --git a/src/app/modules/activities-management/store/activity-management.reducers.spec.ts b/src/app/modules/activities-management/store/activity-management.reducers.spec.ts index 1298ba02f..894d24bd0 100644 --- a/src/app/modules/activities-management/store/activity-management.reducers.spec.ts +++ b/src/app/modules/activities-management/store/activity-management.reducers.spec.ts @@ -1,19 +1,13 @@ import { Activity } from './../../shared/models/activity.model'; -import { - LoadActivitiesFail, - LoadActivities, - CreateActivitySuccess, - CreateActivityFail, - CreateActivity, - DeleteActivitySuccess, -} from './activity-management.actions'; -import { LoadActivitiesSuccess } from './activity-management.actions'; +import * as actions from './activity-management.actions'; import { activityManagementReducer, ActivityState } from './activity-management.reducers'; + describe('activityManagementReducer', () => { - const initialState: ActivityState = { data: [], isLoading: false, message: '' }; + const initialState: ActivityState = { data: [], isLoading: false, message: '', activityIdToEdit: '' }; + const activity: Activity = { id: '1', name: 'Training', description: 'It is good for learning' }; it('on LoadActivities, isLoading is true', () => { - const action = new LoadActivities(); + const action = new actions.LoadActivities(); const state = activityManagementReducer(initialState, action); @@ -22,7 +16,7 @@ describe('activityManagementReducer', () => { it('on LoadActivitiesSuccess, activitiesFound are saved in the store', () => { const activitiesFound: Activity[] = [{ id: '', name: '', description: '' }]; - const action = new LoadActivitiesSuccess(activitiesFound); + const action = new actions.LoadActivitiesSuccess(activitiesFound); const state = activityManagementReducer(initialState, action); @@ -30,7 +24,7 @@ describe('activityManagementReducer', () => { }); it('on LoadActivitiesFail, message equal to Something went wrong fetching activities!', () => { - const action = new LoadActivitiesFail('error'); + const action = new actions.LoadActivitiesFail('error'); const state = activityManagementReducer(initialState, action); @@ -38,8 +32,7 @@ describe('activityManagementReducer', () => { }); it('on CreateActivity, isLoading is true', () => { - const activity: Activity = { id: '1', name: 'Training', description: 'It is good for learning' }; - const action = new CreateActivity(activity); + const action = new actions.CreateActivity(activity); const state = activityManagementReducer(initialState, action); @@ -47,8 +40,7 @@ describe('activityManagementReducer', () => { }); it('on CreateActivitySuccess, activitiesFound are saved in the store', () => { - const activity: Activity = { id: '1', name: 'Training', description: 'It is good for learning' }; - const action = new CreateActivitySuccess(activity); + const action = new actions.CreateActivitySuccess(activity); const state = activityManagementReducer(initialState, action); @@ -57,7 +49,7 @@ describe('activityManagementReducer', () => { }); it('on CreateActivityFail, message equal to Something went wrong creating activities!', () => { - const action = new CreateActivityFail('error'); + const action = new actions.CreateActivityFail('error'); const state = activityManagementReducer(initialState, action); @@ -65,12 +57,75 @@ describe('activityManagementReducer', () => { expect(state.isLoading).toEqual(false); }); - it('on DeleteActivity, message equal to Activity removed successfully!', () => { + it('on DeleteActivity, isLoading is true', () => { const activityToDeleteId = '1'; - const action = new DeleteActivitySuccess(activityToDeleteId); + const action = new actions.DeleteActivity(activityToDeleteId); const state = activityManagementReducer(initialState, action); + expect(state.isLoading).toEqual(true); + }); + + it('on DeleteActivitySuccess, message equal to Activity removed successfully!', () => { + const currentState: ActivityState = { data: [activity], isLoading: false, message: '', activityIdToEdit: '' }; + const activityToDeleteId = '1'; + const action = new actions.DeleteActivitySuccess(activityToDeleteId); + const state = activityManagementReducer(currentState, action); + expect(state.data).toEqual([]); expect(state.message).toEqual('Activity removed successfully!'); }); + + it('on DeleteActivityFail, message equal to Something went wrong deleting activity!', () => { + const activityToDeleteId = '1'; + const action = new actions.DeleteActivityFail(activityToDeleteId); + + const state = activityManagementReducer(initialState, action); + expect(state.isLoading).toEqual(false); + expect(state.message).toEqual('Something went wrong deleting activity!'); + }); + + it('on UpdateActivity, isLoading is true', () => { + const action = new actions.UpdateActivity(activity); + + const state = activityManagementReducer(initialState, action); + + expect(state.isLoading).toEqual(true); + }); + + it('on UpdateActivitySuccess, activitiesFound are saved in the store', () => { + const currentState: ActivityState = { data: [activity], isLoading: false, message: '', activityIdToEdit: '1' }; + const activityEdited: Activity = { id: '1', name: 'Test', description: 'edit test' }; + + const action = new actions.UpdateActivitySuccess(activityEdited); + + const state = activityManagementReducer(currentState, action); + + expect(state.data).toEqual([activityEdited]); + expect(state.isLoading).toEqual(false); + }); + + it('on UpdateActivityFail, message equal to Something went wrong creating activities!', () => { + const action = new actions.UpdateActivityFail('error'); + + const state = activityManagementReducer(initialState, action); + + expect(state.message).toEqual('Something went wrong updating activities!'); + expect(state.isLoading).toEqual(false); + }); + + it('on SetActivityToEdit, should save the activityId to edit', () => { + const action = new actions.SetActivityToEdit(activity.id); + + const state = activityManagementReducer(initialState, action); + + expect(state.activityIdToEdit).toEqual('1'); + }); + + it('on ResetActivityToEdit, should clean the activityIdToEdit variable', () => { + const action = new actions.ResetActivityToEdit(); + + const state = activityManagementReducer(initialState, action); + + expect(state.activityIdToEdit).toEqual(''); + }); }); diff --git a/src/app/modules/activities-management/store/activity-management.reducers.ts b/src/app/modules/activities-management/store/activity-management.reducers.ts index 7150cf7be..6ef86f5dc 100644 --- a/src/app/modules/activities-management/store/activity-management.reducers.ts +++ b/src/app/modules/activities-management/store/activity-management.reducers.ts @@ -5,15 +5,18 @@ export interface ActivityState { data: Activity[]; isLoading: boolean; message: string; + activityIdToEdit: string; } export const initialState: ActivityState = { data: [], isLoading: false, message: '', + activityIdToEdit: '', }; export function activityManagementReducer(state: ActivityState = initialState, action: ActivityManagementActions) { + const activityList = [...state.data]; switch (action.type) { case ActivityManagementActionTypes.LOAD_ACTIVITIES: { return { @@ -31,7 +34,7 @@ export function activityManagementReducer(state: ActivityState = initialState, a }; } case ActivityManagementActionTypes.LOAD_ACTIVITIES_FAIL: { - return { data: [], isLoading: false, message: 'Something went wrong fetching activities!' }; + return { data: [], isLoading: false, message: 'Something went wrong fetching activities!', activityIdToEdit: '' }; } case ActivityManagementActionTypes.CREATE_ACTIVITY: { @@ -49,13 +52,16 @@ export function activityManagementReducer(state: ActivityState = initialState, a message: 'Data created successfully!', }; } + case ActivityManagementActionTypes.CREATE_ACTIVITY_FAIL: { return { data: [], isLoading: false, message: 'Something went wrong creating activities!', + activityIdToEdit: '', }; } + case ActivityManagementActionTypes.DELETE_ACTIVITY: { return { ...state, @@ -66,6 +72,7 @@ export function activityManagementReducer(state: ActivityState = initialState, a case ActivityManagementActionTypes.DELETE_ACTIVITY_SUCCESS: { const activites = state.data.filter((activity) => activity.id !== action.activityId); return { + ...state, data: activites, isLoading: false, message: 'Activity removed successfully!', @@ -77,8 +84,55 @@ export function activityManagementReducer(state: ActivityState = initialState, a data: [], isLoading: false, message: 'Something went wrong deleting activity!', + activityIdToEdit: '', + }; + } + + case ActivityManagementActionTypes.UPDATE_ACTIVITY: { + return { + ...state, + isLoading: true, }; } + + case ActivityManagementActionTypes.UPDATE_ACTIVITY_SUCCESS: { + const index = activityList.findIndex((activity) => activity.id === action.payload.id); + activityList[index] = action.payload; + + return { + ...state, + data: activityList, + isLoading: false, + message: 'Data updated successfully!', + activityIdToEdit: '', + }; + } + + case ActivityManagementActionTypes.UPDATE_ACTIVITY_FAIL: { + return { + data: [], + isLoading: false, + message: 'Something went wrong updating activities!', + activityIdToEdit: '', + }; + } + + case ActivityManagementActionTypes.SET_ACTIVITY_ID_TO_EDIT: { + return { + ...state, + activityIdToEdit: action.payload, + message: 'Set activityIdToEdit property', + }; + } + + case ActivityManagementActionTypes.RESET_ACTIVITY_ID_TO_EDIT: { + return { + ...state, + activityIdToEdit: '', + message: 'Reset activityIdToEdit property', + }; + } + default: return state; } diff --git a/src/app/modules/activities-management/store/activity-management.selectors.ts b/src/app/modules/activities-management/store/activity-management.selectors.ts index bcac26195..277e9c07a 100644 --- a/src/app/modules/activities-management/store/activity-management.selectors.ts +++ b/src/app/modules/activities-management/store/activity-management.selectors.ts @@ -5,5 +5,17 @@ import { ActivityState } from './activity-management.reducers'; const getActivityState = createFeatureSelector('activities'); export const allActivities = createSelector(getActivityState, (state: ActivityState) => { - return state; + return state.data; +}); + +export const activityIdtoEdit = createSelector(getActivityState, (state: ActivityState) => { + return state.activityIdToEdit; +}); + +export const getActivityById = createSelector(allActivities, activityIdtoEdit, (activities, activityId) => { + if (activities && activityId) { + return activities.find((activity) => { + return activity.id === activityId; + }); + } });