Skip to content
This repository has been archived by the owner on Oct 12, 2020. It is now read-only.

Commit

Permalink
More changes to user-related screens, plugins and components, etc.
Browse files Browse the repository at this point in the history
  • Loading branch information
bcdevlucas committed Apr 6, 2020
1 parent f96f791 commit 95956ab
Show file tree
Hide file tree
Showing 17 changed files with 593 additions and 215 deletions.
2 changes: 2 additions & 0 deletions src/app/RootLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import ManageApisPage from './pages/ManageApis';
import ManageRolesPage from './pages/ManageRoles';
import ManageUserRolesPage from './pages/ManageUserRoles';
import ManageSheriffsPage from './pages/ManageSheriffs';
import ManageTeamPage from './pages/ManageTeam';
import ManageUsersPage from './pages/ManageUsers';
import SchedulingPage from './pages/Scheduling';
import PublishSchedulePage from './pages/PublishSchedule/PublishSchedule';
Expand Down Expand Up @@ -142,6 +143,7 @@ class Layout extends React.Component<LayoutStateProps & LayoutDispatchProps> {
<Route path={NavigationComponent.Routes.assignment.path} component={AssignmentPage} />
<Route path={NavigationComponent.Routes.team.path} component={ManageSheriffsPage} />
<Route path={NavigationComponent.Routes.team.children.roles.path} component={ManageRolesPage} />
<Route path={NavigationComponent.Routes.team.children.team.path} component={ManageTeamPage} />
<Route path={NavigationComponent.Routes.team.children.users.path} component={ManageUsersPage} />
<Route path={NavigationComponent.Routes.team.children.userRoles.path} component={ManageUserRolesPage} />
<Route path={NavigationComponent.Routes.types.children.leaveTypes.path} component={ManageLeaveTypesPage} />
Expand Down
10 changes: 9 additions & 1 deletion src/app/api/Api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,9 @@ export interface User {
systemAccountInd?: number;
sheriffId?: IdType;
sheriff?: Sheriff;
effectiveDate?: string;
expiryDate?: string;
isExpired?: boolean; // Only used on the client-side
createdBy?: string;
updatedBy?: string;
createdDtm?: string;
Expand All @@ -457,9 +460,10 @@ export interface UserRole {
id?: IdType;
userId?: IdType;
roleId?: IdType;
locationId?: IdType;
effectiveDate?: string;
expiryDate?: string;
locationId?: IdType;
isExpired?: boolean; // Only used on the client-side
createdBy?: string;
updatedBy?: string;
createdDtm?: string;
Expand Down Expand Up @@ -771,15 +775,19 @@ export interface API {
deleteUser(userId: IdType): Promise<void>;
getUsers(): Promise<User[]>;
deleteUsers(ids: IdType[]): Promise<void>;
expireUsers(ids: IdType[]): Promise<void>;
unexpireUsers(ids: IdType[]): Promise<void>;

getUserRole(): Promise<UserRole>;
createUserRole(newUserRole: Partial<UserRole>): Promise<UserRole>;
updateUserRole(updatedUserRole: UserRole): Promise<UserRole>;
deleteUserRole(id: IdType): Promise<void>;
expireUserRole(id: IdType): Promise<void>;
unexpireUserRole(id: IdType): Promise<void>;
getUserRoles(): Promise<UserRole[]>;
deleteUserRoles(ids: IdType[]): Promise<void>;
expireUserRoles(ids: IdType[]): Promise<void>;
unexpireUserRoles(ids: IdType[]): Promise<void>;

getRole(): Promise<Role>;
createRole(newRole: Partial<Role>): Promise<Role>;
Expand Down
40 changes: 40 additions & 0 deletions src/app/api/Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -927,6 +927,30 @@ export default class Client implements API {
return Promise.resolve();
}

async expireUser(userId: IdType): Promise<void> {
return await this._client.ExpireUser(userId);
}

async expireUsers(ids: IdType[]): Promise<void> {
if (ids.length > 0) {
ids.forEach(id => this._client.ExpireUser(id));
}

return Promise.resolve();
}

async unexpireUser(userId: IdType): Promise<void> {
return await this._client.ExpireUser(userId);
}

async unexpireUsers(ids: IdType[]): Promise<void> {
if (ids.length > 0) {
ids.forEach(id => this._client.UnexpireUser(id));
}

return Promise.resolve();
}

// Methods for roles
async getRoles(): Promise<Role[]> {
const list = await this._client.GetRoles();
Expand Down Expand Up @@ -1249,6 +1273,22 @@ export default class Client implements API {
return Promise.resolve();
}

async unexpireUserRole(userRoleId: IdType): Promise<void> {
if (userRoleId === undefined) {
return;
}

return await this._client.UnexpireUserRole(userRoleId);
}

async unexpireUserRoles(ids: IdType[]): Promise<void> {
if (ids.length > 0) {
ids.forEach(id => this._client.UnexpireUserRole(id));
}

return Promise.resolve();
}

async deleteUserRole(userRoleId: IdType): Promise<void> {
return Promise.resolve();
}
Expand Down
12 changes: 10 additions & 2 deletions src/app/components/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,13 @@ export default class Navigation extends React.Component<NavigationProps & Naviga
path: '/sheriffs/manage',
label: 'My Team', // TODO: Switch between 'Manage' and 'My' prefix depending on the role...
children: {
team: {
path: '/team',
label: 'My Team Members'
},
users: {
path: '/users/manage',
label: 'Manage Users'
label: 'Find / Manage Users'
},
roles: {
path: '/roles/manage',
Expand Down Expand Up @@ -190,7 +194,11 @@ export default class Navigation extends React.Component<NavigationProps & Naviga
</NavigationDropDown>

<NavigationDropDown title={Navigation.Routes.team.label} id="admin_dropdown">
<NavigationLink {...Navigation.Routes.team.children.users} />
<NavigationLink {...Navigation.Routes.team.children.team} />
{currentUserRoleScopes.authScopes
&& currentUserRoleScopes.authScopes.indexOf('users:manage') > -1 && (
<NavigationLink {...Navigation.Routes.team.children.users} />
)}
{currentUserRoleScopes.authScopes
&& currentUserRoleScopes.authScopes.indexOf('roles:manage') > -1 && (
<>
Expand Down
2 changes: 1 addition & 1 deletion src/app/components/TableColumnActions/EditRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const EditRow = ({ model, onClick, showComponent = false }: TableColumnActionPro

return (
<OverlayTrigger overlay={(<Tooltip>Edit</Tooltip>)} placement={'left'}>
<Button bsStyle="info" onClick={handleClick}>
<Button bsStyle="primary" onClick={handleClick}>
<Glyphicon glyph="edit" />
</Button>
</OverlayTrigger>
Expand Down
1 change: 1 addition & 0 deletions src/app/modules/roles/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export const updateUserRole = userRoleRequests.updateUserRoleRequest.actionCreat
export const createOrUpdateUserRoles = userRoleRequests.createOrUpdateUserRolesRequest.actionCreator;
export const deleteUserRoles = userRoleRequests.deleteUserRolesRequest.actionCreator;
export const expireUserRoles = userRoleRequests.expireUserRolesRequest.actionCreator;
export const unexpireUserRoles = userRoleRequests.unexpireUserRolesRequest.actionCreator;

type IActionMap = {
'ADMIN_ROLES_SELECT_SECTION': string | undefined;
Expand Down
27 changes: 26 additions & 1 deletion src/app/modules/roles/requests/userRoles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,38 @@ class ExpireUserRolesRequest extends RequestAction<IdType[], IdType[], RoleModul

setRequestData(moduleState: RoleModuleState, roleScopeIds: IdType[]) {
const newMap = { ...userRoleMapRequest.getRequestData(moduleState) };
roleScopeIds.forEach(id => delete newMap[id]);
roleScopeIds.forEach(id => newMap[id]);
return userRoleMapRequest.setRequestData(moduleState, newMap);
}
}

export const expireUserRolesRequest = new ExpireUserRolesRequest();

class UnexpireUserRolesRequest extends RequestAction<IdType[], IdType[], RoleModuleState> {
constructor() {
super({
namespace: STATE_KEY,
actionName: 'unexpireUserRoles',
toasts: {
success: (ids) => `${ids.length} user role(s) un-expired`,
error: (err) => `Problem encountered while un-expiring user roles: ${err ? err.toString() : 'Unknown Error'}`
}
});
}
public async doWork(request: IdType[], { api }: ThunkExtra): Promise<IdType[]> {
await api.unexpireUserRoles(request);
return request;
}

setRequestData(moduleState: RoleModuleState, roleScopeIds: IdType[]) {
const newMap = { ...userRoleMapRequest.getRequestData(moduleState) };
roleScopeIds.forEach(id => newMap[id]);
return userRoleMapRequest.setRequestData(moduleState, newMap);
}
}

export const unexpireUserRolesRequest = new UnexpireUserRolesRequest();

class DeleteUserRolesRequest extends RequestAction<IdType[], IdType[], RoleModuleState> {
constructor() {
super({
Expand Down
16 changes: 13 additions & 3 deletions src/app/modules/roles/selectors/userRoles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import * as userRoleRequests from '../requests/userRoles';
import mapToArray from '../../../infrastructure/mapToArray';
import { RootState } from '../../../store';

import { func as selectorFunctions } from '../../common';
import { EffectiveSelector } from '../../../infrastructure/EffectiveSelector';
import { UserRole } from '../../../api';

export const getUserRoles = createSelector(
userRoleRequests.userRoleMapRequest.getData,
Expand All @@ -13,16 +14,25 @@ export const getUserRoles = createSelector(
}
);

const userRoleSelector = new EffectiveSelector<UserRole>(
userRoleRequests.userRoleMapRequest.getData,
(ur) => ur.expiryDate
);

export const allUserRoles = userRoleSelector.all;

export const allEffectiveUserRoles = userRoleSelector.effective;

export const getAllUserRoles = (state: RootState) => {
if (state) {
return getUserRoles(state);
return allUserRoles(state);
}
return undefined;
};

export const findAllUserRoles = (filters: any) => (state: RootState) => {
if (state) {
return getUserRoles(state);
return allUserRoles(state);
}
return undefined;
};
2 changes: 2 additions & 0 deletions src/app/modules/users/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ export const uploadUserImage = userRequests.uploadUserImageRequest.actionCreator
export const updateUser = userRequests.updateUserRequest.actionCreator;
export const createOrUpdateUsers = userRequests.createOrUpdateUsersRequest.actionCreator;
export const deleteUsers = userRequests.deleteUsersRequest.actionCreator;
export const expireUsers = userRequests.expireUsersRequest.actionCreator;
export const unexpireUsers = userRequests.unexpireUsersRequest.actionCreator;
68 changes: 67 additions & 1 deletion src/app/modules/users/requests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import CreateEntityRequest from '../../infrastructure/Requests/CreateEntityReque
import UpdateEntityRequest from '../../infrastructure/Requests/UpdateEntityRequest';
import toTitleCase from '../../infrastructure/toTitleCase';
import DeleteEntityRequest from '../../infrastructure/Requests/DeleteEntityRequest';
import { RoleModuleState } from '../roles/common';
import { userRoleMapRequest } from '../roles/requests/userRoles';

// User Map
class UserMapRequest extends GetEntityMapRequest<void, User, UserModuleState> {
Expand Down Expand Up @@ -175,6 +177,64 @@ class CreateOrUpdateUsersRequest extends CreateOrUpdateEntitiesRequest<User, Use

export const createOrUpdateUsersRequest = new CreateOrUpdateUsersRequest();

class ExpireUsersRequest extends RequestAction<IdType[], IdType[], UserModuleState> {
constructor() {
super(
{
namespace: STATE_KEY,
actionName: 'expireUsers',
toasts: {
success: (ids) => `${ids.length} user(s) expired`,
// tslint:disable-next-line:max-line-length
error: (err) => `Problem encountered while expiring users: ${err ? err.toString() : 'Unknown Error'}`
}
}
);
}

public async doWork(request: IdType[], { api }: ThunkExtra): Promise<IdType[]> {
await api.expireUsers(request);
return request;
}

setRequestData(moduleState: UserModuleState, userIds: IdType[]) {
const newMap = { ...userMapRequest.getRequestData(moduleState) };
userIds.forEach(id => newMap[id]);
return userMapRequest.setRequestData(moduleState, newMap);
}
}

export const expireUsersRequest = new ExpireUsersRequest();

class UnexpireUsersRequest extends RequestAction<IdType[], IdType[], UserModuleState> {
constructor() {
super(
{
namespace: STATE_KEY,
actionName: 'unexpireUsers',
toasts: {
success: (ids) => `${ids.length} user(s) un-expired`,
// tslint:disable-next-line:max-line-length
error: (err) => `Problem encountered while un-expiring users: ${err ? err.toString() : 'Unknown Error'}`
}
}
);
}

public async doWork(request: IdType[], { api }: ThunkExtra): Promise<IdType[]> {
await api.unexpireUsers(request);
return request;
}

setRequestData(moduleState: UserModuleState, userIds: IdType[]) {
const newMap = { ...userMapRequest.getRequestData(moduleState) };
userIds.forEach(id => newMap[id]);
return userMapRequest.setRequestData(moduleState, newMap);
}
}

export const unexpireUsersRequest = new UnexpireUsersRequest();

class DeleteUsersRequest extends RequestAction<IdType[], IdType[], UserModuleState> {
constructor() {
super({
Expand All @@ -188,9 +248,15 @@ class DeleteUsersRequest extends RequestAction<IdType[], IdType[], UserModuleSta
}

public async doWork(request: IdType[], { api }: ThunkExtra): Promise<IdType[]> {
await api.deleteRoles(request);
await api.deleteUsers(request);
return request;
}

setRequestData(moduleState: RoleModuleState, userIds: IdType[]) {
const newMap = { ...userMapRequest.getRequestData(moduleState) };
userIds.forEach(id => delete newMap[id]);
return userMapRequest.setRequestData(moduleState, newMap);
}
}

export const deleteUsersRequest = new DeleteUsersRequest();
Loading

0 comments on commit 95956ab

Please sign in to comment.