Skip to content

Commit

Permalink
feat: [CGC-34] Change to DHIS2 UI (#58)
Browse files Browse the repository at this point in the history
  • Loading branch information
henrikmv authored Jun 19, 2024
1 parent 95dd1e8 commit 36b925e
Show file tree
Hide file tree
Showing 13 changed files with 846 additions and 180 deletions.
6 changes: 3 additions & 3 deletions cypress/component/ChartSelector/ChartSelector.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ describe('ChartSelector', () => {
<TestComponent />,
);
cy.get('[data-test="CGC-category-dropdown-button"]').contains('Head circumference for age').click();
cy.get('[data-test="CGC-category-dropdown-item"]').should('have.length', 3);
cy.get('[data-test="CGC-category-dropdown-item"]').should('have.length', 4);
cy.get('[data-test="CGC-category-dropdown-item"]').should('contain', 'Length/height for age');
cy.get('[data-test="CGC-category-dropdown-item"]').should('contain', 'Weight for age');
cy.get('[data-test="CGC-category-dropdown-item"]').should('contain', 'Weight for length/height');
Expand All @@ -74,15 +74,15 @@ describe('ChartSelector', () => {
<TestComponent />,
);
cy.get('[data-test="CGC-category-dropdown-button"]').contains('Head circumference for age').click();
cy.get('[data-test="CGC-category-dropdown-item"]').contains('Weight for age').click();
cy.get('[data-test="CGC-category-dropdown-item"]').contains('Weight for age').click({ force: true });
cy.get('[data-test="CGC-category-dropdown-button"]').should('contain', 'Weight for age');
});

it('Should be able to change the dataset', () => {
cy.mount(
<TestComponent />,
);
cy.get('[data-test="CGC-dataset-dropdown-button"]').contains('0 to 13 weeks').click();
cy.get('[data-test="CGC-dataset-dropdown-button"]').click();
cy.get('[data-test="CGC-dataset-dropdown-item"]').contains('0 to 5 years').click();
cy.get('[data-test="CGC-dataset-dropdown-button"]').should('contain', '0 to 5 years');
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ describe('ChartSelectorDropdown', () => {
const TestComponent = () => {
const [title, handleItemChange] = useState('0 to 13 weeks');
return (
// eslint-disable-next-line react/jsx-filename-extension
// eslint-disable-next-line react/jsx-filename-extension
<ChartSelectorDropdown
title={title}
items={['0 to 13 weeks', '0 to 2 years', '2 to 5 years']}
Expand All @@ -28,15 +28,15 @@ describe('ChartSelectorDropdown', () => {
<TestComponent />,
);
cy.get('[data-test="CGC-dropdown-button"]').click();
cy.get('[data-test="CGC-dropdown-item"]').should('have.length', 2);
cy.get('[data-test="CGC-dropdown-item"]').should('have.length', 3);
});

it('Selecting a new item should change the title', () => {
cy.mount(
<TestComponent />,
);
cy.get('[data-test="CGC-dropdown-button"]').contains('0 to 13 weeks').click();
cy.get('[data-test="CGC-dropdown-item"]').contains('0 to 2 years').click();
cy.get('[data-test="CGC-dropdown-button"]').should('contain', '0 to 2 years');
cy.get('[data-test="CGC-dropdown-button"]').click();
cy.get('[data-test="CGC-dropdown-item"]').contains('2 to 5 years').click({ force: true });
cy.get('[data-test="CGC-dropdown-button"]').should('contain', '2 to 5 years');
});
});
7 changes: 5 additions & 2 deletions i18n/en.pot
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ msgstr ""
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"POT-Creation-Date: 2024-06-10T07:28:02.836Z\n"
"PO-Revision-Date: 2024-06-10T07:28:02.836Z\n"
"POT-Creation-Date: 2024-06-19T13:53:21.384Z\n"
"PO-Revision-Date: 2024-06-19T13:53:21.384Z\n"

msgid "Growth Chart"
msgstr "Growth Chart"
Expand Down Expand Up @@ -46,6 +46,9 @@ msgstr "Year"
msgid "Years"
msgstr "Years"

msgid "Gender is pre-selected based on the profile"
msgstr "Gender is pre-selected based on the profile"

msgid "Months"
msgstr "Months"

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"@dhis2/app-runtime": "^3.10.2",
"@dhis2/d2-i18n": "^1.1.3",
"@dhis2/prop-types": "^3.1.2",
"@dhis2/ui": "^9.0.1",
"@dhis2/ui": "^9.4.3",
"@headlessui/react": "^1.7.18",
"@material-ui/core": "3.9.4",
"@tailwindcss/line-clamp": "^0.4.4",
Expand Down
48 changes: 17 additions & 31 deletions src/Plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,38 +88,24 @@ const PluginInner = (propsFromParent: EnrollmentOverviewProps) => {
}

return (
<QueryClientProvider
client={queryClient}
>
<div
style={{
backgroundColor: 'white',
width: '100vw',
display: 'flex',
margin: 0,
padding: 0,
}}
>
<div
style={{ width: '100%' }}
<QueryClientProvider client={queryClient}>
<div className='bg-white w-screen flex m-0 p-0'>
<WidgetCollapsible
header={i18n.t('Growth Chart')}
borderless={false}
open={open}
onOpen={() => setOpen(true)}
onClose={() => setOpen(false)}
>
<WidgetCollapsible
header={i18n.t('Growth Chart')}
borderless={false}
open={open}
onOpen={() => setOpen(true)}
onClose={() => setOpen(false)}
>
<GrowthChart
trackedEntity={mappedTrackedEntity}
measurementData={mappedGrowthVariables}
chartData={chartConfig.settings.customReferences ? customReferences : chartData}
defaultIndicator={defaultIndicator}
isPercentiles={isPercentiles}
setDefaultIndicatorError={setDefaultIndicatorError}
/>
</WidgetCollapsible>
</div>
<GrowthChart
trackedEntity={mappedTrackedEntity}
measurementData={mappedGrowthVariables}
chartData={chartConfig.settings.customReferences ? customReferences : chartData}
defaultIndicator={defaultIndicator}
isPercentiles={isPercentiles}
setDefaultIndicatorError={setDefaultIndicatorError}
/>
</WidgetCollapsible>
</div>
</QueryClientProvider>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import React, { useState, useRef, useEffect } from 'react';
import React from 'react';
import i18n from '@dhis2/d2-i18n';
import { usePopper } from 'react-popper';
import { MenuItem } from '@dhis2/ui';
import { EllipsisButton } from './EllipsisButton';
import { PopoverList, PopoverListItem, PopoverListDivider } from './PopoverList';
import { CategoryCodes, ChartData } from '../../../types/chartDataTypes';
import { MappedEntityValues } from '../../../utils/DataFetching/Sorting/useMappedTrackedEntity';
import { PrintDocument } from '../../../utils/ChartOptions';
Expand All @@ -21,60 +20,27 @@ export const ChartSettingsButton = ({
gender,
trackedEntity,
}: ChartSettingsButtonProps) => {
const [referenceElement, setReferenceElement] = useState(null);
const [popperElement, setPopperElement] = useState(null);
const [isVisible, setIsVisible] = useState(false);

const { styles, attributes } = usePopper(referenceElement, popperElement, {
placement: 'bottom-end',
modifiers: [
{
name: 'offset',
options: { offset: [0, 2] },
},
],
});

const popoverRef = useRef(null);

useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (popoverRef.current && !popoverRef.current.contains(event.target)) {
setIsVisible(false);
}
};
document.addEventListener('mousedown', handleClickOutside);

return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, []);

const handlePrintDocument = () => PrintDocument({
category, dataset, gender, firstName: trackedEntity.firstName, lastName: trackedEntity.lastName,
});
const handlePrintDocument = () => {
PrintDocument({
category,
dataset,
gender,
firstName: trackedEntity.firstName,
lastName: trackedEntity.lastName,
});
};

return (
<div ref={popoverRef}>
<EllipsisButton
onClick={() => setIsVisible((prevState) => !prevState)}
isVisible={isVisible}
setReferenceElement={setReferenceElement}
<EllipsisButton
dataTest='widget-profile-overflow-menu'
secondary
small
>
<MenuItem
label={i18n.t('Print')}
onClick={handlePrintDocument}
icon={<PrintIcon />}
/>
{isVisible && (
<PopoverList
setPopperElement={setPopperElement}
style={styles.popper}
popoverAttributes={{ ...attributes.popper }}
>
<PopoverListItem
label={i18n.t('Print')}
icon={<PrintIcon />}
onClick={handlePrintDocument}
/>
<PopoverListDivider />
</PopoverList>
)}
</div>
</EllipsisButton>
);
};
Original file line number Diff line number Diff line change
@@ -1,22 +1,53 @@
import React from 'react';
import { Ellipsis } from '../../../../UI/Icons';
import React, { useState, useRef, ReactNode } from 'react';
import { Button, Layer, Popper, FlyoutMenu, IconMore16 } from '@dhis2/ui';

type EllipsisButtonProps = {
onClick: () => void;
isVisible: boolean;
setReferenceElement: (element: HTMLButtonElement | null) => void;
type Props = {
primary?: boolean;
secondary?: boolean;
dataTest?: string;
small?: boolean;
large?: boolean;
children: ReactNode;
};

export const EllipsisButton = ({ onClick, isVisible, setReferenceElement }: EllipsisButtonProps): JSX.Element => (
<button
type='button'
aria-label='Chart settings'
onClick={onClick}
ref={setReferenceElement}
className='flex items-center absolute right-[55px] justify-center w-7 h-7 rounded border
text-gray-600 hover:bg-gray-300 hover:text-gray-700'
style={isVisible ? { border: '1px solid black' } : {}}
>
<Ellipsis />
</button>
);
export const EllipsisButton = ({
primary,
secondary,
small,
large,
dataTest,
children,
}: Props) => {
const anchorRef = useRef(null);
const [actionsIsOpen, setActionsIsOpen] = useState(false);

const toggle = () => {
setActionsIsOpen((prev) => !prev);
};

return (
<>
<div ref={anchorRef}>
{/* @ts-ignore */}
<Button
primary={primary}
secondary={secondary}
dataTest={dataTest}
small={small}
large={large}
onClick={toggle}
icon={<IconMore16 />}
/>
</div>
{actionsIsOpen && (
<Layer onBackdropClick={toggle}>
<Popper reference={anchorRef} placement='bottom-end'>
<FlyoutMenu dense>
{children}
</FlyoutMenu>
</Popper>
</Layer>
)}
</>
);
};
28 changes: 13 additions & 15 deletions src/components/GrowthChart/GrowthChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,21 +79,19 @@ export const GrowthChart = ({
};

return (
<div>
<div className='flex flex-wrap-reverse pl-14'>
<>
<div className='flex justify-between px-14'>
<ChartSelector
category={category}
dataset={dataset}
setCategory={setCategory}
setDataset={setDataset}
chartData={chartDataForGender}
isDisabled={trackedEntityGender !== undefined}
gender={gender}
setGender={setGender}
/>
<div>
<ChartSelector
category={category}
dataset={dataset}
setCategory={setCategory}
setDataset={setDataset}
chartData={chartDataForGender}
isDisabled={trackedEntityGender !== undefined}
gender={gender}
setGender={setGender}
/>
</div>
<div className='grow relative min-w-[100px] text-sm'>
<ChartSettingsButton
category={category}
dataset={dataset}
Expand All @@ -117,6 +115,6 @@ export const GrowthChart = ({
/>
</div>
</div>
</div>
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export const GrowthChartBuilder = ({
return (
<div className='aspect-video min-h-[400px]' id='divToPrint'>
<AutoSizer>
{/* eslint-disable-next-line react/no-unused-prop-types */}
{/* eslint-disable-next-line */}
{({ height, width }: { height: number, width: number }) => (
<div style={{ height, width }}>
<Line data={data} options={options} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const ChartSelector = ({
};

return (
<div className='flex flex-wrap w-full gap-2 text-sm'>
<div className='flex flex-wrap gap-2 items-center'>
<ChartSelectorDropdown
title={gender}
items={Object.values(GenderCodes)}
Expand Down
Loading

0 comments on commit 36b925e

Please sign in to comment.