From 808f6e434af6a285e5623d55cd896a30069294db Mon Sep 17 00:00:00 2001 From: Michal Kuklis Date: Mon, 29 May 2023 20:36:23 -0400 Subject: [PATCH 1/8] UIIN-2384: Move search filters to stripes-inventory-components --- src/common/hooks/useFacets.js | 229 ------- src/common/hooks/useFacets.test.js | 312 ---------- src/components/CheckboxFacet/CheckboxFacet.js | 142 ----- .../CheckboxFacet/CheckboxFacet.test.js | 191 ------ .../CheckboxFacet/CheckboxFacetList.css | 27 - .../CheckboxFacet/CheckboxFacetList.js | 123 ---- .../CheckboxFacet/CheckboxFacetList.test.js | 128 ---- src/components/CheckboxFacet/index.js | 1 - .../DateRangeFilter/DateRangeFilter.js | 39 -- src/components/DateRangeFilter/index.js | 1 - .../FacetOptionFormatter.css | 7 - .../FacetOptionFormatter.js | 34 -- .../FacetOptionFormatter.test.js | 32 - src/components/FacetOptionFormatter/index.js | 2 - .../HoldingsRecordFilters.js | 308 ---------- .../HoldingsRecordFilters.test.js | 70 --- .../holdingsRecordFilterRenderer.js | 44 -- .../holdingsRecordFilterRenderer.test.js | 118 ---- src/components/HoldingsRecordFilters/index.js | 2 - .../InstanceFilters/InstanceFilters.js | 441 -------------- .../InstanceFilters/InstanceFilters.test.js | 208 ------- .../InstanceFiltersBrowse.js | 138 ----- .../InstanceFiltersBrowse/index.js | 1 - .../instanceFiltersBrowse.test.js | 107 ---- src/components/InstanceFilters/index.js | 3 - .../InstanceFilters/instanceFilterRenderer.js | 54 -- src/components/InstanceFilters/languages.js | 561 ------------------ src/components/ItemFilters/ItemFilters.js | 309 ---------- .../ItemFilters/ItemsFilters.test.js | 66 --- src/components/ItemFilters/index.js | 2 - .../ItemFilters/itemFilterRenderer.js | 45 -- .../ItemFilters/itemFilterRenderer.test.js | 46 -- .../MultiSelectionFacet.js | 106 ---- .../MultiSelectionFacet.test.js | 66 --- src/components/MultiSelectionFacet/index.js | 2 - src/components/TagsFilter/TagsFilter.js | 73 --- src/components/TagsFilter/TagsFilter.test.js | 106 ---- src/components/TagsFilter/index.js | 1 - src/facetUtils.js | 252 -------- src/facetUtils.test.js | 263 -------- src/filterConfig.js | 341 ----------- src/routes/InstancesRoute.js | 3 +- src/stores/facetsStore.js | 42 -- src/stores/facetsStore.test.js | 55 -- src/withFacets.js | 182 ------ 45 files changed, 1 insertion(+), 5282 deletions(-) delete mode 100644 src/common/hooks/useFacets.js delete mode 100644 src/common/hooks/useFacets.test.js delete mode 100644 src/components/CheckboxFacet/CheckboxFacet.js delete mode 100644 src/components/CheckboxFacet/CheckboxFacet.test.js delete mode 100644 src/components/CheckboxFacet/CheckboxFacetList.css delete mode 100644 src/components/CheckboxFacet/CheckboxFacetList.js delete mode 100644 src/components/CheckboxFacet/CheckboxFacetList.test.js delete mode 100644 src/components/CheckboxFacet/index.js delete mode 100644 src/components/DateRangeFilter/DateRangeFilter.js delete mode 100644 src/components/DateRangeFilter/index.js delete mode 100644 src/components/FacetOptionFormatter/FacetOptionFormatter.css delete mode 100644 src/components/FacetOptionFormatter/FacetOptionFormatter.js delete mode 100644 src/components/FacetOptionFormatter/FacetOptionFormatter.test.js delete mode 100644 src/components/FacetOptionFormatter/index.js delete mode 100644 src/components/HoldingsRecordFilters/HoldingsRecordFilters.js delete mode 100644 src/components/HoldingsRecordFilters/HoldingsRecordFilters.test.js delete mode 100644 src/components/HoldingsRecordFilters/holdingsRecordFilterRenderer.js delete mode 100644 src/components/HoldingsRecordFilters/holdingsRecordFilterRenderer.test.js delete mode 100644 src/components/HoldingsRecordFilters/index.js delete mode 100644 src/components/InstanceFilters/InstanceFilters.js delete mode 100644 src/components/InstanceFilters/InstanceFilters.test.js delete mode 100644 src/components/InstanceFilters/InstanceFiltersBrowse/InstanceFiltersBrowse.js delete mode 100644 src/components/InstanceFilters/InstanceFiltersBrowse/index.js delete mode 100644 src/components/InstanceFilters/InstanceFiltersBrowse/instanceFiltersBrowse.test.js delete mode 100644 src/components/InstanceFilters/index.js delete mode 100644 src/components/InstanceFilters/instanceFilterRenderer.js delete mode 100644 src/components/InstanceFilters/languages.js delete mode 100644 src/components/ItemFilters/ItemFilters.js delete mode 100644 src/components/ItemFilters/ItemsFilters.test.js delete mode 100644 src/components/ItemFilters/index.js delete mode 100644 src/components/ItemFilters/itemFilterRenderer.js delete mode 100644 src/components/ItemFilters/itemFilterRenderer.test.js delete mode 100644 src/components/MultiSelectionFacet/MultiSelectionFacet.js delete mode 100644 src/components/MultiSelectionFacet/MultiSelectionFacet.test.js delete mode 100644 src/components/MultiSelectionFacet/index.js delete mode 100644 src/components/TagsFilter/TagsFilter.js delete mode 100644 src/components/TagsFilter/TagsFilter.test.js delete mode 100644 src/components/TagsFilter/index.js delete mode 100644 src/facetUtils.js delete mode 100644 src/facetUtils.test.js delete mode 100644 src/filterConfig.js delete mode 100644 src/stores/facetsStore.js delete mode 100644 src/stores/facetsStore.test.js delete mode 100644 src/withFacets.js diff --git a/src/common/hooks/useFacets.js b/src/common/hooks/useFacets.js deleted file mode 100644 index 80dcc35f2..000000000 --- a/src/common/hooks/useFacets.js +++ /dev/null @@ -1,229 +0,0 @@ -import { useCallback, useEffect, useRef, useState } from 'react'; -import { useLocation } from 'react-router-dom'; -import _ from 'lodash'; - -import { useFacetSettings } from '../../stores/facetsStore'; - -const useFacets = ( - segmentAccordions, - segmentOptions, - selectedFacetFilters, - getNewRecords, - data, -) => { - const { - query: { query, filters = '' }, - onFetchFacets, - parentResources: { facets }, - } = data; - - const records = facets.records[0]; - - const location = useLocation(); - const [accordions, setAccordions] = useState(segmentAccordions); - const [accordionsData, setAccordionsData] = useState({}); - const [facetsOptions, setFacetsOptions] = useState(segmentOptions); - const [facetSettings, setFacetSettings] = useFacetSettings(); - const [facetNameToOpen, setFacetNameToOpen] = useState(''); - const [showLoadingForAllFacets, setShowLoadingForAllFacets] = useState(false); - - const prevAccordionsState = useRef(accordions); - const prevFilters = useRef({}); - const prevUrl = useRef({}); - const prevQuery = useRef(''); - - const onToggleSection = useCallback(({ id }) => { - setAccordions(curState => { - const newState = _.cloneDeep(curState); - newState[id] = !curState[id]; - return newState; - }); - }, []); - - const handleFilterSearch = useCallback((filter) => { - const { - name, - value, - } = filter; - setFacetSettings(name, { value }); - }, []); - - const processFilterChange = (selectedFilters, facetName) => { - if (selectedFilters) { - const isFilterChanged = prevFilters.current[facetName]?.length !== selectedFilters.length; - if (isFilterChanged) { - prevFilters.current[facetName] = selectedFilters; - - setAccordionsData(prevAccordionsData => ({ - ...prevAccordionsData, - [facetName]: { - ...prevAccordionsData[facetName], - isSelected: true, - }, - })); - } - } else { - const isLastFilterRemoved = prevFilters.current[facetName]?.length && selectedFilters === undefined; - if (isLastFilterRemoved) { - prevFilters.current[facetName] = []; - - setAccordionsData(prevAccordionsData => ({ - ...prevAccordionsData, - [facetName]: { - ...prevAccordionsData[facetName], - isSelected: false, - }, - })); - } - } - }; - - const processOnMoreClicking = useCallback((onMoreClickedFacet) => { - onFetchFacets({ onMoreClickedFacet }); - - setFacetSettings(onMoreClickedFacet, { isOnMoreClicked: true }); - }, [onFetchFacets]); - - const processAllFacets = useCallback(() => { - const facetsData = { ...accordionsData }; - - _.forEach(facetSettings, (settings, facet) => { - facetsData[facet] = { - ...facetsData[facet], - ...settings, - }; - }); - - onFetchFacets({ - accordions, - accordionsData: facetsData, - }); - }, [ - accordions, - accordionsData, - facetSettings, - onFetchFacets, - ]); - - const handleFetchFacets = useCallback((property = {}) => { - const { - onMoreClickedFacet, - focusedFacet, - facetToOpen, - dateFacet, - } = property; - - const facetName = facetToOpen || onMoreClickedFacet || focusedFacet || dateFacet; - - if (facetName) { - setFacetNameToOpen(facetName); - setShowLoadingForAllFacets(false); - } else { - setFacetNameToOpen(''); - setShowLoadingForAllFacets(true); - } - - if (facetToOpen) { - onFetchFacets({ facetToOpen }); - } else if (onMoreClickedFacet) { - processOnMoreClicking(onMoreClickedFacet); - } else if (focusedFacet) { - onFetchFacets({ focusedFacet }); - } else { - processAllFacets(); - } - }, [ - onFetchFacets, - processAllFacets, - processOnMoreClicking - ]); - - const getIsPending = useCallback((facetName) => { - return facets.isPending && (showLoadingForAllFacets || facetNameToOpen === facetName); - }, [ - facets.isPending, - facetNameToOpen, - showLoadingForAllFacets - ]); - - useEffect(() => { - if (!_.isEmpty(records)) { - const newRecords = getNewRecords(records); - setFacetsOptions(prevFacetOptions => ({ ...prevFacetOptions, ...newRecords })); - } - }, [records]); - - useEffect(() => { - let facetToOpen = ''; - let facetToClose = ''; - - const isFacetOpened = _.some(prevAccordionsState.current, (prevFacetValue, facetName) => { - const curFacetValue = accordions[facetName]; - - if (curFacetValue !== prevFacetValue) { - if (curFacetValue) { - facetToOpen = facetName; - } else { - facetToClose = facetName; - } - return curFacetValue; - } - return false; - }); - - const isUrlChanged = prevUrl.current[facetToOpen] !== location.search; - - if ( - isFacetOpened && - isUrlChanged && - !facetToOpen.match(/createdDate/i) && - !facetToOpen.match(/updatedDate/i) - ) { - handleFetchFacets({ facetToOpen }); - } else { - prevUrl.current[facetToClose] = location.search; - } - - prevAccordionsState.current = { ...accordions }; - }, [accordions]); - - useEffect(() => { - if (!_.isEmpty(accordionsData)) { - const isNoFilterSelected = _.every(accordionsData, value => !value?.isSelected); - if (!query && prevQuery.current && isNoFilterSelected) return; - - handleFetchFacets({ facetToOpen: facetNameToOpen }); - } - }, [accordionsData]); - - useEffect(() => { - _.forEach(selectedFacetFilters, (selectedFilters, facetName) => { - processFilterChange(selectedFilters, facetName); - }); - }, [filters]); - - useEffect(() => { - const isSomeFacetOpened = _.some(accordions, isFacetOpened => isFacetOpened); - const isValidQuery = (query && query !== prevQuery.current) || (query !== undefined && prevQuery.current); - - if (isSomeFacetOpened) { - if (isValidQuery) { - prevQuery.current = query; - handleFetchFacets({ facetToOpen: facetNameToOpen }); - } - } else if (isValidQuery) { - prevQuery.current = query; - } - }, [query]); - - return [ - accordions, - onToggleSection, - handleFetchFacets, - handleFilterSearch, - facetsOptions, - getIsPending, - ]; -}; - -export default useFacets; diff --git a/src/common/hooks/useFacets.test.js b/src/common/hooks/useFacets.test.js deleted file mode 100644 index 5791ee5f9..000000000 --- a/src/common/hooks/useFacets.test.js +++ /dev/null @@ -1,312 +0,0 @@ -import { renderHook, act } from '@testing-library/react-hooks'; -import { useLocation } from 'react-router-dom'; -import React from 'react'; -import { useFacetSettings } from '../../stores/facetsStore'; -import useFacets from './useFacets'; - -jest.mock('react-router-dom', () => ({ - useLocation: jest.fn(), -})); - -jest.mock('../../stores/facetsStore', () => ({ - useFacetSettings: jest - .fn() - .mockReturnValue([{ foo: { value: 'bar' }, quux: { value: 'changed' } }]), -})); - -describe('useFacets', () => { - const segmentAccordions = { - test: true, - foo: true, - baz: false, - }; - const segmentOptions = { baz: ['qux'], quux: ['corge'] }; - const selectedFacetFilters = { - selectedFilters: { foo: { value: 'bar' } }, - facetName: 'test', - }; - const getNewRecords = jest.fn(() => { - return { quux: ['corge', 'grault'], garply: ['waldo'] }; - }); - - const data = { - query: { query: null, filters: 'filters' }, - onFetchFacets: jest.fn(), - parentResources: { - facets: { records: [[{ name: 'baz' }]], isPending: true }, - }, - }; - - beforeEach(() => { - jest.clearAllMocks(); - useLocation.mockReturnValue({ pathname: '/path' }); - useFacetSettings.mockReturnValue([selectedFacetFilters, jest.fn()]); - }); - - it('returns initial state', () => { - const { result } = renderHook(() => useFacets( - segmentAccordions, - segmentOptions, - selectedFacetFilters, - getNewRecords, - data - )); - expect(result.current[0]).toEqual(segmentAccordions); - }); - - it('updates accordions state on new toggle', () => { - const { result } = renderHook(() => useFacets( - segmentAccordions, - segmentOptions, - selectedFacetFilters, - getNewRecords, - data - )); - - act(() => { - result.current[1]({ id: 'foo' }); - }); - expect(result.current[0]).toEqual({ - ...segmentAccordions, - foo: false, - }); - }); - - it('updates accordions state on open toggle', () => { - const { result } = renderHook(() => useFacets( - segmentAccordions, - segmentOptions, - selectedFacetFilters, - getNewRecords, - data - )); - - act(() => { - result.current[2]({ - onMoreClickedFacet: true, - focusedFacet: '', - facetToOpen: true, - dateFacet: true, - }); - }); - expect(result.current[0]).toEqual({ - ...segmentAccordions, - foo: true, - }); - }); - - it('updates accordions state on segment toggle', () => { - const { result } = renderHook(() => useFacets( - segmentAccordions, - segmentOptions, - {}, - getNewRecords, - data - )); - - act(() => { - result.current[2]({ - onMoreClickedFacet: true, - focusedFacet: '', - facetToOpen: true, - dateFacet: true, - }); - }); - expect(result.current[0]).toEqual({ - ...segmentAccordions, - foo: true, - }); - }); - - it('updates accordions state on records toggle', () => { - const { result } = renderHook(() => useFacets( - segmentAccordions, - segmentOptions, - selectedFacetFilters, - getNewRecords, - data - )); - - act(() => { - result.current[2]({ - onMoreClickedFacet: true, - focusedFacet: '', - facetToOpen: false, - dateFacet: true, - }); - }); - expect(result.current[0]).toEqual({ - ...segmentAccordions, - foo: true, - }); - }); - - it('updates accordions state on facet toggle', () => { - const { result } = renderHook(() => useFacets( - segmentAccordions, - segmentOptions, - selectedFacetFilters, - getNewRecords, - data - )); - - act(() => { - result.current[2]({ - onMoreClickedFacet: false, - focusedFacet: true, - facetToOpen: false, - dateFacet: true, - }); - }); - expect(result.current[0]).toEqual({ - ...segmentAccordions, - foo: true, - }); - }); - - it('updates accordions state on date toggle', () => { - const { result } = renderHook(() => useFacets( - segmentAccordions, - segmentOptions, - selectedFacetFilters, - getNewRecords, - data - )); - - act(() => { - result.current[2]({ - onMoreClickedFacet: false, - focusedFacet: true, - facetToOpen: false, - dateFacet: false, - }); - }); - expect(result.current[0]).toEqual({ - ...segmentAccordions, - foo: true, - }); - }); - - it('updates facet settings on data filter search', () => { - const spy = jest.spyOn(React, 'useRef'); - spy.mockImplementation(() => { - return { current: {}, ...segmentAccordions }; - }); - const { result } = renderHook(() => useFacets( - segmentAccordions, - segmentOptions, - selectedFacetFilters, - getNewRecords, - data - )); - - act(() => { - result.current[3]({ name: 'quux', value: 'changed' }); - }); - expect(result.current[0]).toEqual({ - ...segmentAccordions, - foo: true, - }); - }); - - it('updates facet settings on accordions filter search', () => { - const spy = jest.spyOn(React, 'useRef'); - spy.mockImplementation(() => { - return { current: { test: ['ere'] }, ...segmentAccordions }; - }); - const { result } = renderHook(() => useFacets( - segmentAccordions, - segmentOptions, - { selectedFilters: undefined, facetName: 'test' }, - getNewRecords, - data - )); - act(() => { - result.current[3]({ name: 'quux', value: 'changed' }); - }); - expect(result.current[0]).toEqual({ - ...segmentAccordions, - foo: true, - }); - }); - it('updates facet settings on selected filter search', () => { - jest.spyOn(React, 'useRef').mockReturnValueOnce({ - current: {}, - }); - const { result } = renderHook(() => useFacets( - segmentAccordions, - segmentOptions, - { - selectedFilters: undefined, - facetName: 'test', - }, - getNewRecords, - data - )); - - act(() => { - result.current[5]('test'); - }); - expect(result.current[0]).toEqual({ - ...segmentAccordions, - foo: true, - }); - }); - it('updates facet settings on facet filter search', () => { - const spy = jest.spyOn(React, 'useRef'); - spy.mockImplementation(() => { - return { - current: { - test: ['ere'], - prevFacetValue: 'test', - selectedFilters: ['hggh'], - facetName: 'test', - }, - ...segmentAccordions, - }; - }); - const { result } = renderHook(() => useFacets( - segmentAccordions, - segmentOptions, - { - selectedFilters: undefined, - facetName: 'test', - }, - getNewRecords, - data - )); - - act(() => { - result.current[5]('test'); - }); - expect(result.current[0]).toEqual({ - ...segmentAccordions, - foo: true, - }); - }); - it('updates facet settings on ref filter search', () => { - const spy = jest.spyOn(React, 'useRef'); - spy.mockImplementation(() => { - return { - current: { test: ['ere'], prevFacetValue: 'test', facetName: 'test' }, - ...segmentAccordions, - }; - }); - const { result } = renderHook(() => useFacets( - { foo: false }, - segmentOptions, - { - selectedFilters: undefined, - facetName: 'test', - }, - getNewRecords, - data - )); - act(() => { - result.current[5]('test'); - }); - expect(result.current[0]).toEqual({ - foo: false, - }); - }); -}); diff --git a/src/components/CheckboxFacet/CheckboxFacet.js b/src/components/CheckboxFacet/CheckboxFacet.js deleted file mode 100644 index 4bfacd354..000000000 --- a/src/components/CheckboxFacet/CheckboxFacet.js +++ /dev/null @@ -1,142 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -import CheckboxFacetList from './CheckboxFacetList'; - -import { accentFold } from '../../utils'; -import { DEFAULT_FILTERS_NUMBER } from '../../constants'; -import { getSearchTerm } from '../../stores/facetsStore'; - -const SHOW_OPTIONS_COUNT = 5; -const SHOW_OPTIONS_INCREMENT = 5; - -export default class CheckboxFacet extends React.Component { - static propTypes = { - dataOptions: PropTypes.arrayOf(PropTypes.shape({ - disabled: PropTypes.bool, - label: PropTypes.node, - readOnly: PropTypes.bool, - value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), - count: PropTypes.number, - })).isRequired, - name: PropTypes.string.isRequired, - onChange: PropTypes.func.isRequired, - onFetch: PropTypes.func, - onSearch: PropTypes.func, - selectedValues: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.number])), - isFilterable: PropTypes.bool, - isPending: PropTypes.bool, - }; - - static defaultProps = { - selectedValues: [], - isFilterable: false, - } - - state = { - more: SHOW_OPTIONS_COUNT, - isMoreClicked: false, - }; - - componentDidUpdate(prevProps) { - if ( - this.state.isMoreClicked && - prevProps.dataOptions.length === DEFAULT_FILTERS_NUMBER && - this.props.dataOptions.length > DEFAULT_FILTERS_NUMBER - ) { - this.updateMore(); - } - } - - onMoreClick = (totalOptions) => { - const { - onFetch, - name, - } = this.props; - - this.setState(({ more }) => { - let visibleOptionsCount = more + SHOW_OPTIONS_INCREMENT; - const showingAll = visibleOptionsCount >= totalOptions; - if (showingAll) visibleOptionsCount = totalOptions; - - return { more: visibleOptionsCount }; - }); - - this.setState({ isMoreClicked: true }); - onFetch({ onMoreClickedFacet: name }); - }; - - onFacetSearch = searchTerm => { - const { - onSearch, - name, - } = this.props; - - onSearch({ name, value: searchTerm }); - }; - - onFasetChange = (filterValue) => (e) => { - const { - name, - selectedValues, - onChange, - } = this.props; - - const newValues = e.target.checked - ? [...selectedValues, filterValue] - : selectedValues.filter((value) => value !== filterValue); - - onChange({ - name, - values: newValues, - }); - }; - - updateMore = () => { - this.setState(({ more }) => { - return { more: more + SHOW_OPTIONS_INCREMENT }; - }); - } - - render() { - const { - dataOptions, - selectedValues, - isFilterable, - isPending, - name, - onFetch, - } = this.props; - - const searchTerm = getSearchTerm(name); - - const { - more, - } = this.state; - - let filteredOptions = dataOptions; - - if (searchTerm.trim()) { - filteredOptions = filteredOptions.filter(option => { - return accentFold(option.label) - .toLowerCase() - .includes(accentFold(searchTerm).toLowerCase()); - }); - } - - return ( - more} - showSearch={isFilterable} - onMoreClick={() => this.onMoreClick(filteredOptions.length)} - onSearch={this.onFacetSearch} - onChange={this.onFasetChange} - onFetch={onFetch} - isPending={isPending} - /> - ); - } -} diff --git a/src/components/CheckboxFacet/CheckboxFacet.test.js b/src/components/CheckboxFacet/CheckboxFacet.test.js deleted file mode 100644 index 56eb4cf45..000000000 --- a/src/components/CheckboxFacet/CheckboxFacet.test.js +++ /dev/null @@ -1,191 +0,0 @@ -import React from 'react'; -import { screen, act, render } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import '../../../test/jest/__mock__'; -import { renderWithIntl, translationsProperties } from '../../../test/jest/helpers'; -import CheckboxFacet from './CheckboxFacet'; -import facetsStore from '../../stores/facetsStore'; - -const defaultProps = { - dataOptions: [ - { - disabled: false, - label: 'TestOption1', - readOnly: false, - value: 1, - count: 5 - }, - { - disabled: false, - label: 'TestOption2', - readOnly: false, - value: 2, - count: 12 - }, - { - disabled: false, - label: 'TestOption3', - readOnly: false, - value: 3, - count: 4 - }, - { - disabled: false, - label: 'TestOption4', - readOnly: false, - value: 4, - count: 6 - }, - { - disabled: false, - label: 'TestOption5', - readOnly: false, - value: 5, - count: 8 - }, - { - disabled: false, - label: 'TestOption6', - readOnly: false, - value: 6, - count: 10 - } - ], - onFetch: jest.fn(), - onSearch: ({ name, value }) => { - facetsStore.getState().setFacetSettings(name, { value }); - }, - name: 'Test Name', - onChange: jest.fn(), - isPending: false, - selectedValues: [1, 5], - isFilterable: true -}; - -const renderCheckboxFacet = (props, renderer = render) => renderWithIntl( - , - translationsProperties, - renderer -); - -describe('CheckboxFacet', () => { - beforeEach(() => { - facetsStore.getState().resetFacetSettings(); - }); - - it('Component should render', () => { - renderCheckboxFacet(defaultProps); - expect(screen.getByRole('searchbox', { name: 'Test Name-field' })).toBeInTheDocument(); - expect(screen.getAllByRole('checkbox')).toHaveLength(5); - expect(screen.getByRole('button', { name: 'More' })).toBeInTheDocument(); - }); - it('More options should render when More button is click', () => { - renderCheckboxFacet(defaultProps); - userEvent.click(screen.getByRole('button', { name: 'More' })); - expect(screen.getAllByRole('checkbox')).toHaveLength(6); - }); - it('components.readonly should be render when readonly property is true', () => { - const props = { - dataOptions: [ - { - disabled: false, - label: 'Options1', - readOnly: true, - value: 1, - count: 4 - } - ], - name: 'Test Name', - onChange: jest.fn(), - isPending: false - }; - renderCheckboxFacet(props); - expect(screen.getByText('Read-only')).toBeInTheDocument(); - }); - it('No matching options should be render when required search is not found', () => { - const { rerender } = renderCheckboxFacet(defaultProps); - userEvent.type(screen.getByRole('searchbox', { name: 'Test Name-field' }), 'test search'); - - renderCheckboxFacet(defaultProps, rerender); - - expect(screen.getByText('No matching options')).toBeInTheDocument(); - }); - it('component should re-render ', () => { - const props = { - dataOptions: [ - { - disabled: false, - label: 'TestOption1', - readOnly: false, - value: 1, - count: 5 - }, - { - disabled: false, - label: 'TestOption2', - readOnly: false, - value: 2, - count: 12 - }, - { - disabled: false, - label: 'TestOption3', - readOnly: false, - value: 3, - count: 4 - }, - { - disabled: false, - label: 'TestOption4', - readOnly: false, - value: 4, - count: 6 - }, - { - disabled: false, - label: 'TestOption5', - readOnly: false, - value: 5, - count: 8 - }, - { - disabled: false, - label: 'TestOption6', - readOnly: false, - value: 6, - count: 10 - }, - { - disabled: false, - label: 'TestOption7', - readOnly: false, - value: 7, - count: 19 - }, - { - disabled: false, - label: 'TestOption8', - readOnly: false, - value: 8, - count: 17 - } - ], - onFetch: jest.fn(), - onSearch: jest.fn(), - name: 'Test Name', - onChange: jest.fn(), - isPending: false, - selectedValues: [7, 8, 6], - isFilterable: true - }; - const { rerender } = renderCheckboxFacet(defaultProps); - - userEvent.click(screen.getByRole('button', { name: 'More' })); - renderCheckboxFacet(props, rerender); - - userEvent.click(screen.getByRole('checkbox', { name: 'TestOption3 4' })); - userEvent.click(screen.getByRole('checkbox', { name: 'TestOption7 19' })); - - expect(screen.getAllByRole('checkbox')).toHaveLength(8); - }); -}); diff --git a/src/components/CheckboxFacet/CheckboxFacetList.css b/src/components/CheckboxFacet/CheckboxFacetList.css deleted file mode 100644 index 3c8c2c98f..000000000 --- a/src/components/CheckboxFacet/CheckboxFacetList.css +++ /dev/null @@ -1,27 +0,0 @@ -@import '@folio/stripes-components/lib/variables.css'; - -.facetSearchContainer { - max-height: 15.2rem; - overflow-y: auto; - overflow-x: hidden; -} - -.facetSearch { - padding-top: var(--gutter-static-one-third); - - & label { - border: 0; - clip: rect(0 0 0 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; - } -} - -.moreIcon { - font-size: var(--font-size-x-small); - margin-right: var(--gutter-static-one-third); -} diff --git a/src/components/CheckboxFacet/CheckboxFacetList.js b/src/components/CheckboxFacet/CheckboxFacetList.js deleted file mode 100644 index 0212566e4..000000000 --- a/src/components/CheckboxFacet/CheckboxFacetList.js +++ /dev/null @@ -1,123 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { kebabCase } from 'lodash'; -import { FormattedMessage } from 'react-intl'; - -import { - Checkbox, - TextField, - Button, - Icon, -} from '@folio/stripes/components'; - -import { useSearchValue } from '../../stores/facetsStore'; - -import css from './CheckboxFacetList.css'; - -function CheckboxFacetList({ - dataOptions, - selectedValues, - showMore, - showSearch, - onMoreClick, - onSearch, - onChange, - onFetch, - fieldName, - isPending, -}) { - const handleTextFieldFocus = () => { - onFetch({ focusedFacet: fieldName }); - }; - const searchValue = useSearchValue(fieldName); - - return ( -
- {showSearch && ( -
- onSearch(e.target.value)} - onFocus={handleTextFieldFocus} - value={searchValue} - /> -
- )} -
- {isPending && - - } - {!isPending && dataOptions.length < 1 && - - } - - {!isPending && dataOptions.map(({ count, value, label, disabled, readOnly }) => { - const name = typeof label === 'string' ? label : value; - return ( - - ); - })} -
- - {!isPending && showMore && ( - - - { ({ label }) => ( - - )} - - )} -
- ); -} - -CheckboxFacetList.propTypes = { - fieldName: PropTypes.string.isRequired, - isPending: PropTypes.bool, - onMoreClick: PropTypes.func.isRequired, - onSearch: PropTypes.func.isRequired, - dataOptions: PropTypes.arrayOf(PropTypes.shape({ - disabled: PropTypes.bool, - label: PropTypes.node, - readOnly: PropTypes.bool, - value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), - count: PropTypes.number, - })).isRequired, - onChange: PropTypes.func.isRequired, - onFetch: PropTypes.func, - selectedValues: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.number])), - showMore: PropTypes.bool.isRequired, - showSearch: PropTypes.bool, -}; - -CheckboxFacetList.defaultProps = { - onFetch: () => null, -}; - -export default CheckboxFacetList; diff --git a/src/components/CheckboxFacet/CheckboxFacetList.test.js b/src/components/CheckboxFacet/CheckboxFacetList.test.js deleted file mode 100644 index 7a355e523..000000000 --- a/src/components/CheckboxFacet/CheckboxFacetList.test.js +++ /dev/null @@ -1,128 +0,0 @@ -import React from 'react'; -import { render, waitFor, screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import { useSearchValue } from '../../stores/facetsStore'; -import '../../../test/jest/__mock__'; -import CheckboxFacetList from './CheckboxFacetList'; - -jest.mock('../../stores/facetsStore', () => ({ - useSearchValue: jest.fn(), -})); - -jest.mock('react-intl', () => { - const intl = { - formatMessage: ({ id }) => id, - }; - - return { - ...jest.requireActual('react-intl'), - FormattedMessage: jest.fn(({ id, children }) => { - if (children) { - return children([id]); - } - - return id; - }), - useIntl: () => intl, - injectIntl: (Component) => (props) => , - }; -}); - -const dataOptions = [ - { - count: 5, - label: 'Check Box 1', - value: 'checkBox1', - }, - { - count: 7, - label: 'Check Box 2', - value: 'checkBox2', - }, -]; -const selectedValues = ['checkBox1']; -const fieldName = 'testFacet'; -const onChange = jest.fn(); -const onMoreClick = jest.fn(); -const onSearch = jest.fn(); -const showSearch = true; -const showMore = false; -const isPending = false; - -describe('CheckboxFacetList', () => { - beforeEach(() => { - useSearchValue.mockReturnValue(''); - }); - - it('Component should render correctly', () => { - render( - , - ); - expect(screen.getAllByRole('checkbox')).toHaveLength(2); - expect(screen.getByLabelText(`${fieldName}-field`)).toBeInTheDocument(); - expect(screen.getByRole('button', { name: 'ui-inventory.more' })).toBeInTheDocument(); - }); - - it('onSearch to be triggered when typing in the search field', async () => { - render( - , - ); - userEvent.type(screen.getByText(`${fieldName}-field`), 'Test Search'); - await waitFor(() => { - expect(onSearch).toBeCalledWith('Test Search'); - }); - }); - it('noMatchingOptions should be render when dataOptions is empty', () => { - render( - , - ); - expect(screen.getByText('ui-inventory.noMatchingOptions')).toBeInTheDocument(); - }); - it('checkbox should not render when isPending is true', () => { - render( - , - ); - const checkBoxs = screen.findAllByRole('checkbox'); - expect(checkBoxs).toMatchObject({}); - }); -}); diff --git a/src/components/CheckboxFacet/index.js b/src/components/CheckboxFacet/index.js deleted file mode 100644 index 91d6435a0..000000000 --- a/src/components/CheckboxFacet/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './CheckboxFacet'; diff --git a/src/components/DateRangeFilter/DateRangeFilter.js b/src/components/DateRangeFilter/DateRangeFilter.js deleted file mode 100644 index 8431f0b19..000000000 --- a/src/components/DateRangeFilter/DateRangeFilter.js +++ /dev/null @@ -1,39 +0,0 @@ -import { PropTypes } from 'prop-types'; -import { DateRangeFilter as StripesDateRangeFilter } from '@folio/stripes/smart-components'; -import { useStripes } from '@folio/stripes/core'; -import moment from 'moment'; - -// Delegates rendering to DateRangeFilter from smart-components. -// Sets correct tenant timezone when onChange is executed. -const DateRangeFilter = ({ name, dateFormat, selectedValues, onChange, makeFilterString }) => { - const { timezone } = useStripes(); - - const onDateRangeChange = (filterData) => { - // sets current tenant's timezone - moment.tz.setDefault(timezone); - onChange(filterData); - // restore to a default timezone - moment.tz.setDefault(); - }; - - return ; -}; - -DateRangeFilter.propTypes = { - dateFormat: PropTypes.string, - name: PropTypes.string.isRequired, - makeFilterString: PropTypes.func.isRequired, - onChange: PropTypes.func.isRequired, - selectedValues: PropTypes.shape({ - endDate: PropTypes.string.isRequired, - startDate: PropTypes.string.isRequired, - }).isRequired, -}; - -export default DateRangeFilter; diff --git a/src/components/DateRangeFilter/index.js b/src/components/DateRangeFilter/index.js deleted file mode 100644 index ad9503345..000000000 --- a/src/components/DateRangeFilter/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './DateRangeFilter'; diff --git a/src/components/FacetOptionFormatter/FacetOptionFormatter.css b/src/components/FacetOptionFormatter/FacetOptionFormatter.css deleted file mode 100644 index 448207b1a..000000000 --- a/src/components/FacetOptionFormatter/FacetOptionFormatter.css +++ /dev/null @@ -1,7 +0,0 @@ -.optionLabel { - display: block; -} - -.totalRecordsLabel { - display: block; -} diff --git a/src/components/FacetOptionFormatter/FacetOptionFormatter.js b/src/components/FacetOptionFormatter/FacetOptionFormatter.js deleted file mode 100644 index 7cb1d7abd..000000000 --- a/src/components/FacetOptionFormatter/FacetOptionFormatter.js +++ /dev/null @@ -1,34 +0,0 @@ -import PropTypes from 'prop-types'; - -import { OptionSegment } from '@folio/stripes/components'; - -import styles from './FacetOptionFormatter.css'; - -const propTypes = { - option: PropTypes.object, - searchTerm: PropTypes.string, -}; - -const FacetOptionFormatter = ({ option, searchTerm }) => { - if (!option) { - return null; - } - - const formatTotalRecords = totalRecords => `(${totalRecords})`; - - return ( - - {option.label} - {formatTotalRecords(option.totalRecords)} - - ); -}; - -FacetOptionFormatter.propTypes = propTypes; - -FacetOptionFormatter.defaultProps = { - option: null, - searchTerm: '', -}; - -export default FacetOptionFormatter; diff --git a/src/components/FacetOptionFormatter/FacetOptionFormatter.test.js b/src/components/FacetOptionFormatter/FacetOptionFormatter.test.js deleted file mode 100644 index 3b79ae5bd..000000000 --- a/src/components/FacetOptionFormatter/FacetOptionFormatter.test.js +++ /dev/null @@ -1,32 +0,0 @@ -import '../../../test/jest/__mock__'; - -import { render } from '@testing-library/react'; - -import FacetOptionFormatter from './FacetOptionFormatter'; - -import Harness from '../../../test/jest/helpers/Harness'; - -const option = { - label: 'Option label', - totalRecords: 1000, -}; - -const renderFacetOptionFormatter = (props = {}) => render( - - - , -); - -describe('Given FacetOptionFormatter', () => { - it('should render option label', () => { - const { getByText } = renderFacetOptionFormatter(); - - expect(getByText('Option label')).toBeDefined(); - }); - - it('should render option facet count', () => { - const { getByText } = renderFacetOptionFormatter(); - - expect(getByText('(1000)')).toBeDefined(); - }); -}); diff --git a/src/components/FacetOptionFormatter/index.js b/src/components/FacetOptionFormatter/index.js deleted file mode 100644 index 0907577b1..000000000 --- a/src/components/FacetOptionFormatter/index.js +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from './FacetOptionFormatter'; -export { default as FacetOptionFormatter } from './FacetOptionFormatter'; diff --git a/src/components/HoldingsRecordFilters/HoldingsRecordFilters.js b/src/components/HoldingsRecordFilters/HoldingsRecordFilters.js deleted file mode 100644 index dff41c337..000000000 --- a/src/components/HoldingsRecordFilters/HoldingsRecordFilters.js +++ /dev/null @@ -1,308 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { FormattedMessage } from 'react-intl'; -import { reduce } from 'lodash'; - -import { - Accordion, - FilterAccordionHeader, - AccordionSet, -} from '@folio/stripes/components'; - -import DateRangeFilter from '../DateRangeFilter'; -import TagsFilter from '../TagsFilter'; -import CheckboxFacet from '../CheckboxFacet'; -import { useFacets } from '../../common/hooks'; -import { - getSourceOptions, - getSuppressedOptions, - processFacetOptions, - processStatisticalCodes, -} from '../../facetUtils'; -import { - DATE_FORMAT, - FACETS, - FACETS_OPTIONS, - FACETS_CQL, - FACETS_SETTINGS, -} from '../../constants'; -import { - makeDateRangeFilterString, - retrieveDatesFromDateRangeFilterString, -} from '../../utils'; - -const HoldingsRecordFilters = (props) => { - const { - activeFilters, - data: { - locations, - statisticalCodes, - holdingsSources, - holdingsTypes, - }, - onChange, - onClear, - } = props; - - const segmentAccordions = { - [FACETS.EFFECTIVE_LOCATION]: false, - [FACETS.HOLDINGS_PERMANENT_LOCATION]: false, - [FACETS.HOLDINGS_DISCOVERY_SUPPRESS]: false, - [FACETS.HOLDINGS_TAGS]: false, - [FACETS.HOLDINGS_CREATED_DATE]: false, - [FACETS.HOLDINGS_UPDATED_DATE]: false, - [FACETS.HOLDINGS_STATISTICAL_CODE_IDS]: false, - [FACETS.HOLDINGS_SOURCE]: false, - [FACETS.HOLDINGS_TYPE]: false, - }; - - const segmentOptions = { - [FACETS_OPTIONS.EFFECTIVE_LOCATION_OPTIONS]: [], - [FACETS_OPTIONS.HOLDINGS_PERMANENT_LOCATION_OPTIONS]: [], - [FACETS_OPTIONS.HOLDINGS_DISCOVERY_SUPPRESS_OPTIONS]: [], - [FACETS_OPTIONS.HOLDINGS_TAGS_OPTIONS]: [], - [FACETS_OPTIONS.STATISTICAL_CODES_OPTIONS]: [], - [FACETS_OPTIONS.HOLDINGS_SOURCE_OPTIONS]: [], - [FACETS_OPTIONS.HOLDINGS_TYPE_OPTIONS]: [], - }; - - const selectedFacetFilters = { - [FACETS.EFFECTIVE_LOCATION]: activeFilters[FACETS.EFFECTIVE_LOCATION], - [FACETS.HOLDINGS_PERMANENT_LOCATION]: activeFilters[FACETS.HOLDINGS_PERMANENT_LOCATION], - [FACETS.HOLDINGS_DISCOVERY_SUPPRESS]: activeFilters[FACETS.HOLDINGS_DISCOVERY_SUPPRESS], - [FACETS.HOLDINGS_TAGS]: activeFilters[FACETS.HOLDINGS_TAGS], - [FACETS.HOLDINGS_STATISTICAL_CODE_IDS]: activeFilters[FACETS.HOLDINGS_STATISTICAL_CODE_IDS], - [FACETS.HOLDINGS_SOURCE]: activeFilters[FACETS.HOLDINGS_SOURCE], - [FACETS.HOLDINGS_TYPE]: activeFilters[FACETS.HOLDINGS_TYPE], - }; - - const getNewRecords = (records) => { - return reduce(FACETS_SETTINGS, (accum, name, recordName) => { - if (records[recordName]) { - const recordValues = records[recordName].values; - const commonProps = [recordValues, accum, name]; - - switch (recordName) { - case FACETS_CQL.EFFECTIVE_LOCATION: - processFacetOptions(activeFilters[FACETS.EFFECTIVE_LOCATION], locations, ...commonProps); - break; - case FACETS_CQL.HOLDINGS_PERMANENT_LOCATION: - processFacetOptions(activeFilters[FACETS.HOLDINGS_PERMANENT_LOCATION], locations, ...commonProps); - break; - case FACETS_CQL.HOLDINGS_DISCOVERY_SUPPRESS: - accum[name] = getSuppressedOptions(activeFilters[FACETS.HOLDINGS_DISCOVERY_SUPPRESS], recordValues); - break; - case FACETS_CQL.HOLDINGS_STATISTICAL_CODE_IDS: - processStatisticalCodes(activeFilters[FACETS.HOLDINGS_STATISTICAL_CODE_IDS], statisticalCodes, ...commonProps); - break; - case FACETS_CQL.HOLDINGS_SOURCE: - processFacetOptions(activeFilters[FACETS.HOLDINGS_SOURCE], holdingsSources, ...commonProps); - break; - case FACETS_CQL.HOLDINGS_TAGS: - accum[name] = getSourceOptions(activeFilters[FACETS.HOLDINGS_TAGS], recordValues); - break; - case FACETS_CQL.HOLDINGS_TYPE: - processFacetOptions(activeFilters[FACETS.HOLDINGS_TYPE], holdingsTypes, ...commonProps); - break; - default: - } - } - return accum; - }, {}); - }; - - const [ - accordions, - onToggleSection, - handleFetchFacets, - handleFilterSearch, - facetsOptions, - getIsPending, - ] = useFacets( - segmentAccordions, - segmentOptions, - selectedFacetFilters, - getNewRecords, - props.data - ); - - return ( - - } - id={FACETS.EFFECTIVE_LOCATION} - name={FACETS.EFFECTIVE_LOCATION} - separator={false} - header={FilterAccordionHeader} - displayClearButton={activeFilters[FACETS.EFFECTIVE_LOCATION]?.length > 0} - onClearFilter={() => onClear(FACETS.EFFECTIVE_LOCATION)} - > - - - } - id={FACETS.HOLDINGS_PERMANENT_LOCATION} - name={FACETS.HOLDINGS_PERMANENT_LOCATION} - closedByDefault - header={FilterAccordionHeader} - displayClearButton={activeFilters[FACETS.HOLDINGS_PERMANENT_LOCATION]?.length > 0} - onClearFilter={() => onClear(FACETS.HOLDINGS_PERMANENT_LOCATION)} - > - - - } - id={FACETS.HOLDINGS_TYPE} - name={FACETS.HOLDINGS_TYPE} - closedByDefault - header={FilterAccordionHeader} - displayClearButton={activeFilters[FACETS.HOLDINGS_TYPE]?.length > 0} - onClearFilter={() => onClear(FACETS.HOLDINGS_TYPE)} - > - - - } - id={FACETS.HOLDINGS_DISCOVERY_SUPPRESS} - name={FACETS.HOLDINGS_DISCOVERY_SUPPRESS} - closedByDefault - header={FilterAccordionHeader} - displayClearButton={activeFilters[FACETS.HOLDINGS_DISCOVERY_SUPPRESS]?.length > 0} - onClearFilter={() => onClear(FACETS.HOLDINGS_DISCOVERY_SUPPRESS)} - > - - - } - id={FACETS.HOLDINGS_STATISTICAL_CODE_IDS} - name={FACETS.HOLDINGS_STATISTICAL_CODE_IDS} - closedByDefault - header={FilterAccordionHeader} - displayClearButton={activeFilters[FACETS.HOLDINGS_STATISTICAL_CODE_IDS]?.length > 0} - onClearFilter={() => onClear(FACETS.HOLDINGS_STATISTICAL_CODE_IDS)} - > - - - } - id={FACETS.HOLDINGS_CREATED_DATE} - name={FACETS.HOLDINGS_CREATED_DATE} - closedByDefault - header={FilterAccordionHeader} - displayClearButton={activeFilters[FACETS.HOLDINGS_CREATED_DATE]?.length > 0} - onClearFilter={() => onClear(FACETS.HOLDINGS_CREATED_DATE)} - > - - - } - id={FACETS.HOLDINGS_UPDATED_DATE} - name={FACETS.HOLDINGS_UPDATED_DATE} - closedByDefault - header={FilterAccordionHeader} - displayClearButton={activeFilters[FACETS.HOLDINGS_UPDATED_DATE]?.length > 0} - onClearFilter={() => onClear(FACETS.HOLDINGS_UPDATED_DATE)} - > - - - } - id={FACETS.HOLDINGS_SOURCE} - name={FACETS.HOLDINGS_SOURCE} - closedByDefault - header={FilterAccordionHeader} - displayClearButton={activeFilters[FACETS.HOLDINGS_SOURCE]?.length > 0} - onClearFilter={() => onClear(FACETS.HOLDINGS_SOURCE)} - > - - - - - ); -}; - -HoldingsRecordFilters.propTypes = { - activeFilters: PropTypes.object, - onChange: PropTypes.func.isRequired, - onClear: PropTypes.func.isRequired, - data: PropTypes.object, -}; - -HoldingsRecordFilters.defaultProps = { - activeFilters: {}, -}; - -export default HoldingsRecordFilters; diff --git a/src/components/HoldingsRecordFilters/HoldingsRecordFilters.test.js b/src/components/HoldingsRecordFilters/HoldingsRecordFilters.test.js deleted file mode 100644 index a8fb96f13..000000000 --- a/src/components/HoldingsRecordFilters/HoldingsRecordFilters.test.js +++ /dev/null @@ -1,70 +0,0 @@ -import React from 'react'; -import { BrowserRouter as Router } from 'react-router-dom'; -import { noop } from 'lodash'; - -import '../../../test/jest/__mock__'; - -import { ModuleHierarchyProvider } from '@folio/stripes/core'; -import renderWithIntl from '../../../test/jest/helpers/renderWithIntl'; - -import HoldingsRecordFilters from './HoldingsRecordFilters'; - -const resources = { - facets: { - hasLoaded: true, - resource: 'facets', - records: [], - other: { totalRecords: 0 } - }, -}; - -const data = { - locations: [], - resourceTypes: [], - instanceFormats: [], - modesOfIssuance: [], - statisticalCodes: [], - tagsRecords: [], - natureOfContentTerms: [], - query: [], - onFetchFacets: noop, - parentResources: resources, -}; - -const renderHoldingsRecordFilters = () => { - return renderWithIntl( - - - - - - ); -}; - -describe('HoldingsRecordFilters', () => { - beforeEach(() => { - renderHoldingsRecordFilters(); - }); - - it('Contains a filter for creation date', () => { - expect(document.querySelector('#holdingsCreatedDate')).toBeInTheDocument(); - }); - - it('Contains a filter for update date', () => { - expect(document.querySelector('#holdingsUpdatedDate')).toBeInTheDocument(); - }); - - it('Contains a filter for statistical code', () => { - expect(document.querySelector('#holdingsStatisticalCodeIds')).toBeInTheDocument(); - }); - - it('Contains a filter for source', () => { - expect(document.querySelector('#holdingsSource')).toBeInTheDocument(); - }); -}); diff --git a/src/components/HoldingsRecordFilters/holdingsRecordFilterRenderer.js b/src/components/HoldingsRecordFilters/holdingsRecordFilterRenderer.js deleted file mode 100644 index a251c5277..000000000 --- a/src/components/HoldingsRecordFilters/holdingsRecordFilterRenderer.js +++ /dev/null @@ -1,44 +0,0 @@ -import React from 'react'; -import { get } from 'lodash'; - -import HoldingsRecordFilters from './HoldingsRecordFilters'; -import { getCurrentFilters } from '../../utils'; -import facetsStore from '../../stores/facetsStore'; - -// holdingsRecordFilterRenderer is a function that takes a single argument `data` -// and returns a function that takes a single argument `onChange`. -const holdingsRecordFilterRenderer = data => onChange => { - const { - locations, - statisticalCodes, - holdingsSources, - holdingsTypes, - query, - tags, - onFetchFacets, - parentResources, - } = data; - - return ( - { - facetsStore.getState().resetFacetByName(name); - onChange({ name, values: [] }); - }} - /> - ); -}; - -export default holdingsRecordFilterRenderer; diff --git a/src/components/HoldingsRecordFilters/holdingsRecordFilterRenderer.test.js b/src/components/HoldingsRecordFilters/holdingsRecordFilterRenderer.test.js deleted file mode 100644 index 4a461b3f9..000000000 --- a/src/components/HoldingsRecordFilters/holdingsRecordFilterRenderer.test.js +++ /dev/null @@ -1,118 +0,0 @@ -import React from 'react'; -import { BrowserRouter as Router } from 'react-router-dom'; - -import userEvent from '@testing-library/user-event'; -import { screen } from '@testing-library/react'; -import '../../../test/jest/__mock__/currencyData.mock'; -import '../../../test/jest/__mock__/stripesConfig.mock'; -import '../../../test/jest/__mock__/stripesCore.mock'; -import '../../../test/jest/__mock__/stripesIcon.mock'; -import renderWithIntl from '../../../test/jest/helpers/renderWithIntl'; -import translationsProperties from '../../../test/jest/helpers/translationsProperties'; - -import holdingsRecordFilterRenderer from './holdingsRecordFilterRenderer'; - - -import { - getSourceOptions, - getSuppressedOptions, - processFacetOptions, - processStatisticalCodes, -} from '../../facetUtils'; - -jest.mock('../../facetUtils', () => ({ - ...jest.requireActual('../../facetUtils'), - getSourceOptions: jest.fn(), - getSuppressedOptions: jest.fn(), - processFacetOptions: jest.fn(), - processStatisticalCodes: jest.fn(), -})); - -jest.mock('@folio/stripes/components', () => ({ - ...jest.requireActual('@folio/stripes/components'), - Accordion: jest.fn(({ onClearFilter, children }) => ( -
- {children} - -
- )), -}), { virtual: true }); - -jest.mock('../CheckboxFacet/CheckboxFacet', () => ({ onChange }) => ( -
-
CheckboxFacet
- -
-)); - -const onChangeMock = jest.fn(); -const resources = { - facets: { - hasLoaded: true, - resource: 'facets', - records: [{ - 'items.effectiveLocationId': 'effectiveLocationId1', - 'holdings.permanentLocationId': 'permanentLocationId1', - 'holdings.statisticalCodeIds': 'statisticalCodeIds1', - 'holdings.discoverySuppress': 'discoverySuppress1', - 'holdings.sourceId': 'sourceId1', - 'holdingsTags': 'holdingsTags1', - 'holdings.holdingsTypeId': 'holdingsTypeId1', - }], - }, -}; -const DATA = { - - locations: [], - statisticalCodes: [], - holdingsSources: [], - holdingsTypes: [], - tags: [], - query: { filters: '' }, - onFetchFacets: jest.fn(), - parentResources: resources -}; - -const renderFilters = (data = DATA, onChange = onChangeMock) => renderWithIntl( - {holdingsRecordFilterRenderer(data)(onChange)}, - translationsProperties -); - - -describe('holdingsRecordFilterRenderer', () => { - beforeEach(() => { - jest.clearAllMocks(); - }); - - it('processFacetOptions should be called when holdingsRecordFilterRenderer renders', () => { - renderFilters(); - expect(processFacetOptions).toHaveBeenCalledTimes(4); - }); - - it('getSuppressedOptions should be called when holdingsRecordFilterRenderer renders', () => { - renderFilters(); - expect(getSuppressedOptions).toHaveBeenCalledTimes(1); - }); - it('getSourceOptions should be called when holdingsRecordFilterRenderer renders', () => { - renderFilters(); - expect(getSourceOptions).toBeCalled(); - }); - it('processStatisticalCodes should be called when holdingsRecordFilterRenderer renders', () => { - renderFilters(); - expect(processStatisticalCodes).toHaveBeenCalledTimes(1); - }); - - it('onChange function to be called when clearfilter button is clicked', () => { - renderFilters(); - userEvent.click(screen.getAllByRole('button', { name: 'onClearFilter' })[0]); - expect(onChangeMock).toBeCalled(); - }); - it('onChange function to be called when onChange button is clicked', () => { - renderFilters(); - userEvent.click(screen.getAllByRole('button', { name: 'onChange' })[0]); - expect(onChangeMock).toBeCalled(); - }); -}); - - - diff --git a/src/components/HoldingsRecordFilters/index.js b/src/components/HoldingsRecordFilters/index.js deleted file mode 100644 index 7f9729660..000000000 --- a/src/components/HoldingsRecordFilters/index.js +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from './HoldingsRecordFilters'; -export { default as holdingsRecordFilterRenderer } from './holdingsRecordFilterRenderer'; diff --git a/src/components/InstanceFilters/InstanceFilters.js b/src/components/InstanceFilters/InstanceFilters.js deleted file mode 100644 index 8b6f7c4a3..000000000 --- a/src/components/InstanceFilters/InstanceFilters.js +++ /dev/null @@ -1,441 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { FormattedMessage, useIntl } from 'react-intl'; -import _ from 'lodash'; - -import { - Accordion, - AccordionSet, - FilterAccordionHeader, -} from '@folio/stripes/components'; - -import TagsFilter from '../TagsFilter'; -import CheckboxFacet from '../CheckboxFacet'; -import DateRangeFilter from '../DateRangeFilter'; -import { - getSourceOptions, - getSuppressedOptions, - processFacetOptions, - processStatisticalCodes, -} from '../../facetUtils'; -import { - DATE_FORMAT, - FACETS, - FACETS_OPTIONS, - FACETS_SETTINGS, - FACETS_CQL, -} from '../../constants'; -import { useFacets } from '../../common/hooks'; -import { languageOptionsES } from './languages'; -import { - makeDateRangeFilterString, - retrieveDatesFromDateRangeFilterString, -} from '../../utils'; - - -const InstanceFilters = props => { - const { - activeFilters, - data: { - locations, - resourceTypes, - instanceFormats, - instanceStatuses, - modesOfIssuance, - statisticalCodes, - natureOfContentTerms, - }, - onChange, - onClear, - } = props; - - const intl = useIntl(); - - const segmentAccordions = { - [FACETS.EFFECTIVE_LOCATION]: false, - [FACETS.LANGUAGE]: false, - [FACETS.RESOURCE]: false, - [FACETS.FORMAT]: false, - [FACETS.MODE]: false, - [FACETS.NATURE_OF_CONTENT]: false, - [FACETS.STAFF_SUPPRESS]: false, - [FACETS.INSTANCES_DISCOVERY_SUPPRESS]: false, - [FACETS.CREATED_DATE]: false, - [FACETS.UPDATED_DATE]: false, - [FACETS.SOURCE]: false, - [FACETS.STATUS]: false, - [FACETS.INSTANCES_TAGS]: false, - [FACETS.STATISTICAL_CODE_IDS]: false, - }; - - const segmentOptions = { - [FACETS_OPTIONS.EFFECTIVE_LOCATION_OPTIONS]: [], - [FACETS_OPTIONS.LANG_OPTIONS]: [], - [FACETS_OPTIONS.RESOURCE_TYPE_OPTIONS]: [], - [FACETS_OPTIONS.FORMAT_OPTIONS]: [], - [FACETS_OPTIONS.MODE_OF_ISSUANCE_OPTIONS]: [], - [FACETS_OPTIONS.NATURE_OF_CONTENT_OPTIONS]: [], - [FACETS_OPTIONS.SUPPRESSED_OPTIONS]: [], - [FACETS_OPTIONS.INSTANCES_DISCOVERY_SUPPRESS_OPTIONS]: [], - [FACETS_OPTIONS.SOURCE_OPTIONS]: [], - [FACETS_OPTIONS.STATUSES_OPTIONS]: [], - [FACETS_OPTIONS.INSTANCES_TAGS_OPTIONS]: [], - [FACETS_OPTIONS.STATISTICAL_CODES_OPTIONS]: [], - }; - - const selectedFacetFilters = { - [FACETS.EFFECTIVE_LOCATION]: activeFilters[FACETS.EFFECTIVE_LOCATION], - [FACETS.LANGUAGE]: activeFilters[FACETS.LANGUAGE], - [FACETS.RESOURCE]: activeFilters[FACETS.RESOURCE], - [FACETS.FORMAT]: activeFilters[FACETS.FORMAT], - [FACETS.MODE]: activeFilters[FACETS.MODE], - [FACETS.NATURE_OF_CONTENT]: activeFilters[FACETS.NATURE_OF_CONTENT], - [FACETS.STAFF_SUPPRESS]: activeFilters[FACETS.STAFF_SUPPRESS], - [FACETS.INSTANCES_DISCOVERY_SUPPRESS]: activeFilters[FACETS.INSTANCES_DISCOVERY_SUPPRESS], - [FACETS.CREATED_DATE]: activeFilters[FACETS.CREATED_DATE], - [FACETS.UPDATED_DATE]: activeFilters[FACETS.UPDATED_DATE], - [FACETS.SOURCE]: activeFilters[FACETS.SOURCE], - [FACETS.STATUS]: activeFilters[FACETS.STATUS], - [FACETS.INSTANCES_TAGS]: activeFilters[FACETS.INSTANCES_TAGS], - [FACETS.STATISTICAL_CODE_IDS]: activeFilters[FACETS.STATISTICAL_CODE_IDS], - }; - - const getNewRecords = (records) => { - return _.reduce(FACETS_SETTINGS, (accum, name, recordName) => { - if (records[recordName]) { - const recordValues = records[recordName].values; - const commonProps = [recordValues, accum, name]; - - switch (recordName) { - case FACETS_CQL.EFFECTIVE_LOCATION: - processFacetOptions(activeFilters[FACETS.EFFECTIVE_LOCATION], locations, ...commonProps); - break; - case FACETS_CQL.LANGUAGES: - accum[name] = languageOptionsES(activeFilters[FACETS.LANGUAGE], intl, recordValues); - break; - case FACETS_CQL.INSTANCE_TYPE: - processFacetOptions(activeFilters[FACETS.RESOURCE], resourceTypes, ...commonProps); - break; - case FACETS_CQL.INSTANCE_FORMAT: - processFacetOptions(activeFilters[FACETS.FORMAT], instanceFormats, ...commonProps); - break; - case FACETS_CQL.MODE_OF_ISSUANCE: - processFacetOptions(activeFilters[FACETS.MODE], modesOfIssuance, ...commonProps); - break; - case FACETS_CQL.NATURE_OF_CONTENT: - processFacetOptions(activeFilters[FACETS.NATURE_OF_CONTENT], natureOfContentTerms, ...commonProps); - break; - case FACETS_CQL.STAFF_SUPPRESS: - accum[name] = getSuppressedOptions(activeFilters[FACETS.STAFF_SUPPRESS], recordValues); - break; - case FACETS_CQL.INSTANCES_DISCOVERY_SUPPRESS: - accum[name] = getSuppressedOptions(activeFilters[FACETS.INSTANCES_DISCOVERY_SUPPRESS], recordValues); - break; - case FACETS_CQL.SOURCE: - accum[name] = getSourceOptions(activeFilters[FACETS.SOURCE], recordValues); - break; - case FACETS_CQL.STATUS: - processFacetOptions(activeFilters[FACETS.STATUS], instanceStatuses, ...commonProps); - break; - case FACETS_CQL.STATISTICAL_CODE_IDS: - processStatisticalCodes(activeFilters[FACETS.STATISTICAL_CODE_IDS], statisticalCodes, ...commonProps); - break; - case FACETS_CQL.INSTANCES_TAGS: - accum[name] = getSourceOptions(activeFilters[FACETS.INSTANCES_TAGS], recordValues); - break; - default: - } - } - return accum; - }, {}); - }; - - const [ - accordions, - onToggleSection, - handleFetchFacets, - handleFilterSearch, - facetsOptions, - getIsPending, - ] = useFacets( - segmentAccordions, - segmentOptions, - selectedFacetFilters, - getNewRecords, - props.data - ); - - return ( - - } - id={FACETS.EFFECTIVE_LOCATION} - name={FACETS.EFFECTIVE_LOCATION} - separator={false} - header={FilterAccordionHeader} - displayClearButton={activeFilters[FACETS.EFFECTIVE_LOCATION]?.length > 0} - onClearFilter={() => onClear(FACETS.EFFECTIVE_LOCATION)} - > - - - } - id={FACETS.LANGUAGE} - name={FACETS.LANGUAGE} - closedByDefault - header={FilterAccordionHeader} - displayClearButton={activeFilters[FACETS.LANGUAGE]?.length > 0} - onClearFilter={() => onClear(FACETS.LANGUAGE)} - > - - - } - id={FACETS.RESOURCE} - name={FACETS.RESOURCE} - closedByDefault - header={FilterAccordionHeader} - displayClearButton={activeFilters[FACETS.RESOURCE]?.length > 0} - onClearFilter={() => onClear(FACETS.RESOURCE)} - > - - - } - id={FACETS.FORMAT} - name={FACETS.FORMAT} - closedByDefault - header={FilterAccordionHeader} - displayClearButton={activeFilters[FACETS.FORMAT]?.length > 0} - onClearFilter={() => onClear(FACETS.FORMAT)} - > - - - } - id={FACETS.MODE} - name={FACETS.MODE} - closedByDefault - header={FilterAccordionHeader} - displayClearButton={activeFilters[FACETS.MODE]?.length > 0} - onClearFilter={() => onClear(FACETS.MODE)} - > - - - } - id={FACETS.NATURE_OF_CONTENT} - name={FACETS.NATURE_OF_CONTENT} - closedByDefault - header={FilterAccordionHeader} - displayClearButton={activeFilters[FACETS.NATURE_OF_CONTENT]?.length > 0} - onClearFilter={() => onClear(FACETS.NATURE_OF_CONTENT)} - > - - - } - id={FACETS.STAFF_SUPPRESS} - name={FACETS.STAFF_SUPPRESS} - closedByDefault - header={FilterAccordionHeader} - displayClearButton={activeFilters[FACETS.STAFF_SUPPRESS]?.length > 0} - onClearFilter={() => onClear(FACETS.STAFF_SUPPRESS)} - > - - - } - id={FACETS.INSTANCES_DISCOVERY_SUPPRESS} - name={FACETS.INSTANCES_DISCOVERY_SUPPRESS} - closedByDefault - header={FilterAccordionHeader} - displayClearButton={activeFilters[FACETS.INSTANCES_DISCOVERY_SUPPRESS]?.length > 0} - onClearFilter={() => onClear(FACETS.INSTANCES_DISCOVERY_SUPPRESS)} - > - - - } - id={FACETS.STATISTICAL_CODE_IDS} - name={FACETS.STATISTICAL_CODE_IDS} - closedByDefault - header={FilterAccordionHeader} - displayClearButton={activeFilters[FACETS.STATISTICAL_CODE_IDS]?.length > 0} - onClearFilter={() => onClear(FACETS.STATISTICAL_CODE_IDS)} - > - - - } - id={FACETS.CREATED_DATE} - name={FACETS.CREATED_DATE} - closedByDefault - header={FilterAccordionHeader} - displayClearButton={activeFilters[FACETS.CREATED_DATE]?.length > 0} - onClearFilter={() => onClear(FACETS.CREATED_DATE)} - > - - - } - id={FACETS.UPDATED_DATE} - name={FACETS.UPDATED_DATE} - closedByDefault - header={FilterAccordionHeader} - displayClearButton={activeFilters[FACETS.UPDATED_DATE]?.length > 0} - onClearFilter={() => onClear(FACETS.UPDATED_DATE)} - > - - - } - id={FACETS.STATUS} - name={FACETS.STATUS} - closedByDefault - header={FilterAccordionHeader} - displayClearButton={activeFilters[FACETS.STATUS]?.length > 0} - onClearFilter={() => onClear(FACETS.STATUS)} - > - - - } - id={FACETS.SOURCE} - name={FACETS.SOURCE} - closedByDefault - header={FilterAccordionHeader} - displayClearButton={activeFilters[FACETS.SOURCE]?.length > 0} - onClearFilter={() => onClear(FACETS.SOURCE)} - > - - - - - ); -}; - -export default InstanceFilters; - -InstanceFilters.propTypes = { - activeFilters: PropTypes.object, - onChange: PropTypes.func.isRequired, - onClear: PropTypes.func.isRequired, - data: PropTypes.object, -}; - -InstanceFilters.defaultProps = { - activeFilters: {}, -}; diff --git a/src/components/InstanceFilters/InstanceFilters.test.js b/src/components/InstanceFilters/InstanceFilters.test.js deleted file mode 100644 index eb2e4d8b1..000000000 --- a/src/components/InstanceFilters/InstanceFilters.test.js +++ /dev/null @@ -1,208 +0,0 @@ -import React from 'react'; -import '../../../test/jest/__mock__'; -import { BrowserRouter as Router } from 'react-router-dom'; -import { screen, waitFor } from '@testing-library/react'; -import { ModuleHierarchyProvider } from '@folio/stripes-core/src/components/ModuleHierarchy'; - -import userEvent from '@testing-library/user-event'; -import renderWithIntl from '../../../test/jest/helpers/renderWithIntl'; -import { - FACETS -} from '../../constants'; -import InstanceFilters from './InstanceFilters'; -import translationsProperties from '../../../test/jest/helpers/translationsProperties'; - -jest.mock('../CheckboxFacet/CheckboxFacet', () => jest.fn().mockReturnValue('CheckboxFacet')); - -jest.mock('../../facetUtils', () => ({ - ...jest.requireActual('../../facetUtils'), - getSourceOptions: jest.fn(), - getSuppressedOptions: jest.fn(), -})); - -const activeFilters = { - [FACETS.EFFECTIVE_LOCATION]: ['loc1'], - [FACETS.ITEM_STATUS]: ['ITEM_STATUS1'], - [FACETS.RESOURCE]: ['RESOURCE1'], - [FACETS.FORMAT]: ['Format1'], - [FACETS.MODE]: ['Mode1'], - [FACETS.NATURE_OF_CONTENT]: ['NATUREOFCONTENT1'], - [FACETS.STAFF_SUPPRESS]: ['STAFFSUPPRESS1'], - [FACETS.INSTANCES_DISCOVERY_SUPPRESS]: ['DISCOVERYSUPPRESS1'], - [FACETS.STATISTICAL_CODE_IDS]: ['STATISTICALCODEIDS1'], - [FACETS.CREATED_DATE]: ['2022-01-01'], - [FACETS.UPDATED_DATE]: ['2022-01-01'], - [FACETS.STATUS]: ['STATUS1'], - [FACETS.SOURCE]: ['SOURCE1'] -}; - -const resources = { - facets: { - hasLoaded: true, - resource: 'facets', - records: [{ - 'items.effectiveLocationId': 'effectiveLocationId1', - 'languages': 'languages', - 'statisticalCodeIds': 'statisticalCodeIds1', - 'discoverySuppress': 'discoverySuppress1', - 'source': 'source1', - 'instanceTags': 'instanceTags1', - 'statusId': 'statusId1', - 'staffSuppress': 'staffSuppress1', - 'natureOfContentTermIds': 'natureOfContentTermIds1', - 'modeOfIssuanceId': 'modeOfIssuanceId1', - 'instanceFormatIds': 'instanceFormatIds1', - 'instanceTypeId': 'instanceTypeId1', - }], - other: { totalRecords: 0 } - }, -}; - -const data = { - locations: [], - resourceTypes: [], - instanceFormats: [], - modesOfIssuance: [], - statisticalCodes: [], - tagsRecords: [], - natureOfContentTerms: [], - query: [], - onFetchFacets: jest.fn(), - parentResources: resources, -}; -const onChange = jest.fn(); -const onClear = jest.fn(); -const renderInstanceFilters = () => { - return renderWithIntl( - - - - - , - translationsProperties - ); -}; - -describe('InstanceFilters', () => { - it('Should Clear selected filters for effective Location', async () => { - renderInstanceFilters(); - const Clearselectedfilters = screen.getAllByRole('button'); - userEvent.click(Clearselectedfilters[1]); - await waitFor(() => { - expect(onClear).toBeCalled(); - }); - }); - it('Should Clear selected filters for language', async () => { - renderInstanceFilters(); - const Clearselectedfilters = screen.getAllByRole('button'); - userEvent.click(Clearselectedfilters[3]); - await waitFor(() => { - expect(onClear).toBeCalled(); - }); - }); - - it('Should Clear selected filters for resource', async () => { - renderInstanceFilters(); - const Clearselectedfilters = screen.getAllByRole('button'); - userEvent.click(Clearselectedfilters[5]); - await waitFor(() => { - expect(onClear).toBeCalled(); - }); - }); - - it('Should Clear selected filters for format', async () => { - renderInstanceFilters(); - const Clearselectedfilters = screen.getAllByRole('button'); - userEvent.click(Clearselectedfilters[7]); - await waitFor(() => { - expect(onClear).toBeCalled(); - }); - }); - - it('Should Clear selected filters for mode', async () => { - renderInstanceFilters(); - const Clearselectedfilters = screen.getAllByRole('button'); - userEvent.click(Clearselectedfilters[9]); - await waitFor(() => { - expect(onClear).toBeCalled(); - }); - }); - - it('Should Clear selected filters for nature Of Content', async () => { - renderInstanceFilters(); - const Clearselectedfilters = screen.getAllByRole('button'); - userEvent.click(Clearselectedfilters[11]); - await waitFor(() => { - expect(onClear).toBeCalled(); - }); - }); - - it('Should Clear selected filters for staffSuppress', async () => { - renderInstanceFilters(); - const Clearselectedfilters = screen.getAllByRole('button'); - userEvent.click(Clearselectedfilters[13]); - await waitFor(() => { - expect(onClear).toBeCalled(); - }); - }); - - it('Should Clear selected filters for Suppress from discovery', async () => { - renderInstanceFilters(); - const Clearselectedfilters = screen.getAllByRole('button'); - userEvent.click(Clearselectedfilters[15]); - await waitFor(() => { - expect(onClear).toBeCalled(); - }); - }); - - it('Should Clear selected filters for Statistical code filter list', async () => { - renderInstanceFilters(); - const Clearselectedfilters = screen.getAllByRole('button'); - userEvent.click(Clearselectedfilters[17]); - await waitFor(() => { - expect(onClear).toBeCalled(); - }); - }); - - it('Should Clear selected filters for Date created filter list', async () => { - renderInstanceFilters(); - const Clearselectedfilters = screen.getAllByRole('button'); - userEvent.click(Clearselectedfilters[19]); - await waitFor(() => { - expect(onClear).toBeCalled(); - }); - }); - - it('Should Clear selected filters for Date updated filter list', async () => { - renderInstanceFilters(); - const Clearselectedfilters = screen.getAllByRole('button'); - userEvent.click(Clearselectedfilters[26]); - await waitFor(() => { - expect(onClear).toBeCalled(); - }); - }); - - it('Should Clear selected filters for Instance status filter list', async () => { - renderInstanceFilters(); - const Clearselectedfilters = screen.getAllByRole('button'); - userEvent.click(Clearselectedfilters[33]); - await waitFor(() => { - expect(onClear).toBeCalled(); - }); - }); - - it('Should Clear selected filters for Source filter list', async () => { - renderInstanceFilters(); - const Clearselectedfilters = screen.getAllByRole('button'); - userEvent.click(Clearselectedfilters[35]); - await waitFor(() => { - expect(onClear).toBeCalled(); - }); - }); -}); diff --git a/src/components/InstanceFilters/InstanceFiltersBrowse/InstanceFiltersBrowse.js b/src/components/InstanceFilters/InstanceFiltersBrowse/InstanceFiltersBrowse.js deleted file mode 100644 index 1db4ec561..000000000 --- a/src/components/InstanceFilters/InstanceFiltersBrowse/InstanceFiltersBrowse.js +++ /dev/null @@ -1,138 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { FormattedMessage } from 'react-intl'; -import _ from 'lodash'; - -import { - Accordion, - AccordionSet, - FilterAccordionHeader, -} from '@folio/stripes/components'; - -import CheckboxFacet from '../../CheckboxFacet'; -import { MultiSelectionFacet } from '../../MultiSelectionFacet'; -import { processFacetOptions } from '../../../facetUtils'; -import { - FACETS, - FACETS_OPTIONS, - FACETS_SETTINGS, - FACETS_CQL, - browseModeOptions, -} from '../../../constants'; -import { useFacets } from '../../../common/hooks'; - -const InstanceFiltersBrowse = props => { - const { - activeFilters, - data: { - locations, - browseType, - contributorNameTypes, - }, - onChange, - onClear, - } = props; - - const segmentAccordions = { - [FACETS.EFFECTIVE_LOCATION]: false, - [FACETS.NAME_TYPE]: false, - }; - - const segmentOptions = { - [FACETS_OPTIONS.EFFECTIVE_LOCATION_OPTIONS]: [], - [FACETS_OPTIONS.NAME_TYPE_OPTIONS]: [], - }; - - const selectedFacetFilters = { - [FACETS.EFFECTIVE_LOCATION]: activeFilters[FACETS.EFFECTIVE_LOCATION], - [FACETS.NAME_TYPE]: activeFilters[FACETS.NAME_TYPE], - }; - - const getNewRecords = (records) => { - return _.reduce(FACETS_SETTINGS, (accum, name, recordName) => { - if (records[recordName]) { - const recordValues = records[recordName].values; - const commonProps = [recordValues, accum, name]; - - if (recordName === FACETS_CQL.EFFECTIVE_LOCATION) { - processFacetOptions(activeFilters[FACETS.EFFECTIVE_LOCATION], locations, ...commonProps); - } - if (recordName === FACETS_CQL.NAME_TYPE) { - processFacetOptions(activeFilters[FACETS.NAME_TYPE], contributorNameTypes, ...commonProps); - } - } - return accum; - }, {}); - }; - - const [ - accordions, - onToggleSection, - handleFetchFacets, - handleFilterSearch, - facetsOptions, - getIsPending, - ] = useFacets( - segmentAccordions, - segmentOptions, - selectedFacetFilters, - getNewRecords, - props.data - ); - - return ( - - { - browseType === browseModeOptions.CALL_NUMBERS && ( - } - id={FACETS.EFFECTIVE_LOCATION} - name={FACETS.EFFECTIVE_LOCATION} - separator={false} - header={FilterAccordionHeader} - displayClearButton={activeFilters[FACETS.EFFECTIVE_LOCATION]?.length > 0} - onClearFilter={() => onClear(FACETS.EFFECTIVE_LOCATION)} - > - - - )} - { - browseType === browseModeOptions.CONTRIBUTORS && ( - } - name={FACETS.NAME_TYPE} - closedByDefault - options={facetsOptions[FACETS_OPTIONS.NAME_TYPE_OPTIONS]} - selectedValues={activeFilters[FACETS.NAME_TYPE]} - onFilterChange={onChange} - onClearFilter={() => onClear(FACETS.NAME_TYPE)} - displayClearButton={!!activeFilters[FACETS.NAME_TYPE]?.length} - isPending={getIsPending(FACETS.NAME_TYPE)} - /> - )} - - ); -}; - -export default InstanceFiltersBrowse; - -InstanceFiltersBrowse.propTypes = { - activeFilters: PropTypes.object, - onChange: PropTypes.func.isRequired, - onClear: PropTypes.func.isRequired, - data: PropTypes.object, -}; - -InstanceFiltersBrowse.defaultProps = { - activeFilters: {}, -}; diff --git a/src/components/InstanceFilters/InstanceFiltersBrowse/index.js b/src/components/InstanceFilters/InstanceFiltersBrowse/index.js deleted file mode 100644 index 1ce13049a..000000000 --- a/src/components/InstanceFilters/InstanceFiltersBrowse/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './InstanceFiltersBrowse'; diff --git a/src/components/InstanceFilters/InstanceFiltersBrowse/instanceFiltersBrowse.test.js b/src/components/InstanceFilters/InstanceFiltersBrowse/instanceFiltersBrowse.test.js deleted file mode 100644 index cbc74eee2..000000000 --- a/src/components/InstanceFilters/InstanceFiltersBrowse/instanceFiltersBrowse.test.js +++ /dev/null @@ -1,107 +0,0 @@ -import React from 'react'; -import { BrowserRouter as Router } from 'react-router-dom'; -import { noop } from 'lodash'; -import { - screen, - fireEvent, -} from '@testing-library/react'; - -import '../../../../test/jest/__mock__'; - -import { ModuleHierarchyProvider } from '@folio/stripes/core'; - -import renderWithIntl from '../../../../test/jest/helpers/renderWithIntl'; -import translations from '../../../../test/jest/helpers/translationsProperties'; - -import InstanceFiltersBrowse from './InstanceFiltersBrowse'; - -jest.mock('../../MultiSelectionFacet', () => ({ - MultiSelectionFacet: ({ name, onClearFilter }) => ( -
- {name} - -
- ), -})); - -const mockOnChange = jest.fn(); -const mockOnClear = jest.fn(); - -const resources = { - facets: { - hasLoaded: true, - resource: 'facets', - records: [{ - 'id': 'd3c8b511-41e7-422e-a483-18778d0596e5', - 'label': 'important', - 'description': 'important', - }, - { - 'id': 'b822d5a8-1750-4b5f-92bd-9fc73a05ddda', - 'label': 'new', - 'description': 'new', - }], - other: { totalRecords: 0 } - }, -}; - -const data = { - locations: [], - query: [], - onFetchFacets: noop, - parentResources: resources, - browseType: 'callNumbers', -}; - -const renderInstanceFilters = (props = {}) => { - return renderWithIntl( - - - - - , - translations - ); -}; - -describe('InstanceFilters', () => { - it('Contains a filter for creation date ', () => { - const { debug } = renderInstanceFilters(); - - debug(); - expect(screen.getByText('Effective location (item)')).toBeInTheDocument(); - }); - - describe('When contributors browseType was selected', () => { - it('should display filter by nameType accordion', () => { - const { getByText } = renderInstanceFilters({ - data: { - ...data, - browseType: 'contributors', - }, - }); - - fireEvent.click(screen.getByText('Clear nameType')); - - expect(getByText('nameType')).toBeInTheDocument(); - expect(mockOnClear).toHaveBeenCalled(); - }); - }); - - describe('When callNumber browseType was selected', () => { - it('should call onClear handler if clear btn is clicked', () => { - renderInstanceFilters(); - fireEvent.click(screen.getByText('effectiveLocation-field')); - - expect(mockOnClear).toHaveBeenCalled(); - }); - }); -}); - diff --git a/src/components/InstanceFilters/index.js b/src/components/InstanceFilters/index.js deleted file mode 100644 index 11f27b1b7..000000000 --- a/src/components/InstanceFilters/index.js +++ /dev/null @@ -1,3 +0,0 @@ -export { default } from './InstanceFilters'; -export { default as InstanceFiltersBrowse } from './InstanceFiltersBrowse'; -export { default as instanceFilterRenderer } from './instanceFilterRenderer'; diff --git a/src/components/InstanceFilters/instanceFilterRenderer.js b/src/components/InstanceFilters/instanceFilterRenderer.js deleted file mode 100644 index e9f036147..000000000 --- a/src/components/InstanceFilters/instanceFilterRenderer.js +++ /dev/null @@ -1,54 +0,0 @@ -import React from 'react'; -import { get } from 'lodash'; - -import InstanceFilters from './InstanceFilters'; -import { getCurrentFilters } from '../../utils'; -import facetsStore from '../../stores/facetsStore'; - -// instanceFilterRenderer is a function that takes a single argument `data` -// and returns a function that takes a single argument `onChange`. -const instanceFilterRenderer = data => onChange => { - const { - locations, - instanceTypes, - instanceFormats, - instanceStatuses, - modesOfIssuance, - natureOfContentTerms, - query, - tags, - onFetchFacets, - parentResources, - statisticalCodes, - } = data; - - const activeFilters = getCurrentFilters(get(query, 'filters', '')); - - const dataProp = { - locations, - resourceTypes: instanceTypes, - instanceFormats, - modesOfIssuance, - tagsRecords: tags, - natureOfContentTerms, - statisticalCodes, - query, - onFetchFacets, - parentResources, - instanceStatuses, - }; - - return ( - { - facetsStore.getState().resetFacetByName(name); - onChange({ name, values: [] }); - }} - /> - ); -}; - -export default instanceFilterRenderer; diff --git a/src/components/InstanceFilters/languages.js b/src/components/InstanceFilters/languages.js deleted file mode 100644 index 339082eff..000000000 --- a/src/components/InstanceFilters/languages.js +++ /dev/null @@ -1,561 +0,0 @@ -// This file should be removed after stripes-components release. -// Also in InstanceFilters.js we need to change the import of the -// languageOptionsES function to '@folio/stripes-components/util/languages' -// and replace the languageOptionsES function from the stripes-component with -// the languageOptionsES function from the current file. - -import { find } from 'lodash'; - -// This list is derived from the table provided at https://www.loc.gov/standards/iso639-2/ascii_8bits.html -// It uses the ISO 639-2 standard. Not all language names have both a two-character and three-character -// code, but both are provided when available. -const languages = [ - { alpha3: 'aar', alpha2: 'aa', name: 'Afar' }, - { alpha3: 'abk', alpha2: 'ab', name: 'Abkhazian' }, - { alpha3: 'ace', alpha2: '', name: 'Achinese' }, - { alpha3: 'ach', alpha2: '', name: 'Acoli' }, - { alpha3: 'ada', alpha2: '', name: 'Adangme' }, - { alpha3: 'ady', alpha2: '', name: 'Adyghe; Adygei' }, - { alpha3: 'afa', alpha2: '', name: 'Afro-Asiatic languages' }, - { alpha3: 'afh', alpha2: '', name: 'Afrihili' }, - { alpha3: 'afr', alpha2: 'af', name: 'Afrikaans' }, - { alpha3: 'ain', alpha2: '', name: 'Ainu' }, - { alpha3: 'aka', alpha2: 'ak', name: 'Akan' }, - { alpha3: 'akk', alpha2: '', name: 'Akkadian' }, - { alpha3: 'alb', alpha2: 'sq', name: 'Albanian' }, - { alpha3: 'ale', alpha2: '', name: 'Aleut' }, - { alpha3: 'alg', alpha2: '', name: 'Algonquian languages' }, - { alpha3: 'alt', alpha2: '', name: 'Southern Altai' }, - { alpha3: 'amh', alpha2: 'am', name: 'Amharic' }, - { alpha3: 'ang', alpha2: '', name: 'English, Old (ca.450-1100)' }, - { alpha3: 'anp', alpha2: '', name: 'Angika' }, - { alpha3: 'apa', alpha2: '', name: 'Apache languages' }, - { alpha3: 'ara', alpha2: 'ar', name: 'Arabic' }, - { alpha3: 'arc', alpha2: '', name: 'Official Aramaic (700-300 BCE); Imperial Aramaic (700-300 BCE)' }, - { alpha3: 'arg', alpha2: 'an', name: 'Aragonese' }, - { alpha3: 'arm', alpha2: 'hy', name: 'Armenian' }, - { alpha3: 'arn', alpha2: '', name: 'Mapudungun; Mapuche' }, - { alpha3: 'arp', alpha2: '', name: 'Arapaho' }, - { alpha3: 'art', alpha2: '', name: 'Artificial languages' }, - { alpha3: 'arw', alpha2: '', name: 'Arawak' }, - { alpha3: 'asm', alpha2: 'as', name: 'Assamese' }, - { alpha3: 'ast', alpha2: '', name: 'Asturian; Bable; Leonese; Asturleonese' }, - { alpha3: 'ath', alpha2: '', name: 'Athapascan languages' }, - { alpha3: 'aus', alpha2: '', name: 'Australian languages' }, - { alpha3: 'ava', alpha2: 'av', name: 'Avaric' }, - { alpha3: 'ave', alpha2: 'ae', name: 'Avestan' }, - { alpha3: 'awa', alpha2: '', name: 'Awadhi' }, - { alpha3: 'aym', alpha2: 'ay', name: 'Aymara' }, - { alpha3: 'aze', alpha2: 'az', name: 'Azerbaijani' }, - { alpha3: 'bad', alpha2: '', name: 'Banda languages' }, - { alpha3: 'bai', alpha2: '', name: 'Bamileke languages' }, - { alpha3: 'bak', alpha2: 'ba', name: 'Bashkir' }, - { alpha3: 'bal', alpha2: '', name: 'Baluchi' }, - { alpha3: 'bam', alpha2: 'bm', name: 'Bambara' }, - { alpha3: 'ban', alpha2: '', name: 'Balinese' }, - { alpha3: 'baq', alpha2: 'eu', name: 'Basque' }, - { alpha3: 'bas', alpha2: '', name: 'Basa' }, - { alpha3: 'bat', alpha2: '', name: 'Baltic languages' }, - { alpha3: 'bej', alpha2: '', name: 'Beja; Bedawiyet' }, - { alpha3: 'bel', alpha2: 'be', name: 'Belarusian' }, - { alpha3: 'bem', alpha2: '', name: 'Bemba' }, - { alpha3: 'ben', alpha2: 'bn', name: 'Bengali' }, - { alpha3: 'ber', alpha2: '', name: 'Berber languages' }, - { alpha3: 'bho', alpha2: '', name: 'Bhojpuri' }, - { alpha3: 'bih', alpha2: 'bh', name: 'Bihari languages' }, - { alpha3: 'bik', alpha2: '', name: 'Bikol' }, - { alpha3: 'bin', alpha2: '', name: 'Bini; Edo' }, - { alpha3: 'bis', alpha2: 'bi', name: 'Bislama' }, - { alpha3: 'bla', alpha2: '', name: 'Siksika' }, - { alpha3: 'bnt', alpha2: '', name: 'Bantu languages' }, - { alpha3: 'bos', alpha2: 'bs', name: 'Bosnian' }, - { alpha3: 'bra', alpha2: '', name: 'Braj' }, - { alpha3: 'bre', alpha2: 'br', name: 'Breton' }, - { alpha3: 'btk', alpha2: '', name: 'Batak languages' }, - { alpha3: 'bua', alpha2: '', name: 'Buriat' }, - { alpha3: 'bug', alpha2: '', name: 'Buginese' }, - { alpha3: 'bul', alpha2: 'bg', name: 'Bulgarian' }, - { alpha3: 'bur', alpha2: 'my', name: 'Burmese' }, - { alpha3: 'byn', alpha2: '', name: 'Blin; Bilin' }, - { alpha3: 'cad', alpha2: '', name: 'Caddo' }, - { alpha3: 'cai', alpha2: '', name: 'Central American Indian languages' }, - { alpha3: 'car', alpha2: '', name: 'Galibi Carib' }, - { alpha3: 'cat', alpha2: 'ca', name: 'Catalan; Valencian' }, - { alpha3: 'cau', alpha2: '', name: 'Caucasian languages' }, - { alpha3: 'ceb', alpha2: '', name: 'Cebuano' }, - { alpha3: 'cel', alpha2: '', name: 'Celtic languages' }, - { alpha3: 'cha', alpha2: 'ch', name: 'Chamorro' }, - { alpha3: 'chb', alpha2: '', name: 'Chibcha' }, - { alpha3: 'che', alpha2: 'ce', name: 'Chechen' }, - { alpha3: 'chg', alpha2: '', name: 'Chagatai' }, - { alpha3: 'chi', alpha2: 'zh', name: 'Chinese' }, - { alpha3: 'chk', alpha2: '', name: 'Chuukese' }, - { alpha3: 'chm', alpha2: '', name: 'Mari' }, - { alpha3: 'chn', alpha2: '', name: 'Chinook jargon' }, - { alpha3: 'cho', alpha2: '', name: 'Choctaw' }, - { alpha3: 'chp', alpha2: '', name: 'Chipewyan; Dene Suline' }, - { alpha3: 'chr', alpha2: '', name: 'Cherokee' }, - { - alpha3: 'chu', - alpha2: 'cu', - name: 'Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church Slavonic' - }, - { alpha3: 'chv', alpha2: 'cv', name: 'Chuvash' }, - { alpha3: 'chy', alpha2: '', name: 'Cheyenne' }, - { alpha3: 'cmc', alpha2: '', name: 'Chamic languages' }, - { alpha3: 'cnr', alpha2: '', name: 'Montenegrin' }, - { alpha3: 'cop', alpha2: '', name: 'Coptic' }, - { alpha3: 'cor', alpha2: 'kw', name: 'Cornish' }, - { alpha3: 'cos', alpha2: 'co', name: 'Corsican' }, - { alpha3: 'cpe', alpha2: '', name: 'Creoles and pidgins, English based' }, - { alpha3: 'cpf', alpha2: '', name: 'Creoles and pidgins, French-based' }, - { alpha3: 'cpp', alpha2: '', name: 'Creoles and pidgins, Portuguese-based' }, - { alpha3: 'cre', alpha2: 'cr', name: 'Cree' }, - { alpha3: 'crh', alpha2: '', name: 'Crimean Tatar; Crimean Turkish' }, - { alpha3: 'crp', alpha2: '', name: 'Creoles and pidgins' }, - { alpha3: 'csb', alpha2: '', name: 'Kashubian' }, - { alpha3: 'cus', alpha2: '', name: 'Cushitic languages' }, - { alpha3: 'cze', alpha2: 'cs', name: 'Czech' }, - { alpha3: 'dak', alpha2: '', name: 'Dakota' }, - { alpha3: 'dan', alpha2: 'da', name: 'Danish' }, - { alpha3: 'dar', alpha2: '', name: 'Dargwa' }, - { alpha3: 'day', alpha2: '', name: 'Land Dayak languages' }, - { alpha3: 'del', alpha2: '', name: 'Delaware' }, - { alpha3: 'den', alpha2: '', name: 'Slave (Athapascan)' }, - { alpha3: 'dgr', alpha2: '', name: 'Dogrib' }, - { alpha3: 'din', alpha2: '', name: 'Dinka' }, - { alpha3: 'div', alpha2: 'dv', name: 'Divehi; Dhivehi; Maldivian' }, - { alpha3: 'doi', alpha2: '', name: 'Dogri' }, - { alpha3: 'dra', alpha2: '', name: 'Dravidian languages' }, - { alpha3: 'dsb', alpha2: '', name: 'Lower Sorbian' }, - { alpha3: 'dua', alpha2: '', name: 'Duala' }, - { alpha3: 'dum', alpha2: '', name: 'Dutch, Middle (ca.1050-1350)' }, - { alpha3: 'dut', alpha2: 'nl', name: 'Dutch; Flemish' }, - { alpha3: 'dyu', alpha2: '', name: 'Dyula' }, - { alpha3: 'dzo', alpha2: 'dz', name: 'Dzongkha' }, - { alpha3: 'efi', alpha2: '', name: 'Efik' }, - { alpha3: 'egy', alpha2: '', name: 'Egyptian (Ancient)' }, - { alpha3: 'eka', alpha2: '', name: 'Ekajuk' }, - { alpha3: 'elx', alpha2: '', name: 'Elamite' }, - { alpha3: 'eng', alpha2: 'en', name: 'English' }, - { alpha3: 'enm', alpha2: '', name: 'English, Middle (1100-1500)' }, - { alpha3: 'epo', alpha2: 'eo', name: 'Esperanto' }, - { alpha3: 'est', alpha2: 'et', name: 'Estonian' }, - { alpha3: 'ewe', alpha2: 'ee', name: 'Ewe' }, - { alpha3: 'ewo', alpha2: '', name: 'Ewondo' }, - { alpha3: 'fan', alpha2: '', name: 'Fang' }, - { alpha3: 'fao', alpha2: 'fo', name: 'Faroese' }, - { alpha3: 'fat', alpha2: '', name: 'Fanti' }, - { alpha3: 'fij', alpha2: 'fj', name: 'Fijian' }, - { alpha3: 'fil', alpha2: '', name: 'Filipino; Pilipino' }, - { alpha3: 'fin', alpha2: 'fi', name: 'Finnish' }, - { alpha3: 'fiu', alpha2: '', name: 'Finno-Ugrian languages' }, - { alpha3: 'fon', alpha2: '', name: 'Fon' }, - { alpha3: 'fre', alpha2: 'fr', name: 'French' }, - { alpha3: 'frm', alpha2: '', name: 'French, Middle (ca.1400-1600)' }, - { alpha3: 'fro', alpha2: '', name: 'French, Old (842-ca.1400)' }, - { alpha3: 'frr', alpha2: '', name: 'Northern Frisian' }, - { alpha3: 'frs', alpha2: '', name: 'Eastern Frisian' }, - { alpha3: 'fry', alpha2: 'fy', name: 'Western Frisian' }, - { alpha3: 'ful', alpha2: 'ff', name: 'Fulah' }, - { alpha3: 'fur', alpha2: '', name: 'Friulian' }, - { alpha3: 'gaa', alpha2: '', name: 'Ga' }, - { alpha3: 'gay', alpha2: '', name: 'Gayo' }, - { alpha3: 'gba', alpha2: '', name: 'Gbaya' }, - { alpha3: 'gem', alpha2: '', name: 'Germanic languages' }, - { alpha3: 'geo', alpha2: 'ka', name: 'Georgian' }, - { alpha3: 'ger', alpha2: 'de', name: 'German' }, - { alpha3: 'gez', alpha2: '', name: 'Geez' }, - { alpha3: 'gil', alpha2: '', name: 'Gilbertese' }, - { alpha3: 'gla', alpha2: 'gd', name: 'Gaelic; Scottish Gaelic' }, - { alpha3: 'gle', alpha2: 'ga', name: 'Irish' }, - { alpha3: 'glg', alpha2: 'gl', name: 'Galician' }, - { alpha3: 'glv', alpha2: 'gv', name: 'Manx' }, - { alpha3: 'gmh', alpha2: '', name: 'German, Middle High (ca.1050-1500)' }, - { alpha3: 'goh', alpha2: '', name: 'German, Old High (ca.750-1050)' }, - { alpha3: 'gon', alpha2: '', name: 'Gondi' }, - { alpha3: 'gor', alpha2: '', name: 'Gorontalo' }, - { alpha3: 'got', alpha2: '', name: 'Gothic' }, - { alpha3: 'grb', alpha2: '', name: 'Grebo' }, - { alpha3: 'grc', alpha2: '', name: 'Greek, Ancient (to 1453)' }, - { alpha3: 'gre', alpha2: 'el', name: 'Greek, Modern (1453-)' }, - { alpha3: 'grn', alpha2: 'gn', name: 'Guarani' }, - { alpha3: 'gsw', alpha2: '', name: 'Swiss German; Alemannic; Alsatian' }, - { alpha3: 'guj', alpha2: 'gu', name: 'Gujarati' }, - { alpha3: 'gwi', alpha2: '', name: 'Gwich\'in' }, - { alpha3: 'hai', alpha2: '', name: 'Haida' }, - { alpha3: 'hat', alpha2: 'ht', name: 'Haitian; Haitian Creole' }, - { alpha3: 'hau', alpha2: 'ha', name: 'Hausa' }, - { alpha3: 'haw', alpha2: '', name: 'Hawaiian' }, - { alpha3: 'heb', alpha2: 'he', name: 'Hebrew' }, - { alpha3: 'her', alpha2: 'hz', name: 'Herero' }, - { alpha3: 'hil', alpha2: '', name: 'Hiligaynon' }, - { alpha3: 'him', alpha2: '', name: 'Himachali languages; Western Pahari languages' }, - { alpha3: 'hin', alpha2: 'hi', name: 'Hindi' }, - { alpha3: 'hit', alpha2: '', name: 'Hittite' }, - { alpha3: 'hmn', alpha2: '', name: 'Hmong; Mong' }, - { alpha3: 'hmo', alpha2: 'ho', name: 'Hiri Motu' }, - { alpha3: 'hrv', alpha2: 'hr', name: 'Croatian' }, - { alpha3: 'hsb', alpha2: '', name: 'Upper Sorbian' }, - { alpha3: 'hun', alpha2: 'hu', name: 'Hungarian' }, - { alpha3: 'hup', alpha2: '', name: 'Hupa' }, - { alpha3: 'iba', alpha2: '', name: 'Iban' }, - { alpha3: 'ibo', alpha2: 'ig', name: 'Igbo' }, - { alpha3: 'ice', alpha2: 'is', name: 'Icelandic' }, - { alpha3: 'ido', alpha2: 'io', name: 'Ido' }, - { alpha3: 'iii', alpha2: 'ii', name: 'Sichuan Yi; Nuosu' }, - { alpha3: 'ijo', alpha2: '', name: 'Ijo languages' }, - { alpha3: 'iku', alpha2: 'iu', name: 'Inuktitut' }, - { alpha3: 'ile', alpha2: 'ie', name: 'Interlingue; Occidental' }, - { alpha3: 'ilo', alpha2: '', name: 'Iloko' }, - { alpha3: 'ina', alpha2: 'ia', name: 'Interlingua (International Auxiliary Language Association)' }, - { alpha3: 'inc', alpha2: '', name: 'Indic languages' }, - { alpha3: 'ind', alpha2: 'id', name: 'Indonesian' }, - { alpha3: 'ine', alpha2: '', name: 'Indo-European languages' }, - { alpha3: 'inh', alpha2: '', name: 'Ingush' }, - { alpha3: 'ipk', alpha2: 'ik', name: 'Inupiaq' }, - { alpha3: 'ira', alpha2: '', name: 'Iranian languages' }, - { alpha3: 'iro', alpha2: '', name: 'Iroquoian languages' }, - { alpha3: 'ita', alpha2: 'it', name: 'Italian' }, - { alpha3: 'jav', alpha2: 'jv', name: 'Javanese' }, - { alpha3: 'jbo', alpha2: '', name: 'Lojban' }, - { alpha3: 'jpn', alpha2: 'ja', name: 'Japanese' }, - { alpha3: 'jpr', alpha2: '', name: 'Judeo-Persian' }, - { alpha3: 'jrb', alpha2: '', name: 'Judeo-Arabic' }, - { alpha3: 'kaa', alpha2: '', name: 'Kara-Kalpak' }, - { alpha3: 'kab', alpha2: '', name: 'Kabyle' }, - { alpha3: 'kac', alpha2: '', name: 'Kachin; Jingpho' }, - { alpha3: 'kal', alpha2: 'kl', name: 'Kalaallisut; Greenlandic' }, - { alpha3: 'kam', alpha2: '', name: 'Kamba' }, - { alpha3: 'kan', alpha2: 'kn', name: 'Kannada' }, - { alpha3: 'kar', alpha2: '', name: 'Karen languages' }, - { alpha3: 'kas', alpha2: 'ks', name: 'Kashmiri' }, - { alpha3: 'kau', alpha2: 'kr', name: 'Kanuri' }, - { alpha3: 'kaw', alpha2: '', name: 'Kawi' }, - { alpha3: 'kaz', alpha2: 'kk', name: 'Kazakh' }, - { alpha3: 'kbd', alpha2: '', name: 'Kabardian' }, - { alpha3: 'kha', alpha2: '', name: 'Khasi' }, - { alpha3: 'khi', alpha2: '', name: 'Khoisan languages' }, - { alpha3: 'khm', alpha2: 'km', name: 'Central Khmer' }, - { alpha3: 'kho', alpha2: '', name: 'Khotanese; Sakan' }, - { alpha3: 'kik', alpha2: 'ki', name: 'Kikuyu; Gikuyu' }, - { alpha3: 'kin', alpha2: 'rw', name: 'Kinyarwanda' }, - { alpha3: 'kir', alpha2: 'ky', name: 'Kirghiz; Kyrgyz' }, - { alpha3: 'kmb', alpha2: '', name: 'Kimbundu' }, - { alpha3: 'kok', alpha2: '', name: 'Konkani' }, - { alpha3: 'kom', alpha2: 'kv', name: 'Komi' }, - { alpha3: 'kon', alpha2: 'kg', name: 'Kongo' }, - { alpha3: 'kor', alpha2: 'ko', name: 'Korean' }, - { alpha3: 'kos', alpha2: '', name: 'Kosraean' }, - { alpha3: 'kpe', alpha2: '', name: 'Kpelle' }, - { alpha3: 'krc', alpha2: '', name: 'Karachay-Balkar' }, - { alpha3: 'krl', alpha2: '', name: 'Karelian' }, - { alpha3: 'kro', alpha2: '', name: 'Kru languages' }, - { alpha3: 'kru', alpha2: '', name: 'Kurukh' }, - { alpha3: 'kua', alpha2: 'kj', name: 'Kuanyama; Kwanyama' }, - { alpha3: 'kum', alpha2: '', name: 'Kumyk' }, - { alpha3: 'kur', alpha2: 'ku', name: 'Kurdish' }, - { alpha3: 'kut', alpha2: '', name: 'Kutenai' }, - { alpha3: 'lad', alpha2: '', name: 'Ladino' }, - { alpha3: 'lah', alpha2: '', name: 'Lahnda' }, - { alpha3: 'lam', alpha2: '', name: 'Lamba' }, - { alpha3: 'lao', alpha2: 'lo', name: 'Lao' }, - { alpha3: 'lat', alpha2: 'la', name: 'Latin' }, - { alpha3: 'lav', alpha2: 'lv', name: 'Latvian' }, - { alpha3: 'lez', alpha2: '', name: 'Lezghian' }, - { alpha3: 'lim', alpha2: 'li', name: 'Limburgan; Limburger; Limburgish' }, - { alpha3: 'lin', alpha2: 'ln', name: 'Lingala' }, - { alpha3: 'lit', alpha2: 'lt', name: 'Lithuanian' }, - { alpha3: 'lol', alpha2: '', name: 'Mongo' }, - { alpha3: 'loz', alpha2: '', name: 'Lozi' }, - { alpha3: 'ltz', alpha2: 'lb', name: 'Luxembourgish; Letzeburgesch' }, - { alpha3: 'lua', alpha2: '', name: 'Luba-Lulua' }, - { alpha3: 'lub', alpha2: 'lu', name: 'Luba-Katanga' }, - { alpha3: 'lug', alpha2: 'lg', name: 'Ganda' }, - { alpha3: 'lui', alpha2: '', name: 'Luiseno' }, - { alpha3: 'lun', alpha2: '', name: 'Lunda' }, - { alpha3: 'luo', alpha2: '', name: 'Luo (Kenya and Tanzania)' }, - { alpha3: 'lus', alpha2: '', name: 'Lushai' }, - { alpha3: 'mac', alpha2: 'mk', name: 'Macedonian' }, - { alpha3: 'mad', alpha2: '', name: 'Madurese' }, - { alpha3: 'mag', alpha2: '', name: 'Magahi' }, - { alpha3: 'mah', alpha2: 'mh', name: 'Marshallese' }, - { alpha3: 'mai', alpha2: '', name: 'Maithili' }, - { alpha3: 'mak', alpha2: '', name: 'Makasar' }, - { alpha3: 'mal', alpha2: 'ml', name: 'Malayalam' }, - { alpha3: 'man', alpha2: '', name: 'Mandingo' }, - { alpha3: 'mao', alpha2: 'mi', name: 'Maori' }, - { alpha3: 'map', alpha2: '', name: 'Austronesian languages' }, - { alpha3: 'mar', alpha2: 'mr', name: 'Marathi' }, - { alpha3: 'mas', alpha2: '', name: 'Masai' }, - { alpha3: 'may', alpha2: 'ms', name: 'Malay' }, - { alpha3: 'mdf', alpha2: '', name: 'Moksha' }, - { alpha3: 'mdr', alpha2: '', name: 'Mandar' }, - { alpha3: 'men', alpha2: '', name: 'Mende' }, - { alpha3: 'mga', alpha2: '', name: 'Irish, Middle (900-1200)' }, - { alpha3: 'mic', alpha2: '', name: 'Mi\'kmaq; Micmac' }, - { alpha3: 'min', alpha2: '', name: 'Minangkabau' }, - { alpha3: 'mis', alpha2: '', name: 'Uncoded languages' }, - { alpha3: 'mkh', alpha2: '', name: 'Mon-Khmer languages' }, - { alpha3: 'mlg', alpha2: 'mg', name: 'Malagasy' }, - { alpha3: 'mlt', alpha2: 'mt', name: 'Maltese' }, - { alpha3: 'mnc', alpha2: '', name: 'Manchu' }, - { alpha3: 'mni', alpha2: '', name: 'Manipuri' }, - { alpha3: 'mno', alpha2: '', name: 'Manobo languages' }, - { alpha3: 'moh', alpha2: '', name: 'Mohawk' }, - { alpha3: 'mon', alpha2: 'mn', name: 'Mongolian' }, - { alpha3: 'mos', alpha2: '', name: 'Mossi' }, - { alpha3: 'mul', alpha2: '', name: 'Multiple languages' }, - { alpha3: 'mun', alpha2: '', name: 'Munda languages' }, - { alpha3: 'mus', alpha2: '', name: 'Creek' }, - { alpha3: 'mwl', alpha2: '', name: 'Mirandese' }, - { alpha3: 'mwr', alpha2: '', name: 'Marwari' }, - { alpha3: 'myn', alpha2: '', name: 'Mayan languages' }, - { alpha3: 'myv', alpha2: '', name: 'Erzya' }, - { alpha3: 'nah', alpha2: '', name: 'Nahuatl languages' }, - { alpha3: 'nai', alpha2: '', name: 'North American Indian languages' }, - { alpha3: 'nap', alpha2: '', name: 'Neapolitan' }, - { alpha3: 'nau', alpha2: 'na', name: 'Nauru' }, - { alpha3: 'nav', alpha2: 'nv', name: 'Navajo; Navaho' }, - { alpha3: 'nbl', alpha2: 'nr', name: 'Ndebele, South; South Ndebele' }, - { alpha3: 'nde', alpha2: 'nd', name: 'Ndebele, North; North Ndebele' }, - { alpha3: 'ndo', alpha2: 'ng', name: 'Ndonga' }, - { alpha3: 'nds', alpha2: '', name: 'Low German; Low Saxon; German, Low; Saxon, Low' }, - { alpha3: 'nep', alpha2: 'ne', name: 'Nepali' }, - { alpha3: 'new', alpha2: '', name: 'Nepal Bhasa; Newari' }, - { alpha3: 'nia', alpha2: '', name: 'Nias' }, - { alpha3: 'nic', alpha2: '', name: 'Niger-Kordofanian languages' }, - { alpha3: 'niu', alpha2: '', name: 'Niuean' }, - { alpha3: 'nno', alpha2: 'nn', name: 'Norwegian Nynorsk; Nynorsk, Norwegian' }, - { alpha3: 'nob', alpha2: 'nb', name: 'Bokmål, Norwegian; Norwegian Bokmål' }, - { alpha3: 'nog', alpha2: '', name: 'Nogai' }, - { alpha3: 'non', alpha2: '', name: 'Norse, Old' }, - { alpha3: 'nor', alpha2: 'no', name: 'Norwegian' }, - { alpha3: 'nqo', alpha2: '', name: 'N\'Ko' }, - { alpha3: 'nso', alpha2: '', name: 'Pedi; Sepedi; Northern Sotho' }, - { alpha3: 'nub', alpha2: '', name: 'Nubian languages' }, - { alpha3: 'nwc', alpha2: '', name: 'Classical Newari; Old Newari; Classical Nepal Bhasa' }, - { alpha3: 'nya', alpha2: 'ny', name: 'Chichewa; Chewa; Nyanja' }, - { alpha3: 'nym', alpha2: '', name: 'Nyamwezi' }, - { alpha3: 'nyn', alpha2: '', name: 'Nyankole' }, - { alpha3: 'nyo', alpha2: '', name: 'Nyoro' }, - { alpha3: 'nzi', alpha2: '', name: 'Nzima' }, - { alpha3: 'oci', alpha2: 'oc', name: 'Occitan (post 1500)' }, - { alpha3: 'oji', alpha2: 'oj', name: 'Ojibwa' }, - { alpha3: 'ori', alpha2: 'or', name: 'Oriya' }, - { alpha3: 'orm', alpha2: 'om', name: 'Oromo' }, - { alpha3: 'osa', alpha2: '', name: 'Osage' }, - { alpha3: 'oss', alpha2: 'os', name: 'Ossetian; Ossetic' }, - { alpha3: 'ota', alpha2: '', name: 'Turkish, Ottoman (1500-1928)' }, - { alpha3: 'oto', alpha2: '', name: 'Otomian languages' }, - { alpha3: 'paa', alpha2: '', name: 'Papuan languages' }, - { alpha3: 'pag', alpha2: '', name: 'Pangasinan' }, - { alpha3: 'pal', alpha2: '', name: 'Pahlavi' }, - { alpha3: 'pam', alpha2: '', name: 'Pampanga; Kapampangan' }, - { alpha3: 'pan', alpha2: 'pa', name: 'Panjabi; Punjabi' }, - { alpha3: 'pap', alpha2: '', name: 'Papiamento' }, - { alpha3: 'pau', alpha2: '', name: 'Palauan' }, - { alpha3: 'peo', alpha2: '', name: 'Persian, Old (ca.600-400 B.C.)' }, - { alpha3: 'per', alpha2: 'fa', name: 'Persian' }, - { alpha3: 'phi', alpha2: '', name: 'Philippine languages' }, - { alpha3: 'phn', alpha2: '', name: 'Phoenician' }, - { alpha3: 'pli', alpha2: 'pi', name: 'Pali' }, - { alpha3: 'pol', alpha2: 'pl', name: 'Polish' }, - { alpha3: 'pon', alpha2: '', name: 'Pohnpeian' }, - { alpha3: 'por', alpha2: 'pt', name: 'Portuguese' }, - { alpha3: 'pra', alpha2: '', name: 'Prakrit languages' }, - { alpha3: 'pro', alpha2: '', name: 'Provençal, Old (to 1500); Occitan, Old (to 1500)' }, - { alpha3: 'pus', alpha2: 'ps', name: 'Pushto; Pashto' }, - { alpha3: 'que', alpha2: 'qu', name: 'Quechua' }, - { alpha3: 'raj', alpha2: '', name: 'Rajasthani' }, - { alpha3: 'rap', alpha2: '', name: 'Rapanui' }, - { alpha3: 'rar', alpha2: '', name: 'Rarotongan; Cook Islands Maori' }, - { alpha3: 'roa', alpha2: '', name: 'Romance languages' }, - { alpha3: 'roh', alpha2: 'rm', name: 'Romansh' }, - { alpha3: 'rom', alpha2: '', name: 'Romany' }, - { alpha3: 'rum', alpha2: 'ro', name: 'Romanian; Moldavian; Moldovan' }, - { alpha3: 'run', alpha2: 'rn', name: 'Rundi' }, - { alpha3: 'rup', alpha2: '', name: 'Aromanian; Arumanian; Macedo-Romanian' }, - { alpha3: 'rus', alpha2: 'ru', name: 'Russian' }, - { alpha3: 'sad', alpha2: '', name: 'Sandawe' }, - { alpha3: 'sag', alpha2: 'sg', name: 'Sango' }, - { alpha3: 'sah', alpha2: '', name: 'Yakut' }, - { alpha3: 'sai', alpha2: '', name: 'South American Indian languages' }, - { alpha3: 'sal', alpha2: '', name: 'Salishan languages' }, - { alpha3: 'sam', alpha2: '', name: 'Samaritan Aramaic' }, - { alpha3: 'san', alpha2: 'sa', name: 'Sanskrit' }, - { alpha3: 'sas', alpha2: '', name: 'Sasak' }, - { alpha3: 'sat', alpha2: '', name: 'Santali' }, - { alpha3: 'scn', alpha2: '', name: 'Sicilian' }, - { alpha3: 'sco', alpha2: '', name: 'Scots' }, - { alpha3: 'sel', alpha2: '', name: 'Selkup' }, - { alpha3: 'sem', alpha2: '', name: 'Semitic languages' }, - { alpha3: 'sga', alpha2: '', name: 'Irish, Old (to 900)' }, - { alpha3: 'sgn', alpha2: '', name: 'Sign Languages' }, - { alpha3: 'shn', alpha2: '', name: 'Shan' }, - { alpha3: 'sid', alpha2: '', name: 'Sidamo' }, - { alpha3: 'sin', alpha2: 'si', name: 'Sinhala; Sinhalese' }, - { alpha3: 'sio', alpha2: '', name: 'Siouan languages' }, - { alpha3: 'sit', alpha2: '', name: 'Sino-Tibetan languages' }, - { alpha3: 'sla', alpha2: '', name: 'Slavic languages' }, - { alpha3: 'slo', alpha2: 'sk', name: 'Slovak' }, - { alpha3: 'slv', alpha2: 'sl', name: 'Slovenian' }, - { alpha3: 'sma', alpha2: '', name: 'Southern Sami' }, - { alpha3: 'sme', alpha2: 'se', name: 'Northern Sami' }, - { alpha3: 'smi', alpha2: '', name: 'Sami languages' }, - { alpha3: 'smj', alpha2: '', name: 'Lule Sami' }, - { alpha3: 'smn', alpha2: '', name: 'Inari Sami' }, - { alpha3: 'smo', alpha2: 'sm', name: 'Samoan' }, - { alpha3: 'sms', alpha2: '', name: 'Skolt Sami' }, - { alpha3: 'sna', alpha2: 'sn', name: 'Shona' }, - { alpha3: 'snd', alpha2: 'sd', name: 'Sindhi' }, - { alpha3: 'snk', alpha2: '', name: 'Soninke' }, - { alpha3: 'sog', alpha2: '', name: 'Sogdian' }, - { alpha3: 'som', alpha2: 'so', name: 'Somali' }, - { alpha3: 'son', alpha2: '', name: 'Songhai languages' }, - { alpha3: 'sot', alpha2: 'st', name: 'Sotho, Southern' }, - { alpha3: 'spa', alpha2: 'es', name: 'Spanish; Castilian' }, - { alpha3: 'srd', alpha2: 'sc', name: 'Sardinian' }, - { alpha3: 'srn', alpha2: '', name: 'Sranan Tongo' }, - { alpha3: 'srp', alpha2: 'sr', name: 'Serbian' }, - { alpha3: 'srr', alpha2: '', name: 'Serer' }, - { alpha3: 'ssa', alpha2: '', name: 'Nilo-Saharan languages' }, - { alpha3: 'ssw', alpha2: 'ss', name: 'Swati' }, - { alpha3: 'suk', alpha2: '', name: 'Sukuma' }, - { alpha3: 'sun', alpha2: 'su', name: 'Sundanese' }, - { alpha3: 'sus', alpha2: '', name: 'Susu' }, - { alpha3: 'sux', alpha2: '', name: 'Sumerian' }, - { alpha3: 'swa', alpha2: 'sw', name: 'Swahili' }, - { alpha3: 'swe', alpha2: 'sv', name: 'Swedish' }, - { alpha3: 'syc', alpha2: '', name: 'Classical Syriac' }, - { alpha3: 'syr', alpha2: '', name: 'Syriac' }, - { alpha3: 'tah', alpha2: 'ty', name: 'Tahitian' }, - { alpha3: 'tai', alpha2: '', name: 'Tai languages' }, - { alpha3: 'tam', alpha2: 'ta', name: 'Tamil' }, - { alpha3: 'tat', alpha2: 'tt', name: 'Tatar' }, - { alpha3: 'tel', alpha2: 'te', name: 'Telugu' }, - { alpha3: 'tem', alpha2: '', name: 'Timne' }, - { alpha3: 'ter', alpha2: '', name: 'Tereno' }, - { alpha3: 'tet', alpha2: '', name: 'Tetum' }, - { alpha3: 'tgk', alpha2: 'tg', name: 'Tajik' }, - { alpha3: 'tgl', alpha2: 'tl', name: 'Tagalog' }, - { alpha3: 'tha', alpha2: 'th', name: 'Thai' }, - { alpha3: 'tib', alpha2: 'bo', name: 'Tibetan' }, - { alpha3: 'tig', alpha2: '', name: 'Tigre' }, - { alpha3: 'tir', alpha2: 'ti', name: 'Tigrinya' }, - { alpha3: 'tiv', alpha2: '', name: 'Tiv' }, - { alpha3: 'tkl', alpha2: '', name: 'Tokelau' }, - { alpha3: 'tlh', alpha2: '', name: 'Klingon; tlhIngan-Hol' }, - { alpha3: 'tli', alpha2: '', name: 'Tlingit' }, - { alpha3: 'tmh', alpha2: '', name: 'Tamashek' }, - { alpha3: 'tog', alpha2: '', name: 'Tonga (Nyasa)' }, - { alpha3: 'ton', alpha2: 'to', name: 'Tonga (Tonga Islands)' }, - { alpha3: 'tpi', alpha2: '', name: 'Tok Pisin' }, - { alpha3: 'tsi', alpha2: '', name: 'Tsimshian' }, - { alpha3: 'tsn', alpha2: 'tn', name: 'Tswana' }, - { alpha3: 'tso', alpha2: 'ts', name: 'Tsonga' }, - { alpha3: 'tuk', alpha2: 'tk', name: 'Turkmen' }, - { alpha3: 'tum', alpha2: '', name: 'Tumbuka' }, - { alpha3: 'tup', alpha2: '', name: 'Tupi languages' }, - { alpha3: 'tur', alpha2: 'tr', name: 'Turkish' }, - { alpha3: 'tut', alpha2: '', name: 'Altaic languages' }, - { alpha3: 'tvl', alpha2: '', name: 'Tuvalu' }, - { alpha3: 'twi', alpha2: 'tw', name: 'Twi' }, - { alpha3: 'tyv', alpha2: '', name: 'Tuvinian' }, - { alpha3: 'udm', alpha2: '', name: 'Udmurt' }, - { alpha3: 'uga', alpha2: '', name: 'Ugaritic' }, - { alpha3: 'uig', alpha2: 'ug', name: 'Uighur; Uyghur' }, - { alpha3: 'ukr', alpha2: 'uk', name: 'Ukrainian' }, - { alpha3: 'umb', alpha2: '', name: 'Umbundu' }, - { alpha3: 'und', alpha2: '', name: 'Undetermined' }, - { alpha3: 'urd', alpha2: 'ur', name: 'Urdu' }, - { alpha3: 'uzb', alpha2: 'uz', name: 'Uzbek' }, - { alpha3: 'vai', alpha2: '', name: 'Vai' }, - { alpha3: 'ven', alpha2: 've', name: 'Venda' }, - { alpha3: 'vie', alpha2: 'vi', name: 'Vietnamese' }, - { alpha3: 'vol', alpha2: 'vo', name: 'Volapük' }, - { alpha3: 'vot', alpha2: '', name: 'Votic' }, - { alpha3: 'wak', alpha2: '', name: 'Wakashan languages' }, - { alpha3: 'wal', alpha2: '', name: 'Wolaitta; Wolaytta' }, - { alpha3: 'war', alpha2: '', name: 'Waray' }, - { alpha3: 'was', alpha2: '', name: 'Washo' }, - { alpha3: 'wel', alpha2: 'cy', name: 'Welsh' }, - { alpha3: 'wen', alpha2: '', name: 'Sorbian languages' }, - { alpha3: 'wln', alpha2: 'wa', name: 'Walloon' }, - { alpha3: 'wol', alpha2: 'wo', name: 'Wolof' }, - { alpha3: 'xal', alpha2: '', name: 'Kalmyk; Oirat' }, - { alpha3: 'xho', alpha2: 'xh', name: 'Xhosa' }, - { alpha3: 'yao', alpha2: '', name: 'Yao' }, - { alpha3: 'yap', alpha2: '', name: 'Yapese' }, - { alpha3: 'yid', alpha2: 'yi', name: 'Yiddish' }, - { alpha3: 'yor', alpha2: 'yo', name: 'Yoruba' }, - { alpha3: 'ypk', alpha2: '', name: 'Yupik languages' }, - { alpha3: 'zap', alpha2: '', name: 'Zapotec' }, - { alpha3: 'zbl', alpha2: '', name: 'Blissymbols; Blissymbolics; Bliss' }, - { alpha3: 'zen', alpha2: '', name: 'Zenaga' }, - { alpha3: 'zgh', alpha2: '', name: 'Standard Moroccan Tamazight' }, - { alpha3: 'zha', alpha2: 'za', name: 'Zhuang; Chuang' }, - { alpha3: 'znd', alpha2: '', name: 'Zande languages' }, - { alpha3: 'zul', alpha2: 'zu', name: 'Zulu' }, - { alpha3: 'zun', alpha2: '', name: 'Zuni' }, - { alpha3: 'zxx', alpha2: '', name: 'No linguistic content; Not applicable' }, - { alpha3: 'zza', alpha2: '', name: 'Zaza; Dimili; Dimli; Kirdki; Kirmanjki; Zazaki' }, -]; - -// Given a two- or three-character language code, return a localized langugae name string -// @intl is really useIntl(), which can't be invoked outside a functional component -export const formattedLanguageName = (code, intl) => { - const language = find(languages, entry => entry.alpha3 === code || entry.alpha2 === code); - if (language === undefined) { - return intl.formatMessage({ id: 'stripes-components.languages.und' }); - } - const translationId = `stripes-components.languages.${language.alpha3}`; - const translatedName = intl.formatMessage({ id: translationId }); - - if (translatedName !== translationId) return translatedName; - // If no translation is found, use the English name from the list above - else return language.name; -}; - -const getSelectedLangsWithoutCount = (selectedLanguagesId, intl, langs) => { - const selectedLangsWithoutCount = []; - - if (selectedLanguagesId) { - selectedLanguagesId.forEach(selectedLangId => { - const selectedLangWithCount = langs.find(lang => lang.id === selectedLangId); - - if (!selectedLangWithCount) { - const option = { - label: formattedLanguageName(selectedLangId, intl), - value: selectedLangId, - count: 0, - }; - selectedLangsWithoutCount.push(option); - } - }); - } - - return selectedLangsWithoutCount; -}; - -export const languageOptionsES = (selectedLanguagesId, intl, langs = []) => { - const restLangs = langs.reduce((accum, { id, totalRecords }) => { - if (!totalRecords) return accum; - - const option = { - label: formattedLanguageName(id, intl), - value: id, - count: totalRecords, - }; - accum.push(option); - - return accum; - }, []); - - return [ - ...restLangs, - ...getSelectedLangsWithoutCount(selectedLanguagesId, intl, langs), - ]; -}; - -export default languages; diff --git a/src/components/ItemFilters/ItemFilters.js b/src/components/ItemFilters/ItemFilters.js deleted file mode 100644 index b1a12afa6..000000000 --- a/src/components/ItemFilters/ItemFilters.js +++ /dev/null @@ -1,309 +0,0 @@ -import _ from 'lodash'; -import React from 'react'; -import PropTypes from 'prop-types'; -import { FormattedMessage, useIntl } from 'react-intl'; -import { - Accordion, - AccordionSet, - FilterAccordionHeader, -} from '@folio/stripes/components'; - -import DateRangeFilter from '../DateRangeFilter'; -import TagsFilter from '../TagsFilter'; -import CheckboxFacet from '../CheckboxFacet'; -import { useFacets } from '../../common/hooks'; -import { - getSourceOptions, - getSuppressedOptions, - processFacetOptions, - processItemsStatuses, - processStatisticalCodes, -} from '../../facetUtils'; -import { - DATE_FORMAT, - FACETS, - FACETS_OPTIONS, - FACETS_SETTINGS, - FACETS_CQL, -} from '../../constants'; -import { - makeDateRangeFilterString, - retrieveDatesFromDateRangeFilterString, -} from '../../utils'; - -const ItemFilters = (props) => { - const { - activeFilters, - data: { - itemStatuses, - statisticalCodes, - locations, - materialTypes, - }, - onChange, - onClear, - } = props; - - const intl = useIntl(); - - const segmentAccordions = { - [FACETS.ITEM_STATUS]: false, - [FACETS.EFFECTIVE_LOCATION]: false, - [FACETS.HOLDINGS_PERMANENT_LOCATION]: false, - [FACETS.MATERIAL_TYPE]: false, - [FACETS.ITEMS_DISCOVERY_SUPPRESS]: false, - [FACETS.ITEMS_TAGS]: false, - [FACETS.ITEMS_STATISTICAL_CODE_IDS]: false, - }; - - const segmentOptions = { - [FACETS_OPTIONS.ITEMS_STATUSES_OPTIONS]: [], - [FACETS_OPTIONS.EFFECTIVE_LOCATION_OPTIONS]: [], - [FACETS_OPTIONS.HOLDINGS_PERMANENT_LOCATION_OPTIONS]: [], - [FACETS_OPTIONS.MATERIAL_TYPES_OPTIONS]: [], - [FACETS_OPTIONS.ITEMS_DISCOVERY_SUPPRESS_OPTIONS]: [], - [FACETS_OPTIONS.ITEMS_TAGS_OPTIONS]: [], - [FACETS_OPTIONS.STATISTICAL_CODES_OPTIONS]: [], - }; - - const selectedFacetFilters = { - [FACETS.ITEM_STATUS]: activeFilters[FACETS.ITEM_STATUS], - [FACETS.EFFECTIVE_LOCATION]: activeFilters[FACETS.EFFECTIVE_LOCATION], - [FACETS.HOLDINGS_PERMANENT_LOCATION]: activeFilters[FACETS.HOLDINGS_PERMANENT_LOCATION], - [FACETS.MATERIAL_TYPE]: activeFilters[FACETS.MATERIAL_TYPE], - [FACETS.ITEMS_DISCOVERY_SUPPRESS]: activeFilters[FACETS.ITEMS_DISCOVERY_SUPPRESS], - [FACETS.ITEMS_TAGS]: activeFilters[FACETS.ITEMS_TAGS], - [FACETS.ITEMS_STATISTICAL_CODE_IDS]: activeFilters[FACETS.ITEMS_STATISTICAL_CODE_IDS], - }; - - const getNewRecords = (records) => { - return _.reduce(FACETS_SETTINGS, (accum, name, recordName) => { - if (records[recordName]) { - const recordValues = records[recordName].values; - const commonProps = [recordValues, accum, name]; - - switch (recordName) { - case FACETS_CQL.ITEMS_STATUSES: - processItemsStatuses(activeFilters[FACETS.ITEM_STATUS], itemStatuses, intl, ...commonProps); - break; - case FACETS_CQL.EFFECTIVE_LOCATION: - processFacetOptions(activeFilters[FACETS.EFFECTIVE_LOCATION], locations, ...commonProps); - break; - case FACETS_CQL.HOLDINGS_PERMANENT_LOCATION: - processFacetOptions(activeFilters[FACETS.HOLDINGS_PERMANENT_LOCATION], locations, ...commonProps); - break; - case FACETS_CQL.MATERIAL_TYPES: - processFacetOptions(activeFilters[FACETS.MATERIAL_TYPE], materialTypes, ...commonProps); - break; - case FACETS_CQL.ITEMS_STATISTICAL_CODE_IDS: - processStatisticalCodes(activeFilters[FACETS.ITEMS_STATISTICAL_CODE_IDS], statisticalCodes, ...commonProps); - break; - case FACETS_CQL.ITEMS_DISCOVERY_SUPPRESS: - accum[name] = getSuppressedOptions(activeFilters[FACETS.ITEMS_DISCOVERY_SUPPRESS], recordValues); - break; - case FACETS_CQL.ITEMS_TAGS: - accum[name] = getSourceOptions(activeFilters[FACETS.ITEMS_TAGS], recordValues); - break; - default: - } - } - return accum; - }, {}); - }; - - const [ - accordions, - onToggleSection, - handleFetchFacets, - handleFilterSearch, - facetsOptions, - getIsPending, - ] = useFacets( - segmentAccordions, - segmentOptions, - selectedFacetFilters, - getNewRecords, - props.data - ); - - return ( - - } - id={FACETS.ITEM_STATUS} - name={FACETS.ITEM_STATUS} - header={FilterAccordionHeader} - displayClearButton={!_.isEmpty(activeFilters[FACETS.ITEM_STATUS])} - onClearFilter={() => onClear(FACETS.ITEM_STATUS)} - separator={false} - > - - - } - id={FACETS.EFFECTIVE_LOCATION} - name={FACETS.EFFECTIVE_LOCATION} - header={FilterAccordionHeader} - displayClearButton={activeFilters[FACETS.EFFECTIVE_LOCATION]?.length > 0} - onClearFilter={() => onClear(FACETS.EFFECTIVE_LOCATION)} - > - - - } - id={FACETS.HOLDINGS_PERMANENT_LOCATION} - name={FACETS.HOLDINGS_PERMANENT_LOCATION} - closedByDefault - header={FilterAccordionHeader} - displayClearButton={activeFilters[FACETS.HOLDINGS_PERMANENT_LOCATION]?.length > 0} - onClearFilter={() => onClear(FACETS.HOLDINGS_PERMANENT_LOCATION)} - > - - - } - id={FACETS.MATERIAL_TYPE} - name={FACETS.MATERIAL_TYPE} - closedByDefault - header={FilterAccordionHeader} - displayClearButton={!_.isEmpty(activeFilters[FACETS.MATERIAL_TYPE])} - onClearFilter={() => onClear(FACETS.MATERIAL_TYPE)} - > - - - } - id={FACETS.ITEMS_DISCOVERY_SUPPRESS} - name={FACETS.ITEMS_DISCOVERY_SUPPRESS} - closedByDefault - header={FilterAccordionHeader} - displayClearButton={activeFilters[FACETS.ITEMS_DISCOVERY_SUPPRESS]?.length > 0} - onClearFilter={() => onClear(FACETS.ITEMS_DISCOVERY_SUPPRESS)} - > - - - } - id={FACETS.ITEMS_STATISTICAL_CODE_IDS} - name={FACETS.ITEMS_STATISTICAL_CODE_IDS} - closedByDefault - header={FilterAccordionHeader} - displayClearButton={activeFilters[FACETS.ITEMS_STATISTICAL_CODE_IDS]?.length > 0} - onClearFilter={() => onClear(FACETS.ITEMS_STATISTICAL_CODE_IDS)} - > - - - } - id={FACETS.ITEMS_CREATED_DATE} - name={FACETS.ITEMS_CREATED_DATE} - closedByDefault - header={FilterAccordionHeader} - displayClearButton={activeFilters[FACETS.ITEMS_CREATED_DATE]?.length > 0} - onClearFilter={() => onClear(FACETS.ITEMS_CREATED_DATE)} - > - - - } - id={FACETS.ITEMS_UPDATED_DATE} - name={FACETS.ITEMS_UPDATED_DATE} - closedByDefault - header={FilterAccordionHeader} - displayClearButton={activeFilters[FACETS.ITEMS_UPDATED_DATE]?.length > 0} - onClearFilter={() => onClear(FACETS.ITEMS_UPDATED_DATE)} - > - - - - - ); -}; - -ItemFilters.propTypes = { - activeFilters: PropTypes.object, - onChange: PropTypes.func.isRequired, - onClear: PropTypes.func.isRequired, - data: PropTypes.object, -}; - -ItemFilters.defaultProps = { - activeFilters: {}, -}; - -export default ItemFilters; diff --git a/src/components/ItemFilters/ItemsFilters.test.js b/src/components/ItemFilters/ItemsFilters.test.js deleted file mode 100644 index dd3047b31..000000000 --- a/src/components/ItemFilters/ItemsFilters.test.js +++ /dev/null @@ -1,66 +0,0 @@ -import React from 'react'; -import { BrowserRouter as Router } from 'react-router-dom'; -import { noop } from 'lodash'; - -import '../../../test/jest/__mock__'; - -import { ModuleHierarchyProvider } from '@folio/stripes/core'; -import renderWithIntl from '../../../test/jest/helpers/renderWithIntl'; - -import ItemFilters from './ItemFilters'; - -const resources = { - facets: { - hasLoaded: true, - resource: 'facets', - records: [], - other: { totalRecords: 0 } - }, -}; - -const data = { - locations: [], - resourceTypes: [], - instanceFormats: [], - modesOfIssuance: [], - statisticalCodes: [], - tagsRecords: [], - natureOfContentTerms: [], - query: [], - onFetchFacets: noop, - parentResources: resources, -}; - -const renderItemFilters = () => { - return renderWithIntl( - - - - - - ); -}; - -describe('ItemFilters', () => { - beforeEach(() => { - renderItemFilters(); - }); - - it('Contains a filter for creation date ', () => { - expect(document.querySelector('#itemsCreatedDate')).toBeInTheDocument(); - }); - - it('Contains a filter for update date ', () => { - expect(document.querySelector('#itemsUpdatedDate')).toBeInTheDocument(); - }); - - it('Contains a filter for statistical code', () => { - expect(document.querySelector('#itemsStatisticalCodeIds')).toBeInTheDocument(); - }); -}); diff --git a/src/components/ItemFilters/index.js b/src/components/ItemFilters/index.js deleted file mode 100644 index ea257c1df..000000000 --- a/src/components/ItemFilters/index.js +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from './ItemFilters'; -export { default as itemFilterRenderer } from './itemFilterRenderer'; diff --git a/src/components/ItemFilters/itemFilterRenderer.js b/src/components/ItemFilters/itemFilterRenderer.js deleted file mode 100644 index 838e2393a..000000000 --- a/src/components/ItemFilters/itemFilterRenderer.js +++ /dev/null @@ -1,45 +0,0 @@ -import React from 'react'; -import { get } from 'lodash'; - -import ItemFilters from './ItemFilters'; -import { getCurrentFilters } from '../../utils'; -import { itemStatuses } from '../../constants'; -import facetsStore from '../../stores/facetsStore'; - -// itemFilterRenderer is a function that takes a single argument `data` -// and returns a function that takes a single argument `onChange`. -const itemFilterRenderer = data => onChange => { - const { - query, - materialTypes, - statisticalCodes, - locations, - tags, - onFetchFacets, - parentResources, - } = data; - const activeFilters = getCurrentFilters(get(query, 'filters', '')); - - return ( - { - facetsStore.getState().resetFacetByName(name); - onChange({ name, values: [] }); - }} - /> - ); -}; - -export default itemFilterRenderer; diff --git a/src/components/ItemFilters/itemFilterRenderer.test.js b/src/components/ItemFilters/itemFilterRenderer.test.js deleted file mode 100644 index 93a5afbc6..000000000 --- a/src/components/ItemFilters/itemFilterRenderer.test.js +++ /dev/null @@ -1,46 +0,0 @@ -import React from 'react'; -import { screen } from '@testing-library/react'; -import { BrowserRouter as Router } from 'react-router-dom'; -import { noop } from 'lodash'; -import userEvent from '@testing-library/user-event'; - -import '../../../test/jest/__mock__'; - -import itemFilterRenderer from './itemFilterRenderer'; -import renderWithIntl from '../../../test/jest/helpers/renderWithIntl'; -import translationsProperties from '../../../test/jest/helpers/translationsProperties'; - -jest.mock('./ItemFilters', () => ({ onClear }) => ( -
- -
-)); - -const DATA = { - materialTypes: [], - locations: [], - tags: [], - query: {}, - parentResources: { facets: { records: [] } }, -}; - -const renderFilters = (data = DATA, onChange = noop) => (renderWithIntl( - {itemFilterRenderer(data)(onChange)}, - translationsProperties -)); - -describe('itemFilterRenderer fn', () => { - beforeEach(() => renderFilters()); - - it('should click the clearButton', () => { - const clearButton = screen.getByTestId('onClear'); - expect(clearButton).toBeInTheDocument(); - userEvent.click(clearButton); - }); -}); diff --git a/src/components/MultiSelectionFacet/MultiSelectionFacet.js b/src/components/MultiSelectionFacet/MultiSelectionFacet.js deleted file mode 100644 index b3b2412f8..000000000 --- a/src/components/MultiSelectionFacet/MultiSelectionFacet.js +++ /dev/null @@ -1,106 +0,0 @@ -import PropTypes from 'prop-types'; - -import { - MultiSelection, - Accordion, - FilterAccordionHeader, -} from '@folio/stripes/components'; - -import { FacetOptionFormatter } from '../FacetOptionFormatter'; - -const propTypes = { - id: PropTypes.string.isRequired, - label: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired, - name: PropTypes.string.isRequired, - displayClearButton: PropTypes.bool.isRequired, - onClearFilter: PropTypes.func.isRequired, - onFilterChange: PropTypes.func.isRequired, - closedByDefault: PropTypes.bool, - options: PropTypes.arrayOf(PropTypes.shape({ - id: PropTypes.string.isRequired, - label: PropTypes.string, - totalRecords: PropTypes.number.isRequired, - })), - selectedValues: PropTypes.arrayOf(PropTypes.string), -}; - -const MultiSelectionFacet = ({ - id, - label, - name, - closedByDefault = true, - options, - selectedValues, - onFilterChange, - onClearFilter, - displayClearButton, - ...props -}) => { - const onChange = newOptions => { - onFilterChange({ - name, - values: newOptions.map(option => option.value), - }); - }; - - const missingValuesInOptions = selectedValues - .filter(selectedValue => !options.find(option => { - return option.value - ? option.value === selectedValue - : option.id === selectedValue; - })) - .map(value => ({ - label: value, - value, - count: 0, - })); - - // include options returned from backend - // if some selected options are missing from response we're adding them here with 0 results - const dataOptions = [...options.map(option => ({ - label: option.label || option.id, - value: option.value || option.id, - totalRecords: option.count, - })), ...missingValuesInOptions]; - - const itemToString = option => { - return option?.label || ''; - }; - - const selectedOptions = dataOptions.filter(option => selectedValues.includes(option.value)); - - return ( - onClearFilter(name)} - displayClearButton={displayClearButton} - > - option.label} - onChange={onChange} - dataOptions={dataOptions} - itemToString={itemToString} - value={selectedOptions} - {...props} - /> - - ); -}; - -MultiSelectionFacet.defaultProps = { - selectedValues: [], - options: [], - closedByDefault: false, -}; - -MultiSelectionFacet.propTypes = propTypes; - -export default MultiSelectionFacet; diff --git a/src/components/MultiSelectionFacet/MultiSelectionFacet.test.js b/src/components/MultiSelectionFacet/MultiSelectionFacet.test.js deleted file mode 100644 index 4f1c115f5..000000000 --- a/src/components/MultiSelectionFacet/MultiSelectionFacet.test.js +++ /dev/null @@ -1,66 +0,0 @@ -import { - cleanup, - render, - screen, - fireEvent, -} from '@testing-library/react'; - -import '../../../test/jest/__mock__'; - -import MultiSelectionFacet from './MultiSelectionFacet'; -import Harness from '../../../test/jest/helpers/Harness'; - -jest.mock('@folio/stripes/components', () => ({ - ...jest.requireActual('@folio/stripes/components'), - MultiSelection: () =>
MultiSelection
, -})); - -const mockOnFilterChange = jest.fn(); -const mockOnClearFilter = jest.fn(); -const mockFacetOptionFormatter = jest.fn(); - -const renderMultiSelectionFacet = (props = {}) => render( - - - -); - -describe('Given MultiSelectionFacet', () => { - afterEach(cleanup); - - it('Contains a filter for multiselect', () => { - renderMultiSelectionFacet(); - - expect(document.querySelector('#filter-name')).toBeInTheDocument(); - }); - - it('should call onClearFilter handler if clear btn is clicked', () => { - renderMultiSelectionFacet(); - - fireEvent.click(screen.getAllByLabelText('Clear selected filters for "filter-label"')[0]); - - expect(mockOnClearFilter).toHaveBeenCalled(); - }); -}); diff --git a/src/components/MultiSelectionFacet/index.js b/src/components/MultiSelectionFacet/index.js deleted file mode 100644 index 43e3b78c3..000000000 --- a/src/components/MultiSelectionFacet/index.js +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from './MultiSelectionFacet'; -export { default as MultiSelectionFacet } from './MultiSelectionFacet'; diff --git a/src/components/TagsFilter/TagsFilter.js b/src/components/TagsFilter/TagsFilter.js deleted file mode 100644 index a62fd2a84..000000000 --- a/src/components/TagsFilter/TagsFilter.js +++ /dev/null @@ -1,73 +0,0 @@ -import React, { useCallback } from 'react'; -import PropTypes from 'prop-types'; -import { useIntl } from 'react-intl'; -import { useLocation } from 'react-router-dom'; - -import { - Accordion, - FilterAccordionHeader, - filterState, -} from '@folio/stripes/components'; - -import CheckboxFacet from '../CheckboxFacet'; - -const TagsFilter = ({ - id, - name, - onChange, - onFetch, - onSearch, - onClear, - selectedValues, - tagsRecords, - isPending, -}) => { - const intl = useIntl(); - const onClearFilter = useCallback(() => onClear(name), [onClear, name]); - const location = useLocation(); - const urlParams = new URLSearchParams(location.search); - const hasTagsSelected = !!Object.keys(filterState(urlParams.get('filters'))) - .find((key) => key.startsWith(`${name}.`)); - - const tagsOptions = tagsRecords.map(({ label, count }) => ({ label, value: label, count })); - return ( - - - - ); -}; - -TagsFilter.propTypes = { - id: PropTypes.string, - isPending: PropTypes.bool, - name: PropTypes.string, - selectedValues: PropTypes.arrayOf(PropTypes.string), - onChange: PropTypes.func.isRequired, - onClear: PropTypes.func.isRequired, - onFetch: PropTypes.func, - onSearch: PropTypes.func, - tagsRecords: PropTypes.arrayOf(PropTypes.object), -}; - -TagsFilter.defaultProps = { - selectedValues: [], - tagsRecords: [], -}; - -export default TagsFilter; diff --git a/src/components/TagsFilter/TagsFilter.test.js b/src/components/TagsFilter/TagsFilter.test.js deleted file mode 100644 index a27fdda0f..000000000 --- a/src/components/TagsFilter/TagsFilter.test.js +++ /dev/null @@ -1,106 +0,0 @@ -import React from 'react'; -import { BrowserRouter as Router } from 'react-router-dom'; -import { - cleanup, - fireEvent, - screen, -} from '@testing-library/react'; -import { noop } from 'lodash'; - -import '../../../test/jest/__mock__'; - -import TagsFilter from './TagsFilter'; -import renderWithIntl from '../../../test/jest/helpers/renderWithIntl'; -import translationsProperties from '../../../test/jest/helpers/translationsProperties'; - -const TAGS = [{ - 'id': 'd3c8b511-41e7-422e-a483-18778d0596e5', - 'label': 'important', - 'metadata': { - 'createdDate': '2020-11-23T03:21:03.915+00:00', - 'updatedDate': '2020-11-23T03:21:03.915+00:00' - } -}, { - 'id': 'b822d5a8-1750-4b5f-92bd-9fc73a05ddda', - 'label': 'new', - 'description': 'new', - 'metadata': { - 'createdDate': '2020-11-23T11:10:48.413+00:00', - 'createdByUserId': 'f40d6d27-8af3-5718-9eb1-5046622e5f8c', - 'updatedDate': '2020-11-23T11:10:48.413+00:00', - 'updatedByUserId': 'f40d6d27-8af3-5718-9eb1-5046622e5f8c' - } -}, { - 'id': 'c3799dc5-500b-44dd-8e17-2f2354cc43e3', - 'label': 'urgent', - 'description': 'Requires urgent attention', - 'metadata': { - 'createdDate': '2020-11-23T03:21:03.894+00:00', - 'updatedDate': '2020-11-23T03:21:03.894+00:00' - } -}]; - -const filterAccordionTitle = 'Tags'; - -const renderFilter = (tagsRecords, selectedValues, onChange = noop, onClear = noop) => (renderWithIntl( - - - , - translationsProperties, -)); - -describe('TagsFilter component', () => { - afterEach(cleanup); - - it('should display filter without tags', () => { - renderFilter(); - expect(screen.getByText(filterAccordionTitle)).toBeDefined(); - }); - - it('should display filter accordion with tags', () => { - renderFilter(TAGS); - expect(screen.getByText(filterAccordionTitle)).toBeDefined(); - expect(screen.getByText(TAGS[0].label)).toBeDefined(); - }); - - it('should display filter accordion with tags and selected values', () => { - renderFilter(TAGS, ['urgent']); - expect(screen.getByText('new')).toBeDefined(); - }); - - it('should call onChange handler if new tag is clicked', () => { - const onChangeFilter = jest.fn(); - - renderFilter(TAGS, undefined, onChangeFilter); - fireEvent.click(screen.getByText('new')); - expect(onChangeFilter).toHaveBeenCalled(); - }); - - it('should call onChange handler if selected tag is clicked', () => { - const onChangeFilter = jest.fn(); - - renderFilter(TAGS, ['urgent'], onChangeFilter); - fireEvent.click(screen.queryByText('urgent')); // last element is the option in the list - expect(onChangeFilter).toHaveBeenCalled(); - }); - - it('should call onClear handler if clear btn is clicked', () => { - const onClear = jest.fn(); - - renderFilter(TAGS, ['urgent'], undefined, onClear); - fireEvent.click(screen.getAllByLabelText('Clear selected filters for "Tags"')[0]); - expect(onClear).toHaveBeenCalled(); - }); - - - it('should display filter accordion without tags and selected values', () => { - renderFilter(undefined, ['urgent']); - expect(screen.getByText('No matching options')).toBeDefined(); - }); -}); diff --git a/src/components/TagsFilter/index.js b/src/components/TagsFilter/index.js deleted file mode 100644 index f214a10dd..000000000 --- a/src/components/TagsFilter/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './TagsFilter'; diff --git a/src/facetUtils.js b/src/facetUtils.js deleted file mode 100644 index ace177ceb..000000000 --- a/src/facetUtils.js +++ /dev/null @@ -1,252 +0,0 @@ -import React from 'react'; -import { FormattedMessage } from 'react-intl'; - -const getFacetDataMap = (facetData, key = 'id') => { - const facetDataMap = new Map(); - - facetData?.forEach(data => { - const id = data[key]; - facetDataMap.set(id, data); - }); - - return facetDataMap; -}; - - -const parseOption = (entry, totals) => { - const { - name = '', - id, - label = '', - } = entry; - - const option = { - label: name || label, - value: id, - count: totals, - }; - - return option; -}; - - -const getSelectedFacetOptionsWithoutCount = (selectedFiltersId, entries, facetDataMap, parse = parseOption) => { - const selectedFiltersWithoutCount = []; - - if (selectedFiltersId) { - selectedFiltersId.forEach(selectedFilterId => { - const selectedFilterWithCount = entries.find(filter => filter.id === selectedFilterId); - - if (!selectedFilterWithCount) { - const facet = facetDataMap.get(selectedFilterId); - - if (facet) { - const option = parse(facetDataMap.get(selectedFilterId), 0); - selectedFiltersWithoutCount.push(option); - } - } - }); - } - - return selectedFiltersWithoutCount; -}; - -export const getFacetOptions = (selectedFiltersId, entries, facetData, key, parse = parseOption) => { - const facetDataMap = getFacetDataMap(facetData, key); - - const restFilters = entries.reduce((accum, entry) => { - if (!entry.totalRecords) return accum; - - const facet = facetDataMap.get(entry.id); - - if (facet) { - const option = parse(facetDataMap.get(entry.id), entry.totalRecords); - accum.push(option); - } - return accum; - }, []); - - return [ - ...restFilters, - ...getSelectedFacetOptionsWithoutCount(selectedFiltersId, entries, facetDataMap, parse), - ]; -}; - -const getSuppressedLabel = (id) => (id === 'true' ? 'yes' : 'no'); -const getSuppressedValue = (id) => (id === 'true' ? 'true' : 'false'); - -const getSelectedSuppressedOptionsWithoutCount = (selectedFiltersId, suppressedOptionsRecords) => { - const selectedFiltersWithoutCount = []; - - if (selectedFiltersId) { - selectedFiltersId.forEach(selectedFilterId => { - const selectedFilterWithCount = suppressedOptionsRecords.find(record => record.id === selectedFilterId); - - if (!selectedFilterWithCount) { - const option = { - label: , - value: getSuppressedValue(selectedFilterId), - count: 0, - }; - selectedFiltersWithoutCount.push(option); - } - }); - } - - return selectedFiltersWithoutCount; -}; - -export const getSuppressedOptions = (selectedFiltersId, suppressedOptionsRecords) => { - const restFilter = suppressedOptionsRecords.reduce((accum, { id, totalRecords }) => { - if (!totalRecords) return accum; - - const option = { - label: , - value: getSuppressedValue(id), - count: totalRecords, - }; - accum.push(option); - return accum; - }, []); - - return [ - ...restFilter, - ...getSelectedSuppressedOptionsWithoutCount(selectedFiltersId, suppressedOptionsRecords), - ]; -}; - -const getSelectedSourceOptionsWithoutCount = (selectedFiltersId, sourceRecords) => { - const selectedFiltersWithoutCount = []; - - if (selectedFiltersId) { - selectedFiltersId.forEach(selectedFilterId => { - const selectedFilterWithCount = sourceRecords.find(record => record.id === selectedFilterId); - - if (!selectedFilterWithCount) { - const option = { - label: selectedFilterId, - value: selectedFilterId, - count: 0, - }; - selectedFiltersWithoutCount.push(option); - } - }); - } - - return selectedFiltersWithoutCount; -}; - -export const getSourceOptions = (selectedFiltersId, sourceRecords) => { - const restFilter = sourceRecords.reduce((accum, { id, totalRecords }) => { - if (!totalRecords) return accum; - - const option = { - label: id, - value: id, - count: totalRecords, - }; - - accum.push(option); - return accum; - }, []); - - return [ - ...restFilter, - ...getSelectedSourceOptionsWithoutCount(selectedFiltersId, sourceRecords), - ]; -}; - -const getSelectedItemStatusOptions = (selectedFiltersId, entries, facetData, intl) => { - const selectedFiltersWithoutCount = []; - - if (selectedFiltersId) { - selectedFiltersId.forEach(selectedFilterId => { - const selectedFilterWithCount = entries.find(filter => filter.id === selectedFilterId); - - if (!selectedFilterWithCount) { - const { - value, - label, - } = facetData.find(facet => facet.value === selectedFilterId); - - const option = { - label: intl.formatMessage({ id: label }), - value, - count: 0, - }; - selectedFiltersWithoutCount.push(option); - } - }); - } - - return selectedFiltersWithoutCount; -}; - -export const getItemStatusesOptions = (selectedFiltersId, entries, facetData, intl) => { - const restFilters = entries.reduce((accum, entry) => { - if (!entry.totalRecords) return accum; - - const { - value, - label, - } = facetData.find(facet => facet.value === entry.id); - - const option = { - label: intl.formatMessage({ id: label }), - value, - count: entry.totalRecords, - }; - accum.push(option); - return accum; - }, []); - - return [ - ...restFilters, - ...getSelectedItemStatusOptions(selectedFiltersId, entries, facetData, intl), - ]; -}; - -const parseStatisticalCodeOption = (entry, count) => { - const { - name = '', - id: value, - code, - statisticalCodeType, - } = entry; - const label = `${statisticalCodeType?.name}: ${code} - ${name}`; - const option = { - label, - value, - count, - }; - - return option; -}; - -export const processStatisticalCodes = (selectedFiltersId, recordValues, facetData, allFilters, name) => { - if (facetData) { - allFilters[name] = getFacetOptions(selectedFiltersId, facetData, recordValues, 'id', parseStatisticalCodeOption); - } -}; - -/** - * Turns facet data into an array of label/value/count representation used by UI - * - * @param {String} selectedFiltersId selected filters id (is this being used?) - * @param {Array} recordValues all dictionary records for given filter - * @param {Array} facetData ids of records returned from facets - * @param {Object} allFilters object which holds currently active filters - * @param {String} name name of the options key defined in https://github.com/folio-org/ui-inventory/blob/8c20a728d41dcf764c7d894a31c19d8d3215316a/src/constants.js#L245 - * @param {String} key - primiary key in dictionary (usually id) - */ -export const processFacetOptions = (selectedFiltersId, recordValues, facetData, allFilters, name, key) => { - if (facetData) { - allFilters[name] = getFacetOptions(selectedFiltersId, facetData, recordValues, key); - } -}; - -export const processItemsStatuses = (selectedFiltersId, itemStatuses, intl, recordValues, accum, name) => { - if (itemStatuses) { - accum[name] = getItemStatusesOptions(selectedFiltersId, recordValues, itemStatuses, intl); - } -}; diff --git a/src/facetUtils.test.js b/src/facetUtils.test.js deleted file mode 100644 index ee384f70d..000000000 --- a/src/facetUtils.test.js +++ /dev/null @@ -1,263 +0,0 @@ -import { FormattedMessage } from 'react-intl'; -import { - getFacetOptions, - getSuppressedOptions, - getSourceOptions, - getItemStatusesOptions, - processStatisticalCodes, - processFacetOptions, - processItemsStatuses, -} from './facetUtils'; - -describe('getFacetOptions', () => { - it('getFacetOptions returns the expected options with valid input', () => { - const selectedFiltersId = ['filter1', 'filter2']; - const entries = [ - { id: 'filter1', totalRecords: 2 }, - { id: 'filter3', totalRecords: 4 }, - ]; - const facetData = [ - { id: 'filter1', name: 'Filter 1' }, - { id: 'filter2', name: 'Filter 2' }, - { id: 'filter3', name: 'Filter 3' }, - ]; - const key = 'id'; - const expectedOptions = [ - { label: 'Filter 1', value: 'filter1', count: 2 }, - { label: 'Filter 3', value: 'filter3', count: 4 }, - { label: 'Filter 2', value: 'filter2', count: 0 }, - ]; - expect(getFacetOptions(selectedFiltersId, entries, facetData, key)).toEqual(expectedOptions); - }); - it('getFacetOptions handles invalid id values in entries correctly', () => { - const selectedFiltersId = ['filter1', 'filter2']; - const entries = [ - { id: 'filter1', totalRecords: 2 }, - { id: 'invalid', totalRecords: 4 }, - ]; - const facetData = [ - { id: 'filter1', name: 'Filter 1' }, - { id: 'filter2', name: 'Filter 2' }, - { id: 'filter3', name: 'Filter 3' }, - ]; - const key = 'id'; - const expectedOptions = [ - { label: 'Filter 1', value: 'filter1', count: 2 }, - { label: 'Filter 2', value: 'filter2', count: 0 }, - ]; - expect(getFacetOptions(selectedFiltersId, entries, facetData, key)).toEqual(expectedOptions); - }); -}); - -describe('getSuppressedOptions', () => { - it('returns an array of objects with the correct selectedFiltersId & suppressedOptionsRecords', () => { - const selectedFiltersId = []; - const suppressedOptionsRecords = [{ id: 'foo', totalRecords: 10 }]; - const result = getSuppressedOptions(selectedFiltersId, suppressedOptionsRecords); - expect(result).toEqual([ - { - label: expect.any(Object), - value: expect.any(String), - count: expect.any(Number), - }, - ]); - }); - it('should return the correct options when filters are selected', () => { - const selectedFiltersId = []; - const suppressedOptionsRecords = [ - { id: 'on_order', totalRecords: 5 }, - { id: 'suppressed', totalRecords: 0 }, - ]; - const expectedOptions = [ - { - label: , - value: expect.any(String), - count: 5, - }, - ]; - expect(getSuppressedOptions(selectedFiltersId, suppressedOptionsRecords)).toEqual(expectedOptions); - }); - it('should return the correct options when some filters are selected', () => { - const selectedFiltersId = ['on_order', 'suppressed']; - const suppressedOptionsRecords = [ - { id: 'on_order', totalRecords: 5 }, - { id: 'suppressed', totalRecords: 10 }, - ]; - const expectedOptions = [ - { - label: , - value: expect.any(String), - count: 5, - }, - { - label: , - value: expect.any(String), - count: 10, - }, - ]; - expect(getSuppressedOptions(selectedFiltersId, suppressedOptionsRecords)).toEqual(expectedOptions); - }); -}); - -describe('getSourceOptions', () => { - it('returns an array of options with the correct shape for each source record with a totalRecords property', () => { - const sourceRecords = [ - { id: 'source1', totalRecords: 10 }, - { id: 'source2', totalRecords: 20 }, - { id: 'source3', totalRecords: 30 }, - ]; - const selectedFiltersId = ['source1']; - const expectedOptions = [ - { label: 'source1', value: 'source1', count: 10 }, - { label: 'source2', value: 'source2', count: 20 }, - { label: 'source3', value: 'source3', count: 30 }, - ]; - expect(getSourceOptions(selectedFiltersId, sourceRecords)).toEqual(expectedOptions); - }); - it('returns an array of options with the correct shape for each selected filter ID that is not in the source records array', () => { - const sourceRecords = [ - { id: 'source1', totalRecords: 10 }, - { id: 'source2', totalRecords: 20 }, - { id: 'source3', totalRecords: 30 }, - ]; - const selectedFiltersId = ['source1', 'source4']; - const expectedOptions = [ - { label: 'source1', value: 'source1', count: 10 }, - { label: 'source2', value: 'source2', count: 20 }, - { label: 'source3', value: 'source3', count: 30 }, - { label: 'source4', value: 'source4', count: 0 }, - ]; - expect(getSourceOptions(selectedFiltersId, sourceRecords)).toEqual(expectedOptions); - }); - it('returns an empty array when both the sourceRecords and selectedFiltersId parameters are empty arrays', () => { - const sourceRecords = []; - const selectedFiltersId = []; - expect(getSourceOptions(selectedFiltersId, sourceRecords)).toEqual([]); - }); -}); - -describe('getItemStatusesOptions', () => { - it('returns an array of objects with the correct keys and values', () => { - const selectedFiltersId = ['filter1', 'filter2']; - const entries = [ - { id: 'filter1', totalRecords: 10 }, - { id: 'filter2', totalRecords: 20 }, - ]; - const facetData = [ - { value: 'filter1', label: 'Filter 1' }, - { value: 'filter2', label: 'Filter 2' }, - ]; - const intl = { - formatMessage: jest.fn(() => 'Formatted message'), - }; - const options = getItemStatusesOptions(selectedFiltersId, entries, facetData, intl); - expect(intl.formatMessage).toHaveBeenCalledTimes(2); - expect(options).toEqual([ - { label: 'Formatted message', value: 'filter1', count: 10 }, - { label: 'Formatted message', value: 'filter2', count: 20 }, - ]); - }); - - it('includes all filters in entries with a totalRecords value in the returned array', () => { - const selectedFiltersId = ['filter1', 'filter2']; - const entries = [ - { id: 'filter1', totalRecords: 10 }, - { id: 'filter2', totalRecords: 0 }, - { id: 'filter3', totalRecords: 20 }, - ]; - const facetData = [ - { value: 'filter1', label: 'Filter 1' }, - { value: 'filter2', label: 'Filter 2' }, - { value: 'filter3', label: 'Filter 3' }, - ]; - const intl = { - formatMessage: jest.fn(() => 'Formatted message'), - }; - const options = getItemStatusesOptions(selectedFiltersId, entries, facetData, intl); - expect(options).toEqual([ - { label: 'Formatted message', value: 'filter1', count: 10 }, - { label: 'Formatted message', value: 'filter3', count: 20 }, - ]); - }); -}); - -describe('processStatisticalCodes', () => { - const selectedFiltersId = new Set(['123', '456']); - const facetData = [ - { id: '123', name: 'Statistical Code 1', code: 'SC1', statisticalCodeType: { name: 'Type A' } }, - { id: '456', name: 'Statistical Code 2', code: 'SC2', statisticalCodeType: { name: 'Type B' } }, - { id: '789', name: 'Statistical Code 3', code: 'SC3', statisticalCodeType: { name: 'Type C' } }, - ]; - const recordValues = [ - { id: '123', totalRecords: 100 }, - { id: '456', totalRecords: 50 }, - { id: '789', totalRecords: 0 }, - ]; - const allFilters = {}; - const name = 'statisticalCodes'; - it('extracts statistical code options from facetData and recordValues', () => { - processStatisticalCodes(selectedFiltersId, recordValues, facetData, allFilters, name); - expect(allFilters[name]).toHaveLength(0); - }); - it('filters out statistical code options without totalRecords', () => { - const options = getFacetOptions(selectedFiltersId, recordValues, facetData, 'id'); - expect(options).toHaveLength(2); - }); - it('includes selected statistical code options without totalRecords', () => { - const options = getFacetOptions(selectedFiltersId, recordValues, facetData, 'id'); - expect(options).toEqual([ - { count: 100, label: 'Statistical Code 1', value: '123' }, - { count: 50, label: 'Statistical Code 2', value: '456' }, - ]); - }); - it('formats label for each statistical code option using statisticalCodeType and code', () => { - const options = getFacetOptions(selectedFiltersId, recordValues, facetData, 'id'); - expect(options[0]).toHaveProperty('label', 'Statistical Code 1'); - }); - it('sets value and count properties for each statistical code option', () => { - const options = getFacetOptions(selectedFiltersId, recordValues, facetData, 'id'); - expect(options[0]).toMatchObject({ value: '123', count: 100 }); - }); -}); - -describe('processFacetOptions', () => { - it('does not set allFilters[name] when facetData is not provided', () => { - const selectedFiltersId = []; - const recordValues = []; - const facetData = null; - const allFilters = {}; - const name = 'test'; - const key = 'id'; - processFacetOptions(selectedFiltersId, recordValues, facetData, allFilters, name, key); - expect(allFilters).not.toHaveProperty(name); - expect(allFilters).toEqual({}); - }); -}); - -describe('processItemsStatuses', () => { - it('processes item statuses correctly', () => { - const selectedFiltersId = ['status1', 'status2']; - const itemStatuses = [ - { value: 'status1', label: 'Status 1' }, - { value: 'status2', label: 'Status 2' }, - { value: 'status3', label: 'Status 3' }, - ]; - const intl = { - formatMessage: jest.fn(() => 'Status 1'), - }; - const recordValues = [ - { id: 'status1', totalRecords: 5 }, - { id: 'status2', totalRecords: 10 }, - { id: 'status3', totalRecords: 0 }, - ]; - const accum = {}; - const name = 'itemStatuses'; - processItemsStatuses(selectedFiltersId, itemStatuses, intl, recordValues, accum, name); - expect(accum).toEqual({ - itemStatuses: [ - { label: 'Status 1', value: 'status1', count: 5 }, - { label: 'Status 1', value: 'status2', count: 10 }, - ], - }); - }); -}); diff --git a/src/filterConfig.js b/src/filterConfig.js deleted file mode 100644 index ba9f51509..000000000 --- a/src/filterConfig.js +++ /dev/null @@ -1,341 +0,0 @@ -import itemFilterRenderer from './components/ItemFilters/itemFilterRenderer'; -import holdingsRecordFilterRenderer from './components/HoldingsRecordFilters/holdingsRecordFilterRenderer'; -import instanceFilterRenderer from './components/InstanceFilters/instanceFilterRenderer'; - -import { - FACETS, - FACETS_CQL, - browseModeOptions, -} from './constants'; -import { - buildDateRangeQuery, -} from './utils'; - -export const instanceFilterConfig = [ - { - name: FACETS.EFFECTIVE_LOCATION, - cql: FACETS_CQL.EFFECTIVE_LOCATION, - values: [], - }, - { - name: FACETS.LANGUAGE, - cql: FACETS_CQL.LANGUAGES, - values: [], - }, - { - name: FACETS.FORMAT, - cql: FACETS_CQL.INSTANCE_FORMAT, - values: [], - }, - { - name: FACETS.RESOURCE, - cql: FACETS_CQL.INSTANCE_TYPE, - values: [], - }, - { - name: FACETS.MODE, - cql: FACETS_CQL.MODE_OF_ISSUANCE, - values: [], - }, - { - name: FACETS.NATURE_OF_CONTENT, - cql: FACETS_CQL.NATURE_OF_CONTENT, - values: [], - }, - { - name: 'location', - cql: FACETS_CQL.HOLDINGS_PERMANENT_LOCATION, - values: [], - }, - { - name: FACETS_CQL.STAFF_SUPPRESS, - cql: FACETS_CQL.STAFF_SUPPRESS, - values: [], - }, - { - name: FACETS.INSTANCES_DISCOVERY_SUPPRESS, - cql: FACETS_CQL.INSTANCES_DISCOVERY_SUPPRESS, - values: [], - }, - { - name: FACETS.CREATED_DATE, - cql: FACETS_CQL.CREATED_DATE, - values: [], - parse: buildDateRangeQuery(FACETS_CQL.CREATED_DATE), - }, - { - name: FACETS.UPDATED_DATE, - cql: FACETS_CQL.UPDATED_DATE, - values: [], - parse: buildDateRangeQuery(FACETS_CQL.UPDATED_DATE), - }, - { - name: FACETS.STATUS, - cql: FACETS_CQL.STATUS, - operator: '==', - values: [], - }, - { - name: FACETS.SOURCE, - cql: FACETS_CQL.SOURCE, - operator: '==', - values: [], - }, - { - name: FACETS.STATISTICAL_CODE_IDS, - cql: FACETS_CQL.STATISTICAL_CODE_IDS, - values: [], - }, - { - name: FACETS.INSTANCES_TAGS, - cql: FACETS_CQL.INSTANCES_TAGS, - values: [], - }, - { - name: FACETS.EFFECTIVE_LOCATION, - cql: FACETS_CQL.EFFECTIVE_LOCATION, - values: [], - }, - { - name: FACETS.NAME_TYPE, - cql: FACETS_CQL.NAME_TYPE, - values: [], - }, - { - name: FACETS.SEARCH_CONTRIBUTORS, - cql: FACETS_CQL.SEARCH_CONTRIBUTORS, - values: [], - }, -]; - -export const instanceIndexes = [ - // NOTE: the 'all' value was first used for a 'keyword all' query, but then - // a *real* 'all' query option was added ('allInstances any'). That was given the value `allFields` - // instead. It might make sense to rename the keyword option to something like `keywordAll` - // but, without tracing the use of the value, I don't know what effects that would have in the code. - { label: 'ui-inventory.search.all', value: 'all', queryTemplate: 'keyword all "%{query.query}" or isbn="%{query.query}" or hrid=="%{query.query}" or id=="%{query.query}"' }, - { label: 'ui-inventory.contributor', value: 'contributor', queryTemplate: 'contributors.name="%{query.query}"' }, - { label: 'ui-inventory.title', value: 'title', queryTemplate: 'title all "%{query.query}"' }, - { label: 'ui-inventory.identifierAll', value: 'identifier', queryTemplate: 'identifiers.value="%{query.query}" or isbn="%{query.query}"' }, - { label: 'ui-inventory.isbn', value: 'isbn', queryTemplate: 'isbn="%{query.query}"' }, - { label: 'ui-inventory.issn', value: 'issn', queryTemplate: 'issn="%{query.query}"' }, - { label: 'ui-inventory.search.oclc', value: 'oclc', queryTemplate: 'oclc="%{query.query}"' }, - { label: 'ui-inventory.search.instanceNotes', value: 'instanceNotes', queryTemplate: 'notes.note all "%{query.query}" or administrativeNotes all "%{query.query}"' }, - { label: 'ui-inventory.search.instanceAdministrativeNotes', value: 'instanceAdministrativeNotes', queryTemplate: 'administrativeNotes all "%{query.query}"' }, - { label: 'ui-inventory.subject', value: 'subject', queryTemplate: ({ query, authorityId }) => `subjects.value==/string "${query}"${authorityId ? ` and authorityId=="${authorityId}"` : ''}` }, - { label: 'ui-inventory.effectiveCallNumberShelving', value: 'callNumber', queryTemplate: 'itemEffectiveShelvingOrder==/string "%{query.query}"' }, - { label: 'ui-inventory.instanceHrid', value: 'hrid', queryTemplate: 'hrid=="%{query.query}"' }, - { label: 'ui-inventory.instanceId', value: 'id', queryTemplate: 'id="%{query.query}"' }, - { label: 'ui-inventory.authorityId', value: 'authorityId', queryTemplate: 'authorityId == %{query.query}' }, - { label: 'ui-inventory.search.allFields', value: 'allFields', queryTemplate: 'cql.all all "%{query.query}"' }, - { label: 'ui-inventory.querySearch', value: 'querySearch', queryTemplate: '%{query.query}' }, -]; - -export const browseFiltersConfig = [ - { - name: FACETS.EFFECTIVE_LOCATION, - cql: FACETS_CQL.EFFECTIVE_LOCATION, - values: [], - }, - { - name: FACETS.NAME_TYPE, - cql: FACETS_CQL.NAME_TYPE, - values: [], - }, -]; - -export const browseInstanceIndexes = [ - { label: 'ui-inventory.browse.callNumbers', value: `${browseModeOptions.CALL_NUMBERS}`, queryTemplate: '%{query.query}' }, - { label: 'ui-inventory.browse.contributors', value: `${browseModeOptions.CONTRIBUTORS}`, queryTemplate: '%{query.query}' }, - { label: 'ui-inventory.browse.subjects', value: `${browseModeOptions.SUBJECTS}`, queryTemplate: '%{query.query}' }, -]; - -export const instanceBrowseSortMap = { - callNumber: 'callNumber', - title: 'title', - numberOfTitles: 'numberOfTitles', -}; - -export const instanceSortMap = { - Title: 'title', - publishers: 'publication', - Contributors: 'contributors', -}; - -export const holdingIndexes = [ - // See note for instanceIndexes about 'all' vs. 'allFields' - { label: 'ui-inventory.search.all', value: 'all', queryTemplate: 'keyword all "%{query.query}" or isbn="%{query.query}" or holdings.hrid=="%{query.query}" or holdings.id=="%{query.query}"' }, - { label: 'ui-inventory.isbn', value: 'isbn', queryTemplate: 'isbn="%{query.query}"' }, - { label: 'ui-inventory.issn', value: 'issn', queryTemplate: 'issn="%{query.query}"' }, - { label: 'ui-inventory.callNumberEyeReadable', - value: 'holdingsFullCallNumbers', - queryTemplate: 'holdingsFullCallNumbers="%{query.query}"' }, - { label: 'ui-inventory.callNumberNormalized', - value: 'callNumberNormalized', - queryTemplate: 'holdingsNormalizedCallNumbers="%{query.query}"' }, - { label: 'ui-inventory.search.holdingsNotes', value: 'holdingsNotes', queryTemplate: 'holdings.notes.note all "%{query.query}" or holdings.administrativeNotes all "%{query.query}"' }, - { label: 'ui-inventory.search.holdingsAdministrativeNotes', value: 'holdingsAdministrativeNotes', queryTemplate: 'holdings.administrativeNotes all "%{query.query}"' }, - { label: 'ui-inventory.holdingsHrid', value: 'hrid', queryTemplate: 'holdings.hrid=="%{query.query}"' }, - { label: 'ui-inventory.search.holdings.uuid', value: 'hid', queryTemplate: 'holdings.id=="%{query.query}"' }, - { label: 'ui-inventory.search.allFields', value: 'allFields', queryTemplate: 'cql.all all "%{query.query}"' }, - { label: 'ui-inventory.querySearch', value: 'querySearch', queryTemplate: '%{query.query}' }, -]; - -export const holdingSortMap = {}; - -export const holdingFilterConfig = [ - { - name: FACETS.EFFECTIVE_LOCATION, - cql: FACETS_CQL.EFFECTIVE_LOCATION, - values: [], - }, - { - name: FACETS.HOLDINGS_PERMANENT_LOCATION, - cql: FACETS_CQL.HOLDINGS_PERMANENT_LOCATION, - values: [], - }, - { - name: FACETS.HOLDINGS_TYPE, - cql: FACETS_CQL.HOLDINGS_TYPE, - values: [], - }, - { - name: FACETS.HOLDINGS_DISCOVERY_SUPPRESS, - cql: FACETS_CQL.HOLDINGS_DISCOVERY_SUPPRESS, - values: [], - }, - { - name: FACETS.HOLDINGS_TAGS, - cql: FACETS_CQL.HOLDINGS_TAGS, - values: [], - }, - { - name: FACETS.HOLDINGS_STATISTICAL_CODE_IDS, - cql: FACETS_CQL.HOLDINGS_STATISTICAL_CODE_IDS, - values: [], - }, - { - name: FACETS.HOLDINGS_CREATED_DATE, - cql: FACETS_CQL.HOLDINGS_CREATED_DATE, - values: [], - parse: buildDateRangeQuery(FACETS_CQL.HOLDINGS_CREATED_DATE), - }, - { - name: FACETS.HOLDINGS_UPDATED_DATE, - cql: FACETS_CQL.HOLDINGS_UPDATED_DATE, - values: [], - parse: buildDateRangeQuery(FACETS_CQL.HOLDINGS_UPDATED_DATE), - }, - { - name: FACETS.HOLDINGS_SOURCE, - cql: FACETS_CQL.HOLDINGS_SOURCE, - values: [], - }, -]; - -export const itemIndexes = [ - // See note for instanceIndexes about 'all' vs. 'allFields' - { label: 'ui-inventory.search.all', value: 'all', queryTemplate: 'keyword all "%{query.query}" or isbn="%{query.query}" or item.hrid=="%{query.query}" or item.id=="%{query.query}"' }, - { label: 'ui-inventory.barcode', value: 'items.barcode', queryTemplate: 'items.barcode=="%{query.query}"' }, - { label: 'ui-inventory.isbn', value: 'isbn', queryTemplate: 'isbn="%{query.query}"' }, - { label: 'ui-inventory.issn', value: 'issn', queryTemplate: 'issn="%{query.query}"' }, - { label: 'ui-inventory.itemEffectiveCallNumberEyeReadable', - value: 'itemFullCallNumbers', - queryTemplate: 'itemFullCallNumbers="%{query.query}"' }, - { label: 'ui-inventory.itemEffectiveCallNumberNormalized', - value: 'itemNormalizedCallNumbers', - queryTemplate: 'itemNormalizedCallNumbers="%{query.query}"' }, - { label: 'ui-inventory.search.itemNotes', value: 'holdingsNotes', queryTemplate: 'item.notes.note all "%{query.query}" or item.administrativeNotes all "%{query.query}"' }, - { label: 'ui-inventory.search.itemAdministrativeNotes', value: 'itemAdministrativeNotes', queryTemplate: 'item.administrativeNotes all "%{query.query}"' }, - { label: 'ui-inventory.search.itemCirculationNotes', value: 'itemCirculationNotes', queryTemplate: 'item.circulationNotes.note all "%{query.query}"' }, - { label: 'ui-inventory.itemHrid', value: 'hrid', queryTemplate: 'items.hrid=="%{query.query}"' }, - { label: 'ui-inventory.search.item.uuid', value: 'iid', queryTemplate: 'item.id=="%{query.query}"' }, - { label: 'ui-inventory.search.allFields', value: 'allFields', queryTemplate: 'cql.all all "%{query.query}"' }, - { label: 'ui-inventory.querySearch', value: 'querySearch', queryTemplate: '%{query.query}' }, -]; - -export const itemFilterConfig = [ - { - name: FACETS.MATERIAL_TYPE, - cql: FACETS_CQL.MATERIAL_TYPES, - values: [], - }, - { - name: FACETS.ITEM_STATUS, - cql: FACETS_CQL.ITEMS_STATUSES, - operator: '==', - values: [], - }, - { - name: FACETS.EFFECTIVE_LOCATION, - cql: FACETS_CQL.EFFECTIVE_LOCATION, - values: [], - }, - { - name: FACETS.HOLDINGS_PERMANENT_LOCATION, - cql: FACETS_CQL.HOLDINGS_PERMANENT_LOCATION, - values: [], - }, - { - name: FACETS.ITEMS_DISCOVERY_SUPPRESS, - cql: FACETS_CQL.ITEMS_DISCOVERY_SUPPRESS, - values: [], - }, - { - name: FACETS.ITEMS_STATISTICAL_CODE_IDS, - cql: FACETS_CQL.ITEMS_STATISTICAL_CODE_IDS, - values: [], - }, - { - name: FACETS.ITEMS_CREATED_DATE, - cql: FACETS_CQL.ITEMS_CREATED_DATE, - values: [], - parse: buildDateRangeQuery(FACETS_CQL.ITEMS_CREATED_DATE), - }, - { - name: FACETS.ITEMS_UPDATED_DATE, - cql: FACETS_CQL.ITEMS_UPDATED_DATE, - values: [], - parse: buildDateRangeQuery(FACETS_CQL.ITEMS_UPDATED_DATE), - }, - { - name: FACETS.ITEMS_TAGS, - cql: FACETS_CQL.ITEMS_TAGS, - values: [], - }, -]; - -export const itemSortMap = { - Title: 'title', - publishers: 'publication', - Contributors: 'contributors', -}; - -const config = { - instances: { - filters: instanceFilterConfig, - indexes: [...instanceIndexes], - sortMap: instanceSortMap, - renderer: instanceFilterRenderer, - }, - holdings: { - filters: holdingFilterConfig, - indexes: holdingIndexes, - sortMap: holdingSortMap, - renderer: holdingsRecordFilterRenderer, - }, - items: { - filters: itemFilterConfig, - indexes: itemIndexes, - sortMap: itemSortMap, - renderer: itemFilterRenderer, - }, -}; - -export const browseConfig = { - filters: browseFiltersConfig, - indexes: browseInstanceIndexes, - sortMap: instanceBrowseSortMap, -}; - -export const getFilterConfig = (segment = 'instances') => config[segment]; diff --git a/src/routes/InstancesRoute.js b/src/routes/InstancesRoute.js index 0095ae6a4..3fe4074bf 100644 --- a/src/routes/InstancesRoute.js +++ b/src/routes/InstancesRoute.js @@ -3,12 +3,11 @@ import PropTypes from 'prop-types'; import { flowRight } from 'lodash'; import { stripesConnect } from '@folio/stripes/core'; +import { withFacets, getFilterConfig } from '@folio/stripes-inventory-components'; import withLocation from '../withLocation'; -import withFacets from '../withFacets'; import withLastSearchTerms from '../withLastSearchTerms'; import { InstancesView } from '../views'; -import { getFilterConfig } from '../filterConfig'; import { buildManifestObject } from './buildManifestObject'; import { DataContext } from '../contexts'; diff --git a/src/stores/facetsStore.js b/src/stores/facetsStore.js deleted file mode 100644 index 8cd215cd0..000000000 --- a/src/stores/facetsStore.js +++ /dev/null @@ -1,42 +0,0 @@ -import create from 'zustand'; - -// Facets store contains a global state related -// to facets. -// Currently it only holds facetSettings which -// represents a state (searchValue and isOnMoreClicked) -// for each facet. -const facetsStore = create((set) => ({ - facetSettings: {}, - setFacetSettings: (name, value) => { - set(state => { - state.facetSettings = { - ...state.facetSettings, - [name]: { - ...state.facetSettings[name], - ...value, - }, - }; - }); - }, - resetFacetSettings: () => set({ facetSettings: {} }), - resetFacetByName: (name) => { - set(state => { - delete state.facetSettings[name]; - }); - } -})); - -// selectors -export const getSearchTerm = (name) => { - return facetsStore.getState().facetSettings?.[name]?.value ?? ''; -}; - -// hooks -export const useFacetSettings = () => facetsStore(store => [ - store.facetSettings, - store.setFacetSettings, -]); -export const useResetFacetSettings = () => facetsStore(store => store.resetFacetSettings); -export const useSearchValue = name => facetsStore(store => store.facetSettings?.[name]?.value); - -export default facetsStore; diff --git a/src/stores/facetsStore.test.js b/src/stores/facetsStore.test.js deleted file mode 100644 index e785bc0da..000000000 --- a/src/stores/facetsStore.test.js +++ /dev/null @@ -1,55 +0,0 @@ -import facetsStore, { getSearchTerm } from './facetsStore'; - -const getFacetSettings = () => facetsStore.getState().facetSettings; - -describe('facetsStore', () => { - beforeEach(() => { - const { resetFacetSettings } = facetsStore.getState(); - resetFacetSettings(); - }); - - describe('setFacetSettings', () => { - test('setting value', () => { - const { setFacetSettings } = facetsStore.getState(); - setFacetSettings('test', { value: 2 }); - expect(getFacetSettings()).toEqual({ test: { value: 2 } }); - }); - - test('setting value with pre existing values', () => { - const { setFacetSettings } = facetsStore.getState(); - setFacetSettings('test1', { value: 1 }); - setFacetSettings('test2', { value: 2 }); - - expect(getFacetSettings()).toEqual({ test1: { value: 1 }, test2: { value: 2 } }); - }); - }); - - describe('resetFacetSettings', () => { - test('resetting values', () => { - const { setFacetSettings, resetFacetSettings } = facetsStore.getState(); - setFacetSettings('test1', { value: 1 }); - resetFacetSettings(); - - expect(getFacetSettings()).toEqual({}); - }); - }); - - describe('resetFacetByName', () => { - test('resetting values', () => { - const { setFacetSettings, resetFacetByName } = facetsStore.getState(); - setFacetSettings('test1', { value: 1 }); - resetFacetByName('test1'); - - expect(getFacetSettings()).toEqual({}); - }); - }); - - describe('getSearchTerm', () => { - test('getting search term value', () => { - const { setFacetSettings } = facetsStore.getState(); - setFacetSettings('test', { value: 2 }); - - expect(getSearchTerm('test')).toEqual(2); - }); - }); -}); diff --git a/src/withFacets.js b/src/withFacets.js deleted file mode 100644 index 3ac0795f6..000000000 --- a/src/withFacets.js +++ /dev/null @@ -1,182 +0,0 @@ -import { reduce } from 'lodash'; -import React from 'react'; -import PropTypes from 'prop-types'; - -import { makeQueryFunction } from '@folio/stripes/smart-components'; - -import { - getQueryTemplate, -} from './utils'; -import { - browseConfig, - getFilterConfig, -} from './filterConfig'; -import { - DEFAULT_FILTERS_NUMBER, - FACETS, - FACETS_TO_REQUEST, - FACETS_ENDPOINTS, - CQL_FIND_ALL, - browseModeOptions, - browseModeMap, -} from './constants'; - -function buildQuery(queryParams, pathComponents, resourceData, logger, props) { - const queryIndex = queryParams?.qindex ?? 'all'; - const { indexes, filters } = browseModeMap[queryIndex] ? browseConfig : getFilterConfig(queryParams.segment); - const queryTemplate = getQueryTemplate(queryIndex, indexes); - - // reset qindex otherwise makeQueryFunction does not use queryTemplate - // https://github.com/folio-org/stripes-smart-components/blob/e918a620ad2ac2c5b06ce121cd0e061a03bcfdf6/lib/SearchAndSort/makeQueryFunction.js#L46 - // https://issues.folio.org/browse/UIIN-2189 - resourceData.query = { ...resourceData.query, qindex: '' }; - - const cql = makeQueryFunction( - CQL_FIND_ALL, - queryTemplate, - {}, - filters, - 2, - null, - false, - )(queryParams, pathComponents, resourceData, logger, props); - - return cql === undefined - ? CQL_FIND_ALL - : cql; -} - -function withFacets(WrappedComponent) { - class FacetsHoc extends React.Component { - static manifest = Object.freeze( - { - ...WrappedComponent.manifest, - facets: { - type: 'okapi', - records: 'facets', - path: 'search/instances/facets', - fetch: false, - accumulate: true, - throwErrors: false, - }, - }, - ); - - static propTypes = { - activeFilters: PropTypes.object, - resources: PropTypes.shape({ - query: PropTypes.object, - facets: PropTypes.object, - }), - mutator: PropTypes.shape({ - facets: PropTypes.shape({ - GET: PropTypes.func.isRequired, - reset: PropTypes.func, - }), - }), - }; - - getFacets = (accordions, accordionsData) => { - let index = 0; - - return reduce(accordions, (accum, isFacetOpened, facetName) => { - if ( - isFacetOpened && - !facetName.match(/createdDate/i) && - !facetName.match(/updatedDate/i) - ) { - const facetNameToRequest = FACETS_TO_REQUEST[facetName]; - const defaultFiltersNumber = `:${DEFAULT_FILTERS_NUMBER}`; - const isFacetValue = accordionsData?.[facetName]?.value; - const isFilterSelected = accordionsData?.[facetName]?.isSelected; - const isOnMoreClicked = accordionsData?.[facetName]?.isOnMoreClicked; - const isNeedAllFilters = - isOnMoreClicked || - isFacetValue || - isFilterSelected; - - const symbol = index - ? ',' - : ''; - - index++; - return `${accum}${symbol}${facetNameToRequest}${isNeedAllFilters ? '' : defaultFiltersNumber}`; - } - return accum; - }, ''); - }; - - fetchFacets = (data) => async (properties = {}) => { - const { - onMoreClickedFacet, - focusedFacet, - accordions, - accordionsData, - facetToOpen, - } = properties; - const { - resources, - mutator, - } = this.props; - const { - reset, - GET, - } = mutator.facets; - - // Browse page does not use query resource: query params are stored in "activeFilters" of "useLocationFilters" hook - const query = resources.query || this.props.activeFilters; - - // temporary query value - const params = { query: 'id = *' }; - const cqlQuery = buildQuery(query, {}, { ...data, query }, { log: () => null }) || ''; - const facetName = facetToOpen || onMoreClickedFacet || focusedFacet; - const facetNameToRequest = FACETS_TO_REQUEST[facetName]; - const paramsUrl = new URLSearchParams(window.location.search); - const queryIndex = paramsUrl.get('qindex') || query?.qindex; - - if (facetName === FACETS.NAME_TYPE) { - params.query = 'contributorNameTypeId=*'; - } else if (cqlQuery && queryIndex === browseModeOptions.CALL_NUMBERS) { - params.query = 'callNumber=""'; - } else if (cqlQuery && queryIndex !== browseModeOptions.CALL_NUMBERS) { - params.query = cqlQuery; - } - - if (facetToOpen) { - const defaultFiltersNumber = `:${DEFAULT_FILTERS_NUMBER}`; - params.facet = `${facetNameToRequest}${defaultFiltersNumber}`; - } else if (onMoreClickedFacet || focusedFacet) { - params.facet = facetNameToRequest; - } else { - const facets = this.getFacets(accordions, accordionsData); - - if (facets) { - params.facet = facets; - } else { - return; - } - } - - try { - reset(); - const requestPath = FACETS_ENDPOINTS[facetName] || 'search/instances/facets'; - await GET({ path: requestPath, params }); - } catch (error) { - throw new Error(error); - } - }; - - render() { - return ( - - ); - } - } - - return FacetsHoc; -} - -export default withFacets; From 75f0ee58eb7a1eb336d58d72d06bedd60d571e78 Mon Sep 17 00:00:00 2001 From: Michal Kuklis Date: Mon, 29 May 2023 21:11:23 -0400 Subject: [PATCH 2/8] Cleanup --- package.json | 1 + src/common/hooks/index.js | 1 - .../BrowseInventoryFilters/BrowseInventoryFilters.js | 4 ++-- .../BrowseInventoryFilters/BrowseInventoryFilters.test.js | 4 ++-- src/components/InstancesList/InstancesList.js | 2 +- src/components/InstancesList/InstancesList.test.js | 2 +- src/components/index.js | 5 ----- src/routes/buildManifestObject.js | 3 +-- src/routes/buildManifestObject.test.js | 2 +- src/views/BrowseInventory/BrowseInventory.js | 3 ++- 10 files changed, 11 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index 1db228383..ce2c376bf 100644 --- a/package.json +++ b/package.json @@ -886,6 +886,7 @@ "dependencies": { "@folio/quick-marc": "^7.0.0", "@folio/stripes-acq-components": "^4.0.0", + "@folio/stripes-inventory-components": "^1.0.0", "file-saver": "^2.0.0", "final-form": "^4.18.2", "final-form-arrays": "^3.0.1", diff --git a/src/common/hooks/index.js b/src/common/hooks/index.js index 2a1564652..7661761bf 100644 --- a/src/common/hooks/index.js +++ b/src/common/hooks/index.js @@ -1,7 +1,6 @@ export { default as useControlledAccordion } from './useControlledAccordion'; export { default as useInstance } from './useInstance'; export { default as useGoBack } from './useGoBack'; -export { default as useFacets } from './useFacets'; export { default as useHolding } from './useHolding'; export { default as useInstanceQuery } from './useInstanceQuery'; export * from './useConfirmationModal'; diff --git a/src/components/BrowseInventoryFilters/BrowseInventoryFilters.js b/src/components/BrowseInventoryFilters/BrowseInventoryFilters.js index 55ad1ad28..b9ac21cfa 100644 --- a/src/components/BrowseInventoryFilters/BrowseInventoryFilters.js +++ b/src/components/BrowseInventoryFilters/BrowseInventoryFilters.js @@ -3,11 +3,11 @@ import { useContext } from 'react'; import { flowRight, omit } from 'lodash'; import { stripesConnect } from '@folio/stripes/core'; +import { withFacets, InstanceFilters as InstanceFiltersBrowse } from '@folio/stripes-inventory-components'; -import withFacets from '../../withFacets'; import { DataContext } from '../../contexts'; import { parseFiltersToStr } from '../../utils'; -import { InstanceFiltersBrowse } from '../InstanceFilters'; +// import { InstanceFiltersBrowse } from '../InstanceFilters'; const BrowseInventoryFilters = ({ activeFilters, diff --git a/src/components/BrowseInventoryFilters/BrowseInventoryFilters.test.js b/src/components/BrowseInventoryFilters/BrowseInventoryFilters.test.js index b938aebc4..b9781bd26 100644 --- a/src/components/BrowseInventoryFilters/BrowseInventoryFilters.test.js +++ b/src/components/BrowseInventoryFilters/BrowseInventoryFilters.test.js @@ -32,8 +32,8 @@ jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useLocation: jest.fn(() => ({ search: '' })), })); -jest.mock('../../common/hooks', () => ({ - ...jest.requireActual('../../common/hooks'), +jest.mock('@folio/stripes-inventory-components', () => ({ + ...jest.requireActual('@folio/stripes-inventory-components'), useFacets: jest.fn(() => ([ { effectiveLocation: true, nameType: false }, jest.fn(), diff --git a/src/components/InstancesList/InstancesList.js b/src/components/InstancesList/InstancesList.js index 04b012aaf..2c07ee542 100644 --- a/src/components/InstancesList/InstancesList.js +++ b/src/components/InstancesList/InstancesList.js @@ -37,6 +37,7 @@ import { TextLink, DefaultMCLRowFormatter, } from '@folio/stripes/components'; +import { facetsStore } from '@folio/stripes-inventory-components'; import FilterNavigation from '../FilterNavigation'; import SearchModeNavigation from '../SearchModeNavigation'; @@ -73,7 +74,6 @@ import { getItem, setItem, } from '../../storage'; -import facetsStore from '../../stores/facetsStore'; import css from './instances.css'; diff --git a/src/components/InstancesList/InstancesList.test.js b/src/components/InstancesList/InstancesList.test.js index 347b892fd..48162e970 100644 --- a/src/components/InstancesList/InstancesList.test.js +++ b/src/components/InstancesList/InstancesList.test.js @@ -14,11 +14,11 @@ import { import '../../../test/jest/__mock__'; import { StripesContext, ModuleHierarchyProvider } from '@folio/stripes/core'; +import {getFilterConfig } from '@folio/stripes-inventory-components'; import renderWithIntl from '../../../test/jest/helpers/renderWithIntl'; import translationsProperties from '../../../test/jest/helpers/translationsProperties'; import { instances as instancesFixture } from '../../../test/fixtures/instances'; -import { getFilterConfig } from '../../filterConfig'; import InstancesList from './InstancesList'; const updateMock = jest.fn(); diff --git a/src/components/index.js b/src/components/index.js index 3e2ac0035..eb4a985a9 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -1,7 +1,4 @@ export { default as FilterNavigation } from './FilterNavigation'; -export { default as InstanceFilters, InstanceFiltersBrowse, instanceFilterRenderer } from './InstanceFilters'; -export { default as HoldingsRecordFilters, holdingsRecordFilterRenderer } from './HoldingsRecordFilters'; -export { default as ItemFilters, itemFilterRenderer } from './ItemFilters'; export { default as InstancePlugin } from './InstancePlugin'; export { default as ConnectedTitle } from './ConnectedTitle'; export { default as UnconnectedTitle } from './UnconnectedTitle'; @@ -15,8 +12,6 @@ export { default as WarningMessage } from './WarningMessage'; export { default as CalloutRenderer } from './CalloutRenderer'; export { default as ViewSource } from './ViewSource'; export { default as AdministrativeNoteList } from './AdministrativeNoteList'; -export { default as MultiSelectionFacet } from './MultiSelectionFacet'; -export { default as FacetOptionFormatter } from './FacetOptionFormatter'; export { default as SearchModeNavigation } from './SearchModeNavigation'; export { default as BrowseResultsPane } from './BrowseResultsPane'; export { default as BrowseResultsList } from './BrowseResultsList'; diff --git a/src/routes/buildManifestObject.js b/src/routes/buildManifestObject.js index f828f3f03..4694258cd 100644 --- a/src/routes/buildManifestObject.js +++ b/src/routes/buildManifestObject.js @@ -4,6 +4,7 @@ import { } from 'lodash'; import { makeQueryFunction } from '@folio/stripes/smart-components'; +import { getFilterConfig, facetsStore } from '@folio/stripes-inventory-components'; import { CQL_FIND_ALL, queryIndexes @@ -12,8 +13,6 @@ import { getQueryTemplate, getIsbnIssnTemplate, } from '../utils'; -import { getFilterConfig } from '../filterConfig'; -import facetsStore from '../stores/facetsStore'; const INITIAL_RESULT_COUNT = 100; const DEFAULT_SORT = 'title'; diff --git a/src/routes/buildManifestObject.test.js b/src/routes/buildManifestObject.test.js index cdd176a5a..074305ee6 100644 --- a/src/routes/buildManifestObject.test.js +++ b/src/routes/buildManifestObject.test.js @@ -1,7 +1,7 @@ import '../../test/jest/__mock__'; import { queryIndexes } from '../constants'; -import { instanceIndexes } from '../filterConfig'; +import { instanceIndexes } from '@folio/stripes-inventory-components'; import { buildQuery } from './buildManifestObject'; const getQueryTemplate = (qindex) => instanceIndexes.find(({ value }) => value === qindex).queryTemplate; diff --git a/src/views/BrowseInventory/BrowseInventory.js b/src/views/BrowseInventory/BrowseInventory.js index 1f08e2c00..cfdf74393 100644 --- a/src/views/BrowseInventory/BrowseInventory.js +++ b/src/views/BrowseInventory/BrowseInventory.js @@ -16,13 +16,14 @@ import { useItemToView, useLocationFilters, } from '@folio/stripes-acq-components'; +import { browseInstanceIndexes } from '@folio/stripes-inventory-components'; import { BrowseInventoryFilters, BrowseResultsPane, SearchModeNavigation, } from '../../components'; -import { browseInstanceIndexes } from '../../filterConfig'; + import { useBrowseValidation, useInventoryBrowse, From e7998eecfd835fe5838c1c3017980e32cfaabb06 Mon Sep 17 00:00:00 2001 From: Michal Kuklis Date: Wed, 31 May 2023 20:30:39 -0400 Subject: [PATCH 3/8] Cleanup --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index ce2c376bf..20fbcf205 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,8 @@ } ], "stripesDeps": [ - "@folio/stripes-acq-components" + "@folio/stripes-acq-components", + "@folio/stripes-inventory-components" ], "okapiInterfaces": { "alternative-title-types": "1.0", From 7ff0243628a1afb2643925619fcaf630e04848e7 Mon Sep 17 00:00:00 2001 From: Michal Kuklis Date: Wed, 31 May 2023 20:44:12 -0400 Subject: [PATCH 4/8] Cleanup --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 20fbcf205..980eeba2a 100644 --- a/package.json +++ b/package.json @@ -837,7 +837,7 @@ "lint": "eslint .", "test": "yarn run test:unit", "test:jest": "jest", - "test:unit": "jest --ci --coverage", + "test:unit": "jest --ci --coverage --silent", "test:unit:watch": "jest --watch --coverage", "test:e2e": "stripes test karma", "test:e2e:ci": "stripes test karma --karma.singleRun --karma.browsers ChromeDocker --karma.reporters mocha junit --coverage", From df09c08d423d8749402b87920d46b9fc88804ea2 Mon Sep 17 00:00:00 2001 From: Michal Kuklis Date: Wed, 31 May 2023 21:25:30 -0400 Subject: [PATCH 5/8] Cleanup --- src/components/InstancesList/InstancesList.test.js | 2 +- test/jest/helpers/translationsProperties.js | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/InstancesList/InstancesList.test.js b/src/components/InstancesList/InstancesList.test.js index 34a9a63ea..f92b2fae9 100644 --- a/src/components/InstancesList/InstancesList.test.js +++ b/src/components/InstancesList/InstancesList.test.js @@ -15,7 +15,7 @@ import { import '../../../test/jest/__mock__'; import { StripesContext, ModuleHierarchyProvider } from '@folio/stripes/core'; -import {getFilterConfig } from '@folio/stripes-inventory-components'; +import { getFilterConfig } from '@folio/stripes-inventory-components'; import renderWithIntl from '../../../test/jest/helpers/renderWithIntl'; import translationsProperties from '../../../test/jest/helpers/translationsProperties'; diff --git a/test/jest/helpers/translationsProperties.js b/test/jest/helpers/translationsProperties.js index b78695e40..9b4d6063f 100644 --- a/test/jest/helpers/translationsProperties.js +++ b/test/jest/helpers/translationsProperties.js @@ -2,6 +2,7 @@ import stripesComponentsTranslations from '@folio/stripes-components/translation import stripesSmartComponentsTranslations from '@folio/stripes-smart-components/translations/stripes-smart-components/en'; import stripesCoreTranslations from '@folio/stripes-core/translations/stripes-core/en'; import stripesAcqComponentsTranslations from '@folio/stripes-acq-components/translations/stripes-acq-components/en'; +import stripesInvComponentsTranslations from '@folio/stripes-inventory-components/translations/stripes-inventory-components/en'; import translations from '../../../translations/ui-inventory/en'; const translationsProperties = [ @@ -24,6 +25,10 @@ const translationsProperties = [ { prefix: 'stripes-acq-components', translations: stripesAcqComponentsTranslations, + }, + { + prefix: 'stripes-inventory-components', + translations: stripesInvComponentsTranslations } ]; From 026623d298c1d2ce32c68eb813fe93bb6a78be27 Mon Sep 17 00:00:00 2001 From: Michal Kuklis Date: Wed, 31 May 2023 21:26:28 -0400 Subject: [PATCH 6/8] Cleanup --- src/components/BrowseInventoryFilters/BrowseInventoryFilters.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/BrowseInventoryFilters/BrowseInventoryFilters.js b/src/components/BrowseInventoryFilters/BrowseInventoryFilters.js index b9ac21cfa..72fd75b2a 100644 --- a/src/components/BrowseInventoryFilters/BrowseInventoryFilters.js +++ b/src/components/BrowseInventoryFilters/BrowseInventoryFilters.js @@ -7,7 +7,6 @@ import { withFacets, InstanceFilters as InstanceFiltersBrowse } from '@folio/str import { DataContext } from '../../contexts'; import { parseFiltersToStr } from '../../utils'; -// import { InstanceFiltersBrowse } from '../InstanceFilters'; const BrowseInventoryFilters = ({ activeFilters, From 38798f60a80e44cd102c51cddff1ba396d5b38bb Mon Sep 17 00:00:00 2001 From: Michal Kuklis Date: Wed, 31 May 2023 21:55:24 -0400 Subject: [PATCH 7/8] Cleanup --- src/components/InstancesList/InstancesList.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/components/InstancesList/InstancesList.js b/src/components/InstancesList/InstancesList.js index 2d519591c..76fe09060 100644 --- a/src/components/InstancesList/InstancesList.js +++ b/src/components/InstancesList/InstancesList.js @@ -1081,13 +1081,8 @@ class InstancesList extends React.Component { }; const formattedSearchableIndexes = searchableIndexes.map(index => { - const { prefix = '' } = index; - let label = index.label; - if (index.label.includes('ui-inventory')) { - label = prefix + intl.formatMessage({ id: index.label }); - } - - return { ...index, label }; + const { label: id } = index; + return { ...index, label: intl.formatMessage({ id }) }; }); const shortcuts = [ From df3113de1e53523c783d69c8cb94d79d34d42cbb Mon Sep 17 00:00:00 2001 From: Michal Kuklis Date: Wed, 31 May 2023 22:18:08 -0400 Subject: [PATCH 8/8] Fix tests --- .../BrowseInventoryFilters/BrowseInventoryFilters.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/BrowseInventoryFilters/BrowseInventoryFilters.test.js b/src/components/BrowseInventoryFilters/BrowseInventoryFilters.test.js index b9781bd26..f18440e28 100644 --- a/src/components/BrowseInventoryFilters/BrowseInventoryFilters.test.js +++ b/src/components/BrowseInventoryFilters/BrowseInventoryFilters.test.js @@ -47,7 +47,7 @@ jest.mock('@folio/stripes-inventory-components', () => ({ const defaultProps = { activeFilters: {}, applyFilters: jest.fn(), - fetchFacets: jest.fn(), + fetchFacets: () => jest.fn(), resources: { facets: { records: [] }, }, @@ -83,7 +83,7 @@ describe('BrowseInventoryFilters', () => { expect(defaultProps.applyFilters).toHaveBeenCalled(); }); - it('should call "applyFilters" when clear button was clicked for facet acccordion', async () => { + it('should call "applyFilters" when clear button was clicked for facet accordion', async () => { const { container } = renderBrowseInventoryFilters({ activeFilters: { [FACETS.EFFECTIVE_LOCATION]: [facetOptions.effectiveLocationOptions[0].value],