diff --git a/CHANGELOG.md b/CHANGELOG.md index cfff866ca..422870ab6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ * Browse refactor: Show instance result in third pane when Number of titles = `1`. Refs UIIN-2186. * Optimistic locking error appears when user adds more than 1 tag to "Holdings" record. Fixes UIIN-2242. * Fix holdings view bound-with table also displaying directly linked items. Fixes UIIN-2260. +* Display "Inactive" by inactive locations on instance view. Fixes UIIN-1970. ## [9.2.0](https://github.com/folio-org/ui-inventory/tree/v9.2.0) (2022-10-27) [Full Changelog](https://github.com/folio-org/ui-inventory/compare/v9.1.0...v9.2.0) diff --git a/src/Instance/HoldingsList/Holding/HoldingAccordion.js b/src/Instance/HoldingsList/Holding/HoldingAccordion.js index 927132977..d7c198f60 100644 --- a/src/Instance/HoldingsList/Holding/HoldingAccordion.js +++ b/src/Instance/HoldingsList/Holding/HoldingAccordion.js @@ -30,7 +30,8 @@ const HoldingAccordion = ({ }; const { locationsById } = useContext(DataContext); - const labelLocation = locationsById[holding.permanentLocationId]?.name ?? ''; + const labelLocation = locationsById[holding.permanentLocationId]; + const labelLocationName = labelLocation?.name ?? ''; const [open, setOpen] = useState(false); const [openFirstTime, setOpenFirstTime] = useState(false); const { totalRecords, isFetching } = useHoldingItemsQuery(holding.id, { searchParams, key: 'itemCount' }); @@ -54,6 +55,15 @@ const HoldingAccordion = ({ isOpen={open} />; + const location = labelLocation?.isActive ? + labelLocationName : + ; + return ( ( - {() => null} + <> @@ -49,6 +59,13 @@ describe('HoldingAccordion', () => { jest.clearAllMocks(); }); + it('should display "inactive" if applicable in the accordion header', async () => { + await waitFor(() => { + const accordionSection = document.querySelector('*[data-test-accordion-section=true]').innerHTML; + expect(accordionSection).toContain('Inactive'); + }); + }); + it('should render items counter', () => { expect(screen.getByText('3')).toBeInTheDocument(); }); diff --git a/src/Instance/ItemsList/ItemsList.js b/src/Instance/ItemsList/ItemsList.js index 4f6561333..0ba7e3424 100644 --- a/src/Instance/ItemsList/ItemsList.js +++ b/src/Instance/ItemsList/ItemsList.js @@ -3,6 +3,7 @@ import React, { useCallback, useState, useEffect, + useContext, } from 'react'; import PropTypes from 'prop-types'; import { @@ -27,8 +28,12 @@ import { } from './utils'; import useBoundWithHoldings from '../../Holding/ViewHolding/HoldingBoundWith/useBoundWithHoldings'; +import { DataContext } from '../../contexts'; + const getTableAria = (intl) => intl.formatMessage({ id: 'ui-inventory.items' }); const getFormatter = ( + intl, + locationsById, holding, holdingsMapById, selectItemsForDrag, @@ -81,7 +86,15 @@ const getFormatter = ( 'copyNumber': ({ copyNumber }) => copyNumber || noValue, 'materialType': x => x.materialType?.name || noValue, 'loanType': x => x.temporaryLoanType?.name || x.permanentLoanType?.name || noValue, - 'effectiveLocation': x => x.effectiveLocation?.name || noValue, + 'effectiveLocation': x => { + const effectiveLocation = locationsById[x.effectiveLocation?.id]; + return effectiveLocation?.isActive ? + effectiveLocation?.name || noValue : + intl.formatMessage( + { id: 'ui-inventory.inactive.gridCell' }, + { location: effectiveLocation?.name } + ); + }, 'enumeration': x => x.enumeration || noValue, 'chronology': x => x.chronology || noValue, 'volume': x => x.volume || noValue, @@ -145,6 +158,7 @@ const ItemsList = ({ }); const [records, setRecords] = useState([]); const [paginatedItems, setPaginatedItems] = useState([]); + const { locationsById } = useContext(DataContext); const ariaLabel = useMemo(() => getTableAria(intl), []); const columnMapping = useMemo( @@ -152,7 +166,7 @@ const ItemsList = ({ [holding.id, records, isItemsDragSelected, selectItemsForDrag], ); const formatter = useMemo( - () => getFormatter(holding, holdingsMapById, selectItemsForDrag, isItemsDragSelected), + () => getFormatter(intl, locationsById, holding, holdingsMapById, selectItemsForDrag, isItemsDragSelected), [holding, holdingsMapById, selectItemsForDrag, isItemsDragSelected], ); const rowProps = useMemo(() => ({ diff --git a/src/Instance/ItemsList/tests/ItemsList.test.js b/src/Instance/ItemsList/tests/ItemsList.test.js new file mode 100644 index 000000000..88a8281d3 --- /dev/null +++ b/src/Instance/ItemsList/tests/ItemsList.test.js @@ -0,0 +1,73 @@ +import React from 'react'; +import { QueryClient, QueryClientProvider } from 'react-query'; +import { BrowserRouter as Router } from 'react-router-dom'; +import { act } from 'react-dom/test-utils'; +import { screen } from '@testing-library/react'; + +import '../../../../test/jest/__mock__'; + +import DataContext from '../../../contexts/DataContext'; + +import { items as itemsFixture } from '../../../../test/fixtures/items'; +import { holdingsRecords as holdingsRecordsFixture } from '../../../../test/fixtures/holdingsRecords'; +import renderWithIntl from '../../../../test/jest/helpers/renderWithIntl'; +import translations from '../../../../test/jest/helpers/translationsProperties'; +import ItemsList from '../ItemsList'; +import useHoldingItemsQuery from '../../../hooks/useHoldingItemsQuery'; + +jest.mock('../../../hooks/useHoldingItemsQuery', () => jest.fn()); + +const queryClient = new QueryClient(); + +const locations = { + 'fcd64ce1-6995-48f0-840e-89ffa2288371': + { + id: 'fcd64ce1-6995-48f0-840e-89ffa2288371', + name: 'Main Library', + isActive: true, + }, + 'fcd64ce1-6995-48f0-840e-89ffa2288372' : + { + id: 'fcd64ce1-6995-48f0-840e-89ffa2288372', + name: 'Annex', + isActive: false, + }, +}; + +const ItemsListSetup = () => ( + + + + false} + selectItemsForDrag={(_) => {}} + getDraggingItems={jest.fn()} + draggable={false} + /> + + + +); + +describe('ItemsList', () => { + beforeEach(async () => { + useHoldingItemsQuery.mockReturnValue({ + isFetching: false, + totalRecords: itemsFixture.length, + }); + + await act(async () => { + await renderWithIntl(, translations); + }); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should display "inactive" by a location if applicable', () => { + expect(screen.queryByText('Inactive')).toBeInTheDocument(); + }); +}); diff --git a/src/components/InstanceFilters/InstanceFiltersBrowse/instanceFiltersBrowse.test.js b/src/components/InstanceFilters/InstanceFiltersBrowse/instanceFiltersBrowse.test.js index 2984fcc47..04032cf0d 100644 --- a/src/components/InstanceFilters/InstanceFiltersBrowse/instanceFiltersBrowse.test.js +++ b/src/components/InstanceFilters/InstanceFiltersBrowse/instanceFiltersBrowse.test.js @@ -10,6 +10,7 @@ import { ModuleHierarchyProvider } from '@folio/stripes-core/src/components/Modu import '../../../../test/jest/__mock__'; import renderWithIntl from '../../../../test/jest/helpers/renderWithIntl'; +import translations from '../../../../test/jest/helpers/translationsProperties'; import InstanceFiltersBrowse from './InstanceFiltersBrowse'; @@ -64,15 +65,17 @@ const renderInstanceFilters = (props = {}) => { {...props} /> - + , + translations ); }; describe('InstanceFilters', () => { it('Contains a filter for creation date ', () => { - renderInstanceFilters(); + const { debug } = renderInstanceFilters(); - expect(screen.getByText('ui-inventory.filters.effectiveLocation')).toBeInTheDocument(); + debug(); + expect(screen.getByText('Effective location (item)')).toBeInTheDocument(); }); describe('When contributors browseType was selected', () => { diff --git a/test/fixtures/holdingsRecords.js b/test/fixtures/holdingsRecords.js new file mode 100644 index 000000000..5bbacfb8f --- /dev/null +++ b/test/fixtures/holdingsRecords.js @@ -0,0 +1,5 @@ +export const holdingsRecords = [ + { + id: '44a21d17-a666-4f34-b24d-644f8ed1537b', + } +]; diff --git a/test/fixtures/items.js b/test/fixtures/items.js index 6023dbad5..89c104035 100644 --- a/test/fixtures/items.js +++ b/test/fixtures/items.js @@ -102,7 +102,8 @@ export const items = [ id: 'fcd64ce1-6995-48f0-840e-89ffa2288371', name: 'Main Library', }, - }, { + }, + { id: '6abd8dfe-0234-4256-b2e6-539499999cac', status: { name: 'Paged', diff --git a/test/jest/__mock__/index.js b/test/jest/__mock__/index.js index 76472897b..be8d0d50f 100644 --- a/test/jest/__mock__/index.js +++ b/test/jest/__mock__/index.js @@ -9,3 +9,4 @@ import './stripesSmartComponents.mock'; import './InstancePlugin.mock'; import './quickMarc.mock'; import './stripesComponents.mock'; +import './reactBeautifulDnd.mock'; diff --git a/test/jest/__mock__/reactBeautifulDnd.mock.js b/test/jest/__mock__/reactBeautifulDnd.mock.js new file mode 100644 index 000000000..83eb141e0 --- /dev/null +++ b/test/jest/__mock__/reactBeautifulDnd.mock.js @@ -0,0 +1,15 @@ +jest.mock('react-beautiful-dnd', () => ({ + Droppable: ({ children }) => children({ + draggableProps: { + style: {}, + }, + innerRef: jest.fn(), + }, {}), + Draggable: ({ children }) => children({ + draggableProps: { + style: {}, + }, + innerRef: jest.fn(), + }, {}), + DragDropContext: ({ children }) => children, +})); diff --git a/test/jest/helpers/Harness.js b/test/jest/helpers/Harness.js index f83851c76..6e8649f71 100644 --- a/test/jest/helpers/Harness.js +++ b/test/jest/helpers/Harness.js @@ -1,5 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; +import { noop } from 'lodash'; import { IntlProvider } from 'react-intl'; import { CalloutContext } from '@folio/stripes/core'; @@ -24,12 +25,21 @@ const Harness = ({ mockOffsetSize(width, height); } + const defaultRichTextElements = ['b', 'i', 'em', 'strong', 'span', 'div', 'p', 'ul', 'ol', 'li', 'code'].reduce((res, Tag) => { + res[Tag] = chunks => {chunks}; + + return res; + }, {}); + return ( { } }}> {children} diff --git a/translations/ui-inventory/en.json b/translations/ui-inventory/en.json index 3cd4650b7..ac9904e8d 100644 --- a/translations/ui-inventory/en.json +++ b/translations/ui-inventory/en.json @@ -146,6 +146,7 @@ "temporary": "Temporary", "inactive": "Inactive", "inactive.paneTitle": "Inactive {location}", + "inactive.gridCell": "Inactive {location}", "selectPermanenLocation": "Select permanent location", "statisticalCodes": "Statistical codes", "statisticalCode": "Statistical code", @@ -359,7 +360,7 @@ "alternativeTitleType": "Alternative title type", "materialType": "Material type", "materialTypeRequired": "Material type *", - "holdingsHeader": "Holdings: {location} > {callNumber} {copyNumber}", + "holdingsHeader": "Holdings: {location} > {callNumber} {copyNumber}", "holdingsDetails": "Holdings details", "numberOfItems": "Number of items", "acquisitions": "Acquisitions",