Skip to content

Commit

Permalink
MPDX-8057 - tools sidebar (#1010)
Browse files Browse the repository at this point in the history
* Adds tools navbar.
  • Loading branch information
wjames111 authored Sep 4, 2024
1 parent 20ce9ed commit 7760bad
Show file tree
Hide file tree
Showing 12 changed files with 345 additions and 208 deletions.
15 changes: 3 additions & 12 deletions pages/accountLists/[accountListId]/tools.page.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,13 @@
import Head from 'next/head';
import React, { ReactElement } from 'react';
import { useTranslation } from 'react-i18next';
import { loadSession } from 'pages/api/utils/pagePropsHelpers';
import ToolHome from 'src/components/Tool/Home/Home';
import useGetAppSettings from 'src/hooks/useGetAppSettings';
import { ToolsWrapper } from './tools/ToolsWrapper';

const ToolsPage = (): ReactElement => {
const { t } = useTranslation();
const { appName } = useGetAppSettings();
return (
<>
<Head>
<title>
{appName} | {t('Tools')}
</title>
</Head>
<ToolsWrapper pageUrl={'tools'}>
<ToolHome />
</>
</ToolsWrapper>
);
};

Expand Down
36 changes: 31 additions & 5 deletions pages/accountLists/[accountListId]/tools/ToolsWrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,36 @@
import Head from 'next/head';
import React, { JSXElementConstructor, ReactElement } from 'react';
import React, { JSXElementConstructor, ReactElement, useState } from 'react';
import { DynamicContactsRightPanel } from 'src/components/Contacts/ContactsRightPanel/DynamicContactsRightPanel';
import { SidePanelsLayout } from 'src/components/Layouts/SidePanelsLayout';
import Loading from 'src/components/Loading';
import {
HeaderTypeEnum,
MultiPageHeader,
} from 'src/components/Shared/MultiPageLayout/MultiPageHeader';
import NavToolList from 'src/components/Tool/NavToolList/NavToolList';
import useGetAppSettings from 'src/hooks/useGetAppSettings';
import { ContactsWrapper } from '../contacts/ContactsWrapper';
import { useToolsHelper } from './useToolsHelper';

interface ToolsWrapperProps {
pageTitle: string;
pageTitle?: string;
pageUrl: string;
selectedMenuId: string; // for later use
selectedMenuId?: string;
children: ReactElement<unknown, string | JSXElementConstructor<unknown>>;
styles?: React.ReactNode;
}

export const ToolsWrapper: React.FC<ToolsWrapperProps> = ({
pageTitle,
pageUrl,
selectedMenuId,
children,
styles,
}) => {
const { appName } = useGetAppSettings();
const { accountListId, selectedContactId, handleSelectContact } =
useToolsHelper();
const [isToolDrawerOpen, setIsToolDrawerOpen] = useState<boolean>(false);

return (
<>
Expand All @@ -33,11 +40,30 @@ export const ToolsWrapper: React.FC<ToolsWrapperProps> = ({
</title>
{styles}
</Head>

{accountListId ? (
<SidePanelsLayout
leftOpen={false}
leftOpen={isToolDrawerOpen}
isScrollBox={false}
leftPanel={
<NavToolList
selectedId={selectedMenuId || ''}
isOpen={isToolDrawerOpen}
toggle={setIsToolDrawerOpen}
/>
}
leftWidth="290px"
mainContent={children}
mainContent={
<>
<MultiPageHeader
isNavListOpen={isToolDrawerOpen}
onNavListToggle={() => setIsToolDrawerOpen(!isToolDrawerOpen)}
title={pageTitle || ''}
headerType={HeaderTypeEnum.Tools}
/>
{children}
</>
}
rightPanel={
selectedContactId ? (
<ContactsWrapper>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ const useStyles = makeStyles()(() => ({
},
}));

enum ToolName {
export enum ToolName {
FixCommitmentInfo = 'fixCommitmentInfo',
FixMailingAddresses = 'fixMailingAddresses',
FixSendNewsletter = 'fixSendNewsletter',
Expand Down
17 changes: 17 additions & 0 deletions src/components/Shared/MultiPageLayout/MultiPageHeader.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,21 @@ describe('MultiPageHeader', () => {
expect(getByText('Toggle Preferences Menu')).toBeInTheDocument();
expect(getByTestId('SettingsMenuIcon')).toBeInTheDocument();
});

it('should render the Tools menu', async () => {
const { getByTestId, getByText } = render(
<ThemeProvider theme={theme}>
<MultiPageHeader
isNavListOpen={true}
title={title}
onNavListToggle={onNavListToggle}
rightExtra={undefined}
headerType={HeaderTypeEnum.Tools}
/>
</ThemeProvider>,
);

expect(getByText('Toggle Tools Menu')).toBeInTheDocument();
expect(getByTestId('ToolsMenuIcon')).toBeInTheDocument();
});
});
9 changes: 9 additions & 0 deletions src/components/Shared/MultiPageLayout/MultiPageHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import theme from 'src/theme';
export enum HeaderTypeEnum {
Report = 'reports',
Settings = 'settings',
Tools = 'tools',
}

export const multiPageHeaderHeight = theme.spacing(10);
Expand Down Expand Up @@ -70,6 +71,8 @@ export const MultiPageHeader: FC<MultiPageHeaderProps> = ({
titleAccess = t('Toggle Navigation Panel');
} else if (headerType === HeaderTypeEnum.Settings) {
titleAccess = t('Toggle Preferences Menu');
} else if (headerType === HeaderTypeEnum.Tools) {
titleAccess = t('Toggle Tools Menu');
}

return (
Expand All @@ -93,6 +96,12 @@ export const MultiPageHeader: FC<MultiPageHeaderProps> = ({
data-testid="SettingsMenuIcon"
/>
)}
{headerType === HeaderTypeEnum.Tools && (
<NavMenuIcon
titleAccess={titleAccess}
data-testid="ToolsMenuIcon"
/>
)}
</NavListButton>
<Typography variant="h5" sx={{ flex: 1 }}>
{title}
Expand Down
62 changes: 35 additions & 27 deletions src/components/Tool/Home/ToolList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
mdiTrophy,
mdiWrench,
} from '@mdi/js';
import i18n from 'src/lib/i18n';

export interface ToolItem {
tool: string;
Expand All @@ -29,104 +30,111 @@ interface ToolsGroup {

export const ToolsList: ToolsGroup[] = [
{
groupName: 'Appeals',
groupName: i18n.t('Appeals'),
groupIcon: mdiWrench,
items: [
{
tool: 'Appeal',
desc: 'Set goals, create asks, and track progress for one-time needs',
tool: i18n.t('Appeal'),
desc: i18n.t(
'Set goals, create asks, and track progress for one-time needs',
),
icon: mdiTrophy,
id: 'appeals',
url: 'appeals',
},
],
},
{
groupName: 'Contacts',
groupName: i18n.t('Contacts'),
groupIcon: mdiHome,
items: [
{
tool: 'Fix Commitment Info',
desc: 'Set the correct contacts commitment info for each contact',
tool: i18n.t('Fix Commitment Info'),
desc: i18n.t(
'Set the correct contacts commitment info for each contact',
),

icon: mdiCurrencyUsd,
id: 'fixCommitmentInfo',
url: 'fix/commitmentInfo',
},
{
tool: 'Fix Mailing Addresses',
desc: 'Set the correct primary mailing address for each contact',
tool: i18n.t('Fix Mailing Addresses'),
desc: i18n.t(
'Set the correct primary mailing address for each contact',
),
icon: mdiMap,
id: 'fixMailingAddresses',
url: 'fix/mailingAddresses',
},
{
tool: 'Fix Send Newsletter',
desc: 'Set the correct newsletter state for each contact',
tool: i18n.t('Fix Send Newsletter'),
desc: i18n.t('Set the correct newsletter state for each contact'),
icon: mdiNewspaperVariantOutline,
id: 'fixSendNewsletter',
url: 'fix/sendNewsletter',
},
{
tool: 'Merge Contacts',
desc: 'Review and merge duplicate contacts',
tool: i18n.t('Merge Contacts'),
desc: i18n.t('Review and merge duplicate contacts'),
icon: mdiHome,
id: 'mergeContacts',
url: 'merge/contacts',
},
],
},
{
groupName: 'People',
groupName: i18n.t('People'),
groupIcon: mdiAccountGroup,
items: [
{
tool: 'Fix Email Addresses',
desc: 'Set the correct primary email address for each person',
tool: i18n.t('Fix Email Addresses'),
desc: i18n.t('Set the correct primary email address for each person'),
icon: mdiEmail,
id: 'fixEmailAddresses',
url: 'fix/emailAddresses',
},
{
tool: 'Fix Phone Numbers',
desc: 'Set the correct primary phone number for each person',
tool: i18n.t('Fix Phone Numbers'),
desc: i18n.t('Set the correct primary phone number for each person'),
icon: mdiPhone,
id: 'fixPhoneNumbers',
url: 'fix/phoneNumbers',
},
{
tool: 'Merge People',
desc: 'Review and merge duplicate people',
tool: i18n.t('Merge People'),
desc: i18n.t('Review and merge duplicate people'),
icon: mdiAccountGroup,
id: 'mergePeople',
url: 'merge/people',
},
],
},
{
groupName: 'Imports',
groupName: i18n.t('Imports'),
groupIcon: mdiCloudUpload,
items: [
{
tool: 'Import from Google',
desc: 'Import your contact information from your Google account',
tool: i18n.t('Import from Google'),
desc: i18n.t(
'Import your contact information from your Google account',
),

icon: mdiGoogle,
id: 'import/google',
url: 'import/google',
},

{
tool: 'Import from TntConnect',
desc: 'Import your contacts from your TntConnect database',
tool: i18n.t('Import from TntConnect'),
desc: i18n.t('Import your contacts from your TntConnect database'),
icon: mdiCloudUpload,
id: 'import/tnt',
url: 'import/tnt',
},

{
tool: 'Import from CSV',
desc: 'Import contacts you have saved in a CSV file',
tool: i18n.t('Import from CSV'),
desc: i18n.t('Import contacts you have saved in a CSV file'),
icon: mdiTable,
id: 'import/csv',
url: 'import/csv',
Expand Down
45 changes: 40 additions & 5 deletions src/components/Tool/NavToolList/Item/Item.test.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,56 @@
import React from 'react';
import { ThemeProvider } from '@mui/material/styles';
import TestWrapper from '__tests__/util/TestWrapper';
import { render } from '__tests__/util/testingLibraryReactMock';
import theme from '../../../../theme';
import { Item } from './Item';

const item = {
url: 'testItem',
title: 'test title',
isSelected: false,
id: 'testItem',
};

const TestComponent = ({ totalCount = 0 }: { totalCount?: number }) => (
<ThemeProvider theme={theme}>
<TestWrapper>
<Item
url={item.url}
title={item.title}
isSelected={item.isSelected}
loading={false}
totalCount={totalCount}
toolId={item.id}
/>
</TestWrapper>
</ThemeProvider>
);

describe('ToolItem', () => {
it('default', () => {
const { queryByText } = render(
<TestWrapper>
<Item url={item.url} title={item.title} isSelected={item.isSelected} />
</TestWrapper>,
);
const { queryByText } = render(<TestComponent />);
expect(queryByText(item.title)).toBeInTheDocument();
});

it('renders count less then 9', () => {
const { queryByText } = render(<TestComponent totalCount={8} />);
expect(queryByText(item.title)).toBeInTheDocument();
expect(queryByText('8')).toBeInTheDocument();
});

it('renders count greater then 9', () => {
const { queryByText } = render(<TestComponent totalCount={10} />);
expect(queryByText(item.title)).toBeInTheDocument();
expect(queryByText('9+')).toBeInTheDocument();
});

it('renders without Badge', () => {
const { queryByText, queryByTestId } = render(<TestComponent />);
expect(queryByText(item.title)).toBeInTheDocument();

expect(
queryByTestId('fixCommitmentInfo-notifications'),
).not.toBeInTheDocument();
});
});
Loading

0 comments on commit 7760bad

Please sign in to comment.