-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
SHIBUI-1031 Added state and service for admin users
- Loading branch information
Showing
8 changed files
with
467 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
import { Action } from '@ngrx/store'; | ||
import { Update } from '@ngrx/entity'; | ||
import { Admin } from '../model/admin'; | ||
|
||
export enum AdminCollectionActionTypes { | ||
SELECT_ADMIN_REQUEST = '[Admin Collection] Select Admin Request', | ||
SELECT_ADMIN_SUCCESS = '[Admin Collection] Select Admin Success', | ||
SELECT_ADMIN_FAIL = '[Admin Collection] Select Admin Fail', | ||
|
||
UPDATE_ADMIN_REQUEST = '[Admin Collection] Update Admin Request', | ||
UPDATE_ADMIN_SUCCESS = '[Admin Collection] Update Admin Success', | ||
UPDATE_ADMIN_FAIL = '[Admin Collection] Update Admin Fail', | ||
|
||
LOAD_ADMIN_REQUEST = '[Admin Collection] Load Admin Request', | ||
LOAD_ADMIN_SUCCESS = '[Admin Collection] Load Admin Success', | ||
LOAD_ADMIN_ERROR = '[Admin Collection] Load Admin Error', | ||
|
||
ADD_ADMIN_REQUEST = '[Admin Collection] Add Admin Request', | ||
ADD_ADMIN_SUCCESS = '[Admin Collection] Add Admin Success', | ||
ADD_ADMIN_FAIL = '[Admin Collection] Add Admin Fail', | ||
|
||
REMOVE_ADMIN_REQUEST = '[Admin Collection] Remove Admin Request', | ||
REMOVE_ADMIN_SUCCESS = '[Admin Collection] Remove Admin Success', | ||
REMOVE_ADMIN_FAIL = '[Admin Collection] Remove Admin Fail', | ||
|
||
CLEAR_ADMINS = '[Admin Collection] Clear Admins' | ||
|
||
} | ||
|
||
export class SelectAdmin implements Action { | ||
readonly type = AdminCollectionActionTypes.SELECT_ADMIN_REQUEST; | ||
|
||
constructor(public payload: string) { } | ||
} | ||
|
||
export class SelectAdminSuccess implements Action { | ||
readonly type = AdminCollectionActionTypes.SELECT_ADMIN_SUCCESS; | ||
|
||
constructor(public payload: Admin) { } | ||
} | ||
|
||
export class SelectAdminFail implements Action { | ||
readonly type = AdminCollectionActionTypes.SELECT_ADMIN_FAIL; | ||
|
||
constructor(public payload: Error) { } | ||
} | ||
|
||
export class LoadAdminRequest implements Action { | ||
readonly type = AdminCollectionActionTypes.LOAD_ADMIN_REQUEST; | ||
|
||
constructor() { } | ||
} | ||
|
||
export class LoadAdminSuccess implements Action { | ||
readonly type = AdminCollectionActionTypes.LOAD_ADMIN_SUCCESS; | ||
|
||
constructor(public payload: Admin[]) { } | ||
} | ||
|
||
export class LoadAdminError implements Action { | ||
readonly type = AdminCollectionActionTypes.LOAD_ADMIN_ERROR; | ||
|
||
constructor(public payload: any) { } | ||
} | ||
|
||
export class UpdateAdminRequest implements Action { | ||
readonly type = AdminCollectionActionTypes.UPDATE_ADMIN_REQUEST; | ||
|
||
constructor(public payload: Admin) { } | ||
} | ||
|
||
export class UpdateAdminSuccess implements Action { | ||
readonly type = AdminCollectionActionTypes.UPDATE_ADMIN_SUCCESS; | ||
|
||
constructor(public payload: Update<Admin>) { } | ||
} | ||
|
||
export class UpdateAdminFail implements Action { | ||
readonly type = AdminCollectionActionTypes.UPDATE_ADMIN_FAIL; | ||
|
||
constructor(public payload: Admin) { } | ||
} | ||
|
||
export class AddAdminRequest implements Action { | ||
readonly type = AdminCollectionActionTypes.ADD_ADMIN_REQUEST; | ||
|
||
constructor(public payload: Admin) { } | ||
} | ||
|
||
export class AddAdminSuccess implements Action { | ||
readonly type = AdminCollectionActionTypes.ADD_ADMIN_SUCCESS; | ||
|
||
constructor(public payload: Admin) { } | ||
} | ||
|
||
export class AddAdminFail implements Action { | ||
readonly type = AdminCollectionActionTypes.ADD_ADMIN_FAIL; | ||
|
||
constructor(public payload: any) { } | ||
} | ||
|
||
export class RemoveAdminRequest implements Action { | ||
readonly type = AdminCollectionActionTypes.REMOVE_ADMIN_REQUEST; | ||
|
||
constructor(public payload: string) { } | ||
} | ||
|
||
export class RemoveAdminSuccess implements Action { | ||
readonly type = AdminCollectionActionTypes.REMOVE_ADMIN_SUCCESS; | ||
|
||
constructor(public payload: string) { } | ||
} | ||
|
||
export class RemoveAdminFail implements Action { | ||
readonly type = AdminCollectionActionTypes.REMOVE_ADMIN_FAIL; | ||
|
||
constructor(public error: Error) { } | ||
} | ||
|
||
export class ClearAdmins implements Action { | ||
readonly type = AdminCollectionActionTypes.CLEAR_ADMINS; | ||
} | ||
|
||
|
||
export type AdminCollectionActionsUnion = | ||
| LoadAdminRequest | ||
| LoadAdminSuccess | ||
| LoadAdminError | ||
| AddAdminRequest | ||
| AddAdminSuccess | ||
| AddAdminFail | ||
| RemoveAdminRequest | ||
| RemoveAdminSuccess | ||
| RemoveAdminFail | ||
| SelectAdmin | ||
| SelectAdminSuccess | ||
| SelectAdminFail | ||
| UpdateAdminRequest | ||
| UpdateAdminSuccess | ||
| UpdateAdminFail | ||
| ClearAdmins; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import { Injectable } from '@angular/core'; | ||
import { Effect, Actions, ofType } from '@ngrx/effects'; | ||
import { Store } from '@ngrx/store'; | ||
import { switchMap, map } from 'rxjs/operators'; | ||
|
||
import * as fromAdmin from '../reducer'; | ||
import { | ||
LoadAdminRequest, | ||
AdminCollectionActionTypes, | ||
LoadAdminSuccess, | ||
UpdateAdminRequest, | ||
UpdateAdminSuccess, | ||
RemoveAdminRequest, | ||
RemoveAdminSuccess | ||
} from '../action/collection.action'; | ||
import { AdminService } from '../service/admin.service'; | ||
|
||
|
||
/* istanbul ignore next */ | ||
@Injectable() | ||
export class AdminCollectionEffects { | ||
|
||
@Effect() | ||
loadAdminRequest$ = this.actions$.pipe( | ||
ofType<LoadAdminRequest>(AdminCollectionActionTypes.LOAD_ADMIN_REQUEST), | ||
switchMap(() => this.adminService.query().pipe( | ||
map(users => new LoadAdminSuccess(users)) | ||
)) | ||
); | ||
|
||
@Effect() | ||
updateAdminRequest$ = this.actions$.pipe( | ||
ofType<UpdateAdminRequest>(AdminCollectionActionTypes.UPDATE_ADMIN_REQUEST), | ||
map(action => action.payload), | ||
switchMap(changes => this.adminService.update(changes).pipe( | ||
map(user => new UpdateAdminSuccess({ | ||
id: changes.resourceId, | ||
changes | ||
})) | ||
)) | ||
); | ||
|
||
@Effect() | ||
removeAdminRequest$ = this.actions$.pipe( | ||
ofType<RemoveAdminRequest>(AdminCollectionActionTypes.REMOVE_ADMIN_REQUEST), | ||
map(action => action.payload), | ||
switchMap(id => this.adminService.remove(id).pipe( | ||
map(user => new RemoveAdminSuccess(id)) | ||
)) | ||
); | ||
|
||
@Effect() | ||
removeAdminSuccessReload$ = this.actions$.pipe( | ||
ofType<RemoveAdminSuccess>(AdminCollectionActionTypes.REMOVE_ADMIN_SUCCESS), | ||
map(action => new LoadAdminRequest()) | ||
); | ||
|
||
constructor( | ||
private actions$: Actions, | ||
private adminService: AdminService, | ||
private store: Store<fromAdmin.State> | ||
) { } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { User } from '../../../core/model/user'; | ||
|
||
export interface Admin extends User { | ||
createdDate?: string; | ||
updatedDate?: string; | ||
resourceId: string; | ||
|
||
email: string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import { reducer, initialState as snapshot } from './collection.reducer'; | ||
import * as fromAdmin from './collection.reducer'; | ||
import { | ||
AdminCollectionActionTypes, | ||
LoadAdminSuccess, | ||
UpdateAdminSuccess, | ||
RemoveAdminSuccess | ||
} from '../action/collection.action'; | ||
import { Admin } from '../model/admin'; | ||
|
||
let users = <Admin[]>[ | ||
{ | ||
resourceId: 'abc', | ||
role: 'SUPER_ADMIN', | ||
email: 'foo@bar.com', | ||
name: { | ||
first: 'Jane', | ||
last: 'Doe' | ||
} | ||
}, | ||
{ | ||
resourceId: 'def', | ||
role: 'DELEGATED_ADMIN', | ||
email: 'bar@baz.com', | ||
name: { | ||
first: 'John', | ||
last: 'Doe' | ||
} | ||
} | ||
]; | ||
|
||
describe('Admin Collection Reducer', () => { | ||
describe('undefined action', () => { | ||
it('should return the default state', () => { | ||
const result = reducer(snapshot, {} as any); | ||
|
||
expect(result).toEqual(snapshot); | ||
}); | ||
}); | ||
|
||
describe(`${AdminCollectionActionTypes.LOAD_ADMIN_SUCCESS}`, () => { | ||
it('should add the loaded filters to the collection', () => { | ||
spyOn(fromAdmin.adapter, 'addAll').and.callThrough(); | ||
const action = new LoadAdminSuccess(users); | ||
const result = reducer(snapshot, action); | ||
expect(fromAdmin.adapter.addAll).toHaveBeenCalled(); | ||
}); | ||
}); | ||
|
||
describe(`${AdminCollectionActionTypes.UPDATE_ADMIN_SUCCESS}`, () => { | ||
it('should update the filter in the collection', () => { | ||
spyOn(fromAdmin.adapter, 'updateOne').and.callThrough(); | ||
const update = { | ||
id: 'abc', | ||
changes: { role: 'DELEGATED_ADMIN' } | ||
}; | ||
const action = new UpdateAdminSuccess(update); | ||
const result = reducer(snapshot, action); | ||
expect(fromAdmin.adapter.updateOne).toHaveBeenCalled(); | ||
}); | ||
}); | ||
|
||
describe(`${AdminCollectionActionTypes.REMOVE_ADMIN_SUCCESS}`, () => { | ||
it('should set saving to false', () => { | ||
const action = new RemoveAdminSuccess('abc'); | ||
expect(reducer(snapshot, action).saving).toBe(false); | ||
}); | ||
}); | ||
|
||
describe('selector methods', () => { | ||
describe('getSelectedAdminId', () => { | ||
it('should return the state selectedAdminId', () => { | ||
expect(fromAdmin.getSelectedAdminId(snapshot)).toBe(snapshot.selectedAdminId); | ||
}); | ||
}); | ||
|
||
describe('getError', () => { | ||
it('should return the state saving', () => { | ||
expect(fromAdmin.getIsSaving(snapshot)).toBe(snapshot.saving); | ||
}); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity'; | ||
import { Admin } from '../model/admin'; | ||
import { AdminCollectionActionsUnion, AdminCollectionActionTypes } from '../action/collection.action'; | ||
|
||
export interface CollectionState extends EntityState<Admin> { | ||
selectedAdminId: string | null; | ||
saving: boolean; | ||
} | ||
|
||
export const adapter: EntityAdapter<Admin> = createEntityAdapter<Admin>({ | ||
selectId: (model: Admin) => model.resourceId | ||
}); | ||
|
||
export const initialState: CollectionState = adapter.getInitialState({ | ||
selectedAdminId: null, | ||
saving: false | ||
}); | ||
|
||
export function reducer(state = initialState, action: AdminCollectionActionsUnion): CollectionState { | ||
switch (action.type) { | ||
case AdminCollectionActionTypes.LOAD_ADMIN_SUCCESS: { | ||
let s = adapter.addAll(action.payload, { | ||
...state, | ||
selectedAdminId: state.selectedAdminId | ||
}); | ||
return s; | ||
} | ||
case AdminCollectionActionTypes.UPDATE_ADMIN_SUCCESS: { | ||
return adapter.updateOne(action.payload, { | ||
...state, | ||
saving: false | ||
}); | ||
} | ||
case AdminCollectionActionTypes.REMOVE_ADMIN_SUCCESS: { | ||
return adapter.removeOne(action.payload, { | ||
...state, | ||
saving: false | ||
}); | ||
} | ||
|
||
default: { | ||
return state; | ||
} | ||
} | ||
} | ||
|
||
export const getSelectedAdminId = (state: CollectionState) => state.selectedAdminId; | ||
export const getIsSaving = (state: CollectionState) => state.saving; | ||
export const { | ||
selectIds: selectAdminIds, | ||
selectEntities: selectAdminEntities, | ||
selectAll: selectAllAdmins, | ||
selectTotal: selectAdminTotal | ||
} = adapter.getSelectors(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { createSelector, createFeatureSelector } from '@ngrx/store'; | ||
import * as fromRoot from '../../../core/reducer'; | ||
import * as fromCollection from './collection.reducer'; | ||
|
||
export interface AdminState { | ||
collection: fromCollection.CollectionState; | ||
} | ||
|
||
export const reducers = { | ||
collection: fromCollection.reducer | ||
}; | ||
|
||
export interface State extends fromRoot.State { | ||
'admin': AdminState; | ||
} | ||
|
||
export const getCollectionFromStateFn = (state: AdminState) => state.collection; | ||
|
||
export const getAdminState = createFeatureSelector<AdminState>('admin'); | ||
|
||
/* | ||
* Select pieces of Admin Collection | ||
*/ | ||
export const getCollectionState = createSelector(getAdminState, getCollectionFromStateFn); | ||
export const getAllAdmins = createSelector(getCollectionState, fromCollection.selectAllAdmins); | ||
export const getCollectionSaving = createSelector(getCollectionState, fromCollection.getIsSaving); | ||
|
||
export const getAdminEntities = createSelector(getCollectionState, fromCollection.selectAdminEntities); | ||
export const getSelectedAdminId = createSelector(getCollectionState, fromCollection.getSelectedAdminId); | ||
export const getSelectedAdmin = createSelector(getAdminEntities, getSelectedAdminId, (entities, selectedId) => { | ||
return selectedId && entities[selectedId]; | ||
}); | ||
export const getAdminIds = createSelector(getCollectionState, fromCollection.selectAdminIds); |
Oops, something went wrong.