diff --git a/ui/src/app/core/action/configuration.action.ts b/ui/src/app/core/action/configuration.action.ts new file mode 100644 index 000000000..33c9e4c82 --- /dev/null +++ b/ui/src/app/core/action/configuration.action.ts @@ -0,0 +1,29 @@ +import { Action } from '@ngrx/store'; + +export enum ConfigurationActionTypes { + LOAD_ROLE_REQUEST = '[Config] Load User Role Request', + LOAD_ROLE_SUCCESS = '[Config] Load User Role Success', + LOAD_ROLE_FAIL = '[Config] Load User Role Fail' +} + +export class LoadRoleRequest implements Action { + readonly type = ConfigurationActionTypes.LOAD_ROLE_REQUEST; + + constructor() {} +} +export class LoadRoleSuccess implements Action { + readonly type = ConfigurationActionTypes.LOAD_ROLE_SUCCESS; + + constructor(public payload: string[]) { } +} +export class LoadRoleFail implements Action { + readonly type = ConfigurationActionTypes.LOAD_ROLE_FAIL; + + constructor() { } +} + +export type ConfigurationActionUnion = + | LoadRoleRequest + | LoadRoleSuccess + | LoadRoleFail +; diff --git a/ui/src/app/core/effect/user.effect.ts b/ui/src/app/core/effect/user.effect.ts index 72f3a8aac..42cc412ba 100644 --- a/ui/src/app/core/effect/user.effect.ts +++ b/ui/src/app/core/effect/user.effect.ts @@ -5,6 +5,7 @@ import { of } from 'rxjs'; import { map, tap, catchError, switchMap } from 'rxjs/operators'; import * as user from '../action/user.action'; +import { LoadRoleRequest, LoadRoleFail, LoadRoleSuccess, ConfigurationActionTypes } from '../action/configuration.action'; import { UserService } from '../service/user.service'; @Injectable() @@ -21,6 +22,19 @@ export class UserEffects { ) ) ); + + @Effect() + loadRoles$ = this.actions$.pipe( + ofType(ConfigurationActionTypes.LOAD_ROLE_REQUEST), + switchMap(() => + this.userService.getRoles() + .pipe( + map(roles => new LoadRoleSuccess(roles)), + catchError(error => of(new LoadRoleFail())) + ) + ) + ); + @Effect({dispatch: false}) redirect$ = this.actions$.pipe( ofType(user.REDIRECT), diff --git a/ui/src/app/core/reducer/configuration.reducer.ts b/ui/src/app/core/reducer/configuration.reducer.ts new file mode 100644 index 000000000..8f29e4126 --- /dev/null +++ b/ui/src/app/core/reducer/configuration.reducer.ts @@ -0,0 +1,25 @@ +import { ConfigurationActionUnion, ConfigurationActionTypes } from '../action/configuration.action'; + +export interface ConfigState { + roles: string[]; +} + +export const initialState: ConfigState = { + roles: [] +}; + +export function reducer(state = initialState, action: ConfigurationActionUnion): ConfigState { + switch (action.type) { + case ConfigurationActionTypes.LOAD_ROLE_SUCCESS: { + return { + roles: [...action.payload] + }; + } + default: { + return state; + } + } +} + + +export const getRoles = (state: ConfigState) => state.roles; diff --git a/ui/src/app/core/reducer/index.ts b/ui/src/app/core/reducer/index.ts index 15098e68e..9d9f91dec 100644 --- a/ui/src/app/core/reducer/index.ts +++ b/ui/src/app/core/reducer/index.ts @@ -5,11 +5,13 @@ import { import * as fromUser from './user.reducer'; import * as fromVersion from './version.reducer'; +import * as fromConfig from './configuration.reducer'; import * as fromRoot from '../../app.reducer'; export interface CoreState { user: fromUser.UserState; version: fromVersion.VersionState; + config: fromConfig.ConfigState; } export interface State extends fromRoot.State { @@ -18,19 +20,24 @@ export interface State extends fromRoot.State { export const reducers = { user: fromUser.reducer, - version: fromVersion.reducer + version: fromVersion.reducer, + config: fromConfig.reducer }; export const getCoreFeature = createFeatureSelector('core'); export const getUserStateFn = (state: CoreState) => state.user; export const getVersionStateFn = (state: CoreState) => state.version; +export const getConfigStateFn = (state: CoreState) => state.config; export const getUserState = createSelector(getCoreFeature, getUserStateFn); export const getUser = createSelector(getUserState, fromUser.getUser); export const isFetching = createSelector(getUserState, fromUser.isFetching); export const getUserError = createSelector(getUserState, fromUser.getError); -export const getVersionState = createSelector(getCoreFeature, (state: CoreState) => state.version); +export const getVersionState = createSelector(getCoreFeature, getVersionStateFn); export const getVersionInfo = createSelector(getVersionState, fromVersion.getVersionInfo); export const getVersionLoading = createSelector(getVersionState, fromVersion.getVersionIsLoading); export const getVersionError = createSelector(getVersionState, fromVersion.getVersionError); + +export const getConfigState = createSelector(getCoreFeature, getConfigStateFn); +export const getRoles = createSelector(getConfigState, fromConfig.getRoles); diff --git a/ui/src/app/core/service/user.service.ts b/ui/src/app/core/service/user.service.ts index 6570b4482..dae49d4e3 100644 --- a/ui/src/app/core/service/user.service.ts +++ b/ui/src/app/core/service/user.service.ts @@ -1,11 +1,16 @@ import { Injectable } from '@angular/core'; import { Observable, of } from 'rxjs'; import { User } from '../model/user'; +import { HttpClient } from '@angular/common/http'; @Injectable() export class UserService { - constructor() { } + readonly base = `/api`; + + constructor( + private http: HttpClient + ) { } get(): Observable { const defUser = Object.assign({}, { @@ -18,4 +23,10 @@ export class UserService { }); return of(defUser); } + + getRoles(): Observable { + return this.http.get( + `${this.base}/supportedRoles` + ); + } } /* istanbul ignore next */ diff --git a/ui/src/app/user/admin/container/admin-management.component.html b/ui/src/app/user/admin/container/admin-management.component.html index 7b32aa82f..5cc2e72b1 100644 --- a/ui/src/app/user/admin/container/admin-management.component.html +++ b/ui/src/app/user/admin/container/admin-management.component.html @@ -20,16 +20,16 @@ - {{ user.resourceId }} - {{ user.name.first }} {{ user.name.last }} - {{ user.email }} + {{ user.username }} + {{ user.firstName }} {{ user.lastName }} + {{ user.emailAddress }} - + - diff --git a/ui/src/app/user/admin/container/admin-management.component.ts b/ui/src/app/user/admin/container/admin-management.component.ts index 08c69264d..b94a8c396 100644 --- a/ui/src/app/user/admin/container/admin-management.component.ts +++ b/ui/src/app/user/admin/container/admin-management.component.ts @@ -3,11 +3,12 @@ import { Store } from '@ngrx/store'; import { Observable, of } from 'rxjs'; import * as fromRoot from '../../../app.reducer'; +import * as fromCore from '../../../core/reducer'; import * as fromAdmin from '../reducer'; -import { UserService } from '../../../core/service/user.service'; import { LoadAdminRequest, UpdateAdminRequest, RemoveAdminRequest } from '../action/collection.action'; import { Admin } from '../model/admin'; +import { LoadRoleRequest } from '../../../core/action/configuration.action'; @Component({ selector: 'admin-management-page', @@ -18,14 +19,16 @@ import { Admin } from '../model/admin'; export class AdminManagementPageComponent { users$: Observable; - roles$: Observable = of(['SUPER_ADMIN', 'DELEGATED_ADMIN']); + roles$: Observable; constructor( private store: Store ) { this.store.dispatch(new LoadAdminRequest()); + this.store.dispatch(new LoadRoleRequest()); this.users$ = this.store.select(fromAdmin.getAllAdmins); + this.roles$ = this.store.select(fromCore.getRoles); } setUserRole(user: Admin, change: string): void { diff --git a/ui/src/app/user/admin/effect/collection.effect.ts b/ui/src/app/user/admin/effect/collection.effect.ts index 6120faf5b..4958f1d8e 100644 --- a/ui/src/app/user/admin/effect/collection.effect.ts +++ b/ui/src/app/user/admin/effect/collection.effect.ts @@ -34,7 +34,7 @@ export class AdminCollectionEffects { map(action => action.payload), switchMap(changes => this.adminService.update(changes).pipe( map(user => new UpdateAdminSuccess({ - id: changes.resourceId, + id: changes.username, changes })) )) diff --git a/ui/src/app/user/admin/model/admin-entity.ts b/ui/src/app/user/admin/model/admin-entity.ts new file mode 100644 index 000000000..8993660b2 --- /dev/null +++ b/ui/src/app/user/admin/model/admin-entity.ts @@ -0,0 +1,17 @@ +import { Admin } from './admin'; + +export class AdminEntity implements Admin { + + username: string; + firstName: string; + lastName: string; + emailAddress: string; + + role: string; + + constructor( + properties: Admin + ) { + Object.assign(this, properties); + } +} diff --git a/ui/src/app/user/admin/model/admin.ts b/ui/src/app/user/admin/model/admin.ts index 5a5a9400a..b7cd90296 100644 --- a/ui/src/app/user/admin/model/admin.ts +++ b/ui/src/app/user/admin/model/admin.ts @@ -1,9 +1,11 @@ -import { User } from '../../../core/model/user'; - -export interface Admin extends User { +export interface Admin { createdDate?: string; updatedDate?: string; - resourceId: string; + username: string; + firstName: string; + lastName: string; + + role: string; - email: string; + emailAddress: string; } diff --git a/ui/src/app/user/admin/reducer/collection.reducer.ts b/ui/src/app/user/admin/reducer/collection.reducer.ts index 1e884b907..70d8ba9a4 100644 --- a/ui/src/app/user/admin/reducer/collection.reducer.ts +++ b/ui/src/app/user/admin/reducer/collection.reducer.ts @@ -8,7 +8,7 @@ export interface CollectionState extends EntityState { } export const adapter: EntityAdapter = createEntityAdapter({ - selectId: (model: Admin) => model.resourceId + selectId: (model: Admin) => model.username }); export const initialState: CollectionState = adapter.getInitialState({ diff --git a/ui/src/app/user/admin/service/admin.service.ts b/ui/src/app/user/admin/service/admin.service.ts index 77bd39c05..9f97e489d 100644 --- a/ui/src/app/user/admin/service/admin.service.ts +++ b/ui/src/app/user/admin/service/admin.service.ts @@ -1,47 +1,39 @@ import { Injectable } from '@angular/core'; import { Observable, of } from 'rxjs'; import { Admin } from '../model/admin'; - -let users = [ - { - 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' - } - } -]; +import { HttpClient } from '@angular/common/http'; +import { map, catchError } from 'rxjs/operators'; +import { AdminEntity } from '../model/admin-entity'; @Injectable() export class AdminService { - constructor() { } + private endpoint = '/admin/users'; + private base = '/api'; + + constructor( + private http: HttpClient + ) { } query(): Observable { - return of([ - ...users - ]); + return this.http.get( + `${this.base}${this.endpoint}`, {} + ).pipe( + map(users => users.map(u => new AdminEntity(u))) + ); } update(user: Admin): Observable { - return of({ - ...users.find(u => u.resourceId === user.resourceId), - ...user - }); + return this.http.put( + `${this.base}${this.endpoint}/${user.username}`, {...user} + ); } remove(userId: string): Observable { - users = users.filter(u => u.resourceId !== userId); - return of(true); + return this.http.delete( + `${this.base}${this.endpoint}/${userId}` + ).pipe( + map(response => !!response), + catchError(() => of(false)) + ); } }