diff --git a/CHANGELOG.md b/CHANGELOG.md index 67c56f59c..bc9bdfe4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -86,6 +86,7 @@ UIIN-3437. * Wrong message is displayed after updating ownership of item. Fixes UIIN-3560. * 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. ## [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) diff --git a/src/Item/ViewItem/components/ItemVersionHistory/ItemVersionHistory.js b/src/Item/ViewItem/components/ItemVersionHistory/ItemVersionHistory.js index 3254e94b0..d35de7b80 100644 --- a/src/Item/ViewItem/components/ItemVersionHistory/ItemVersionHistory.js +++ b/src/Item/ViewItem/components/ItemVersionHistory/ItemVersionHistory.js @@ -58,6 +58,32 @@ export const createFieldFormatter = (referenceData, circulationHistory) => ({ }, }); +export const createItemFormatter = (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 ( +
  • + {fieldName && {label}: } + {formattedValue} +
  • + ); +}; + + const ItemVersionHistory = ({ item, onClose, @@ -137,9 +163,21 @@ const ItemVersionHistory = ({ typeId: formatMessage({ id: 'ui-inventory.effectiveCallNumberType' }), volume: formatMessage({ id: 'ui-inventory.volume' }), yearCaption: formatMessage({ id: 'ui-inventory.yearCaption' }), + 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' }), + 'circulationNotes.noteType': formatMessage({ id: 'ui-inventory.noteType' }), + 'circulationNotes.note': formatMessage({ id: 'ui-inventory.note' }), + 'circulationNotes.id': formatMessage({ id: 'ui-inventory.identifier' }), + 'circulationNotes.date': formatMessage({ id: 'ui-inventory.date' }), + 'circulationNotes.staffOnly': formatMessage({ id: 'ui-inventory.staffOnly' }), + 'circulationNotes.source': formatMessage({ id: 'ui-inventory.source' }), }; const fieldFormatter = createFieldFormatter(referenceData, circulationHistory); + const itemFormatter = createItemFormatter(fieldLabelsMap, fieldFormatter); return ( diff --git a/src/Item/ViewItem/components/ItemVersionHistory/ItemVersionHistory.test.js b/src/Item/ViewItem/components/ItemVersionHistory/ItemVersionHistory.test.js index 07e8da29a..16c378b0b 100644 --- a/src/Item/ViewItem/components/ItemVersionHistory/ItemVersionHistory.test.js +++ b/src/Item/ViewItem/components/ItemVersionHistory/ItemVersionHistory.test.js @@ -11,7 +11,7 @@ import { translationsProperties, } from '../../../../../test/jest/helpers'; -import ItemVersionHistory, { createFieldFormatter } from './ItemVersionHistory'; +import ItemVersionHistory, { createFieldFormatter, createItemFormatter } from './ItemVersionHistory'; import { DataContext } from '../../../../contexts'; import { @@ -278,3 +278,104 @@ describe('createFieldFormatter', () => { expect(fieldFormatter.source({ personal: { lastName: 'Doe' } })).toBe('Doe'); }); }); + +describe('createItemFormatter', () => { + const fieldLabelsMap = { + barcode: 'Item Barcode', + discoverySuppress: 'Discovery Suppress', + circulationNotes: 'Circulation History', + 'additionalCallNumbers.prefix': 'Additional call number prefix', + 'additionalCallNumbers.suffix': 'Additional call number suffix', + 'additionalCallNumbers.typeId': 'Additional call number type', + 'additionalCallNumbers.callNumber': 'Additional call number', + 'circulationNotes.staffOnly': 'Staff Only', + 'circulationNotes.note': 'Note', + 'circulationNotes.noteType': 'Note Type', + materialTypeId: 'Material Type', + }; + + const fieldFormatter = createFieldFormatter(mockReferenceData, { + servicePointName: 'Main Desk', + source: 'Librarian User', + }); + + const itemFormatter = createItemFormatter(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: 'circulationNotes', + }; + + 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: 'discoverySuppress', + value: true, + collectionName: 'unknownCollection', + }; + + const result = itemFormatter(element, 0); + const { container } = renderWithIntl(result, translationsProperties); + + expect(container.querySelector('strong')).toHaveTextContent('Discovery Suppress:'); + expect(container.querySelector('li')).toHaveTextContent('Discovery Suppress: true'); + }); + + it('should fallback to collectionName label when fieldName not found', () => { + const element = { + name: 'unknownField', + value: 'test value', + collectionName: 'circulationNotes', + }; + + const result = itemFormatter(element, 0); + const { container } = renderWithIntl(result, translationsProperties); + + expect(container.querySelector('strong')).toHaveTextContent('Circulation History:'); + expect(container.querySelector('li')).toHaveTextContent('Circulation History: 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'); + }); + + it('should render circulationNotes.note with label and value', () => { + const element = { + name: 'note', + value: 'Damaged cover', + collectionName: 'circulationNotes', + }; + + const result = itemFormatter(element, 0); + const { container } = renderWithIntl(result, translationsProperties); + + expect(container.querySelector('li')) + .toHaveTextContent('Note: Damaged cover'); + }); +}); diff --git a/src/edit/items/ItemForm.test.js b/src/edit/items/ItemForm.test.js index f821c680e..7f429f952 100644 --- a/src/edit/items/ItemForm.test.js +++ b/src/edit/items/ItemForm.test.js @@ -258,7 +258,7 @@ describe('ItemForm', () => { ...mockReferenceTables, callNumberTypes: [{ id: '1', name: 'Library of Congress classification' }], }; - const { getByText, getAllByText, queryByText } = renderItemForm({ + const { getByText, getAllByText } = renderItemForm({ initialValues, referenceTables, }); @@ -291,9 +291,9 @@ describe('ItemForm', () => { 'itemLevelCallNumberTypeId': { value: '2' }, 'additionalCallNumbers': { value: [{ - callNumber: 'cn1', - prefix: 'prefix1', - suffix: 'suffix1', + additionalCallNumber: 'cn1', + additionalCallNumberPrefix: 'prefix1', + additionalCallNumberSuffix: 'suffix1', typeId: '1' }] } diff --git a/translations/ui-inventory/en.json b/translations/ui-inventory/en.json index 5667e6d83..965623bdd 100644 --- a/translations/ui-inventory/en.json +++ b/translations/ui-inventory/en.json @@ -216,6 +216,11 @@ "callNumberPrefix": "Call number prefix", "callNumberSuffix": "Call number suffix", "primaryItemCallNumber": "Primary item call number", + "additionalCallNumbers": "Additional call numbers", + "additionalCallNumber": "Additional call number", + "additionalCallNumberPrefix": "Additional call number prefix", + "additionalCallNumberSuffix": "Additional call number suffix", + "additionalCallNumberType": "Additional call number type", "additionalItemCallNumbers": "Additional item call numbers", "primaryHoldingsCallNumber": "Primary holdings call number", "additionalHoldingsCallNumbers": "Additional holdings call numbers",