diff --git a/lib/FindLocation/FindLocation.js b/lib/FindLocation/FindLocation.js index ac815d56..f3507ef8 100644 --- a/lib/FindLocation/FindLocation.js +++ b/lib/FindLocation/FindLocation.js @@ -1,3 +1,4 @@ +import keyBy from 'lodash/keyBy'; import PropTypes from 'prop-types'; import { useCallback, useEffect, useMemo, useState } from 'react'; import { FormattedMessage } from 'react-intl'; @@ -6,7 +7,12 @@ import { ColumnManager } from '@folio/stripes/smart-components'; import { EVENT_EMMITER_EVENTS } from '../constants';4 import { FindRecords } from '../FindRecords'; -import { useEventEmitter } from '../hooks'; +import { + useCampuses, + useEventEmitter, + useInstitutions, + useLibraries, +} from '../hooks'; import { COLUMN_MAPPING, COLUMN_NAMES, @@ -30,6 +36,11 @@ export const FindLocation = (props) => { const eventEmitter = useEventEmitter(); const [selectedLocations, setSelectedLocations] = useState({}); + + const { institutions, isLoading: isInstitutionsLoading } = useInstitutions(); + const { campuses, isLoading: isCampusesLoading } = useCampuses(); + const { libraries, isLoading: isLibrariesLoading } = useLibraries(); + const { locations, isLoading: isLocationsLoading } = useLocationsRecords(); useEffect(() => { const eventType = EVENT_EMMITER_EVENTS.FIND_RECORDS_SELECTED_CHANGED; @@ -51,32 +62,56 @@ export const FindLocation = (props) => { ) }), [isMultiSelect]); + const institutionsMap = useMemo(() => keyBy(institutions, 'id'), [institutions]); + const campusessMap = useMemo(() => keyBy(campuses, 'id'), [campuses]); + const librariesMap = useMemo(() => keyBy(libraries, 'id'), [libraries]); + const resultsFormatter = useMemo(() => ({ [COLUMN_NAMES.name]: ({ name }) => name, - // TODO: add formatters for the rest of colls [COLUMN_NAMES.code]: ({ code }) => code, + [COLUMN_NAMES.institution]: ({ institutionId }) => institutionsMap[institutionId]?.name, + [COLUMN_NAMES.campus]: ({ campusId }) => campusessMap[campusId]?.name, + [COLUMN_NAMES.library]: ({ libraryId }) => librariesMap[libraryId]?.name, [COLUMN_NAMES.isActive]: ({ isActive }) => ( ), [COLUMN_NAMES.isAssigned]: ({ id }) => ( ), - }), [selectedLocations]); - - const { locations, isLoading } = useLocationsRecords(); + }), [ + campusessMap, + institutionsMap, + librariesMap, + selectedLocations, + ]); const renderFilters = useCallback((activeFilters, applyFilters) => ( - ), [isMultiSelect]); + ), [ + campuses, + institutions, + isMultiSelect, + libraries, + ]); const refreshRecords = useCallback((data) => { console.log('refresh', data) }, []); + const isLoading = ( + isInstitutionsLoading + || isCampusesLoading + || isLibrariesLoading + || isLocationsLoading + ); + return ( ({ + label: [name, code && `(${code})`].join(' '), + value: id, +}); + export const FindLocationFilters = ({ activeFilters, applyFilters, + campuses, disabled, + institutions, isMultiSelect, + libraries, }) => { const adaptedApplyFilters = useCallback(({ name, values }) => applyFilters(name, values), [applyFilters]); + const institutionOptions = useMemo(() => institutions.map(getSelectionFilterOptions), [institutions]); + const campusesOptions = useMemo(() => campuses.map(getSelectionFilterOptions), [campuses]); + const librariesOptions = useMemo(() => libraries.map(getSelectionFilterOptions), [libraries]); + return ( {isMultiSelect && ( @@ -63,11 +75,32 @@ export const FindLocationFilters = ({ )} ); -} +}; + +FindLocationFilters.defaultProps = { + campuses: [], + institutions: [], + libraries: [], +}; FindLocationFilters.propTypes = { activeFilters: PropTypes.object.isRequired, applyFilters: PropTypes.func.isRequired, + campuses: PropTypes.arrayOf(PropTypes.shape({ + id: PropTypes.string, + name: PropTypes.string, + code: PropTypes.string, + })), disabled: PropTypes.bool, + institutions: PropTypes.arrayOf(PropTypes.shape({ + id: PropTypes.string, + name: PropTypes.string, + code: PropTypes.string, + })), isMultiSelect: PropTypes.bool, + libraries: PropTypes.arrayOf(PropTypes.shape({ + id: PropTypes.string, + name: PropTypes.string, + code: PropTypes.string, + })), }; diff --git a/lib/constants/api.js b/lib/constants/api.js index 75d0dd7a..e0f27866 100644 --- a/lib/constants/api.js +++ b/lib/constants/api.js @@ -3,15 +3,18 @@ export const ACQUISITIONS_UNITS_API = 'acquisitions-units/units'; export const ACQUISITIONS_UNIT_MEMBERSHIPS_API = 'acquisitions-units/memberships'; export const BATCH_GROUPS_API = 'batch-groups'; export const BUDGETS_API = 'finance/budgets'; +export const CAMPUSES_API = 'location-units/campuses'; export const CONFIG_API = 'configurations/entries'; export const CONTRIBUTOR_NAME_TYPES_API = 'contributor-name-types'; export const EXCHANGE_RATE_API = 'finance/exchange-rate'; export const EXPENSE_CLASSES_API = 'finance/expense-classes'; export const FUNDS_API = 'finance/funds'; +export const INSTITUTIONS_API = 'location-units/institutions'; export const INVOICES_API = 'invoice/invoices'; export const INVOICE_LINE_API = 'invoice/invoice-lines'; export const ITEMS_API = 'inventory/items'; export const IDENTIFIER_TYPES_API = 'identifier-types'; +export const LIBRARIES_API = 'location-units/libraries'; export const LINES_API = 'orders/order-lines'; export const LOAN_TYPES_API = 'loan-types'; export const LOCATIONS_API = 'locations'; diff --git a/lib/constants/constants.js b/lib/constants/constants.js index b6d568ea..f61758a6 100644 --- a/lib/constants/constants.js +++ b/lib/constants/constants.js @@ -2,6 +2,7 @@ export const DATE_FORMAT = 'YYYY-MM-DD'; export const TIMEZONE = 'UTC'; export const LIMIT_MAX = 1000; +export const LIMIT_MAX_EXTENDED = 5000; export const RESULT_COUNT_INCREMENT = 50; export const PLUGIN_RESULT_COUNT_INCREMENT = 50; diff --git a/lib/hooks/index.js b/lib/hooks/index.js index 86479e66..d5d1b6e6 100644 --- a/lib/hooks/index.js +++ b/lib/hooks/index.js @@ -1,9 +1,12 @@ export * from './useAccordionToggle'; export * from './useAcqMethodsOptions'; export * from './useAsyncDebounce'; +export * from './useCampuses'; export * from './useEventEmitter'; export * from './useFunds'; +export * from './useInstitutions'; export * from './useIntegrationConfigs'; +export * from './useLibraries'; export * from './useLineHoldings'; export * from './useLocaleDateFormat'; export * from './useLocations'; diff --git a/lib/hooks/useCampuses/index.js b/lib/hooks/useCampuses/index.js new file mode 100644 index 00000000..11ef3bda --- /dev/null +++ b/lib/hooks/useCampuses/index.js @@ -0,0 +1 @@ +export { useCampuses } from './useCampuses'; diff --git a/lib/hooks/useCampuses/useCampuses.js b/lib/hooks/useCampuses/useCampuses.js new file mode 100644 index 00000000..ba2f8d96 --- /dev/null +++ b/lib/hooks/useCampuses/useCampuses.js @@ -0,0 +1,33 @@ +import { useQuery } from 'react-query'; + +import { + useNamespace, + useOkapiKy, +} from '@folio/stripes/core'; + +import { + CAMPUSES_API, + LIMIT_MAX_EXTENDED, +} from '../../constants'; + +const DEFAULT_DATA = []; + +export const useCampuses = () => { + const ky = useOkapiKy(); + const [namespace] = useNamespace({ key: 'location-units-campuses' }); + + const searchParams = { + limit: LIMIT_MAX_EXTENDED, + query: 'cql.allRecords=1 sortby name', + }; + + const { isLoading, data = {} } = useQuery( + [namespace], + () => ky.get(CAMPUSES_API, { searchParams }).json(), + ); + + return { + campuses: data.loccamps || DEFAULT_DATA, + isLoading, + }; +}; diff --git a/lib/hooks/useInstitutions/index.js b/lib/hooks/useInstitutions/index.js new file mode 100644 index 00000000..d2723e09 --- /dev/null +++ b/lib/hooks/useInstitutions/index.js @@ -0,0 +1 @@ +export { useInstitutions } from './useInstitutions'; diff --git a/lib/hooks/useInstitutions/useInstitutions.js b/lib/hooks/useInstitutions/useInstitutions.js new file mode 100644 index 00000000..a8231387 --- /dev/null +++ b/lib/hooks/useInstitutions/useInstitutions.js @@ -0,0 +1,33 @@ +import { useQuery } from 'react-query'; + +import { + useNamespace, + useOkapiKy, +} from '@folio/stripes/core'; + +import { + INSTITUTIONS_API, + LIMIT_MAX_EXTENDED, +} from '../../constants'; + +const DEFAULT_DATA = []; + +export const useInstitutions = () => { + const ky = useOkapiKy(); + const [namespace] = useNamespace({ key: 'location-units-institutions' }); + + const searchParams = { + limit: LIMIT_MAX_EXTENDED, + query: 'cql.allRecords=1 sortby name', + }; + + const { isLoading, data = {} } = useQuery( + [namespace], + () => ky.get(INSTITUTIONS_API, { searchParams }).json(), + ); + + return { + institutions: data.locinsts || DEFAULT_DATA, + isLoading, + }; +}; diff --git a/lib/hooks/useLibraries/index.js b/lib/hooks/useLibraries/index.js new file mode 100644 index 00000000..7b5e060c --- /dev/null +++ b/lib/hooks/useLibraries/index.js @@ -0,0 +1 @@ +export { useLibraries } from './useLibraries'; diff --git a/lib/hooks/useLibraries/useLibraries.js b/lib/hooks/useLibraries/useLibraries.js new file mode 100644 index 00000000..d3f0dccd --- /dev/null +++ b/lib/hooks/useLibraries/useLibraries.js @@ -0,0 +1,33 @@ +import { useQuery } from 'react-query'; + +import { + useNamespace, + useOkapiKy, +} from '@folio/stripes/core'; + +import { + LIBRARIES_API, + LIMIT_MAX_EXTENDED, +} from '../../constants'; + +const DEFAULT_DATA = []; + +export const useLibraries = () => { + const ky = useOkapiKy(); + const [namespace] = useNamespace({ key: 'location-units-libraries' }); + + const searchParams = { + limit: LIMIT_MAX_EXTENDED, + query: 'cql.allRecords=1 sortby name', + }; + + const { isLoading, data = {} } = useQuery( + [namespace], + () => ky.get(LIBRARIES_API, { searchParams }).json(), + ); + + return { + libraries: data.loclibs || DEFAULT_DATA, + isLoading, + }; +}; diff --git a/lib/hooks/useLocations/useLocations.js b/lib/hooks/useLocations/useLocations.js index 0777ba2e..e2bc57b5 100644 --- a/lib/hooks/useLocations/useLocations.js +++ b/lib/hooks/useLocations/useLocations.js @@ -35,8 +35,6 @@ export const useLocations = () => { } ); - console.log('locations', data); - return ({ locations: data || DEFAULT_DATA, isLoading,