Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
cf9da60
Implement thanks for submitting dialog (partial impl)
VadimKovalenkoSNF Nov 29, 2024
bfe527a
Add submit production location modal (partial impl)
VadimKovalenkoSNF Nov 29, 2024
4fae202
Refactor styles
VadimKovalenkoSNF Dec 2, 2024
b9f216c
Apply tooltip for the claim button
VadimKovalenkoSNF Dec 2, 2024
7325e3d
Abstract tooltip UI to the DialogTooltip
VadimKovalenkoSNF Dec 2, 2024
9417f0e
Apply unit tests
VadimKovalenkoSNF Dec 2, 2024
6723561
Minor fixes, update Release notes
VadimKovalenkoSNF Dec 2, 2024
36cc496
Apply minor changes, update tests
VadimKovalenkoSNF Dec 3, 2024
bd9eb59
Refactor popper mock
VadimKovalenkoSNF Dec 3, 2024
49eeac8
Improve tooltip settings and tests
VadimKovalenkoSNF Dec 3, 2024
3c098dc
Apply proptypes
VadimKovalenkoSNF Dec 3, 2024
96934da
Minor proptype fix
VadimKovalenkoSNF Dec 3, 2024
80f0c94
Remove proptypes from ProductionLocationDialog
VadimKovalenkoSNF Dec 3, 2024
71de095
Merge branch 'main' into OSDEV-1132-implement-thanks-for-submitting-s…
VadimKovalenkoSNF Dec 3, 2024
b0b02b1
Merge branch 'main' into OSDEV-1132-implement-thanks-for-submitting-s…
VadimKovalenkoSNF Dec 3, 2024
21f6065
Merge branch 'main' into OSDEV-1132-implement-thanks-for-submitting-s…
VadimKovalenkoSNF Dec 4, 2024
f08dd6b
Merge branch 'main' into OSDEV-1132-implement-thanks-for-submitting-s…
VadimKovalenkoSNF Dec 5, 2024
167e828
Merge branch 'main' into OSDEV-1132-implement-thanks-for-submitting-s…
VadimKovalenkoSNF Dec 6, 2024
1738737
Merge branch 'main' into OSDEV-1132-implement-thanks-for-submitting-s…
VadimKovalenkoSNF Dec 6, 2024
7dc2758
Merge branch 'main' into OSDEV-1132-implement-thanks-for-submitting-s…
VadimKovalenkoSNF Dec 6, 2024
13352ff
Merge branch 'main' into OSDEV-1132-implement-thanks-for-submitting-s…
VadimKovalenkoSNF Dec 6, 2024
af24f30
Merge branch 'main' into OSDEV-1132-implement-thanks-for-submitting-s…
VadimKovalenkoSNF Dec 6, 2024
f5ce8c5
Merge branch 'main' into OSDEV-1132-implement-thanks-for-submitting-s…
VadimKovalenkoSNF Dec 9, 2024
3acb03a
Merge branch 'main' into OSDEV-1132-implement-thanks-for-submitting-s…
VadimKovalenkoSNF Dec 9, 2024
25308d7
Merge branch 'main' into OSDEV-1132-implement-thanks-for-submitting-s…
VadimKovalenkoSNF Dec 9, 2024
1967a45
Refactor styles definition, minor fixes
VadimKovalenkoSNF Dec 10, 2024
48e8a72
Remove redundant console.log
VadimKovalenkoSNF Dec 10, 2024
917f981
Minor lint fix
VadimKovalenkoSNF Dec 10, 2024
c78c1b0
Fix unit test
VadimKovalenkoSNF Dec 10, 2024
e0ff124
Replace DialogTooltip, add minor changes
VadimKovalenkoSNF Dec 10, 2024
8bc989a
Minor fixes for COLOUR import
VadimKovalenkoSNF Dec 10, 2024
986aec6
Add aria labels
VadimKovalenkoSNF Dec 10, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/release/RELEASE-NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ This issue has been fixed by adding additional requests to delete the appropriat
* [OSDEV-1482](https://opensupplyhub.atlassian.net/browse/OSDEV-1482) - The `GET api/v1/moderation-events/{moderation_id}` endpoint returns a single response instead of an array containing one item.

### What's new
* [OSDEV-1132](https://opensupplyhub.atlassian.net/browse/OSDEV-1132) - Added FE for the "thanks for submitting" screen when user submits production location's data.
* [OSDEV-1373](https://opensupplyhub.atlassian.net/browse/OSDEV-1373) - The tab `Search by Name and Address.` on the Production Location Search screen has been implemented. There are three required properties (name, address, country). The "Search" button becomes clickable after filling out inputs, creates a link with parameters, and allows users to proceed to the results screen.
* [OSDEV-1175](https://opensupplyhub.atlassian.net/browse/OSDEV-1175) - New Moderation Queue Page was integrated with `GET api/v1/moderation-events/` endpoint that include pagination, sorting and filtering.

Expand Down
1 change: 1 addition & 0 deletions src/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"@craco/craco": "6.1.1",
"@material-ui/core": "3.1.0",
"@material-ui/icons": "3.0.1",
"@popperjs/core": "^2.11.8",
"@reduxjs/toolkit": "^2.2.7",
"@rollbar/react": "^0.11.2",
"@turf/distance": "6.0.1",
Expand Down
60 changes: 60 additions & 0 deletions src/react/src/__tests__/components/DialogTooltip.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import React from 'react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import DialogTooltip from '../../components/Contribute/DialogTooltip';

global.cancelAnimationFrame = jest.fn();

jest.mock('@popperjs/core', () => ({
__esModule: true,
default: jest.fn(() => ({
destroy: jest.fn(),
update: jest.fn(),
scheduleUpdate: jest.fn(),
enableEventListeners: jest.fn(),
disableEventListeners: jest.fn(),
setOptions: jest.fn(),
})),
}));

beforeAll(() => {
global.Node = global.Node || {};
});

describe('DialogTooltip Component', () => {
test('renders tooltip on hover', async () => {
const mockChildComponent = <span>Hover over this element</span>;
const mockText = "You'll be able to claim the location after the moderation is done";

render(
<DialogTooltip text={mockText} childComponent={mockChildComponent} classes={{}} />
);

expect(screen.queryByText(mockText)).not.toBeInTheDocument();

fireEvent.mouseEnter(screen.getByText('Hover over this element'));
await waitFor(() => {
expect(screen.getByText(mockText)).toBeInTheDocument();
});
});

test('hides tooltip on mouse leave', async () => {
const mockChildComponent = <span>Hover over this element</span>;
const mockText = "Test tooltip";

render(
<DialogTooltip text={mockText} childComponent={mockChildComponent} classes={{}} />
);

const element = screen.getByText('Hover over this element');

fireEvent.mouseEnter(element);
await waitFor(() => {
expect(screen.getByText(mockText)).toBeInTheDocument();
});

fireEvent.mouseLeave(element);
await waitFor(() => {
expect(screen.queryByText(mockText)).not.toBeInTheDocument();
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import { BrowserRouter as Router, useHistory } from 'react-router-dom';
import UserEvent from "user-event";
import ProductionLocationDialog from '../../components/Contribute/ProductionLocationDialog';

jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useHistory: jest.fn(),
}));

const mockHistoryPush = jest.fn();

beforeEach(() => {
useHistory.mockReturnValue({
push: mockHistoryPush,
});
});

test('renders dialog content', () => {
render(
<Router>
<ProductionLocationDialog classes={{}} />
</Router>
);

expect(screen.getByText(/Thanks for adding data for this production location!/i)).toBeInTheDocument();
expect(screen.getByText(/Facility name/i)).toBeInTheDocument();
expect(screen.getByText(/OS ID/i)).toBeInTheDocument();
expect(screen.getByText(/Pending/i)).toBeInTheDocument();
});

test('should render multiple instances of text element', () => {
const text = "Unifill Composite Dyeing Mills Ltd.";

render(
<Router>
<ProductionLocationDialog classes={{}} />
</Router>
);

const elements = screen.getAllByText(new RegExp(text, 'i'));

expect(elements).toHaveLength(2);
});

test('navigates when "Search OS Hub" button is clicked', () => {
render(
<Router>
<ProductionLocationDialog classes={{}} />
</Router>
);

const button = screen.getByText(/Search OS Hub/i);
UserEvent.click(button);

expect(mockHistoryPush).toHaveBeenCalledWith('/');
});

test('calls console log when "Submit another Location" button is clicked', () => {
const consoleLogSpy = jest.spyOn(console, 'log').mockImplementation();

render(
<Router>
<ProductionLocationDialog classes={{}} />
</Router>
);

const button = screen.getByText(/Submit another Location/i);
UserEvent.click(button);

expect(consoleLogSpy).toHaveBeenCalledWith('submit another location');
consoleLogSpy.mockRestore();
});
3 changes: 2 additions & 1 deletion src/react/src/components/ConfirmActionButton.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import DialogContent from '@material-ui/core/DialogContent';
import DialogTitle from '@material-ui/core/DialogTitle';
import { useMergeButtonClickHandler } from './../util/hooks';
import { CONFIRM_ACTION, MERGE_ACTION, REJECT_ACTION } from '../util/constants';
import COLOURS from '../util/COLOURS';

const actionDialogStates = Object.freeze({
none: 'none',
Expand Down Expand Up @@ -151,7 +152,7 @@ const ConfirmActionButton = ({
<div key={facilityMatchToReject.id}>
<li>name: {facilityMatchToReject?.name}</li>
<li>address: {facilityMatchToReject?.address}</li>
<hr color="#E7E8EA" />
<hr color={COLOURS.ACCENT_GREY} />
</div>
))}
</ul>
Expand Down
58 changes: 58 additions & 0 deletions src/react/src/components/Contribute/DialogTooltip.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React, { useState } from 'react';
import { shape, string, node } from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import Tooltip from '@material-ui/core/Tooltip';
import { makeDialogTooltipStyles } from '../../util/styles';

const DialogTooltip = ({ text, childComponent, classes }) => {
const [arrowRef, setArrowRef] = useState(null);
return (
<Tooltip
aria-label={text}
enterDelay={200}
leaveDelay={200}
title={
<>
{text}
<span className={classes.arrow} ref={setArrowRef} />
</>
}
classes={{
tooltip: classes.tooltipStyles,
popper: classes.popperStyles,
tooltipPlacementLeft: classes.placementLeft,
tooltipPlacementRight: classes.placementRight,
tooltipPlacementTop: classes.placementTop,
tooltipPlacementBottom: classes.placementBottom,
}}
PopperProps={{
popperOptions: {
modifiers: {
arrow: {
enabled: Boolean(arrowRef),
element: arrowRef,
},
},
},
}}
>
{childComponent}
</Tooltip>
);
};

DialogTooltip.propTypes = {
text: string.isRequired,
childComponent: node.isRequired,
classes: shape({
arrow: shape({}).isRequired,
tooltipStyles: shape({}).isRequired,
popperStyles: shape({}).isRequired,
placementLeft: shape({}).isRequired,
placementRight: shape({}).isRequired,
placementTop: shape({}).isRequired,
placementBottom: shape({}).isRequired,
}).isRequired,
};

export default withStyles(makeDialogTooltipStyles)(DialogTooltip);
Loading