Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
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
5 changes: 4 additions & 1 deletion doc/release/RELEASE-NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,15 @@ This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html

### Bugfix
* [OSDEV-1747](https://opensupplyhub.atlassian.net/browse/OSDEV-1747) - The pages `My Claimed Facilities`, `Claimed Facility Details`, `My Lists`, and `My Lists/id` are now accessible only to authorized users. Additionally, styles have been refactored, an `InputSelect` component has been moved to the separate file, and input styling on the `Claimed Facility Details` page has been fixed.
* [OSDEV-1830](https://opensupplyhub.atlassian.net/browse/OSDEV-1830) - Updated implementation for `Production Location Info` page to input any values for `Location Type` and `Processing Type`, except when the sector is `Apparel` — in that case, enforce taxonomy filters.

### What's new
* *Describe what's new here. The changes that can impact user experience should be listed in this section.*

### Release instructions:
* *Provide release instructions here.*
* Ensure that the following commands are included in the `post_deployment` command:
* `migrate`
* `reindex_database`


## Release 2.0.0
Expand Down
37 changes: 28 additions & 9 deletions src/react/src/__tests__/components/ProductionLocationInfo.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,19 @@ jest.mock('@material-ui/core/Popper', () => ({ children }) => children);
jest.mock('@material-ui/core/Portal', () => ({ children }) => children);

jest.mock("../../components/Filters/StyledSelect", () => (props) => {
const { options = [], value, onChange, onBlur, placeholder } = props;
const { options = [], value, onChange, onBlur, placeholder, name } = props;

return (
<select
data-testid="mocked-select"
data-testid={`mocked-select-${name}`}
value={value ? value.value : ""}
onChange={(e) => {
const selectedOption = options.find(
(opt) => opt.value === e.target.value,
);
onChange(selectedOption);
onChange(
name === 'country' ? selectedOption : [selectedOption]
);
}}
onBlur={onBlur}
>
Expand Down Expand Up @@ -100,7 +103,7 @@ describe("ProductionLocationInfo component, test input fields for POST v1/produc
expect(addressInput).toBeInTheDocument();
expect(addressInput).toHaveValue("");

const countrySelect = getByTestId("mocked-select");
const countrySelect = getByTestId("mocked-select-country");
expect(countrySelect).toBeInTheDocument();
expect(countrySelect).toHaveValue("");

Expand All @@ -116,7 +119,7 @@ describe("ProductionLocationInfo component, test input fields for POST v1/produc

const nameInput = getByPlaceholderText("Enter the name");
const addressInput = getByPlaceholderText("Enter the full address");
const countrySelect = getByTestId("mocked-select");
const countrySelect = getByTestId("mocked-select-country");

fireEvent.blur(nameInput);
fireEvent.blur(addressInput);
Expand All @@ -137,7 +140,7 @@ describe("ProductionLocationInfo component, test input fields for POST v1/produc

const nameInput = getByPlaceholderText("Enter the name");
const addressInput = getByPlaceholderText("Enter the full address");
const countrySelect = getByTestId("mocked-select");
const countrySelect = getByTestId("mocked-select-country");

fireEvent.change(nameInput, { target: { value: "Test Name" } });
fireEvent.change(addressInput, { target: { value: "Test Address" } });
Expand All @@ -158,9 +161,9 @@ describe("ProductionLocationInfo component, test input fields for POST v1/produc
expect(getByText("Product Type(s)")).toBeInTheDocument();
expect(getByText("Enter the type of products produced at this location. For example: Shirts, Laptops, Solar Panels.")).toBeInTheDocument();
expect(getByText("Location Type(s)")).toBeInTheDocument();
expect(getByText("Select the location type(s) for this production location. For example: Final Product Assembly, Raw Materials Production or Processing, Office/HQ.")).toBeInTheDocument();
expect(getByText("Select or enter the location type(s) for this production location. For example: Final Product Assembly, Raw Materials Production or Processing, Office/HQ.")).toBeInTheDocument();
expect(getByText("Processing Type(s)")).toBeInTheDocument();
expect(getByText("Select the type of processing activities that take place at this location. For example: Printing, Tooling, Assembly.")).toBeInTheDocument();
expect(getByText("Select or enter the type of processing activities that take place at this location. For example: Printing, Tooling, Assembly.")).toBeInTheDocument();
expect(getByText("Number of Workers")).toBeInTheDocument();
expect(getByText("Enter a number or a range for the number of people employed at the location. For example: 100, 100-150.")).toBeInTheDocument();
expect(getByText("Parent Company")).toBeInTheDocument();
Expand All @@ -184,7 +187,7 @@ describe("ProductionLocationInfo component, test input fields for POST v1/produc

const nameInput = getByPlaceholderText("Enter the name");
const addressInput = getByPlaceholderText("Enter the full address");
const countrySelect = getByTestId("mocked-select");
const countrySelect = getByTestId("mocked-select-country");

fireEvent.change(nameInput, { target: { value: "Test Name" } });
fireEvent.change(addressInput, { target: { value: "Test Address" } });
Expand Down Expand Up @@ -268,6 +271,22 @@ describe("ProductionLocationInfo component, test input fields for POST v1/produc

expect(noTooltipElementAfter).toBeInTheDocument();
});

test("displays select or input for location and processing type fields", () => {
const { getByTestId, getByText } = renderComponent();

const switchButton = getByTestId("switch-additional-info-fields");
fireEvent.click(switchButton);

expect(getByText("Enter location type(s)")).toBeInTheDocument();
expect(getByText("Enter processing type(s)")).toBeInTheDocument();

const sectorSelect = getByTestId("mocked-select-sector");
fireEvent.change(sectorSelect, { target: { value: 'Apparel' } });

expect(getByText("Select location type(s)")).toBeInTheDocument();
expect(getByText("Select processing type(s)")).toBeInTheDocument();
});
});

describe("ProductionLocationInfo component, test invalid incoming data for UPDATE v1/production-locations", () => {
Expand Down
109 changes: 74 additions & 35 deletions src/react/src/components/Contribute/ProductionLocationInfo.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ const ProductionLocationInfo = ({
const [nameTouched, setNameTouched] = useState(false);
const [addressTouched, setAddressTouched] = useState(false);
const [countryTouched, setCountryTouched] = useState(false);
const [enabledTaxonomy, setEnabledTaxonomy] = useState(false);
const [sector, setSector] = useState('');
const [productType, setProductType] = useState([]);
const [locationType, setLocationType] = useState(null);
Expand Down Expand Up @@ -400,6 +401,12 @@ const ProductionLocationInfo = ({
moderationID,
]);

useEffect(() => {
setEnabledTaxonomy(
sector.length === 1 && sector[0].value === 'Apparel',
);
}, [sector]);

useEffect(
() => () => {
handleCleanupContributionRecord();
Expand Down Expand Up @@ -595,7 +602,7 @@ const ProductionLocationInfo = ({
</Typography>
<StyledSelect
id="country"
name="Country"
name="country"
aria-label="Country"
options={countriesOptions || []}
value={inputCountry}
Expand Down Expand Up @@ -698,7 +705,7 @@ const ProductionLocationInfo = ({

<StyledSelect
creatable
name="Product Type"
name="product-type"
value={productType}
onChange={setProductType}
placeholder="Enter product type(s)"
Expand All @@ -721,25 +728,40 @@ const ProductionLocationInfo = ({
component="h4"
className={classes.subTitleStyles}
>
Select the location type(s) for this
production location. For example: Final
Product Assembly, Raw Materials
Select or enter the location type(s) for
this production location. For example:
Final Product Assembly, Raw Materials
Production or Processing, Office/HQ.
</Typography>
<StyledSelect
id="location_type"
name="Location type"
aria-label="Location type"
options={mapFacilityTypeOptions(
facilityProcessingTypeOptions || [],
processingType || [],
)}
value={locationType}
onChange={setLocationType}
styles={getSelectStyles()}
className={classes.selectStyles}
placeholder="Select location type(s)"
/>
{enabledTaxonomy ? (
<StyledSelect
id="location_type"
name="location-type"
aria-label="Location type"
options={mapFacilityTypeOptions(
facilityProcessingTypeOptions ||
[],
processingType || [],
)}
value={locationType}
onChange={setLocationType}
styles={getSelectStyles()}
className={classes.selectStyles}
placeholder="Select location type(s)"
/>
) : (
<StyledSelect
creatable
name="location-type"
value={locationType || []}
onChange={setLocationType}
placeholder="Enter location type(s)"
aria-label="Location type"
styles={getSelectStyles()}
className={classes.selectStyles}
components={customSelectComponents}
/>
)}
</div>
<div
className={`${classes.inputSectionWrapStyles} ${classes.wrapStyles}`}
Expand All @@ -754,23 +776,40 @@ const ProductionLocationInfo = ({
component="h4"
className={classes.subTitleStyles}
>
Select the type of processing activities
that take place at this location. For
example: Printing, Tooling, Assembly.
Select or enter the type of processing
activities that take place at this
location. For example: Printing,
Tooling, Assembly.
</Typography>
<StyledSelect
id="processing_type"
name="Processing Type"
aria-label="Processing Type"
options={mapProcessingTypeOptions(
facilityProcessingTypeOptions || [],
locationType || [],
)}
value={processingType}
onChange={setProcessingType}
styles={getSelectStyles()}
className={classes.selectStyles}
/>
{enabledTaxonomy ? (
<StyledSelect
id="processing_type"
name="processing-type"
aria-label="Processing Type"
options={mapProcessingTypeOptions(
facilityProcessingTypeOptions ||
[],
locationType || [],
)}
value={processingType}
onChange={setProcessingType}
styles={getSelectStyles()}
className={classes.selectStyles}
placeholder="Select processing type(s)"
/>
) : (
<StyledSelect
creatable
name="processing-type"
value={processingType || []}
onChange={setProcessingType}
placeholder="Enter processing type(s)"
aria-label="Processing Type"
styles={getSelectStyles()}
className={classes.selectStyles}
components={customSelectComponents}
/>
)}
</div>
<div
className={`${classes.inputSectionWrapStyles} ${classes.wrapStyles}`}
Expand Down