Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ UIIN-3437.
* When moving item within one holding manually, recalculate other item orders based on their position in the list. Fixes UIIN-3539.
* Handle audit-marc dependency: hide audit button. Refs UIIN-3576.
* Include additional call numbers in Version History for Inventory Item. Refs UIIN-3558.
* Include additional call numbers in Version History for Inventory Holdings. Refs UIIN-3540.

## [13.0.10](https://github.com/folio-org/ui-inventory/tree/v13.0.10) (2025-09-01)
[Full Changelog](https://github.com/folio-org/ui-inventory/compare/v13.0.9...v13.0.10)
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1071,7 +1071,7 @@
"@folio/eslint-config-stripes": "^8.0.0",
"@folio/jest-config-stripes": "^3.0.0",
"@folio/service-interaction": "^4.0.0",
"@folio/stripes": "^10.0.0",
"@folio/stripes": "^10.1.0",
"@folio/stripes-cli": "^4.0.0",
"@folio/stripes-components": "^13.0.0",
"@folio/stripes-connect": "^10.0.0",
Expand Down Expand Up @@ -1124,7 +1124,7 @@
},
"peerDependencies": {
"@folio/service-interaction": "^4.0.0",
"@folio/stripes": "^10.0.0",
"@folio/stripes": "^10.1.0",
"@folio/stripes-erm-components": "^10.0.0",
"@folio/stripes-inventory-components": "^2.0.0",
"@folio/stripes-marc-components": "^2.0.0",
Expand Down
52 changes: 52 additions & 0 deletions src/Holding/HoldingVersionHistory/HoldingVersionHistory.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,31 @@ export const getFieldFormatter = referenceData => ({
publicDisplay: value => value.toString(),
});

export const getItemFormatter = (fieldLabelsMap, fieldFormatter) => (element, i) => {
if (!element) return null;

const { name: fieldName, value, collectionName } = element;
const compositeKey = collectionName && fieldName
? `${collectionName}.${fieldName}`
: null;

const label = (compositeKey && fieldLabelsMap?.[compositeKey])
|| fieldLabelsMap?.[fieldName]
|| fieldLabelsMap?.[collectionName];

const formattedValue = (compositeKey && fieldFormatter?.[compositeKey]?.(value))
|| fieldFormatter?.[fieldName]?.(value)
|| fieldFormatter?.[collectionName]?.(value)
|| value;

return (
<li key={i}>
{fieldName && <strong>{label}: </strong>}
{formattedValue}
</li>
);
};

const HoldingVersionHistory = ({ onClose, holdingId }) => {
const { formatMessage } = useIntl();
const referenceData = useContext(DataContext);
Expand Down Expand Up @@ -81,9 +106,35 @@ const HoldingVersionHistory = ({ onClose, holdingId }) => {
acquisitionMethod: formatMessage({ id: 'ui-inventory.acquisitionMethod' }),
receiptStatus: formatMessage({ id: 'ui-inventory.receiptStatus' }),
entries: formatMessage({ id: 'ui-inventory.receivingHistory' }),
additionalCallNumbers: formatMessage({ id: 'ui-inventory.additionalCallNumbers' }),
'additionalCallNumbers.prefix': formatMessage({ id: 'ui-inventory.additionalCallNumberPrefix' }),
'additionalCallNumbers.suffix': formatMessage({ id: 'ui-inventory.additionalCallNumberSuffix' }),
'additionalCallNumbers.typeId': formatMessage({ id: 'ui-inventory.additionalCallNumberType' }),
'additionalCallNumbers.callNumber': formatMessage({ id: 'ui-inventory.additionalCallNumber' }),
'holdingsStatements.statement': formatMessage({ id: 'ui-inventory.holdingsStatement' }),
'holdingsStatements.note': formatMessage({ id: 'ui-inventory.holdingsStatementPublicNote' }),
'holdingsStatements.staffNote': formatMessage({ id: 'ui-inventory.holdingsStatementStaffNote' }),
'holdingsStatementsForSupplements.statement': formatMessage({ id: 'ui-inventory.holdingsStatementForSupplements' }),
'holdingsStatementsForSupplements.note': formatMessage({ id: 'ui-inventory.holdingsStatementForSupplementsPublicNote' }),
'holdingsStatementsForSupplements.staffNote': formatMessage({ id: 'ui-inventory.holdingsStatementForSupplementsStaffNote' }),
'holdingsStatementsForIndexes.statement': formatMessage({ id: 'ui-inventory.holdingsStatementForIndexes' }),
'holdingsStatementsForIndexes.note': formatMessage({ id: 'ui-inventory.holdingsStatementForIndexesPublicNote' }),
'holdingsStatementsForIndexes.staffNote': formatMessage({ id: 'ui-inventory.holdingsStatementForIndexesStaffNote' }),
'notes.holdingsNoteTypeId': formatMessage({ id: 'ui-inventory.noteType' }),
'notes.note': formatMessage({ id: 'ui-inventory.note' }),
'notes.staffOnly': formatMessage({ id: 'ui-inventory.staffOnly' }),
'electronicAccess.urlRelationship': formatMessage({ id: 'ui-inventory.urlRelationship' }),
'electronicAccess.uri': formatMessage({ id: 'ui-inventory.uri' }),
'electronicAccess.linkText': formatMessage({ id: 'ui-inventory.linkText' }),
'electronicAccess.materialsSpecification': formatMessage({ id: 'ui-inventory.materialsSpecification' }),
'electronicAccess.urlPublicNote': formatMessage({ id: 'ui-inventory.urlPublicNote' }),
'entries.publicDisplay': formatMessage({ id: 'ui-inventory.publicDisplay' }),
'entries.enumeration': formatMessage({ id: 'ui-inventory.enumeration' }),
'entries.chronology': formatMessage({ id: 'ui-inventory.chronology' }),
};

const fieldFormatter = getFieldFormatter(referenceData);
const itemFormatter = getItemFormatter(fieldLabelsMap, fieldFormatter);

return (
<AuditLogPane
Expand All @@ -95,6 +146,7 @@ const HoldingVersionHistory = ({ onClose, holdingId }) => {
isInitialLoading={isLoading}
fieldLabelsMap={fieldLabelsMap}
fieldFormatter={fieldFormatter}
itemFormatter={itemFormatter}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

itemFormatter was added to AuditLogPane in folio-org/stripes-components#2519 and will be available in the next version of @folio/stripes, likely 10.1.0. Since many breaking changes have already been added the next release of ui-inventory, consider bumping the deps on @folio/stripes in package.json to ^10.1.0.

Technically, passing new props to an existing function is backwards compatible; in an older version they'll be ignored but won't cause an error. Ultimately, up to you.

actionsMap={actionsMap}
totalVersions={totalVersions}
/>
Expand Down
85 changes: 84 additions & 1 deletion src/Holding/HoldingVersionHistory/HoldingVersionHistory.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
} from '../../../test/jest/helpers';

import { DataContext } from '../../contexts';
import HoldingVersionHistory, { getFieldFormatter } from './HoldingVersionHistory';
import HoldingVersionHistory, { getFieldFormatter, getItemFormatter } from './HoldingVersionHistory';

jest.mock('@folio/stripes/components', () => ({
...jest.requireActual('@folio/stripes/components'),
Expand Down Expand Up @@ -115,3 +115,86 @@ describe('field formatter', () => {
expect(fieldFormatter.publicDisplay(false)).toBe('false');
});
});

describe('getItemFormatter', () => {
const fieldLabelsMap = {
formerIds: 'Former ID',
additionalCallNumbers: 'Additional call numbers',
notes: 'Notes',
'additionalCallNumbers.prefix': 'Additional call number prefix',
'additionalCallNumbers.suffix': 'Additional call number suffix',
'additionalCallNumbers.typeId': 'Additional call number type',
'additionalCallNumbers.callNumber': 'Additional call number',
'notes.holdingsNoteTypeId': 'Note type',
'notes.note': 'Note',
'notes.staffOnly': 'Staff only',
};

const fieldFormatter = getFieldFormatter(mockReferenceData);
const itemFormatter = getItemFormatter(fieldLabelsMap, fieldFormatter);

it('should return null for null element', () => {
expect(itemFormatter(null, 0)).toBeNull();
});

it('should return null for undefined element', () => {
expect(itemFormatter(undefined, 0)).toBeNull();
});

it('should format field with collectionName using composite key', () => {
const element = {
name: 'staffOnly',
value: false,
collectionName: 'notes',
};

const result = itemFormatter(element, 0);
const { container } = renderWithIntl(result, translationsProperties);

expect(container.querySelector('strong')).toHaveTextContent('Staff only:');
expect(container.querySelector('li')).toHaveTextContent('Staff only: false');
});

it('should fallback to fieldName label when composite key not found', () => {
const element = {
name: 'formerIds',
value: '1123',
collectionName: 'unknownCollection',
};

const result = itemFormatter(element, 0);
const { container } = renderWithIntl(result, translationsProperties);

expect(container.querySelector('strong')).toHaveTextContent('Former ID:');
expect(container.querySelector('li')).toHaveTextContent('Former ID: 1123');
});

it('should fallback to collectionName label when fieldName not found', () => {
const element = {
name: 'unknownField',
value: 'test value',
collectionName: 'notes',
};

const result = itemFormatter(element, 0);
const { container } = renderWithIntl(result, translationsProperties);

expect(container.querySelector('strong')).toHaveTextContent('Notes:');
expect(container.querySelector('li')).toHaveTextContent('Notes: test value');
});

it('should render additionalCallNumbers.prefix with label and value', () => {
const element = {
name: 'prefix',
value: 'ABC',
collectionName: 'additionalCallNumbers',
};

const result = itemFormatter(element, 0);
const { container } = renderWithIntl(result, translationsProperties);

expect(container.querySelector('li'))
.toHaveTextContent('Additional call number prefix: ABC');
});
});

Loading