From 0b2872dc332393999dc4b595522baa1ab85bf258 Mon Sep 17 00:00:00 2001 From: Dmitriy-Litvinenko Date: Tue, 23 Apr 2024 15:04:11 +0300 Subject: [PATCH] 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 62169621..c3f18437 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * [UITEN-274](https://folio-org.atlassian.net/browse/UITEN-274) Use Save & close button label stripes-component translation key. * [UITEN-280](https://folio-org.atlassian.net/browse/UITEN-280) Conditionally include SSO Settings based on login-saml interface. * [UITEN-286](https://folio-org.atlassian.net/browse/UITEN-286) *BREAKING* Add new interface. Add new permission to view reading room access in tenant settings. +* [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 e51d4862..3bc841cc 100644 --- a/translations/ui-tenant-settings/en.json +++ b/translations/ui-tenant-settings/en.json @@ -138,6 +138,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", @@ -163,8 +164,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", @@ -219,6 +220,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" }