diff --git a/CHANGELOG.md b/CHANGELOG.md index ea3a3c4..3bc599a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ * [UITEN-301] (https://issues.folio.org/browse/UITEN-301) Display Reading room access in alphabetical order on settings page. * [UITEN-212](https://folio-org.atlassian.net/browse/UITEN-212) Permission changes for service point management. * [UITEN-299](https://folio-org.atlassian.net/browse/UITEN-299) Rewrite class components to functional ones (ui-tenant-settings module). +* [UITEN-292](https://folio-org.atlassian.net/browse/UITEN-292) Change visibility rules for routing service points. ## [8.1.0](https://github.com/folio-org/ui-tenant-settings/tree/v8.1.0)(2024-03-19) [Full Changelog](https://github.com/folio-org/ui-tenant-settings/compare/v8.0.0...v8.1.0) diff --git a/package.json b/package.json index dda5033..0201ceb 100644 --- a/package.json +++ b/package.json @@ -194,7 +194,8 @@ "inventory-storage.location-units.libraries.collection.get", "inventory-storage.service-points.collection.get", "inventory-storage.service-points.item.get", - "circulation-storage.staff-slips.collection.get" + "circulation-storage.staff-slips.collection.get", + "circulation.settings.collection.get" ], "visible": false }, @@ -284,6 +285,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-intl": "^6.4.4", + "react-query": "^3.6.0", "react-redux": "^7.2.0", "react-router-dom": "^5.2.0", "redux": "^4.0.0", diff --git a/src/hooks/index.js b/src/hooks/index.js new file mode 100644 index 0000000..86ec60a --- /dev/null +++ b/src/hooks/index.js @@ -0,0 +1 @@ +export { default as useCirculationSettingsEcsTlrFeature } from './useCirculationSettingsEcsTlrFeature'; diff --git a/src/hooks/useCirculationSettingsEcsTlrFeature/index.js b/src/hooks/useCirculationSettingsEcsTlrFeature/index.js new file mode 100644 index 0000000..e02e3cc --- /dev/null +++ b/src/hooks/useCirculationSettingsEcsTlrFeature/index.js @@ -0,0 +1 @@ +export { default } from './useCirculationSettingsEcsTlrFeature'; diff --git a/src/hooks/useCirculationSettingsEcsTlrFeature/useCirculationSettingsEcsTlrFeature.js b/src/hooks/useCirculationSettingsEcsTlrFeature/useCirculationSettingsEcsTlrFeature.js new file mode 100644 index 0000000..0266cbe --- /dev/null +++ b/src/hooks/useCirculationSettingsEcsTlrFeature/useCirculationSettingsEcsTlrFeature.js @@ -0,0 +1,27 @@ +import { useQuery } from 'react-query'; + +import { useNamespace, useOkapiKy } from '@folio/stripes/core'; + +import { getEcsTlrFeature } from '../../settings/ServicePoints/utils'; + +const useCirculationSettingsEcsTlrFeature = (enabled) => { + const ky = useOkapiKy(); + const [namespace] = useNamespace({ key: 'circulationSettingsEcsTlrFeature' }); + const searchParams = { + query: 'name==ecsTlrFeature', + }; + const { isLoading, data, refetch, isFetching } = useQuery( + [namespace], + () => ky.get('circulation/settings', { searchParams }).json(), + { enabled }, + ); + + return ({ + titleLevelRequestsFeatureEnabled: getEcsTlrFeature(data?.circulationSettings), + isLoading, + isFetching, + refetch, + }); +}; + +export default useCirculationSettingsEcsTlrFeature; diff --git a/src/settings/ServicePoints/ServicePointDetail.js b/src/settings/ServicePoints/ServicePointDetail.js index 0b35ecf..fa21919 100644 --- a/src/settings/ServicePoints/ServicePointDetail.js +++ b/src/settings/ServicePoints/ServicePointDetail.js @@ -21,11 +21,11 @@ class ServicePointDetail extends React.Component { intl: PropTypes.object, stripes: PropTypes.shape({ connect: PropTypes.func.isRequired, - hasInterface: PropTypes.func.isRequired, }).isRequired, initialValues: PropTypes.object, parentResources: PropTypes.object, - parentMutator: PropTypes.object + parentMutator: PropTypes.object, + titleLevelRequestsFeatureEnabled: PropTypes.bool, }; constructor(props) { @@ -83,7 +83,7 @@ class ServicePointDetail extends React.Component { } render() { - const { initialValues, parentResources, stripes } = this.props; + const { initialValues, parentResources, titleLevelRequestsFeatureEnabled } = this.props; const locations = (parentResources.locations || {}).records || []; const staffSlips = orderBy((parentResources.staffSlips || {}).records || [], 'name'); const servicePoint = initialValues; @@ -136,7 +136,7 @@ class ServicePointDetail extends React.Component { /> - {isEcsRequestRoutingVisible(stripes) && ( + {isEcsRequestRoutingVisible(titleLevelRequestsFeatureEnabled) && ( }> @@ -148,7 +148,7 @@ class ServicePointDetail extends React.Component { )} - {isEcsRequestRoutingAssociatedFieldsVisible(stripes, servicePoint.ecsRequestRouting) && ( + {isEcsRequestRoutingAssociatedFieldsVisible(titleLevelRequestsFeatureEnabled, servicePoint.ecsRequestRouting) && ( <> @@ -196,7 +196,7 @@ class ServicePointDetail extends React.Component { )} - {isEcsRequestRoutingAssociatedFieldsVisible(stripes, servicePoint.ecsRequestRouting) && ( + {isEcsRequestRoutingAssociatedFieldsVisible(titleLevelRequestsFeatureEnabled, servicePoint.ecsRequestRouting) && ( { + const { titleLevelRequestsFeatureEnabled } = useCirculationSettingsEcsTlrFeature(true); const [sections, setSections] = useState({ generalSection: true, locationSection: true @@ -302,7 +307,7 @@ const ServicePointForm = ({ /> - {isEcsRequestRoutingVisible(stripes) && ( + {isEcsRequestRoutingVisible(titleLevelRequestsFeatureEnabled) && ( )} - {isEcsRequestRoutingAssociatedFieldsVisible(stripes, formValues.ecsRequestRouting) && ( + {isEcsRequestRoutingAssociatedFieldsVisible(titleLevelRequestsFeatureEnabled, formValues.ecsRequestRouting) && ( <> @@ -376,7 +381,7 @@ const ServicePointForm = ({ )} - {isEcsRequestRoutingAssociatedFieldsVisible(stripes, formValues.ecsRequestRouting) && ( + {isEcsRequestRoutingAssociatedFieldsVisible(titleLevelRequestsFeatureEnabled, formValues.ecsRequestRouting) && ( ({ + useCirculationSettingsEcsTlrFeature: jest.fn().mockReturnValue({ titleLevelRequestsFeatureEnabled: true }), +})); + const onSave = jest.fn(); const staffSlips = [true, true, true, true]; diff --git a/src/settings/ServicePoints/ServicePointManager.js b/src/settings/ServicePoints/ServicePointManager.js index 2dce366..090b7b6 100644 --- a/src/settings/ServicePoints/ServicePointManager.js +++ b/src/settings/ServicePoints/ServicePointManager.js @@ -7,6 +7,7 @@ import { TitleManager } from '@folio/stripes/core'; import { injectIntl } from 'react-intl'; import ServicePointDetail from './ServicePointDetail'; import ServicePointFormContainer from './ServicePointFormContainer'; +import { getEcsTlrFeature } from './utils'; class ServicePointManager extends React.Component { static manifest = Object.freeze({ @@ -49,6 +50,11 @@ class ServicePointManager extends React.Component { limit: '1000', }, }, + settings: { + type: 'okapi', + path: 'circulation/settings?query=(name==ecsTlrFeature)', + records: 'circulationSettings', + }, }); static propTypes = { @@ -57,6 +63,9 @@ class ServicePointManager extends React.Component { entries: PropTypes.shape({ records: PropTypes.arrayOf(PropTypes.object), }), + settings: PropTypes.shape({ + records: PropTypes.arrayOf(PropTypes.object), + }), staffSlips: PropTypes.object, }).isRequired, mutator: PropTypes.shape({ @@ -87,6 +96,8 @@ class ServicePointManager extends React.Component { } render() { + const { resources } = this.props; + const titleLevelRequestsFeatureEnabled = getEcsTlrFeature(resources?.settings?.records); let entryList = sortBy((this.props.resources.entries || {}).records || [], ['name']); entryList = entryList.map(item => { item.pickupLocation = item.pickupLocation || false; @@ -117,6 +128,7 @@ class ServicePointManager extends React.Component { nameKey="name" editable={isEditable} permissions={permissions} + titleLevelRequestsFeatureEnabled={titleLevelRequestsFeatureEnabled} /> ); diff --git a/src/settings/ServicePoints/utils.js b/src/settings/ServicePoints/utils.js index af581fa..0ac4b4c 100644 --- a/src/settings/ServicePoints/utils.js +++ b/src/settings/ServicePoints/utils.js @@ -1,5 +1,6 @@ import React from 'react'; import { FormattedMessage } from 'react-intl'; +import { get } from 'lodash'; export const validateServicePointForm = (values) => { const errors = {}; @@ -54,10 +55,14 @@ export const getUniquenessValidation = (field, mutator) => { }; }; -export const isEcsRequestRoutingVisible = (stripes) => ( - stripes.hasInterface('consortia') && stripes.hasInterface('ecs-tlr') +export const isEcsRequestRoutingVisible = (titleLevelRequestsFeatureEnabled) => ( + !!titleLevelRequestsFeatureEnabled ); -export const isEcsRequestRoutingAssociatedFieldsVisible = (stripes, ecsRequestRouting) => ( - (isEcsRequestRoutingVisible(stripes) && !ecsRequestRouting) || !isEcsRequestRoutingVisible(stripes) +export const isEcsRequestRoutingAssociatedFieldsVisible = (titleLevelRequestsFeatureEnabled, ecsRequestRouting) => ( + (isEcsRequestRoutingVisible(titleLevelRequestsFeatureEnabled) && !ecsRequestRouting) || !isEcsRequestRoutingVisible(titleLevelRequestsFeatureEnabled) +); + +export const getEcsTlrFeature = (data = []) => ( + get(data, '[0].value.enabled', false) ); diff --git a/src/settings/ServicePoints/utils.test.js b/src/settings/ServicePoints/utils.test.js index 41bd7c3..0bdd987 100644 --- a/src/settings/ServicePoints/utils.test.js +++ b/src/settings/ServicePoints/utils.test.js @@ -1,128 +1,63 @@ import { isEcsRequestRoutingVisible, isEcsRequestRoutingAssociatedFieldsVisible, + getEcsTlrFeature, } from './utils'; describe('isEcsRequestRoutingVisible', () => { - it('should return true when both interfaces present', () => { - const stripes = { - hasInterface: (currentInterface) => { - const interfaces = { - consortia: true, - 'ecs-tlr': true, - }; - - return interfaces[currentInterface]; - }, - }; - - expect(isEcsRequestRoutingVisible(stripes)).toBe(true); + it('should return true when titleLevelRequestsFeatureEnabled true', () => { + expect(isEcsRequestRoutingVisible(true)).toBe(true); }); - it('should return false when ecs-tlr interface absent', () => { - const stripes = { - hasInterface: (currentInterface) => { - const interfaces = { - consortia: true, - 'ecs-tlr': false, - }; - - return interfaces[currentInterface]; - }, - }; - - expect(isEcsRequestRoutingVisible(stripes)).toBe(false); + it('should return false when titleLevelRequestsFeatureEnabled false', () => { + expect(isEcsRequestRoutingVisible(false)).toBe(false); }); - it('should return false when consortia interface absent', () => { - const stripes = { - hasInterface: (currentInterface) => { - const interfaces = { - consortia: false, - 'ecs-tlr': true, - }; - - return interfaces[currentInterface]; - }, - }; - - expect(isEcsRequestRoutingVisible(stripes)).toBe(false); - }); - - it('should return false when both interfaces absent', () => { - const stripes = { - hasInterface: (currentInterface) => { - const interfaces = { - consortia: false, - 'ecs-tlr': false, - }; - - return interfaces[currentInterface]; - }, - }; - - expect(isEcsRequestRoutingVisible(stripes)).toBe(false); + it('should return false when titleLevelRequestsFeatureEnabled absent', () => { + expect(isEcsRequestRoutingVisible(undefined)).toBe(false); }); }); describe('isEcsRequestRoutingAssociatedFieldsVisible', () => { it('should return false when both condition true', () => { - const stripes = { - hasInterface: (currentInterface) => { - const interfaces = { - consortia: true, - 'ecs-tlr': true, - }; - - return interfaces[currentInterface]; - }, - }; - - expect(isEcsRequestRoutingAssociatedFieldsVisible(stripes, true)).toBe(false); + expect(isEcsRequestRoutingAssociatedFieldsVisible(true, true)).toBe(false); }); it('should return true when first condition false', () => { - const stripes = { - hasInterface: (currentInterface) => { - const interfaces = { - consortia: false, - 'ecs-tlr': false, - }; - - return interfaces[currentInterface]; - }, - }; - - expect(isEcsRequestRoutingAssociatedFieldsVisible(stripes, true)).toBe(true); + expect(isEcsRequestRoutingAssociatedFieldsVisible(false, true)).toBe(true); }); it('should return true when second condition false', () => { - const stripes = { - hasInterface: (currentInterface) => { - const interfaces = { - consortia: true, - 'ecs-tlr': true, - }; + expect(isEcsRequestRoutingAssociatedFieldsVisible(true, false)).toBe(true); + }); + + it('should return true when both condition false', () => { + expect(isEcsRequestRoutingAssociatedFieldsVisible(false, false)).toBe(true); + }); +}); - return interfaces[currentInterface]; +describe('getEcsTlrFeature', () => { + it('should return true when ecsTlrFeature true', () => { + const data = [{ + value: { + enabled: true, }, - }; + }]; - expect(isEcsRequestRoutingAssociatedFieldsVisible(stripes, false)).toBe(true); + expect(getEcsTlrFeature(data)).toBe(true); }); - it('should return true when both condition false', () => { - const stripes = { - hasInterface: (currentInterface) => { - const interfaces = { - consortia: false, - 'ecs-tlr': false, - }; - - return interfaces[currentInterface]; + it('should return false when ecsTlrFeature false', () => { + const data = [{ + value: { + enabled: false, }, - }; + }]; + + expect(getEcsTlrFeature(data)).toBe(false); + }); - expect(isEcsRequestRoutingAssociatedFieldsVisible(stripes, false)).toBe(true); + it('should return false when ecsTlrFeature absent', () => { + expect(getEcsTlrFeature(undefined)).toBe(false); }); });