diff --git a/doc/release/RELEASE-NOTES.md b/doc/release/RELEASE-NOTES.md
index ad353f152..34e083ca3 100644
--- a/doc/release/RELEASE-NOTES.md
+++ b/doc/release/RELEASE-NOTES.md
@@ -61,6 +61,7 @@ This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html
All other traffic will be redirected to the React application.
### Bugfix
+* [OSDEV-1700](https://opensupplyhub.atlassian.net/browse/OSDEV-1700) - SLC: Keep only one previous OS ID in the search result if it matches the search query.
* [OSDEV-1697](https://opensupplyhub.atlassian.net/browse/OSDEV-1697) - Added a redirect to the main page upon closing the SLC modal window to prevent the creation of multiple moderation events.
* [OSDEV-1695](https://opensupplyhub.atlassian.net/browse/OSDEV-1695) - [SLC] Enabled the claim button for updated production locations when a moderation event has a pending status. Disabled claim button explicitly if production location has pending claim status.
* [OSDEV-1701](https://opensupplyhub.atlassian.net/browse/OSDEV-1701) - Refactored "Go Back" button in production location info page.
diff --git a/src/react/src/__tests__/components/ProductionLocationDetails.test.js b/src/react/src/__tests__/components/ProductionLocationDetails.test.js
index 471f2c201..92fecd8fe 100644
--- a/src/react/src/__tests__/components/ProductionLocationDetails.test.js
+++ b/src/react/src/__tests__/components/ProductionLocationDetails.test.js
@@ -1,7 +1,13 @@
import React from 'react';
+import { useLocation } from 'react-router-dom';
import ProductionLocationDetails from '../../components/Contribute/ProductionLocationDetails';
import renderWithProviders from '../../util/testUtils/renderWithProviders';
+jest.mock('react-router-dom', () => ({
+ ...jest.requireActual('react-router-dom'),
+ useLocation: jest.fn(),
+}));
+
describe('ProductionLocationDetails component', () => {
const osId = 'US2021250D1DTN7';
const name = 'Production Location Name';
@@ -17,17 +23,26 @@ describe('ProductionLocationDetails component', () => {
historicalOsIds,
};
- test('renders the production location details correctly', () => {
- const { getByText } = renderWithProviders();
-
+ beforeEach(() => {
+ jest.clearAllMocks();
+ useLocation.mockReturnValue({ pathname: '' });
+ });
+
+ test('renders production location details correctly', () => {
+ useLocation.mockReturnValue({
+ pathname: '/contribute/production-location/search/id/US2021250D1DTN7',
+ });
+
+ const { getByText } = renderWithProviders(
+
+ );
+
expect(getByText(name)).toBeInTheDocument();
- expect(getByText(`Current OS ID: ${osId}`)).toBeInTheDocument();
- expect(getByText(`Previous OS ID: ${historicalOsIds[0]}`)).toBeInTheDocument();
- expect(getByText(`Previous OS ID: ${historicalOsIds[1]}`)).toBeInTheDocument();
+ expect(getByText(`OS ID: ${osId}`)).toBeInTheDocument();
expect(getByText(address)).toBeInTheDocument();
expect(getByText(countryName)).toBeInTheDocument();
});
-
+
test('does not render historical OS IDs if the array is empty', () => {
const props = { ...defaultProps, historicalOsIds: [] };
const { getByText, queryByText } = renderWithProviders();
@@ -42,13 +57,54 @@ describe('ProductionLocationDetails component', () => {
expect(getByText(`OS ID: ${osId}`)).toBeInTheDocument();
});
-
- test('renders the tooltip for each historical OS ID', () => {
- const { getAllByTestId } = renderWithProviders();
-
- const tooltips = getAllByTestId('previous-os-id-tooltip');
- expect(tooltips.length).toBe(defaultProps.historicalOsIds.length);
+
+ test('renders previous OS IDs that match the search parameter', () => {
+ useLocation.mockReturnValue({
+ pathname: '/contribute/production-location/search/id/US2020053ZH1RY5',
+ });
+
+ const { getByText } = renderWithProviders(
+
+ );
+
+ expect(getByText(`Current OS ID: ${osId}`)).toBeInTheDocument();
+ expect(getByText('Previous OS ID: US2020053ZH1RY5')).toBeInTheDocument();
});
-});
+ test('does not render previous OS IDs if they do not match the search parameter', () => {
+ useLocation.mockReturnValue({
+ pathname: '/contribute/production-location/search/id/UNKNOWN_OS_ID',
+ });
+
+ const { queryByText } = renderWithProviders(
+
+ );
+
+ expect(queryByText(`Previous OS ID: ${osId}`)).not.toBeInTheDocument();
+ });
+
+ test('renders only "OS ID:" if there are no historical OS IDs', () => {
+ useLocation.mockReturnValue({
+ pathname: '/contribute/production-location/search/id/US2021250D1DTN7',
+ });
+ const { getByText } = renderWithProviders(
+
+ );
+
+ expect(getByText(`OS ID: ${osId}`)).toBeInTheDocument();
+ });
+
+ test('handles missing location pathname gracefully', () => {
+ useLocation.mockReturnValue({});
+
+ const { getByText } = renderWithProviders(
+
+ );
+
+ expect(getByText(`OS ID: ${osId}`)).toBeInTheDocument();
+ });
+});
diff --git a/src/react/src/__tests__/utils.tests.js b/src/react/src/__tests__/utils.tests.js
index 382e341d4..aec2c4bfd 100644
--- a/src/react/src/__tests__/utils.tests.js
+++ b/src/react/src/__tests__/utils.tests.js
@@ -77,6 +77,7 @@ const {
createUserDropdownLinks,
createUploadFormErrorMessages,
updateStateFromData,
+ getLastPathParameter,
generateRangeField,
} = require('../util/util');
@@ -1874,6 +1875,46 @@ it('should not call setter when dataKey is null', () => {
expect(mockSetter).not.toHaveBeenCalled();
});
+it('extracts the ID from a valid URL without a trailing slash', () => {
+ const url = '/contribute/production-location/search/id/BD202034606B9SA';
+ expect(getLastPathParameter(url)).toBe('BD202034606B9SA');
+});
+
+it('extracts the ID from a valid URL with a trailing slash', () => {
+ const url = '/contribute/production-location/search/id/BD202034606B9SA/';
+ expect(getLastPathParameter(url)).toBe('BD202034606B9SA');
+});
+
+it('returns id when the URL ends at "id/" with no ID', () => {
+ const url = '/contribute/production-location/search/id/';
+ expect(getLastPathParameter(url)).toBe('id');
+});
+
+it('returns the correct ID when the URL contains query parameters', () => {
+ const url = '/contribute/production-location/search/id/BD202034606B9SA?foo=bar';
+ expect(getLastPathParameter(url)).toBe('BD202034606B9SA');
+});
+
+it('returns the correct ID when the URL has multiple segments after "id/"', () => {
+ const url = '/contribute/production-location/search/id/BD202034606B9SA/extra';
+ expect(getLastPathParameter(url)).toBe('extra');
+});
+
+it('returns the whole string if no slashes exist', () => {
+ const url = 'BD202034606B9SA';
+ expect(getLastPathParameter(url)).toBe('BD202034606B9SA');
+});
+
+it('returns empty string for an empty string', () => {
+ const url = '';
+ expect(getLastPathParameter(url)).toBe('');
+});
+
+it('returns empty string for a URL that only contains slashes', () => {
+ const url = '///';
+ expect(getLastPathParameter(url)).toBe('');
+});
+
it('should return { min: value, max: value } when value is a number', () => {
expect(generateRangeField(10)).toEqual({ min: 10, max: 10 });
expect(generateRangeField(0)).toEqual({ min: 0, max: 0 });
diff --git a/src/react/src/components/Contribute/ProductionLocationDetails.jsx b/src/react/src/components/Contribute/ProductionLocationDetails.jsx
index 7148042da..1fbc317e1 100644
--- a/src/react/src/components/Contribute/ProductionLocationDetails.jsx
+++ b/src/react/src/components/Contribute/ProductionLocationDetails.jsx
@@ -1,9 +1,11 @@
import React from 'react';
+import { useLocation } from 'react-router-dom';
import { string, arrayOf, object } from 'prop-types';
import { Typography } from '@material-ui/core';
import { withStyles } from '@material-ui/core/styles';
import PreviousOsIdTooltip from './PreviousOsIdTooltip';
import { makeProductionLocationDetailsStyles } from '../../util/styles';
+import { getLastPathParameter } from '../../util/util';
const ProductionLocationDetails = ({
osId,
@@ -13,8 +15,12 @@ const ProductionLocationDetails = ({
historicalOsIds,
classes,
}) => {
- const historicalOsIdsNotEmpty =
- Array.isArray(historicalOsIds) && historicalOsIds.length > 0;
+ const { pathname = '' } = useLocation();
+ const osIdSearchParameter = pathname ? getLastPathParameter(pathname) : '';
+
+ const previousOsId = historicalOsIds.find(
+ historicalOsId => historicalOsId === osIdSearchParameter,
+ );
return (
@@ -25,17 +31,13 @@ const ProductionLocationDetails = ({
component="h6"
className={classes.locationCurrentOsIdStyles}
>
- {historicalOsIdsNotEmpty ? 'Current OS ID:' : 'OS ID:'} {osId}
+ {previousOsId ? 'Current OS ID:' : 'OS ID:'} {osId}
- {historicalOsIdsNotEmpty &&
- historicalOsIds.map(historicalOsId => (
-
- Previous OS ID: {historicalOsId}
-
- ))}
+ {previousOsId && (
+
+ Previous OS ID: {previousOsId}
+
+ )}
{address}
diff --git a/src/react/src/util/styles.js b/src/react/src/util/styles.js
index 37e769018..7b18b3329 100644
--- a/src/react/src/util/styles.js
+++ b/src/react/src/util/styles.js
@@ -1246,6 +1246,9 @@ export const makeProductionLocationDetailsStyles = theme => ({
marginTop: '8px',
}),
locationHistoricalOsIdStyles: Object.freeze({
+ display: 'flex',
+ alignItems: 'center',
+ gap: '5px',
fontSize: '14px',
lineHeight: '20px',
fontWeight: theme.typography.fontWeightBold,
diff --git a/src/react/src/util/util.js b/src/react/src/util/util.js
index be5938d54..3c43a4fba 100644
--- a/src/react/src/util/util.js
+++ b/src/react/src/util/util.js
@@ -4,6 +4,8 @@ import isArray from 'lodash/isArray';
import isObject from 'lodash/isObject';
import flatten from 'lodash/flatten';
import identity from 'lodash/identity';
+import split from 'lodash/split';
+import last from 'lodash/last';
import some from 'lodash/some';
import size from 'lodash/size';
import negate from 'lodash/negate';
@@ -1484,3 +1486,9 @@ export const parseContribData = contribData => {
: null,
};
};
+
+export const getLastPathParameter = url => {
+ if (typeof url !== 'string') return '';
+ const cleanUrl = url.split('?')[0];
+ return last(split(trimEnd(cleanUrl, '/'), '/')) || '';
+};