Skip to content

Commit

Permalink
Merge pull request #340 from cisagov/362-add-508-labels-to-organizati…
Browse files Browse the repository at this point in the history
…ons-list-and-users

CRASM-362 Add 508 Unique Button Descriptions for Organizations, Users, and Vulnerability Details Tables
  • Loading branch information
cduhn17 authored Jun 17, 2024
2 parents 62f764f + 38e06ac commit 112e456
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 62 deletions.
29 changes: 17 additions & 12 deletions frontend/src/components/OrganizationList/OrganizationList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,32 @@ export const OrganizationList: React.FC<{

const orgCols: GridColDef[] = [
{ field: 'name', headerName: 'Organization', minWidth: 100, flex: 2 },
// { field: 'userCount', headerName: 'Members', minWidth: 100, flex: 1 },
{ field: 'state', headerName: 'State', minWidth: 100, flex: 1 },
{ field: 'regionId', headerName: 'Region', minWidth: 100, flex: 1 },
// { field: 'tagNames', headerName: 'Tags', minWidth: 100, flex: 1 },
{
field: 'view',
headerName: 'View/Edit',
minWidth: 100,
flex: 1,
renderCell: (cellValues: GridRenderCellParams) => {
const ariaLabel = `View or edit organization ${cellValues.row.name}`;
const descriptionId = `description-${cellValues.row.id}`;
return (
<IconButton
color="primary"
onClick={() => history.push('/organizations/' + cellValues.row.id)}
>
<EditNoteOutlinedIcon />
</IconButton>
<>
<span id={descriptionId} style={{ display: 'none' }}>
{`Edit details for organization ${cellValues.row.name}`}
</span>
<IconButton
color="primary"
aria-label={ariaLabel}
aria-describedby={descriptionId}
onClick={() =>
history.push('/organizations/' + cellValues.row.id)
}
>
<EditNoteOutlinedIcon />
</IconButton>
</>
);
}
}
Expand All @@ -73,10 +82,6 @@ export const OrganizationList: React.FC<{
const fetchOrganizations = useCallback(async () => {
try {
const rows = await apiGet<Organization[]>(orgsUrl);
// rows.forEach((obj) => {
// // obj.userCount = obj.userRoles.length;
// obj.tagNames = obj.tags.map((tag) => tag.name);
// });
setOrganizations(rows);
} catch (e) {
console.error(e);
Expand Down
5 changes: 4 additions & 1 deletion frontend/src/pages/Risk/VulnerabilityCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ const VulnerabilityCard = (props: {
const vulnDomain = vuln.domain ? '&domain=' + vuln.domain.name : '';
const domainDetailsLink =
'/inventory/vulnerabilities?title=' + vuln.title + vulnDomain;
const ariaLabel = `A link to the details page for vulnerability ${vuln.title}.`;
return (
<Tooltip
title={
Expand Down Expand Up @@ -95,7 +96,9 @@ const VulnerabilityCard = (props: {
{vuln.severity}
</p>
</div>
<button className={button}>DETAILS</button>
<button aria-label={ariaLabel} className={button}>
DETAILS
</button>
</div>
{
<hr
Expand Down
105 changes: 56 additions & 49 deletions frontend/src/pages/Users/Users.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import { ImportExport } from 'components';
import { initializeUser, Organization, User } from 'types';
import { useAuthContext } from 'context';
import { STATE_OPTIONS } from '../../constants/constants';
// @ts-ignore:next-line
import { formatDistanceToNow, parseISO } from 'date-fns';

type ErrorStates = {
Expand Down Expand Up @@ -77,7 +76,7 @@ export const Users: React.FC = () => {
const [editUserDialogOpen, setEditUserDialogOpen] = useState(false);
const [deleteUserDialogOpen, setDeleteUserDialogOpen] = useState(false);
const [infoDialogOpen, setInfoDialogOpen] = useState(false);
const [infoDialogContent, setInfoDialogContent] = useState<String>('');
const [infoDialogContent, setInfoDialogContent] = useState<string>('');
const [formDisabled, setFormDisabled] = React.useState(true);
const [formErrors, setFormErrors] = useState({
firstName: false,
Expand Down Expand Up @@ -114,22 +113,19 @@ export const Users: React.FC = () => {
if (user?.userType === 'globalAdmin') {
setUsers(rows);
} else if (user?.userType === 'regionalAdmin' && user?.regionId) {
rows.filter((row) => row.regionId === user.regionId);
setUsers(rows);
setUsers(rows.filter((row) => row.regionId === user.regionId));
} else if (user) {
setUsers([user]);
}
setErrorStates({ ...errorStates, getUsersError: '' });
setErrorStates((prev) => ({ ...prev, getUsersError: '' }));
} catch (e: any) {
setErrorStates({ ...errorStates, getUsersError: e.message });
setErrorStates((prev) => ({ ...prev, getUsersError: e.message }));
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [apiGet]);
}, [apiGet, user]);

useEffect(() => {
fetchUsers();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
}, [fetchUsers]);

const userCols: GridColDef[] = [
{ field: 'fullName', headerName: 'Name', minWidth: 100, flex: 1 },
Expand Down Expand Up @@ -158,50 +154,65 @@ export const Users: React.FC = () => {
headerName: 'Last Logged In',
minWidth: 100,
flex: 0.75
}
];

if (user?.userType === 'globalAdmin') {
userCols.push({
},
{
field: 'edit',
headerName: 'Edit',
minWidth: 50,
flex: 0.4,
renderCell: (cellValues: GridRenderCellParams) => {
const ariaLabel = `Edit user ${cellValues.row.email}`;
const descriptionId = `edit-description-${cellValues.row.id}`;
return (
<IconButton
color="primary"
onClick={() => {
setSelectedRow(cellValues.row);
setValues(cellValues.row);
setEditUserDialogOpen(true);
}}
>
<Edit />
</IconButton>
<>
<span id={descriptionId} style={{ display: 'none' }}>
{`Edit details for user ${cellValues.row.email}`}
</span>
<IconButton
color="primary"
aria-label={ariaLabel}
aria-describedby={descriptionId}
onClick={() => {
setSelectedRow(cellValues.row);
setValues(cellValues.row);
setEditUserDialogOpen(true);
}}
>
<Edit />
</IconButton>
</>
);
}
},
{
field: 'delete',
headerName: 'Delete',
minWidth: 50,
flex: 0.4,
renderCell: (cellValues: GridRenderCellParams) => {
const ariaLabel = `Delete user ${cellValues.row.fullName}`;
const descriptionId = `delete-description-${cellValues.row.id}`;
return (
<>
<span id={descriptionId} style={{ display: 'none' }}>
{`Delete user ${cellValues.row.email}`}
</span>
<IconButton
color="primary"
aria-label={ariaLabel}
aria-describedby={descriptionId}
onClick={() => {
setSelectedRow(cellValues.row);
setDeleteUserDialogOpen(true);
}}
>
<Delete />
</IconButton>
</>
);
}
});
}
userCols.push({
field: 'delete',
headerName: 'Delete',
minWidth: 50,
flex: 0.4,
renderCell: (cellValues: GridRenderCellParams) => {
return (
<IconButton
color="primary"
onClick={() => {
setSelectedRow(cellValues.row);
setDeleteUserDialogOpen(true);
}}
>
<Delete />
</IconButton>
);
}
});
];

const addUserButton = user?.userType === 'globalAdmin' && (
<MuiButton
Expand Down Expand Up @@ -255,7 +266,6 @@ export const Users: React.FC = () => {

const onCreateUserSubmit = async (e: any) => {
e.preventDefault();
console.log(e);
const body = {
firstName: values.firstName,
lastName: values.lastName,
Expand Down Expand Up @@ -570,15 +580,13 @@ export const Users: React.FC = () => {
'state'
]}
onImport={async (results) => {
// TODO: use a batch call here instead.
const createdUsers = [];
for (const result of results) {
const parsedRoles: {
organization: string;
role: string;
}[] = JSON.parse(result.roles as string);
const body: any = result;
// For now, just create role with the first organization
if (parsedRoles.length > 0) {
body.organization = parsedRoles[0].organization;
body.organizationAdmin = parsedRoles[0].role === 'admin';
Expand All @@ -590,7 +598,6 @@ export const Users: React.FC = () => {
})
);
} catch (e) {
// Just continue when an error occurs
console.error(e);
}
}
Expand Down

0 comments on commit 112e456

Please sign in to comment.