From a0605da74b565182b0530575da15b042c70b589f Mon Sep 17 00:00:00 2001 From: elsenhans Date: Mon, 15 Dec 2025 14:31:34 +0100 Subject: [PATCH 1/3] UIIN-3558-add-additionalCallNumber-to-versionHistory-for-item --- CHANGELOG.md | 1 + .../ItemVersionHistory/ItemVersionHistory.js | 37 +++++++++++++++++++ src/edit/items/ItemForm.test.js | 8 ++-- translations/ui-inventory/en.json | 5 +++ 4 files changed, 47 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6278931bf..9b9e054b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -82,6 +82,7 @@ UIIN-3437. * ECS | Display item data when user tries to open it from another tenant in the new tab. Fixes UIIN-3528. * *BREAKING* Replace dependency on `mod-configuration` with `mod-settings`. Refs UIIN-3219. * Provide error message if MARC record could not be set for deletion because it was not found. Refs UIIN-3502. +* Include additional cal 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 f77209f80..1f8cec750 100644 --- a/src/Item/ViewItem/components/ItemVersionHistory/ItemVersionHistory.js +++ b/src/Item/ViewItem/components/ItemVersionHistory/ItemVersionHistory.js @@ -137,10 +137,46 @@ const ItemVersionHistory = ({ typeId: formatMessage({ id: 'ui-inventory.callNumberType' }), 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 = (element, i) => { + if (!element) return null; + + const { name: fieldName, value, collectionName } = item; + 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} +
  • + ); + }; + return ( 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 535167122..3adc34dbe 100644 --- a/translations/ui-inventory/en.json +++ b/translations/ui-inventory/en.json @@ -213,6 +213,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", From e15ad7abc31741932ff38da745f5ccf54fc5b69a Mon Sep 17 00:00:00 2001 From: elsenhans Date: Thu, 18 Dec 2025 12:04:01 +0100 Subject: [PATCH 2/3] UIIN-3558-add-additionalCallNumber-to-versionHistory-for-item fix bug --- .../components/ItemVersionHistory/ItemVersionHistory.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Item/ViewItem/components/ItemVersionHistory/ItemVersionHistory.js b/src/Item/ViewItem/components/ItemVersionHistory/ItemVersionHistory.js index 1f8cec750..d55e2299a 100644 --- a/src/Item/ViewItem/components/ItemVersionHistory/ItemVersionHistory.js +++ b/src/Item/ViewItem/components/ItemVersionHistory/ItemVersionHistory.js @@ -155,7 +155,7 @@ const ItemVersionHistory = ({ const itemFormatter = (element, i) => { if (!element) return null; - const { name: fieldName, value, collectionName } = item; + const { name: fieldName, value, collectionName } = element; const compositeKey = collectionName && fieldName ? `${collectionName}.${fieldName}` : null; From df2deb9dd0f7c08cb6494247f6c2923902288541 Mon Sep 17 00:00:00 2001 From: elsenhans Date: Thu, 18 Dec 2025 16:00:30 +0100 Subject: [PATCH 3/3] UIIN-3558-add-additionalCallNumber-to-versionHistory-for-item add createItemFormatter, add tests --- CHANGELOG.md | 2 +- .../ItemVersionHistory/ItemVersionHistory.js | 52 ++++----- .../ItemVersionHistory.test.js | 103 +++++++++++++++++- 3 files changed, 130 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59f777d5e..3fc57d7c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -83,7 +83,7 @@ UIIN-3437. * *BREAKING* Replace dependency on `mod-configuration` with `mod-settings`. Refs UIIN-3219. * Provide error message if MARC record could not be set for deletion because it was not found. Refs UIIN-3502. * Acquisition accordion does not display PO line link after moving holding until page is refreshed. Fixes UIIN-3554. -* Include additional cal numbers in Version History for Inventory Item. Refs UIIN-3558. +* 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 1014cda24..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, @@ -151,31 +177,7 @@ const ItemVersionHistory = ({ }; const fieldFormatter = createFieldFormatter(referenceData, circulationHistory); - - const itemFormatter = (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 itemFormatter = createItemFormatter(fieldLabelsMap, fieldFormatter); return ( { 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'); + }); +});