Skip to content

Commit

Permalink
page working
Browse files Browse the repository at this point in the history
  • Loading branch information
ssundahlTTD committed Feb 28, 2025
1 parent 872ce47 commit fb04dcc
Show file tree
Hide file tree
Showing 12 changed files with 111 additions and 33 deletions.
4 changes: 2 additions & 2 deletions src/api/routers/adminRouter.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import express from 'express';

import { isUid2SuperuserCheck2 } from '../middleware/userRoleMiddleware';
import { isSuperUserCheck } from '../middleware/userRoleMiddleware';
import { getAdminUserList } from '../services/usersService';
// import { getSiteList, getVisibleSiteList } from '../services/adminServiceClient';
// import { AdminSiteDTO, mapAdminSitesToSiteDTOs } from '../services/adminServiceHelpers';
Expand All @@ -9,7 +9,7 @@ import { getAdminUserList } from '../services/usersService';
export function createAdminRouter() {
const adminRouter = express.Router();

adminRouter.get('/users', isUid2SuperuserCheck2, async (_req, res) => {
adminRouter.get('/users', isSuperUserCheck, async (_req, res) => {
// const allSitesPromise = getSiteList();
// const attachedSitesPromise = getAttachedSiteIDs();
// const [allSites, attachedSites] = await Promise.all([allSitesPromise, attachedSitesPromise]);
Expand Down
8 changes: 5 additions & 3 deletions src/api/routers/businessContactsRouter.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import express, { Response } from 'express';

import { BusinessContactSchema } from '../entities/BusinessContact';
import { BusinessContact, BusinessContactSchema } from '../entities/BusinessContact';
import {
BusinessContactRequest,
hasBusinessContactAccess,
Expand All @@ -18,14 +18,16 @@ export function createBusinessContactsRouter() {

businessContactsRouter.get('/', async (req: ParticipantRequest, res: Response) => {
const { participant } = req;
const businessContacts = await participant!.$relatedQuery('businessContacts');
const businessContacts = await BusinessContact.query().where('participantId', participant?.id!);
return res.status(200).json(businessContacts);
});

businessContactsRouter.post('/', async (req: ParticipantRequest, res: Response) => {
const data = BusinessContactsDTO.parse(req.body);
const { participant } = req;
const newContact = await participant!.$relatedQuery('businessContacts').insert(data);
const newContact = await BusinessContact.query()
.where('participantId', participant?.id!)
.insert({ ...data, participantId: participant?.id! });
return res.status(201).json(newContact);
});

Expand Down
3 changes: 2 additions & 1 deletion src/api/services/usersService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ export const inviteUserToParticipant = async (
};

export const getAdminUserList = async () => {
const userList = User.query();
// do we want any other filtering here?
const userList = await User.query().where('deleted', 0).orderBy('email');
return userList;
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { Knex } from 'knex';

export async function up(knex: Knex): Promise<void> {
await knex('userRoles').insert({
id: 4,
roleName: 'Super User',
});
}
Expand Down
20 changes: 20 additions & 0 deletions src/web/components/UserManagement/UserManagementItem.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
.user-management-item {
line-height: 2;

.user-item-name-cell {
display: flex;
align-items: center;
}

.approve-button {
padding-right: 0;
}

.approver-date {
margin-right: 80px;
}

.approver-name {
margin-right: 40px;
}
}
6 changes: 6 additions & 0 deletions src/web/components/UserManagement/UserManagementItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@ type UserManagementItemProps = Readonly<{
export function UserManagementItem({ user }: UserManagementItemProps) {
return (
<tr className='user-management-item'>
<td>{user.email}</td>
<td>{user.firstName}</td>
<td>{user.lastName}</td>
<td>{user.jobFunction}</td>
<td>{user.acceptedTerms}</td>
<td />
<td />
</tr>
);
}
49 changes: 49 additions & 0 deletions src/web/components/UserManagement/UserManagementTable.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
.users-table-container {
.users-table {
width: 100%;

tr th {
font-size: 0.875rem;
line-height: 1.5;
}
}

.users-table-header {
display: flex;
justify-content: end;
align-items: baseline;
padding-bottom: 10px;

&-right {
display: flex;
justify-content: right;
}

.users-search-bar-container {
display: flex;
align-items: center;
border-bottom: 2px solid var(--theme-action);
padding: 6px 2px;
::placeholder {
color: var(--theme-search-text);
opacity: 1;
}
}

.users-search-bar-icon {
color: var(--theme-search-text);
height: 16px;
margin-left: 8px;
}

.users-search-bar {
width: 100%;
border: none;
outline: none;
color: var(--theme-search-text);
font-weight: 400;
font-size: 0.75rem;
background: none;
}
}
}
20 changes: 12 additions & 8 deletions src/web/components/UserManagement/UserManagementTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,11 @@ function UserManagementTableContent({ users }: UserManagementTableProps) {
if (searchText.length > 1) {
searchedUsers = users.filter((item) => {
const search = searchText.toLowerCase();
return item.lastName.toLowerCase().indexOf(search) >= 0;
return (
item.lastName.toLowerCase().indexOf(search) >= 0 ||
item.firstName.toLowerCase().indexOf(search) >= 0 ||
item.email.toLowerCase().indexOf(search) >= 0
);
});
}

Expand Down Expand Up @@ -87,13 +91,13 @@ function UserManagementTableContent({ users }: UserManagementTableProps) {
<table className='users-table'>
<thead>
<tr>
<SortableTableHeader<UserDTO> sortKey='lastName' header='Name' />
<th>User Type</th>
<SortableTableHeader<UserDTO> sortKey='lastName' header='Approver' />
<SortableTableHeader<UserDTO> sortKey='lastName' header='Date Approved' />
<th>API Permissions</th>
<SortableTableHeader<UserDTO> sortKey='lastName' header='Salesforce Agreement Number' />
<th className='action'>Action</th>
<SortableTableHeader<UserDTO> sortKey='email' header='Email' />
<SortableTableHeader<UserDTO> sortKey='firstName' header='First Name' />
<SortableTableHeader<UserDTO> sortKey='lastName' header='Last Name' />
<SortableTableHeader<UserDTO> sortKey='jobFunction' header='Job Function' />
<th>Accepted Terms</th>
<th>Delete Action Here</th>
<th>Lock Action Here</th>
</tr>
</thead>

Expand Down
9 changes: 7 additions & 2 deletions src/web/contexts/SortableTableProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,13 @@ export function SortableProvider<TData extends {}>({ children }: { children: Rea
(a: TData, b: TData): number => {
if (!sortKey) return 0;

if (a[sortKey] > b[sortKey]) return sortOrder === 'asc' ? 1 : -1;
if (a[sortKey] < b[sortKey]) return sortOrder === 'asc' ? -1 : 1;
const aSort =
typeof a[sortKey] === 'string' ? (a[sortKey] as string).toLowerCase() : a[sortKey];
const bSort =
typeof b[sortKey] === 'string' ? (b[sortKey] as string).toLowerCase() : b[sortKey];

if (aSort > bSort) return sortOrder === 'asc' ? 1 : -1;
if (aSort < bSort) return sortOrder === 'asc' ? -1 : 1;

return 0;
},
Expand Down
3 changes: 2 additions & 1 deletion src/web/screens/dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { EmailContactsRoute } from './emailContacts';
import { HomeRoute } from './home';
import { LogoutRoute } from './logout';
import { ManageParticipantsRoute } from './manageParticipants';
import { ManageUsersRoute } from './manageUsers';
import { ParticipantInformationRoute } from './participantInformation';
import { PortalRoute } from './routeUtils';
import { SharingPermissionsRoute } from './sharingPermissions';
Expand All @@ -34,7 +35,7 @@ export const StandardRoutes: PortalRoute[] = [
export const Uid2SupportRoutes: PortalRoute[] = [ManageParticipantsRoute];

// TODO: add route for Users List once created
export const SuperUserRoutes: PortalRoute[] = [];
export const SuperUserRoutes: PortalRoute[] = [ManageUsersRoute];

export const DashboardRoutes: PortalRoute[] = [
...StandardRoutes,
Expand Down
16 changes: 3 additions & 13 deletions src/web/screens/manageUsers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,9 @@ import { ScreenContentContainer } from '../components/Core/ScreenContentContaine
import UserManagementTable from '../components/UserManagement/UserManagementTable';
import { GetAllUsersAdmin } from '../services/userAccount';
import { AwaitTypesafe } from '../utils/AwaitTypesafe';
import { makeParticipantLoader } from '../utils/loaderHelpers';
import { RouteErrorBoundary } from '../utils/RouteErrorBoundary';
import { PortalRoute } from './routeUtils';

// const oldloader = makeParticipantLoader((participantId) => {
// const auditTrail = GetAllUsersAdmin(participantId);
// return defer({ auditTrail });
// });

const loader = () => {
const userList = GetAllUsersAdmin();
return defer({ userList });
Expand All @@ -25,11 +19,8 @@ function ManageUsers() {

return (
<>
<h1>Audit Trail</h1>
<p className='heading-details'>
View a detailed log of all past actions performed by, or on behalf of, the current
participant.
</p>
<h1>Users</h1>
<p className='heading-details'>Manage portal users</p>
<ScreenContentContainer>
<Suspense fallback={<Loading message='Loading users...' />}>
<AwaitTypesafe resolve={data.userList}>
Expand All @@ -46,7 +37,6 @@ export const ManageUsersRoute: PortalRoute = {
element: <ManageUsers />,
errorElement: <RouteErrorBoundary />,
// ****** should we change the route here?
path: '/participant/:participantId/ManageUsers',
path: '/participant/:participantId/manageUsers',
loader,
isHidden: true,
};
5 changes: 3 additions & 2 deletions src/web/services/userAccount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { KeycloakProfile } from 'keycloak-js';
import log from 'loglevel';
import { z } from 'zod';

import { UserCreationPartial } from '../../api/entities/User';
import { UserCreationPartial, UserDTO } from '../../api/entities/User';
import { UserWithParticipantRoles } from '../../api/services/usersService';
import { backendError } from '../utils/apiError';

Expand Down Expand Up @@ -107,7 +107,8 @@ export async function SetTermsAccepted() {

export async function GetAllUsersAdmin() {
try {
return await axios.get('/admin/users');
const userResponse = await axios.get<UserDTO[]>('/admin/users');
return userResponse.data;
} catch (e: unknown) {
throw backendError(e, 'Unable to get admin user list.');
}
Expand Down

0 comments on commit fb04dcc

Please sign in to comment.