From 9daf3c342059c580d97230df9eac820f9a806059 Mon Sep 17 00:00:00 2001 From: Dmitriy-Litvinenko Date: Tue, 23 Apr 2024 15:04:11 +0300 Subject: [PATCH 1/6] UITEN-281: Add Routing service point option with Confirm modal to Service point page(ECS only) --- CHANGELOG.md | 1 + .../ConfirmPickupLocationChangeModal.js | 4 +- .../ConfirmPickupLocationChangeModal.test.js | 4 +- .../ServicePoints/ServicePointDetail.js | 101 +++++++----- .../ServicePoints/ServicePointForm.js | 150 +++++++++++------- .../ServicePointFormContainer.js | 15 +- .../ServicePointFormContainer.test.js | 22 ++- src/settings/ServicePoints/utils.js | 8 + src/settings/ServicePoints/utils.test.js | 128 +++++++++++++++ translations/ui-tenant-settings/en.json | 9 +- 10 files changed, 329 insertions(+), 113 deletions(-) create mode 100644 src/settings/ServicePoints/utils.test.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 6845b214..85e51e2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ * [UITEN-278] (https://issues.folio.org/browse/UITEN-278) Reading Room Access (settings): Create new reading room. * [UITEN-282] (https://issues.folio.org/browse/UITEN-282) Reading Room Access (settings): Update reading room. * [UITEN-283] (https://issues.folio.org/browse/UITEN-283) Reading Room Access (settings): Delete reading room. +* [UITEN-281](https://folio-org.atlassian.net/browse/UITEN-281) Add Routing service point option to Service point page(ECS only). ## [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/src/settings/ServicePoints/ConfirmPickupLocationChangeModal.js b/src/settings/ServicePoints/ConfirmPickupLocationChangeModal.js index 258e8698..6c32e96d 100644 --- a/src/settings/ServicePoints/ConfirmPickupLocationChangeModal.js +++ b/src/settings/ServicePoints/ConfirmPickupLocationChangeModal.js @@ -20,13 +20,13 @@ const ConfirmPickupLocationChangeModal = ({ autoFocus onClick={onConfirm} > - + ); diff --git a/src/settings/ServicePoints/ConfirmPickupLocationChangeModal.test.js b/src/settings/ServicePoints/ConfirmPickupLocationChangeModal.test.js index 93865153..5e696d3e 100644 --- a/src/settings/ServicePoints/ConfirmPickupLocationChangeModal.test.js +++ b/src/settings/ServicePoints/ConfirmPickupLocationChangeModal.test.js @@ -22,8 +22,8 @@ const testIds = { const messageIds = { title: 'ui-tenant-settings.settings.confirmPickupLocationChangeModal.title', message: 'ui-tenant-settings.settings.confirmPickupLocationChangeModal.message', - buttonConfirm: 'ui-tenant-settings.settings.confirmPickupLocationChangeModal.button.confirm', - buttonCancel: 'ui-tenant-settings.settings.confirmPickupLocationChangeModal.button.cancel', + buttonConfirm: 'ui-tenant-settings.settings.modal.button.confirm', + buttonCancel: 'ui-tenant-settings.settings.modal.button.cancel', }; describe('ConfirmPickupLocationChangeModal', () => { diff --git a/src/settings/ServicePoints/ServicePointDetail.js b/src/settings/ServicePoints/ServicePointDetail.js index 0443d6d3..0b35ecf7 100644 --- a/src/settings/ServicePoints/ServicePointDetail.js +++ b/src/settings/ServicePoints/ServicePointDetail.js @@ -1,16 +1,18 @@ -import { cloneDeep, keyBy, orderBy } from 'lodash'; import React from 'react'; import PropTypes from 'prop-types'; import { injectIntl, FormattedMessage, } from 'react-intl'; +import { cloneDeep, keyBy, orderBy } from 'lodash'; + import { Accordion, Col, ExpandAllButton, KeyValue, Row } from '@folio/stripes/components'; import { ViewMetaData } from '@folio/stripes/smart-components'; - import { TitleManager } from '@folio/stripes/core'; + import LocationList from './LocationList'; import StaffSlipList from './StaffSlipList'; +import { isEcsRequestRoutingVisible, isEcsRequestRoutingAssociatedFieldsVisible } from './utils'; import { intervalPeriods } from '../../constants'; import { closedLibraryDateManagementMapping } from './constants'; @@ -19,6 +21,7 @@ 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, @@ -80,7 +83,7 @@ class ServicePointDetail extends React.Component { } render() { - const { initialValues, parentResources } = this.props; + const { initialValues, parentResources, stripes } = this.props; const locations = (parentResources.locations || {}).records || []; const staffSlips = orderBy((parentResources.staffSlips || {}).records || [], 'name'); const servicePoint = initialValues; @@ -133,56 +136,74 @@ class ServicePointDetail extends React.Component { /> - - - } - value={servicePoint.shelvingLagTime} - /> - - - - - }> - { servicePoint.pickupLocation - ? - : - } - - - - { servicePoint.pickupLocation && ( + {isEcsRequestRoutingVisible(stripes) && ( + + + }> + { servicePoint.ecsRequestRouting + ? + : + } + + + + )} + {isEcsRequestRoutingAssociatedFieldsVisible(stripes, servicePoint.ecsRequestRouting) && ( <> - + } - value={`${duration} ${this.intervalPeriodMap[intervalId].label}`} + label={} + value={servicePoint.shelvingLagTime} /> - - }> - + + }> + { servicePoint.pickupLocation + ? + : + } + { servicePoint.pickupLocation && ( + <> + + + } + value={`${duration} ${this.intervalPeriodMap[intervalId].label}`} + /> + + + + + }> + + + + + + ) + } + - ) - } - + )} - + {isEcsRequestRoutingAssociatedFieldsVisible(stripes, servicePoint.ecsRequestRouting) && ( + + )} ); diff --git a/src/settings/ServicePoints/ServicePointForm.js b/src/settings/ServicePoints/ServicePointForm.js index 1e0c0e3a..fc2ecec9 100644 --- a/src/settings/ServicePoints/ServicePointForm.js +++ b/src/settings/ServicePoints/ServicePointForm.js @@ -39,6 +39,8 @@ import { intervalPeriods } from '../../constants'; import { validateServicePointForm, getUniquenessValidation, + isEcsRequestRoutingVisible, + isEcsRequestRoutingAssociatedFieldsVisible, } from './utils'; import { @@ -49,6 +51,7 @@ import { import styles from './ServicePoints.css'; +export const SELECTED_ROUTING_SERVICE_POINT_VALUE = 'true'; export const SELECTED_PICKUP_LOCATION_VALUE = 'true'; export const UNSELECTED_PICKUP_LOCATION_VALUE = 'false'; export const LAYER_EDIT = 'layer=edit'; @@ -88,11 +91,11 @@ const ServicePointForm = ({ const selectOptions = [ { - label: intl.formatMessage({ id: 'ui-tenant-settings.settings.servicePoints.pickupLocation.no' }), + label: intl.formatMessage({ id: 'ui-tenant-settings.settings.servicePoints.value.no' }), value: false }, { - label: intl.formatMessage({ id: 'ui-tenant-settings.settings.servicePoints.pickupLocation.yes' }), + label: intl.formatMessage({ id: 'ui-tenant-settings.settings.servicePoints.value.yes' }), value: true } ]; @@ -200,6 +203,12 @@ const ServicePointForm = ({ ))); }; + const handleEcsRequestRoutingChange = (e) => { + const value = e.target.value; + + form.change('ecsRequestRouting', value === SELECTED_ROUTING_SERVICE_POINT_VALUE); + }; + const handleChange = (e) => { const value = e.target.value; @@ -290,67 +299,88 @@ const ServicePointForm = ({ /> - - - } - name="shelvingLagTime" - id="input-service-shelvingLagTime" - component={TextField} - fullWidth - disabled={disabled} - /> - - - - - } - name="pickupLocation" - id="input-service-pickupLocation" - component={Select} - dataOptions={selectOptions} - onChange={handleChange} - disabled={disabled} - /> - - - { - formValues.pickupLocation && ( - <> -
- + + } + name="ecsRequestRouting" + id="input-service-ecsRequestRouting" + component={Select} + dataOptions={selectOptions} + onChange={handleEcsRequestRoutingChange} + disabled={disabled} + /> + + + )} + {isEcsRequestRoutingAssociatedFieldsVisible(stripes, formValues.ecsRequestRouting) && ( + <> + + + } + name="shelvingLagTime" + id="input-service-shelvingLagTime" + component={TextField} + fullWidth + disabled={disabled} /> -
-
+ + + + } - name="holdShelfClosedLibraryDateManagement" + data-test-pickup-location + label={} + name="pickupLocation" + id="input-service-pickupLocation" component={Select} - dataOptions={getClosedLibraryDateManagementOptions()} + dataOptions={selectOptions} + onChange={handleChange} + disabled={disabled} /> -
- - ) - } - + + + { + formValues.pickupLocation && ( + <> +
+ +
+
+ } + name="holdShelfClosedLibraryDateManagement" + component={Select} + dataOptions={getClosedLibraryDateManagementOptions()} + /> +
+ + ) + } + + + )} - + {isEcsRequestRoutingAssociatedFieldsVisible(stripes, formValues.ecsRequestRouting) && ( + + )} - { userEvent.selectOptions(screen.getByRole('combobox', { name: /settings.servicePoints.pickupLocation/ }), 'true'); - expect(screen.getByRole('option', { name: /settings.servicePoints.pickupLocation.yes/ }).selected).toBe(true); + expect(screen.getAllByRole('option', { name: /settings.servicePoints.value.yes/ })[1].selected).toBe(true); + }); + + describe('ecs request routing', () => { + beforeEach(() => { + renderServicePointFormContainer(); + }); + + it('should not render pick location', () => { + userEvent.selectOptions(screen.getByRole('combobox', { name: /settings.servicePoints.ecsRequestRouting/ }), 'true'); + + expect(screen.queryByText(/settings.servicePoints.pickupLocation/)).not.toBeInTheDocument(); + }); + + it('should not render pick location', () => { + userEvent.selectOptions(screen.getByRole('combobox', { name: /settings.servicePoints.ecsRequestRouting/ }), 'false'); + + expect(screen.queryByText(/settings.servicePoints.pickupLocation/)).toBeInTheDocument(); + }); }); describe('when pick location is yes', () => { @@ -97,7 +115,7 @@ describe('ServicePointFormContainer', () => { describe('when hold shelf expiry interval id is short term period Days', () => { beforeEach(() => { - userEvent.selectOptions(screen.getAllByRole('combobox')[1], 'Days'); + userEvent.selectOptions(screen.getAllByRole('combobox')[2], 'Days'); }); it('should render ServicePointFormContainer closed library date management select with changed options ', () => { diff --git a/src/settings/ServicePoints/utils.js b/src/settings/ServicePoints/utils.js index 9df81086..af581fae 100644 --- a/src/settings/ServicePoints/utils.js +++ b/src/settings/ServicePoints/utils.js @@ -53,3 +53,11 @@ export const getUniquenessValidation = (field, mutator) => { }); }; }; + +export const isEcsRequestRoutingVisible = (stripes) => ( + stripes.hasInterface('consortia') && stripes.hasInterface('ecs-tlr') +); + +export const isEcsRequestRoutingAssociatedFieldsVisible = (stripes, ecsRequestRouting) => ( + (isEcsRequestRoutingVisible(stripes) && !ecsRequestRouting) || !isEcsRequestRoutingVisible(stripes) +); diff --git a/src/settings/ServicePoints/utils.test.js b/src/settings/ServicePoints/utils.test.js new file mode 100644 index 00000000..41bd7c38 --- /dev/null +++ b/src/settings/ServicePoints/utils.test.js @@ -0,0 +1,128 @@ +import { + isEcsRequestRoutingVisible, + isEcsRequestRoutingAssociatedFieldsVisible, +} 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 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 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); + }); +}); + +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); + }); + + 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); + }); + + it('should return true when second condition false', () => { + const stripes = { + hasInterface: (currentInterface) => { + const interfaces = { + consortia: true, + 'ecs-tlr': true, + }; + + return interfaces[currentInterface]; + }, + }; + + expect(isEcsRequestRoutingAssociatedFieldsVisible(stripes, false)).toBe(true); + }); + + it('should return true when both condition false', () => { + const stripes = { + hasInterface: (currentInterface) => { + const interfaces = { + consortia: false, + 'ecs-tlr': false, + }; + + return interfaces[currentInterface]; + }, + }; + + expect(isEcsRequestRoutingAssociatedFieldsVisible(stripes, false)).toBe(true); + }); +}); diff --git a/translations/ui-tenant-settings/en.json b/translations/ui-tenant-settings/en.json index a7512009..98727dcd 100644 --- a/translations/ui-tenant-settings/en.json +++ b/translations/ui-tenant-settings/en.json @@ -139,6 +139,7 @@ "settings.servicePoints.code": "Code", "settings.servicePoints.discoveryDisplayName": "Discovery display name", "settings.servicePoints.description": "Description", + "settings.servicePoints.ecsRequestRouting": "Routing service point", "settings.servicePoints.shelvingLagTime": "Shelving lag time (minutes)", "settings.servicePoints.pickupLocation": "Pickup location", "settings.servicePoints.feeFineOwner": "Fee fine owner", @@ -164,8 +165,8 @@ "settings.servicePoints.validation.numeric": "Please enter a number to continue", "settings.servicePoints.validation.name.unique": "Service point name must be unique", "settings.servicePoints.validation.code.unique": "Code must be unique", - "settings.servicePoints.pickupLocation.yes": "Yes", - "settings.servicePoints.pickupLocation.no": "No", + "settings.servicePoints.value.yes": "Yes", + "settings.servicePoints.value.no": "No", "settings.intervalPeriod.minutes": "Minutes", "settings.intervalPeriod.hours": "Hours", "settings.intervalPeriod.days": "Days", @@ -231,6 +232,6 @@ "settings.confirmPickupLocationChangeModal.title": "Confirm Pickup location change", "settings.confirmPickupLocationChangeModal.message": "Changing this Pickup location from \"Yes\" to \"No\" will remove it from existing Request policies and affect all Circulation rules using the policies.", - "settings.confirmPickupLocationChangeModal.button.confirm": "Confirm", - "settings.confirmPickupLocationChangeModal.button.cancel": "Back" + "settings.modal.button.confirm": "Confirm", + "settings.modal.button.cancel": "Back" } From 9ac5cfddfe5110d26df46b3bb2ec519934df1080 Mon Sep 17 00:00:00 2001 From: Dmitriy-Litvinenko Date: Fri, 24 May 2024 14:00:36 +0300 Subject: [PATCH 2/6] UITEN-294: Show routing service points on settings -> tenant -> servicePoints --- CHANGELOG.md | 1 + src/settings/ServicePoints/ServicePointManager.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11c5fc75..8d27a382 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ * [UITEN-283] (https://issues.folio.org/browse/UITEN-283) Reading Room Access (settings): Delete reading room. * [UITEN-281](https://folio-org.atlassian.net/browse/UITEN-281) Add Routing service point option to Service point page(ECS only). * [UITEN-285](https://folio-org.atlassian.net/browse/UITEN-285) Disable edit of Routing service point field (ECS only). +* [UITEN-294](https://folio-org.atlassian.net/browse/UITEN-294) Show routing service points on settings -> tenant -> servicePoints. ## [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/src/settings/ServicePoints/ServicePointManager.js b/src/settings/ServicePoints/ServicePointManager.js index 8d50b1d1..2dce3667 100644 --- a/src/settings/ServicePoints/ServicePointManager.js +++ b/src/settings/ServicePoints/ServicePointManager.js @@ -13,7 +13,7 @@ class ServicePointManager extends React.Component { entries: { type: 'okapi', records: 'servicepoints', - path: 'service-points?query=cql.allRecords=1 sortby name&limit=1000', + path: 'service-points?query=cql.allRecords=1 sortby name&limit=1000&includeRoutingServicePoints=true', resourceShouldRefresh: true, throwErrors: false, POST: { From 73da56cd94f78c653c2f737ece060128709c0193 Mon Sep 17 00:00:00 2001 From: Dmitriy-Litvinenko Date: Fri, 17 May 2024 14:58:47 +0300 Subject: [PATCH 3/6] UITEN-285: Disable edit of Routing service point field (ECS only) --- CHANGELOG.md | 1 + src/settings/ServicePoints/ServicePointForm.js | 7 +++++-- .../ServicePoints/ServicePointForm.test.js | 15 +++++++++++++-- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 85e51e2e..11c5fc75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ * [UITEN-282] (https://issues.folio.org/browse/UITEN-282) Reading Room Access (settings): Update reading room. * [UITEN-283] (https://issues.folio.org/browse/UITEN-283) Reading Room Access (settings): Delete reading room. * [UITEN-281](https://folio-org.atlassian.net/browse/UITEN-281) Add Routing service point option to Service point page(ECS only). +* [UITEN-285](https://folio-org.atlassian.net/browse/UITEN-285) Disable edit of Routing service point field (ECS only). ## [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/src/settings/ServicePoints/ServicePointForm.js b/src/settings/ServicePoints/ServicePointForm.js index fc2ecec9..5e40c3ff 100644 --- a/src/settings/ServicePoints/ServicePointForm.js +++ b/src/settings/ServicePoints/ServicePointForm.js @@ -55,8 +55,11 @@ export const SELECTED_ROUTING_SERVICE_POINT_VALUE = 'true'; export const SELECTED_PICKUP_LOCATION_VALUE = 'true'; export const UNSELECTED_PICKUP_LOCATION_VALUE = 'false'; export const LAYER_EDIT = 'layer=edit'; +export const isLayerEdit = (search) => ( + search.includes(LAYER_EDIT) +); export const isConfirmPickupLocationChangeModalShouldBeVisible = (search, value) => ( - search.includes(LAYER_EDIT) && value === UNSELECTED_PICKUP_LOCATION_VALUE + isLayerEdit(search) && value === UNSELECTED_PICKUP_LOCATION_VALUE ); const ServicePointForm = ({ @@ -309,7 +312,7 @@ const ServicePointForm = ({ component={Select} dataOptions={selectOptions} onChange={handleEcsRequestRoutingChange} - disabled={disabled} + disabled={disabled || isLayerEdit(search)} /> diff --git a/src/settings/ServicePoints/ServicePointForm.test.js b/src/settings/ServicePoints/ServicePointForm.test.js index c224887d..3e5e5889 100644 --- a/src/settings/ServicePoints/ServicePointForm.test.js +++ b/src/settings/ServicePoints/ServicePointForm.test.js @@ -2,13 +2,24 @@ import { SELECTED_PICKUP_LOCATION_VALUE, UNSELECTED_PICKUP_LOCATION_VALUE, LAYER_EDIT, + isLayerEdit, isConfirmPickupLocationChangeModalShouldBeVisible, } from './ServicePointForm'; describe('ServicePointForm', () => { - describe('isConfirmPickupLocationChangeModalShouldBeVisible', () => { - const OTHER_LAYER = 'other'; + const OTHER_LAYER = 'other'; + + describe('isLayerEdit', () => { + it(`should return true for layer equal "${LAYER_EDIT}"`, () => { + expect(isLayerEdit(LAYER_EDIT)).toBe(true); + }); + it(`should return false for layer not equal "${LAYER_EDIT}"(${OTHER_LAYER})`, () => { + expect(isLayerEdit(OTHER_LAYER)).toBe(false); + }); + }); + + describe('isConfirmPickupLocationChangeModalShouldBeVisible', () => { it(`should return true for layer equal "${LAYER_EDIT}" and value "${UNSELECTED_PICKUP_LOCATION_VALUE}"`, () => { expect(isConfirmPickupLocationChangeModalShouldBeVisible(LAYER_EDIT, UNSELECTED_PICKUP_LOCATION_VALUE)).toBe(true); }); From e6c7375ff5bb790d96e7367d4b2394498f8e22aa Mon Sep 17 00:00:00 2001 From: Dmitriy-Litvinenko Date: Tue, 20 Aug 2024 12:58:36 +0300 Subject: [PATCH 4/6] UITEN-292: Change visibility rules for routing service points --- CHANGELOG.md | 1 + package.json | 4 +- src/hooks/index.js | 1 + .../index.js | 1 + .../useCirculationSettingsEcsTlrFeature.js | 27 ++++ .../ServicePoints/ServicePointDetail.js | 12 +- .../ServicePoints/ServicePointForm.js | 12 +- .../ServicePointFormContainer.test.js | 4 + .../ServicePoints/ServicePointManager.js | 12 ++ src/settings/ServicePoints/utils.js | 13 +- src/settings/ServicePoints/utils.test.js | 131 +++++------------- 11 files changed, 105 insertions(+), 113 deletions(-) create mode 100644 src/hooks/index.js create mode 100644 src/hooks/useCirculationSettingsEcsTlrFeature/index.js create mode 100644 src/hooks/useCirculationSettingsEcsTlrFeature/useCirculationSettingsEcsTlrFeature.js diff --git a/CHANGELOG.md b/CHANGELOG.md index ea3a3c4d..3bc599ab 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 dda50338..0201ceb0 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 00000000..86ec60ac --- /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 00000000..e02e3cc7 --- /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 00000000..0266cbe5 --- /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 0b35ecf7..fa21919e 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 2dce3667..090b7b67 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 af581fae..0ac4b4c6 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 41bd7c38..0bdd9879 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); }); }); From 31247b446bbf6028be78904465de085931ba44a3 Mon Sep 17 00:00:00 2001 From: Dmitriy-Litvinenko Date: Tue, 3 Sep 2024 16:26:56 +0300 Subject: [PATCH 5/6] UITEN-306: Fix saving problem for routing service point(ECS only) --- CHANGELOG.md | 1 + package.json | 1 + ...seCirculationSettingsEcsTlrFeature.test.js | 43 +++++++++++++++++++ .../ServicePointFormContainer.js | 1 + 4 files changed, 46 insertions(+) create mode 100644 src/hooks/useCirculationSettingsEcsTlrFeature/useCirculationSettingsEcsTlrFeature.test.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 35a7f27b..c0013201 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ * [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. * [UITEN-304](https://folio-org.atlassian.net/browse/UITEN-304) Provide case insensitive sorted data to edit record, field components. +* [UITEN-306](https://folio-org.atlassian.net/browse/UITEN-306) Fix saving problem for routing service point(ECS only). ## [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 0201ceb0..ce71eac7 100644 --- a/package.json +++ b/package.json @@ -261,6 +261,7 @@ "@testing-library/dom": "^7.26.3", "@testing-library/jest-dom": "^5.11.1", "@testing-library/react": "^11.0.2", + "@testing-library/react-hooks": "^7.0.1", "@testing-library/user-event": "^12.1.10", "babel-eslint": "^9.0.0", "babel-jest": "^26.3.0", diff --git a/src/hooks/useCirculationSettingsEcsTlrFeature/useCirculationSettingsEcsTlrFeature.test.js b/src/hooks/useCirculationSettingsEcsTlrFeature/useCirculationSettingsEcsTlrFeature.test.js new file mode 100644 index 00000000..3068bf86 --- /dev/null +++ b/src/hooks/useCirculationSettingsEcsTlrFeature/useCirculationSettingsEcsTlrFeature.test.js @@ -0,0 +1,43 @@ +import { + QueryClient, + QueryClientProvider, +} from 'react-query'; +import { + renderHook, + act, +} from '@testing-library/react-hooks'; + +import { useOkapiKy } from '@folio/stripes/core'; + +import useCirculationSettingsEcsTlrFeature from './useCirculationSettingsEcsTlrFeature'; + +const queryClient = new QueryClient(); + +// eslint-disable-next-line react/prop-types +const wrapper = ({ children }) => ( + + {children} + +); + +const data = 'data'; + +describe('useCirculationSettingsEcsTlrFeature', () => { + it('should fetch data', async () => { + useOkapiKy.mockClear().mockReturnValue({ + get: () => ({ + json: () => ({ + data, + }), + }), + }); + + const { result } = renderHook(() => useCirculationSettingsEcsTlrFeature(true), { wrapper }); + + await act(() => { + return !result.current.isLoading; + }); + + expect(result.current.titleLevelRequestsFeatureEnabled).toBeFalsy(); + }); +}); diff --git a/src/settings/ServicePoints/ServicePointFormContainer.js b/src/settings/ServicePoints/ServicePointFormContainer.js index a4000b23..ec66497a 100644 --- a/src/settings/ServicePoints/ServicePointFormContainer.js +++ b/src/settings/ServicePoints/ServicePointFormContainer.js @@ -63,6 +63,7 @@ const ServicePointFormContainer = ({ } if (data.ecsRequestRouting) { + unset(data, 'shelvingLagTime'); unset(data, 'pickupLocation'); unset(data, 'holdShelfExpiryPeriod'); unset(data, 'holdShelfClosedLibraryDateManagement'); From 4b387a609e6776961b2331cba63e848fcd9c92ca Mon Sep 17 00:00:00 2001 From: Artem_Blazhko Date: Wed, 6 Nov 2024 13:44:25 +0200 Subject: [PATCH 6/6] Update changelog --- CHANGELOG.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 63296ec3..19984ae0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Change history for ui-tenant-settings ## 9.1.0 (IN PROGRESS) +* [UITEN-281](https://folio-org.atlassian.net/browse/UITEN-281) Add Routing service point option to Service point page(ECS only). +* [UITEN-285](https://folio-org.atlassian.net/browse/UITEN-285) Disable edit of Routing service point field (ECS only). +* [UITEN-294](https://folio-org.atlassian.net/browse/UITEN-294) Show routing service points on settings -> tenant -> servicePoints. +* [UITEN-292](https://folio-org.atlassian.net/browse/UITEN-292) Change visibility rules for routing service points. ## [9.0.0](https://github.com/folio-org/ui-tenant-settings/tree/v9.0.0)(2024-10-30) @@ -13,15 +17,11 @@ * [UITEN-278] (https://issues.folio.org/browse/UITEN-278) Reading Room Access (settings): Create new reading room. * [UITEN-282] (https://issues.folio.org/browse/UITEN-282) Reading Room Access (settings): Update reading room. * [UITEN-283] (https://issues.folio.org/browse/UITEN-283) Reading Room Access (settings): Delete reading room. -* [UITEN-281](https://folio-org.atlassian.net/browse/UITEN-281) Add Routing service point option to Service point page(ECS only). -* [UITEN-285](https://folio-org.atlassian.net/browse/UITEN-285) Disable edit of Routing service point field (ECS only). -* [UITEN-294](https://folio-org.atlassian.net/browse/UITEN-294) Show routing service points on settings -> tenant -> servicePoints. * [UITEN-290] (https://issues.folio.org/browse/UITEN-290) Make dependency on mod-reading-rooms optional. * [UITEN-298] (https://issues.folio.org/browse/UITEN-298) Update translation ids for reading room. * [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. * [UITEN-304](https://folio-org.atlassian.net/browse/UITEN-304) Provide case insensitive sorted data to edit record, field components. * [UITEN-306](https://folio-org.atlassian.net/browse/UITEN-306) Fix saving problem for routing service point(ECS only). * [UITEN-302](https://folio-org.atlassian.net/browse/UITEN-302) Address existing UI issues on Settings > Tenant > Locations