Skip to content
20 changes: 3 additions & 17 deletions doc/release/RELEASE-NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html
* *Describe high-level database changes.*

#### Migrations:
* *Describe migrations here.*
* 0168_introduce_show_additional_identifiers_switch.py - This migration introduces a new switch called `show_additional_identifiers`, which will be used on the production location profile page to show or hide additional identifiers of the production location.

#### Schema changes
* *Describe schema changes here.*
Expand All @@ -26,12 +26,13 @@ This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html

### Bugfix
* [OSDEV-1943](https://opensupplyhub.atlassian.net/browse/OSDEV-1943) - Fixed flickering behavior when opening the SLC form to contribute to an existing production location by marking fields as touched if they match the fetched data, ensuring smoother UI during re-renders.
* [OSDEV-1930](https://opensupplyhub.atlassian.net/browse/OSDEV-1930) - Updated the styles of primary and secondary text in the data points UI and the location details contributor drawer on the location profile page, as well as the hash in the React error boundary component, to prevent overflow on the page or within its field location. Replaced the deprecated `word-wrap` CSS property with the supported `overflow-wrap` CSS property.
* [OSDEV-1914](https://opensupplyhub.atlassian.net/browse/OSDEV-1914) - The following changes have been made:
* Fixed an issue with fuzzy search on fields containing long text. Replaced the `match` query with `match_phrase` (with a configurable `slop` parameter) for such cases to improve accuracy for the GET `/api/v1/production-locations/` endpoint.
* Replaced regular text with a toast component to display server errors when fetching potential matches on the Contribution Record page of the Moderation queue dashboard.

### What's new
* *Describe what's new here. The changes that can impact user experience should be listed in this section.*
* [OSDEV-1930](https://opensupplyhub.atlassian.net/browse/OSDEV-1930) - Implemented front-end logic to display additional identifiers such as RBA, LEI, and DUNS IDs as data points on the production location profile page, once the `show_additional_identifiers` feature flag is returned with a true value from the backend.

### Release instructions:
* Ensure that the following commands are included in the `post_deployment` command:
Expand Down Expand Up @@ -176,21 +177,6 @@ Also was added sanitization on the server side by using the `Django-Bleach` libr
* Product name: Open Supply Hub
* Release date: March 8, 2025

### Database changes
* *Describe high-level database changes.*

#### Migrations:
* *Describe migrations here.*

#### Schema changes
* *Describe schema changes here.*

### Code/API changes
* *Describe code/API changes here.*

### Architecture/Environment changes
* *Describe architecture/environment changes here.*

### Bugfix
* [OSDEV-1777](https://opensupplyhub.atlassian.net/browse/OSDEV-1777) - A consistent URL style was established across all pages of the SLC workflow. After the changes, the URL begins from `/contribute/single-location/`.
* [OSDEV-1678](https://opensupplyhub.atlassian.net/browse/OSDEV-1678) - Added asterisks next to each required form field (Name, Address, and Country) on the "Production Location Information" page. Highlighted an empty field and displayed an error message if it loses focus.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Generated by Django 3.2.17 on 2025-04-18 14:00

from django.db import migrations


class Migration(migrations.Migration):
def create_show_additional_identifiers_switch(apps, schema_editor):
Switch = apps.get_model('waffle', 'Switch')
Switch.objects.create(name='show_additional_identifiers',
active=False)

def delete_show_additional_identifiers_switch(apps, schema_editor):
Switch = apps.get_model('waffle', 'Switch')
Switch.objects.get(name='show_additional_identifiers').delete()

dependencies = [
('api', '0167_add_moderationevent_action_reason_text_fields'),
]

operations = [
migrations.RunPython(
create_show_additional_identifiers_switch,
delete_show_additional_identifiers_switch
)
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
import React from 'react';
import renderWithProviders from '../../util/testUtils/renderWithProviders';
import FacilityDetailsGeneralFields from '../../components/FacilityDetailsGeneralFields';

describe('FacilityDetailsGeneralFields component: test rendering of additional identifiers', () => {
const mockData = {
id: 'US202510850SQCV',
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [-73.8314318, 40.762569],
},
properties: {
name: 'Nice production location LTD',
country_code: 'US',
os_id: 'US202510850SQCV',
other_names: [],
contributors: [
{
id: 1139,
name: 'Test Org (Test list)',
is_verified: false,
contributor_name: 'Test Org',
list_name: 'Test list',
},
],
country_name: 'United States',
claim_info: null,
other_locations: [],
is_closed: null,
activity_reports: [],
contributor_fields: [],
new_os_id: null,
has_inexact_coordinates: false,
extended_fields: {
name: [
{
value: 'Nice production location LTD',
field_name: 'name',
contributor_id: 1139,
contributor_name: 'Test Org',
updated_at: '2025-04-18T11:25:32.798875Z',
created_at: '2025-04-18T11:21:15.877648Z',
},
],
number_of_workers: [],
native_language_name: [],
facility_type: [],
processing_type: [],
product_type: [],
parent_company: [
{
id: 3394113,
is_verified: false,
value: {
name: 'Moon company',
raw_value: 'Moon company',
},
created_at: '2025-04-18T11:21:15.940646Z',
updated_at: '2025-04-18T11:25:32.885850Z',
contributor_name: 'Test Org',
contributor_id: 1139,
value_count: 1,
is_from_claim: false,
field_name: 'parent_company',
verified_count: 0,
},
],
duns_id: [
{
id: 83087,
is_verified: false,
value: {
raw_value: 2120383532,
},
created_at: '2022-04-01T10:49:15.174025Z',
updated_at: '2022-04-01T10:58:25.043413Z',
contributor_name: 'Test Org',
contributor_id: 1139,
value_count: 1,
is_from_claim: false,
field_name: 'duns_id',
verified_count: 0,
},
],
lei_id: [
{
id: 83087,
is_verified: false,
value: {
raw_value: '529900T8BM49AURSDO55',
},
created_at: '2022-04-01T10:49:15.174025Z',
updated_at: '2022-04-01T10:58:25.043413Z',
contributor_name: 'Test Org',
contributor_id: 1139,
value_count: 1,
is_from_claim: false,
field_name: 'lei_id',
verified_count: 0,
},
],
rba_id: [
{
id: 83087,
is_verified: false,
value: {
raw_value:
'F342E6157BD84B70AB40BF9A6C0C19E1F342E6157BD84B70AB40BF9A6C0C19E1F342E6157BD84B70AB40BF9A6C0C19E1F342E6157BD84B70AB40BF9A6C0C19E1F342E6157BD84B70AB40BF9A6C0C19E1F342E6157BD84B70AB40BF9A6C0C19E',
},
created_at: '2022-04-01T10:49:15.174025Z',
updated_at: '2022-04-01T10:58:25.043413Z',
contributor_name: 'Test Org',
contributor_id: 1139,
value_count: 1,
is_from_claim: false,
field_name: 'rba_id',
verified_count: 0,
},
],
},
created_from: {
created_at: '2025-04-18T11:21:15.877648Z',
contributor: 'Test Org',
},
sector: [
{
updated_at: '2025-04-18T11:25:32.798875Z',
contributor_id: 1139,
contributor_name: 'Test Org',
values: ['Unspecified'],
is_from_claim: false,
created_at: '2025-04-18T11:21:15.877648Z',
},
],
is_claimed: false,
},
};

const handleFormat = ({ value, formatValue }) => ({
primary: formatValue(value),
});

const defaultProps = {
data: mockData,
nameField: { primary: 'Nice production location LTD' },
otherNames: [],
embed: false,
embedConfig: {},
formatExtendedField: handleFormat,
formatIfListAndRemoveDuplicates: jest.fn(),
hideSectorData: false,
isClaimed: false,
};

test('renders only non-additional identifier extended fields when the show_additional_identifiers feature flag is false', () => {
const preloadedState = {
featureFlags: {
fetching: false,
flags: {
show_additional_identifiers: false,
},
},
};
const {
getByText,
queryByText,
} = renderWithProviders(
<FacilityDetailsGeneralFields {...defaultProps} />,
{ preloadedState },
);

expect(getByText('Name')).toBeInTheDocument();
expect(getByText('Nice production location LTD')).toBeInTheDocument();
expect(getByText('Parent Company')).toBeInTheDocument();
expect(getByText('Moon company')).toBeInTheDocument();

expect(queryByText('LEI ID')).not.toBeInTheDocument();
expect(queryByText('RBA ID')).not.toBeInTheDocument();
expect(queryByText('DUNS ID')).not.toBeInTheDocument();
});

test('renders all extended fields when the show_additional_identifiers feature flag is true', () => {
const preloadedState = {
featureFlags: {
fetching: false,
flags: {
show_additional_identifiers: true,
},
},
};
const { getByText } = renderWithProviders(
<FacilityDetailsGeneralFields {...defaultProps} />,
{ preloadedState },
);

expect(getByText('Name')).toBeInTheDocument();
expect(getByText('Nice production location LTD')).toBeInTheDocument();
expect(getByText('Parent Company')).toBeInTheDocument();
expect(getByText('Moon company')).toBeInTheDocument();

expect(getByText('LEI ID')).toBeInTheDocument();
expect(getByText('2120383532')).toBeInTheDocument();
expect(getByText('RBA ID')).toBeInTheDocument();
expect(getByText('529900T8BM49AURSDO55')).toBeInTheDocument();
expect(getByText('DUNS ID')).toBeInTheDocument();
expect(
getByText(
'F342E6157BD84B70AB40BF9A6C0C19E1F342E6157BD84B70AB40BF9A6C0C19E1F342E6157BD84B70AB40BF9A6C0C19E1F342E6157BD84B70AB40BF9A6C0C19E1F342E6157BD84B70AB40BF9A6C0C19E1F342E6157BD84B70AB40BF9A6C0C19E',
),
).toBeInTheDocument();
});
});
2 changes: 1 addition & 1 deletion src/react/src/components/ErrorBoundary.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const styles = {
background: '#e6e6e6',
padding: '20px',
width: '100%',
wordWrap: 'break-word',
overflowWrap: 'break-word',
margin: 'auto',
fontSize: '12px',
letterSpacing: '1px',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const contributorsDrawerStyles = theme =>
paddingBottom: theme.spacing.unit,
},
primaryText: {
wordWrap: 'break-word',
overflowWrap: 'break-word',
},
link: {
color: theme.palette.primary.main,
Expand Down
4 changes: 2 additions & 2 deletions src/react/src/components/FacilityDetailsDetail.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ const detailsStyles = theme =>
paddingTop: theme.spacing.unit,
},
primaryText: {
wordWrap: 'break-word',
overflowWrap: 'anywhere',
fontWeight: 500,
fontSize: '18px',
lineHeight: '21px',
paddingTop: theme.spacing.unit,
},
secondaryText: {
wordWrap: 'break-word',
overflowWrap: 'anywhere',
fontWeight: 500,
fontSize: '14px',
lineHeight: '17px',
Expand Down
23 changes: 20 additions & 3 deletions src/react/src/components/FacilityDetailsGeneralFields.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ import { formatAttribution } from '../util/util';

import {
EXTENDED_FIELD_TYPES,
ADDITIONAL_IDENTIFIERS,
CLAIM_A_FACILITY,
REPORT_A_FACILITY,
SHOW_ADDITIONAL_IDENTIFIERS,
} from '../util/constants';

const locationFieldsStyles = theme =>
Expand Down Expand Up @@ -162,6 +164,23 @@ const FacilityDetailsLocationFields = ({
[data],
);

const renderExtendedFields = () => {
const extendedFieldsWithoutAdditionalIdentifiers = EXTENDED_FIELD_TYPES.filter(
field => !ADDITIONAL_IDENTIFIERS.includes(field.fieldName),
);

return (
<FeatureFlag
flag={SHOW_ADDITIONAL_IDENTIFIERS}
alternative={extendedFieldsWithoutAdditionalIdentifiers.map(
renderExtendedField,
)}
>
{EXTENDED_FIELD_TYPES.map(renderExtendedField)}
</FeatureFlag>
);
};

return (
<div className={classes.root}>
<div className={classes.contentContainer}>
Expand All @@ -184,9 +203,7 @@ const FacilityDetailsLocationFields = ({
/>
</Grid>
)}
{embed
? renderEmbedFields()
: EXTENDED_FIELD_TYPES.map(renderExtendedField)}
{embed ? renderEmbedFields() : renderExtendedFields()}
<FeatureFlag flag={REPORT_A_FACILITY}>
<ShowOnly when={!!activityReport}>
<FacilityDetailsItem
Expand Down
Loading
Loading