Skip to content

Commit

Permalink
[MINT-3014] CR TDL Collab Card (#1388)
Browse files Browse the repository at this point in the history
* Init card work

* Added unit test

* Added external link echimp prop and unit test

* Update beneficiaries test

* Updated unit test
  • Loading branch information
patrickseguraoddball authored and garyjzhao committed Oct 9, 2024
1 parent 5af5642 commit 3f80941
Show file tree
Hide file tree
Showing 13 changed files with 238 additions and 13 deletions.
24 changes: 24 additions & 0 deletions src/components/ExternalLink/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,28 @@ describe('ExternalLink', () => {
expect(externalLink).toHaveAttribute('target', '_blank');
expect(externalLink).toHaveAttribute('rel', 'noopener noreferrer');
});

it('renders the modal with the correct text when toEchimp is true', () => {
render(
<ExternalLink href="https://echimp.cmsnet/" toEchimp>
Click me
</ExternalLink>
);

const linkElement = screen.getByText('Click me');

fireEvent.click(linkElement);

expect(
screen.getByText(i18next.t('externalLinkModal:heading'))
).toBeInTheDocument();

expect(
screen.getByText(
(_, element) =>
element?.textContent ===
i18next.t('externalLinkModal:descriptionEchimp')
)
).toBeInTheDocument();
});
});
18 changes: 12 additions & 6 deletions src/components/ExternalLink/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,22 @@ import Modal from 'components/Modal';
import PageHeading from 'components/PageHeading';

type ExternalLinkModalTypes = {
children?: React.ReactNode;
className?: string;
children: React.ReactNode;
href: string;
variant?: 'external' | 'unstyled' | 'nav';
asButton?: boolean;
className?: string;
toEchimp?: boolean;
inlineText?: boolean;
};

