Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CRDCDH-1993 Submitter Study Assignment (1/2) – User Mgmt #554

Merged
merged 11 commits into from
Dec 11, 2024
1 change: 0 additions & 1 deletion src/components/APITokenDialog/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ const baseUser: User = {
role: null,
IDP: "nih",
email: "",
organization: null,
studies: null,
dataCommons: [],
createdAt: "",
Expand Down
8 changes: 1 addition & 7 deletions src/components/Contexts/AuthContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,7 @@ export const AuthProvider: FC<ProviderProps> = ({ children }: ProviderProps) =>
const setData = (data: Partial<User>): void => {
if (!state.isLoggedIn) return;

// Remove any nested objects that are null
const newUser = { ...state.user, ...data };
if (!data?.organization) {
delete newUser.organization;
}

setState((prev) => ({ ...prev, user: newUser }));
setState((prev) => ({ ...prev, user: { ...state.user, ...data } }));
};

useEffect(() => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { FC } from "react";
import { MemoryRouter } from "react-router-dom";
import { fireEvent, render, waitFor, within } from "@testing-library/react";
import { render, waitFor, within } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { MockedProvider, MockedResponse } from "@apollo/client/testing";
import { GraphQLError } from "graphql";
Expand Down Expand Up @@ -120,13 +120,6 @@ const baseUser: Omit<User, "role"> = {
userStatus: "Active",
IDP: "nih",
email: "",
organization: {
orgID: "some-org-1",
orgName: "org1",
status: "Active",
createdAt: "2023-10-06T19:19:04.183Z",
updateAt: "2024-07-03T19:09:29.513Z",
},
studies: null,
dataCommons: [],
createdAt: "",
Expand Down Expand Up @@ -188,7 +181,6 @@ describe("Basic Functionality", () => {
).toBeInTheDocument();
expect(getByText("Submission Type")).toBeInTheDocument();
expect(getByText("Data Type")).toBeInTheDocument();
expect(getByText("Organization")).toBeInTheDocument();
expect(getByText("Data Commons")).toBeInTheDocument();
expect(getByText("Study")).toBeInTheDocument();
expect(getByText("dbGaP ID")).toBeInTheDocument();
Expand Down Expand Up @@ -254,77 +246,6 @@ describe("Basic Functionality", () => {
expect(handleCreate).toHaveBeenCalledTimes(1);
});

it("should disable open dialog button and show tooltip if user has 'Inactive' org", async () => {
const { getByTestId, getByRole } = render(
<TestParent
authCtxState={{
...baseAuthCtx,
user: {
...baseUser,
role: "Submitter",
organization: { ...baseUser.organization, status: "Inactive" },
},
}}
>
<CreateDataSubmissionDialog onCreate={handleCreate} />
</TestParent>
);

const openDialogButton = getByRole("button", { name: "Create a Data Submission" });
expect(openDialogButton).toBeInTheDocument();
expect(openDialogButton).toBeDisabled();

userEvent.click(openDialogButton);

await waitFor(() => {
expect(() => getByTestId("create-submission-dialog")).toThrow();
});

fireEvent.mouseOver(openDialogButton);

await waitFor(() => {
const tooltip = getByRole("tooltip");
expect(tooltip).toBeInTheDocument();
expect(tooltip).toHaveTextContent(
"Your associated organization is inactive. You cannot create a data submission at this time."
);
});
});

it("should not disable open dialog button or show tooltip if user has 'Active' org", async () => {
const { getByTestId, getByRole } = render(
<TestParent
authCtxState={{
...baseAuthCtx,
user: {
...baseUser,
role: "Submitter",
organization: { ...baseUser.organization, status: "Active" },
},
}}
>
<CreateDataSubmissionDialog onCreate={handleCreate} />
</TestParent>
);

const openDialogButton = getByRole("button", { name: "Create a Data Submission" });
expect(openDialogButton).toBeInTheDocument();

await waitFor(() => expect(openDialogButton).toBeEnabled());

fireEvent.mouseOver(openDialogButton);

await waitFor(() => {
expect(() => getByRole("tooltip")).toThrow();
});

userEvent.click(openDialogButton);

await waitFor(() => {
expect(getByTestId("create-submission-dialog")).toBeInTheDocument();
});
});

it("should only show the dbGaP ID if study is controlled access", async () => {
const { getByText, getByRole, getByTestId } = render(
<TestParent authCtxState={{ ...baseAuthCtx, user: { ...baseUser, role: "Submitter" } }}>
Expand Down
48 changes: 8 additions & 40 deletions src/components/DataSubmissions/CreateDataSubmissionDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FC, useEffect, useMemo, useState } from "react";
import { FC, useEffect, useState } from "react";
import {
Button,
Dialog,
Expand Down Expand Up @@ -170,10 +170,6 @@ const StyledField = styled("div")({
position: "relative",
});

const StyledOrganizationField = styled(StyledField)({
marginBottom: "25px",
});

const StyledHelperText = styled(BaseStyledHelperText)({
marginTop: "5px",
});
Expand Down Expand Up @@ -241,13 +237,7 @@ const CreateDataSubmissionDialog: FC<Props> = ({ onCreate }) => {
});

const orgOwnerOrSubmitter = user?.role === "Organization Owner" || user?.role === "Submitter";
const hasOrganizationAssigned = user?.organization !== null && user?.organization?.orgID !== null;
const intention = watch("intention");
const userHasInactiveOrg = useMemo(
() => user?.organization?.status === "Inactive",
[user?.organization?.status]
);

const submissionTypeOptions: RadioOption[] = [
{
label: "New/Update",
Expand Down Expand Up @@ -415,14 +405,6 @@ const CreateDataSubmissionDialog: FC<Props> = ({ onCreate }) => {
{errors?.intention?.message}
</StyledHelperText>
</StyledField>
<StyledOrganizationField>
<StyledLabel id="organization">Organization</StyledLabel>
<StyledOutlinedInput
value={user?.organization?.orgName}
inputProps={{ "aria-labelledby": "organization" }}
readOnly
/>
</StyledOrganizationField>
<StyledField>
<StyledLabel id="dataCommons">
Data Commons
Expand Down Expand Up @@ -572,28 +554,14 @@ const CreateDataSubmissionDialog: FC<Props> = ({ onCreate }) => {

{orgOwnerOrSubmitter && (
<StyledTooltipWrapper alignItems="center" justifyContent="flex-end">
<Tooltip
placement="top"
title="Your associated organization is inactive. You cannot create a data submission at this time."
open={undefined}
disableHoverListener={!userHasInactiveOrg}
<StyledButton
type="button"
variant="contained"
onClick={handleOpenDialog}
disabled={authStatus === AuthStatus.LOADING || approvedStudiesLoading}
>
<span>
<StyledButton
type="button"
variant="contained"
onClick={handleOpenDialog}
disabled={
!hasOrganizationAssigned ||
userHasInactiveOrg ||
authStatus === AuthStatus.LOADING ||
approvedStudiesLoading
}
>
Create a Data Submission
</StyledButton>
</span>
</Tooltip>
Create a Data Submission
</StyledButton>
</StyledTooltipWrapper>
)}
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ const baseUser: Omit<User, "role"> = {
userStatus: "Active",
IDP: "nih",
email: "",
organization: null,
studies: null,
dataCommons: [],
createdAt: "",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ const baseUser: User = {
role: null,
IDP: "nih",
email: "",
organization: null,
studies: null,
dataCommons: [],
createdAt: "",
Expand Down
1 change: 0 additions & 1 deletion src/components/DataSubmissions/DataUpload.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ const baseUser: User = {
role: "Submitter", // NOTE: This base role allows for all actions
IDP: "nih",
email: "",
organization: null,
studies: null,
dataCommons: null,
createdAt: "",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ const baseUser: User = {
role: "Submitter", // NOTE: This role has access to the delete button by default
IDP: "nih",
email: "",
organization: null,
studies: null,
dataCommons: [],
createdAt: "",
Expand Down
1 change: 0 additions & 1 deletion src/components/DataSubmissions/MetadataUpload.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ const baseUser: Omit<User, "role"> = {
userStatus: "Active",
IDP: "nih",
email: "",
organization: null,
studies: null,
dataCommons: [],
createdAt: "",
Expand Down
1 change: 0 additions & 1 deletion src/components/DataSubmissions/ValidationControls.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ const baseUser: Omit<User, "role"> = {
userStatus: "Active",
IDP: "nih",
email: "",
organization: null,
studies: null,
dataCommons: [],
createdAt: "",
Expand Down
19 changes: 0 additions & 19 deletions src/config/AuthRoles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,6 @@ export const Roles: UserRole[] = [
"Admin",
];

/**
* Defines a list of roles that are required to have an
* organization assigned to them. This unlocks the Organization assignment dropdown.
*/
export const OrgRequiredRoles: UserRole[] = ["Submitter", "Organization Owner", "Data Commons POC"];

/**
* A map of the roles that are required to be pre-assigned
* to a specific organization in the database. This locks the Organization assignment dropdown.
*
* @note This requires that an organization with the specified name exists in the database.
*/
type RoleSubset = Extends<UserRole, "Admin" | "Federal Lead" | "Federal Monitor">;
export const OrgAssignmentMap: Record<RoleSubset, string> = {
Admin: "FNL",
"Federal Lead": "NCI",
"Federal Monitor": "NCI",
};

/**
* Defines a list of roles that are allowed to interact with regular Validation.
*/
Expand Down
1 change: 0 additions & 1 deletion src/content/OperationDashboard/Controller.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ const baseUser: Omit<User, "role"> = {
userStatus: "Active",
IDP: "nih",
email: "",
organization: null,
dataCommons: [],
createdAt: "",
updateAt: "",
Expand Down
1 change: 0 additions & 1 deletion src/content/OperationDashboard/DashboardView.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ const baseUser: Omit<User, "role"> = {
userStatus: "Active",
IDP: "nih",
email: "",
organization: null,
dataCommons: [],
createdAt: "",
updateAt: "",
Expand Down
5 changes: 4 additions & 1 deletion src/content/OperationDashboard/DashboardView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,10 @@ const DashboardView: FC<DashboardViewProps> = ({
const params: DashboardContentOptions["parameters"] = [];

if (role === "Federal Monitor" && Array.isArray(studies) && studies.length > 0) {
params.push({ Name: "studiesParameter", Values: studies });
params.push({
Name: "studiesParameter",
Values: studies?.map((study: ApprovedStudy) => study?._id),
});
} else if (role === "Federal Monitor") {
Logger.error("This role requires studies to be set but none were found.", studies);
params.push({ Name: "studiesParameter", Values: ["NO-CONTENT"] });
Expand Down
1 change: 0 additions & 1 deletion src/content/dataSubmissions/SubmittedData.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ const baseUser: User = {
role: "Submitter", // NOTE: This role has access to everything nested here by default
IDP: "nih",
email: "",
organization: null,
studies: null,
dataCommons: [],
createdAt: "",
Expand Down
1 change: 0 additions & 1 deletion src/content/questionnaire/ListView.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ const baseUser: Omit<User, "role"> = {
userStatus: "Active",
IDP: "nih",
email: "",
organization: null,
dataCommons: [],
createdAt: "",
updateAt: "",
Expand Down
1 change: 0 additions & 1 deletion src/content/studies/Controller.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ const baseUser: Omit<User, "role"> = {
userStatus: "Active",
IDP: "nih",
email: "",
organization: null,
dataCommons: [],
createdAt: "",
updateAt: "",
Expand Down
23 changes: 3 additions & 20 deletions src/content/users/Controller.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React, { memo } from "react";
import React from "react";
import { Navigate, useParams } from "react-router-dom";
import { useAuthContext } from "../../components/Contexts/AuthContext";
import { OrganizationProvider } from "../../components/Contexts/OrganizationListContext";
import ListView from "./ListView";
import ProfileView from "./ProfileView";
import { CanManageUsers } from "../../config/AuthRoles";
Expand All @@ -10,14 +9,6 @@ type Props = {
type: "users" | "profile";
};

/**
* A memoized version of OrganizationProvider
* which caches data between ListView and ProfileView
*
* @see OrganizationProvider
*/
const MemorizedProvider = memo(OrganizationProvider);

/**
* Renders the correct view based on the URL and permissions-tier
*
Expand Down Expand Up @@ -54,19 +45,11 @@ const UserController = ({ type }: Props) => {

// Show list of users to Admin or Org Owner
if (!userId && isAdministrative) {
return (
<MemorizedProvider preload>
<ListView />
</MemorizedProvider>
);
return <ListView />;
}

// Admin or Org Owner viewing a user's "Edit User" page or their own "Edit User" page
return (
<MemorizedProvider preload={isAdministrative && type === "users"}>
<ProfileView _id={userId} viewType={type} />
</MemorizedProvider>
);
return <ProfileView _id={userId} viewType={type} />;
};

export default UserController;
Loading
Loading