Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/feature/SHIBUI-1031' into featur…
Browse files Browse the repository at this point in the history
…e/SHIBUI-1031
  • Loading branch information
Bill Smith committed Jan 7, 2019
2 parents 25dfb81 + c207bd2 commit 73f744a
Show file tree
Hide file tree
Showing 12 changed files with 149 additions and 49 deletions.
29 changes: 29 additions & 0 deletions ui/src/app/core/action/configuration.action.ts
Original file line number Diff line number Diff line change
@@ -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
;
14 changes: 14 additions & 0 deletions ui/src/app/core/effect/user.effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -21,6 +22,19 @@ export class UserEffects {
)
)
);

@Effect()
loadRoles$ = this.actions$.pipe(
ofType<LoadRoleRequest>(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),
Expand Down
25 changes: 25 additions & 0 deletions ui/src/app/core/reducer/configuration.reducer.ts
Original file line number Diff line number Diff line change
@@ -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;
11 changes: 9 additions & 2 deletions ui/src/app/core/reducer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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<CoreState>('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);
13 changes: 12 additions & 1 deletion ui/src/app/core/service/user.service.ts
Original file line number Diff line number Diff line change
@@ -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<User> {
const defUser = Object.assign({}, {
Expand All @@ -18,4 +23,10 @@ export class UserService {
});
return of(defUser);
}

getRoles(): Observable<string[]> {
return this.http.get<string[]>(
`${this.base}/supportedRoles`
);
}
} /* istanbul ignore next */
12 changes: 6 additions & 6 deletions ui/src/app/user/admin/container/admin-management.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@
</thead>
<tbody>
<tr *ngFor="let user of users$ | async">
<th>{{ user.resourceId }}</th>
<td>{{ user.name.first }} {{ user.name.last }}</td>
<td>{{ user.email }}</td>
<th>{{ user.username }}</th>
<td>{{ user.firstName }} {{ user.lastName }}</td>
<td>{{ user.emailAddress }}</td>
<td>
<select [name]="user.resourceId" [ngModel]="user.role" class="form-control" (change)="setUserRole(user, $event.target.value)">
<option *ngFor="let role of roles$ | async">{{ role }}</option>
<select [name]="user.username" [ngModel]="user.role" class="form-control" (change)="setUserRole(user, $event.target.value)">
<option *ngFor="let role of roles$ | async" [value]="role">{{ role }}</option>
</select>
</td>
<td>
<button class="btn btn-link" (click)="deleteUser(user.resourceId)">
<button class="btn btn-link" (click)="deleteUser(user.username)">
<span class="sr-only">Delete User</span>
<i class="fa fa-trash fa-lg text-danger"></i>
</button>
Expand Down
7 changes: 5 additions & 2 deletions ui/src/app/user/admin/container/admin-management.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -18,14 +19,16 @@ import { Admin } from '../model/admin';
export class AdminManagementPageComponent {

users$: Observable<Admin[]>;
roles$: Observable<string[]> = of(['SUPER_ADMIN', 'DELEGATED_ADMIN']);
roles$: Observable<string[]>;

constructor(
private store: Store<fromRoot.State>
) {
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 {
Expand Down
2 changes: 1 addition & 1 deletion ui/src/app/user/admin/effect/collection.effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
}))
))
Expand Down
17 changes: 17 additions & 0 deletions ui/src/app/user/admin/model/admin-entity.ts
Original file line number Diff line number Diff line change
@@ -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);
}
}
12 changes: 7 additions & 5 deletions ui/src/app/user/admin/model/admin.ts
Original file line number Diff line number Diff line change
@@ -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;
}
2 changes: 1 addition & 1 deletion ui/src/app/user/admin/reducer/collection.reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export interface CollectionState extends EntityState<Admin> {
}

export const adapter: EntityAdapter<Admin> = createEntityAdapter<Admin>({
selectId: (model: Admin) => model.resourceId
selectId: (model: Admin) => model.username
});

export const initialState: CollectionState = adapter.getInitialState({
Expand Down
54 changes: 23 additions & 31 deletions ui/src/app/user/admin/service/admin.service.ts
Original file line number Diff line number Diff line change
@@ -1,47 +1,39 @@
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
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'
}
}
];
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<Admin[]> {
return of([
...users
]);
return this.http.get<Admin[]>(
`${this.base}${this.endpoint}`, {}
).pipe(
map(users => users.map(u => new AdminEntity(u)))
);
}

update(user: Admin): Observable<Admin> {
return of({
...users.find(u => u.resourceId === user.resourceId),
...user
});
return this.http.put<Admin>(
`${this.base}${this.endpoint}/${user.username}`, {...user}
);
}

remove(userId: string): Observable<boolean> {
users = users.filter(u => u.resourceId !== userId);
return of(true);
return this.http.delete<Admin>(
`${this.base}${this.endpoint}/${userId}`
).pipe(
map(response => !!response),
catchError(() => of(false))
);
}
}

0 comments on commit 73f744a

Please sign in to comment.