const ExternalLink = ({
children,
href,
variant,
asButton,
className,
toEchimp,
inlineText = false
}: ExternalLinkModalTypes) => {
const { t: externalT } = useTranslation('externalLinkModal');
Expand All @@ -44,19 +48,21 @@ const ExternalLink = ({
className="font-body-md line-height-sans-4 margin-top-0 margin-bottom-4"
style={{ whiteSpace: 'break-spaces' }}
>
{externalT('description')}
{toEchimp ? externalT('descriptionEchimp') : externalT('description')}
</p>

<Link
href={href}
aria-label={externalT('continueButton')}
aria-label={
toEchimp ? externalT('continueEchimp') : externalT('continueButton')
}
target="_blank"
rel="noopener noreferrer"
className="usa-button text-white text-no-underline"
onClick={() => setIsModalOpen(false)}
variant={variant}
>
{externalT('leave')}
{toEchimp ? externalT('continueEchimp') : externalT('leave')}
</Link>

<Button
Expand Down Expand Up @@ -93,7 +99,7 @@ const ExternalLink = ({
) : (
<Button
type="button"
unstyled
unstyled={!asButton}
className={classNames(className, 'margin-right-2')}
onClick={() => {
setIsModalOpen(true);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import React from 'react';
import { BrowserRouter as Router } from 'react-router-dom';
import { render, screen } from '@testing-library/react';
import i18next from 'i18next';

import CRTDLCard, { CRTDLType } from './index';

const mockCrtdls: CRTDLType[] = [
{ id: 'crtdl1', __typename: 'EChimpCR' },
{ id: 'crtdl2', __typename: 'EChimpTDL' }
];

describe('CRTDLCard', () => {
it('renders the card with the correct heading', () => {
render(
<Router>
<CRTDLCard crtdls={mockCrtdls} modelID="model123" />
</Router>
);

expect(
screen.getByText(i18next.t('collaborationArea:crtdlsCard.heading'))
).toBeInTheDocument();
});

it('displays a message when there are no crtdls', () => {
render(
<Router>
<CRTDLCard crtdls={[]} modelID="model123" />
</Router>
);

expect(
screen.getByText(i18next.t('collaborationArea:crtdlsCard.noCrtdls'))
).toBeInTheDocument();
});

it('displays a list of crtdls when they are present', () => {
render(
<Router>
<CRTDLCard crtdls={mockCrtdls} modelID="model123" />
</Router>
);

expect(screen.getByText('crtdl1, crtdl2')).toBeInTheDocument();
});

it('renders the "View All" button when crtdls are present', () => {
render(
<Router>
<CRTDLCard crtdls={mockCrtdls} modelID="model123" />
</Router>
);

expect(
screen.getByText(i18next.t('collaborationArea:crtdlsCard.viewAll'))
).toBeInTheDocument();
});

it('does not render the "View All" button when there are no crtdls', () => {
render(
<Router>
<CRTDLCard crtdls={[]} modelID="model123" />
</Router>
);

expect(
screen.queryByText(i18next.t('collaborationArea:crtdlsCard.viewAll'))
).not.toBeInTheDocument();
});
});
86 changes: 86 additions & 0 deletions src/features/ModelPlan/CollaborationArea/Cards/CRTDLCard/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import {
Card,
CardBody,
CardFooter,
CardHeader
} from '@trussworks/react-uswds';
import { GetModelPlanQuery } from 'gql/generated/graphql';

import ExternalLink from 'components/ExternalLink';
import UswdsReactLink from 'components/LinkWrapper';

import '../../index.scss';

export type CRTDLType = GetModelPlanQuery['modelPlan']['echimpCRsAndTDLs'][0];

type CRTDLCardType = {
crtdls: CRTDLType[];
modelID: string;
};

const CRTDLCard = ({ crtdls = [], modelID }: CRTDLCardType) => {
const { t: collaborationAreaT } = useTranslation('collaborationArea');

const firstFirstFiveCRTDLs = crtdls.slice(0, 5);

const remainingCRTDLs: number = crtdls.length - firstFirstFiveCRTDLs.length;

return (
<Card
gridLayout={{ mobile: { col: 12 }, desktop: { col: 4 } }}
className="collaboration-area__card"
>
<CardHeader>
<h3 className="usa-card__heading">
{collaborationAreaT('crtdlsCard.heading')}
</h3>
</CardHeader>

<CardBody>
{crtdls?.length === 0 ? (
<p className="text-base">
{collaborationAreaT('crtdlsCard.noCrtdls')}
</p>
) : (
<p className="text-base-dark">
{firstFirstFiveCRTDLs.map(crtdl => crtdl.id).join(', ')}
{remainingCRTDLs > 0 && (
<>
{' '}
{collaborationAreaT('crtdlsCard.andMore', {
count: remainingCRTDLs
})}
</>
)}
</p>
)}
</CardBody>

<CardFooter>
<ExternalLink
href="https://echimp.cmsnet/"
className="usa-button"
variant="unstyled"
asButton
toEchimp
>
{collaborationAreaT('crtdlsCard.addInEChimp')}
</ExternalLink>

{crtdls?.length !== 0 && (
<UswdsReactLink
className="usa-button usa-button--outline"
variant="unstyled"
to={`/models/${modelID}/collaboration-area/cr-and-tdl`}
>
{collaborationAreaT('crtdlsCard.viewAll')}
</UswdsReactLink>
)}
</CardFooter>
</Card>
);
};

export default CRTDLCard;
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ const modelPlan = {
},
crs: [],
tdls: [],
echimpCRsAndTDLs: [],
operationalNeeds: [] as any,
documents: [
{
Expand Down
4 changes: 4 additions & 0 deletions src/features/ModelPlan/CollaborationArea/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import useMessage from 'hooks/useMessage';

import { UpdateFavoriteProps } from '../ModelPlanOverview';

import CRTDLCard from './Cards/CRTDLCard';
import DiscussionsCard from './Cards/DiscussionsCard';
import DocumentsCard from './Cards/DocumentsCard';
import ModelPlanCard from './Cards/ModelPlanCard';
Expand Down Expand Up @@ -59,6 +60,7 @@ const CollaborationArea = () => {
modelName,
discussions,
documents,
echimpCRsAndTDLs,
status,
collaborators,
isFavorite,
Expand Down Expand Up @@ -234,6 +236,8 @@ const CollaborationArea = () => {
<DiscussionsCard discussions={discussions} modelID={modelID} />

<DocumentsCard documents={documents} modelID={modelID} />

<CRTDLCard crtdls={echimpCRsAndTDLs} modelID={modelID} />
</CardGroup>
</GridContainer>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import React from 'react';
import { MemoryRouter, Route } from 'react-router-dom';
import { MockedProvider } from '@apollo/client/testing';
import { render, screen, waitFor } from '@testing-library/react';
import {
render,
screen,
waitFor,
waitForElementToBeRemoved
} from '@testing-library/react';
import {
ConfidenceType,
GetPeopleImpactedDocument,
Expand Down Expand Up @@ -93,9 +98,9 @@ describe('Model Plan Beneficiaries', () => {
</MemoryRouter>
);

await waitFor(() => {
expect(screen.getByTestId('expected-people-impacted')).toHaveValue(100);
});
await waitForElementToBeRemoved(() =>
screen.getByTestId('beneficiaries-selection-note-add-note-toggle')
);

expect(asFragment()).toMatchSnapshot();
});
Expand Down
1 change: 1 addition & 0 deletions src/features/ModelPlan/TaskList/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ describe('The Model Plan Task List', () => {
},
crs: [],
tdls: [],
echimpCRsAndTDLs: [],
operationalNeeds: [] as any,
documents: [
{
Expand Down
12 changes: 10 additions & 2 deletions src/gql/generated/graphql.ts

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions src/gql/operations/ModelPlan/GetModelPlan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ export default gql(/* GraphQL */ `
id
idNumber
}
echimpCRsAndTDLs {
... on EChimpCR {
id
}
... on EChimpTDL {
id
}
}
discussions {
id
content {
Expand Down
4 changes: 4 additions & 0 deletions src/i18n/en-US/externalLinkModal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@ const externalLinkModal = {
heading: 'Are you sure you want to leave MINT?',
description: `This link may require additional job codes, permissions, and/or connectivity via VPN to access content.
Please contact the CMS IT Service Desk at 410-786-2580 or 800-562-1963 if you need assistance.`,
descriptionEchimp: `ECHIMP requires additional job codes and/or permissions and connectivity via VPN to access content within the system.
Please contact the CMS IT Service Desk at 410-786-2580 or 800-562-1963 if you need assistance.`,
leave: 'Leave MINT',
continueEchimp: 'Continue to ECHIMP',
return: 'Go back to MINT',
document: {
heading: 'You are leaving MINT.',
Expand Down
2 changes: 1 addition & 1 deletion src/i18n/en-US/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import homepageSettings from './home/settings';
import { basics, basicsMisc } from './modelPlan/basics';
import { beneficiaries, beneficiariesMisc } from './modelPlan/beneficiaries';
import changeHistory from './modelPlan/changeHistory';
import collaborationArea from './modelPlan/collaborationArea';
import { collaborators, collaboratorsMisc } from './modelPlan/collaborators';
import crs from './modelPlan/crs';
import crtdlsMisc from './modelPlan/crtdlsMisc';
Expand Down Expand Up @@ -49,7 +50,6 @@ import modelSummary from './readOnly/modelSummary';
import readOnlyModelPlan from './readOnly/readOnlyModelPlan';
import accessibilityStatement from './accessibilityStatement';
import auth from './auth';
import collaborationArea from './collaborationArea';
import cookies from './cookies';
import error from './error';
import externalLinkModal from './externalLinkModal';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ const collaborationArea = {
discussion: '{{count}} discussion',
discussion_other: '{{count}} discussions',
noDiscussions: 'No discussions started'
},
crtdlsCard: {
heading: 'FFS CRs and TDLS',
addInEChimp: 'Add in ECHIMP',
viewAll: 'View all',
noCrtdls: 'No CRs or TDLs',
andMore: ' + {{count}} more'
}
};

Expand Down

0 comments on commit 3f80941

Please sign in to comment.