diff --git a/CHANGELOG.md b/CHANGELOG.md index defa7fa9..6a7a2b60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Create a new setting - Enable ECS title level requests. Refs UICIRC-1040. * Add view permissions for Circulation settings. Refs UICIRC-1056. * Fix DOMPurify import. Refs UICIRC-1122. +* Implement feature toggle for ECS and not ECS envs. Refs UICIRC-1118. ## [9.2.0](https://github.com/folio-org/ui-circulation/tree/v9.2.0) (2024-10-30) [Full Changelog](https://github.com/folio-org/ui-circulation/compare/v9.1.0...v9.2.0) diff --git a/package.json b/package.json index db547dfb..99d2777e 100644 --- a/package.json +++ b/package.json @@ -393,7 +393,8 @@ "mod-settings.global.read.circulation", "mod-settings.entries.collection.get", "mod-settings.entries.item.get", - "circulation.requests.collection.get" + "circulation.requests.collection.get", + "configuration.entries.collection.get" ] }, { @@ -403,7 +404,9 @@ "ui-circulation.settings.view-titleLevelRequests", "mod-settings.global.write.circulation", "mod-settings.entries.item.put", - "mod-settings.entries.item.post" + "mod-settings.entries.item.post", + "configuration.entries.item.post", + "configuration.entries.item.put" ], "visible": true }, diff --git a/src/deprecated/settings/TitleLevelRequests/TitleLevelRequests.js b/src/deprecated/settings/TitleLevelRequests/TitleLevelRequests.js new file mode 100644 index 00000000..1942687d --- /dev/null +++ b/src/deprecated/settings/TitleLevelRequests/TitleLevelRequests.js @@ -0,0 +1,58 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { injectIntl } from 'react-intl'; + +import { ConfigManager } from '@folio/stripes/smart-components'; +import { + withStripes, + TitleManager, +} from '@folio/stripes/core'; + +import TitleLevelRequestsForm from './TitleLevelRequestsForm'; +import { + getInitialValues, + normalizeData, +} from './utils'; +import { + MODULE_NAMES, +} from '../../../constants'; + +export const CONFIG_NAMES = { + TLR: 'TLR', + PRINT_HOLD_REQUESTS: 'PRINT_HOLD_REQUESTS', +}; + +const TitleLevelRequests = ({ + stripes, + intl: { + formatMessage, + }, +}) => { + const ConnectedConfigManager = stripes.connect(ConfigManager); + + return ( + + + + ); +}; + +TitleLevelRequests.propTypes = { + stripes: PropTypes.shape({ + connect: PropTypes.func.isRequired, + }).isRequired, + intl: PropTypes.object.isRequired, +}; + +export default withStripes(injectIntl(TitleLevelRequests)); diff --git a/src/deprecated/settings/TitleLevelRequests/TitleLevelRequests.test.js b/src/deprecated/settings/TitleLevelRequests/TitleLevelRequests.test.js new file mode 100644 index 00000000..ba6411f0 --- /dev/null +++ b/src/deprecated/settings/TitleLevelRequests/TitleLevelRequests.test.js @@ -0,0 +1,68 @@ +import { + render, +} from '@folio/jest-config-stripes/testing-library/react'; +import { ConfigManager } from '@folio/stripes/smart-components'; +import { TitleManager } from '@folio/stripes/core'; + +import TitleLevelRequests, { + CONFIG_NAMES, +} from './TitleLevelRequests'; +import TitleLevelRequestsForm from './TitleLevelRequestsForm'; +import { + getInitialValues, + normalizeData, +} from './utils'; +import { + MODULE_NAMES, +} from '../../../constants'; + +describe('deprecated TitleLevelRequests', () => { + const paneTitleLabelId = 'ui-circulation.settings.titleLevelRequests.paneTitle'; + const mockedStripes = { + connect: jest.fn((component) => component), + }; + const labelIds = { + generalTitle: 'ui-circulation.settings.title.general', + titleLevelRequestsTitle: 'ui-circulation.settings.title.titleLevelRequests', + }; + + beforeEach(() => { + render( + + ); + }); + + afterEach(() => { + ConfigManager.mockClear(); + mockedStripes.connect.mockClear(); + }); + + it('should connect "ConfigManager" to stripes', () => { + expect(mockedStripes.connect).toHaveBeenLastCalledWith(ConfigManager); + }); + + it('should execute "ConfigManager" with passed props', () => { + const expectedResult = { + label: paneTitleLabelId, + moduleName: MODULE_NAMES.SETTINGS, + configName: CONFIG_NAMES.TLR, + configFormComponent: TitleLevelRequestsForm, + stripes: mockedStripes, + getInitialValues, + onBeforeSave: normalizeData, + }; + + expect(ConfigManager).toHaveBeenLastCalledWith(expectedResult, {}); + }); + + it('should trigger TitleManager with correct props', () => { + const expectedProps = { + page: labelIds.generalTitle, + record: labelIds.titleLevelRequestsTitle, + }; + + expect(TitleManager).toHaveBeenCalledWith(expect.objectContaining(expectedProps), {}); + }); +}); diff --git a/src/deprecated/settings/TitleLevelRequests/TitleLevelRequestsForm.css b/src/deprecated/settings/TitleLevelRequests/TitleLevelRequestsForm.css new file mode 100644 index 00000000..db366aa9 --- /dev/null +++ b/src/deprecated/settings/TitleLevelRequests/TitleLevelRequestsForm.css @@ -0,0 +1,7 @@ +.titleLevelRequestsForm { + height: 100%; +} + +.tlrSettings { + margin: 1.5em 0 2em; +} diff --git a/src/deprecated/settings/TitleLevelRequests/TitleLevelRequestsForm.js b/src/deprecated/settings/TitleLevelRequests/TitleLevelRequestsForm.js new file mode 100644 index 00000000..abeec08d --- /dev/null +++ b/src/deprecated/settings/TitleLevelRequests/TitleLevelRequestsForm.js @@ -0,0 +1,212 @@ +import React, { useState } from 'react'; +import PropTypes from 'prop-types'; +import { injectIntl } from 'react-intl'; + +import { Field } from 'react-final-form'; + +import stripesFinalForm from '@folio/stripes/final-form'; +import { stripesConnect } from '@folio/stripes/core'; +import { + Button, + Checkbox, + Col, + Pane, + Row, + PaneFooter, + Modal, +} from '@folio/stripes/components'; + +import NoticeTemplates from '../../../settings/TLRPatronNotices/NoticeTemplates'; +import { + patronNoticeCategoryIds, + MAX_UNPAGED_RESOURCE_COUNT, + TITLE_LEVEL_REQUESTS, + OPEN_REQUESTS_STATUSES, + REQUEST_LEVEL, +} from '../../../constants'; + +import css from './TitleLevelRequestsForm.css'; + +const statusesQueryPart = OPEN_REQUESTS_STATUSES.map(status => `status=="${status}"`).join(' OR '); + +const TitleLevelRequestsForm = (props) => { + const { + handleSubmit, + intl: { formatMessage }, + label, + pristine, + submitting, + form, + resources, + mutator, + } = props; + + const [isErrorModalOpen, setIsErrorModalOpen] = useState(false); + const templates = resources.templates?.records || []; + const { values: titleLevelRequestsValues } = form.getState(); + + const renderFooter = () => ( + + {formatMessage({ id: 'stripes-core.button.save' })} + + )} + /> + ); + + const handleTlrCheckboxClick = async () => { + if (!titleLevelRequestsValues[TITLE_LEVEL_REQUESTS.TLR_ENABLED]) { + form.change(TITLE_LEVEL_REQUESTS.TLR_ENABLED, true); + + return; + } + + const activeTitleRequests = await mutator.requests.GET(); + + if (activeTitleRequests.length) { + setIsErrorModalOpen(true); + + return; + } + + form.change(TITLE_LEVEL_REQUESTS.TLR_ENABLED, false); + }; + + const handleModalClose = () => setIsErrorModalOpen(false); + + const modalFooter = ( + + ); + + return ( +
+ + + + + + + { + titleLevelRequestsValues[TITLE_LEVEL_REQUESTS.TLR_ENABLED] && + <> +
+ + +
+
+ +
+ + } + + {formatMessage({ id: 'ui-circulation.settings.titleLevelRequests.forbiddenDisableTlrModal.description' })} + +
+
+ ); +}; + +TitleLevelRequestsForm.manifest = Object.freeze({ + templates: { + type: 'okapi', + path: 'templates', + records: 'templates', + params: { + query: `cql.allRecords=1 AND category="${patronNoticeCategoryIds.REQUEST}" AND active="true"`, + }, + perRequest: MAX_UNPAGED_RESOURCE_COUNT, + }, + requests: { + type: 'okapi', + path: 'circulation/requests', + records: 'requests', + accumulate: true, + fetch: false, + params: { + query: `${statusesQueryPart} AND requestLevel=="${REQUEST_LEVEL.TITLE}"`, + limit: '1', + }, + }, +}); + +TitleLevelRequestsForm.propTypes = { + handleSubmit: PropTypes.func.isRequired, + intl: PropTypes.object.isRequired, + label: PropTypes.string.isRequired, + pristine: PropTypes.bool.isRequired, + submitting: PropTypes.bool.isRequired, + form: PropTypes.object.isRequired, + resources: PropTypes.shape({ + templates: PropTypes.shape({ + records: PropTypes.arrayOf(PropTypes.shape({ + id: PropTypes.string.isRequired, + name: PropTypes.string.isRequired, + })), + }), + requests: PropTypes.shape({ + records: PropTypes.arrayOf(PropTypes.object).isRequired, + }).isRequired, + }).isRequired, + mutator: PropTypes.shape({ + requests: PropTypes.shape({ + GET: PropTypes.func.isRequired, + }).isRequired, + }).isRequired, +}; + +const withStripes = stripesConnect(TitleLevelRequestsForm); + +export default injectIntl(stripesFinalForm({ + navigationCheck: true, + subscription: { values: true }, +})(withStripes)); diff --git a/src/deprecated/settings/TitleLevelRequests/TitleLevelRequestsForm.test.js b/src/deprecated/settings/TitleLevelRequests/TitleLevelRequestsForm.test.js new file mode 100644 index 00000000..fa2d8021 --- /dev/null +++ b/src/deprecated/settings/TitleLevelRequests/TitleLevelRequestsForm.test.js @@ -0,0 +1,353 @@ +import { + render, + screen, + fireEvent, + cleanup, + waitFor, +} from '@folio/jest-config-stripes/testing-library/react'; + +import { + Button, + Checkbox, + Pane, + PaneFooter, + Modal, +} from '@folio/stripes/components'; +import { Field } from 'react-final-form'; + +import TitleLevelRequestsForm from './TitleLevelRequestsForm'; +import NoticeTemplates from '../../../settings/TLRPatronNotices/NoticeTemplates'; +import { + TITLE_LEVEL_REQUESTS, +} from '../../../constants'; +import { + TITLE_LEVEL_REQUESTS_DEFAULT_VALUES, +} from './constants'; + +jest.mock('../../../settings/TLRPatronNotices/NoticeTemplates', () => jest.fn(() => null)); +PaneFooter.mockImplementation(jest.fn(({ renderEnd }) => ( +
+ {renderEnd} +
+))); +Modal.mockImplementation(jest.fn(({ onClose, footer, children, open, ...rest }) => ( + // eslint-disable-next-line jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events +
+ {children} + {footer} +
+))); +Field.mockImplementation(jest.fn(({ onChange, ...rest }) => ( + // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions +
+))); + +describe('deprecated TitleLevelRequestsForm', () => { + const mockedHandleSubmit = jest.fn(); + const mockedRecord = [ + { + id: 'testId', + name: 'testName', + }, + ]; + const mockedResources = { + templates: { + records: mockedRecord, + }, + }; + const mockedRequest = [{ id: 'testRequest' }]; + const defaultProps = { + handleSubmit: mockedHandleSubmit, + label: 'testLabel', + pristine: false, + submitting: false, + resources: mockedResources, + mutator: { + requests: { + GET: () => mockedRequest, + }, + }, + }; + const testIds = { + form: 'tlrForm', + pane: 'tlrPane', + tlrCheckbox: 'tlrSwitchCheckbox', + errorModal: 'forbiddenDisableTlrModal', + }; + const labelIds = { + tlrEnabled: 'ui-circulation.settings.titleLevelRequests.allow', + tlrByDefault: 'ui-circulation.settings.titleLevelRequests.createTLR', + tlrHoldShouldFollowCirculationRules: 'ui-circulation.settings.titleLevelRequests.tlrHoldShouldFollowCirculationRules', + saveButon: 'stripes-core.button.save', + errorModalTitle: 'ui-circulation.settings.titleLevelRequests.forbiddenDisableTlrModal.title', + errorModalDescription: 'ui-circulation.settings.titleLevelRequests.forbiddenDisableTlrModal.description', + closeButton: 'stripes-core.button.close', + }; + const orderOfFieldCall = { + tlrEnabled: 1, + tlrByDefault: 2, + tlrHoldShouldFollowCirculationRules: 3, + }; + const mockedFormChange = jest.fn(); + + afterEach(() => { + Pane.mockClear(); + Field.mockClear(); + Button.mockClear(); + NoticeTemplates.mockClear(); + mockedFormChange.mockClear(); + }); + + describe('when "titleLevelRequestsFeatureEnabled" is true', () => { + const mockedForm = { + getState: jest.fn(() => ({ + values: { + ...TITLE_LEVEL_REQUESTS_DEFAULT_VALUES, + titleLevelRequestsFeatureEnabled: true, + }, + })), + change: mockedFormChange, + }; + + beforeEach(() => { + render( + + ); + }); + + it('should render form', () => { + expect(screen.getByTestId(testIds.form)).toBeVisible(); + }); + + it('should correctly handle form submit', () => { + expect(mockedHandleSubmit).toHaveBeenCalledTimes(0); + fireEvent.submit(screen.getByTestId(testIds.form)); + expect(mockedHandleSubmit).toHaveBeenCalledTimes(1); + }); + + it('should execute "Pane" with passed props', () => { + const expectedResult = { + defaultWidth: 'fill', + fluidContentWidth: true, + paneTitle:'testLabel', + }; + + expect(Pane).toHaveBeenLastCalledWith(expect.objectContaining(expectedResult), {}); + }); + + it('should execute "Field" associated with "TLR eneblade" with passed props', () => { + const expectedResult = { + name: TITLE_LEVEL_REQUESTS.TLR_ENABLED, + type: 'checkbox', + label: labelIds.tlrEnabled, + component: Checkbox, + }; + + expect(Field).toHaveBeenNthCalledWith(orderOfFieldCall.tlrEnabled, expect.objectContaining(expectedResult), {}); + }); + + it('should execute "Field" associated with "TLR by default" with passed props', () => { + const expectedResult = { + name: TITLE_LEVEL_REQUESTS.CREATE_TLR_BY_DEFAULT, + type: 'checkbox', + label: labelIds.tlrByDefault, + component: Checkbox, + }; + + expect(Field).toHaveBeenNthCalledWith(orderOfFieldCall.tlrByDefault, expectedResult, {}); + }); + + it('should execute "Field" associated with "tlr hold should follow circulation rules" with passed props', () => { + const expectedResult = { + name: TITLE_LEVEL_REQUESTS.TLR_HOLD_SHOULD_FOLLOW_CIRCULATION_RULES, + type: 'checkbox', + label: labelIds.tlrHoldShouldFollowCirculationRules, + component: Checkbox, + }; + + expect(Field).toHaveBeenNthCalledWith(orderOfFieldCall.tlrHoldShouldFollowCirculationRules, expectedResult, {}); + }); + + it('should execute "NoticeTemplates" with passed props', () => { + expect(NoticeTemplates).toHaveBeenLastCalledWith({ templates: mockedRecord }, {}); + }); + + it('should execute "Button" with passed props', () => { + const expectedResult = { + type: 'submit', + buttonStyle: 'primary paneHeaderNewButton', + disabled: false, + marginBottom0: true, + children: labelIds.saveButon, + }; + + expect(Button).toHaveBeenLastCalledWith(expectedResult, {}); + }); + + describe('when resources are empty', () => { + it('should execute "NoticeTemplates" with empty array instead of templates', () => { + render( + + ); + + expect(NoticeTemplates).toHaveBeenLastCalledWith({ templates: [] }, {}); + }); + }); + + describe('"Button" should be disabled', () => { + it('when "pristine" is true', () => { + render( + + ); + + expect(Button).toHaveBeenLastCalledWith(expect.objectContaining({ disabled: true }), {}); + }); + + it('when "submitting" is true', () => { + render( + + ); + + expect(Button).toHaveBeenLastCalledWith(expect.objectContaining({ disabled: true }), {}); + }); + }); + + describe('Modal', () => { + it('should be executed with passed props', () => { + const expectedResult = { + label: labelIds.errorModalTitle, + open: false, + dismissible: true, + children: labelIds.errorModalDescription, + }; + + expect(Modal).toHaveBeenLastCalledWith(expect.objectContaining(expectedResult), {}); + }); + + it('should be open', async () => { + expect(screen.getByTestId(testIds.errorModal)).not.toHaveAttribute('open'); + + fireEvent.click(screen.getByTestId(testIds.tlrCheckbox)); + + const modalAfterClick = await screen.findByTestId(testIds.errorModal); + + expect(mockedFormChange).not.toHaveBeenCalled(); + expect(modalAfterClick).toHaveAttribute('open'); + }); + + it('should have "Close" button', () => { + expect(screen.getByText(labelIds.closeButton)).toBeVisible(); + }); + + it('should close modal on "Close" button click', async () => { + expect(screen.getByTestId(testIds.errorModal)).not.toHaveAttribute('open'); + fireEvent.click(screen.getByTestId(testIds.tlrCheckbox)); + const modalAfterFirstClick = await screen.findByTestId(testIds.errorModal); + expect(modalAfterFirstClick).toHaveAttribute('open'); + + fireEvent.click(screen.getByText(labelIds.closeButton)); + const modalAfterSecondClick = await screen.findByTestId(testIds.errorModal); + expect(modalAfterSecondClick).not.toHaveAttribute('open'); + }); + }); + + describe('when there are no "Title" requests in data base', () => { + it('should disable TLR on checkbox click', async () => { + cleanup(); + render( + [], + }, + }} + /> + ); + + fireEvent.click(screen.getByTestId(testIds.tlrCheckbox)); + + await waitFor(() => { + expect(mockedFormChange).toHaveBeenCalledWith(TITLE_LEVEL_REQUESTS.TLR_ENABLED, false); + }); + }); + }); + }); + + describe('when "titleLevelRequestsFeatureEnabled" is false', () => { + const mockedForm = { + getState: jest.fn(() => ({ + values: { + ...TITLE_LEVEL_REQUESTS_DEFAULT_VALUES, + titleLevelRequestsFeatureEnabled: false, + }, + })), + change: mockedFormChange, + }; + + beforeEach(() => { + render( + + ); + }); + + it('should render only one "Field"', () => { + const expectedResult = { + name: TITLE_LEVEL_REQUESTS.TLR_ENABLED, + type: 'checkbox', + label: labelIds.tlrEnabled, + component: Checkbox, + }; + + expect(Field).toHaveBeenCalledTimes(1); + expect(Field).toHaveBeenNthCalledWith(orderOfFieldCall.tlrEnabled, expect.objectContaining(expectedResult), {}); + }); + + it('should not render "NoticeTemplates"', () => { + expect(NoticeTemplates).toHaveBeenCalledTimes(0); + }); + + it('should execute "Button" with passed props', () => { + const expectedResult = { + type: 'submit', + buttonStyle: 'primary paneHeaderNewButton', + disabled: false, + marginBottom0: true, + children: labelIds.saveButon, + }; + + expect(Button).toHaveBeenLastCalledWith(expectedResult, {}); + }); + + it('should enable TLR on checkbox click', async () => { + fireEvent.click(screen.getByTestId(testIds.tlrCheckbox)); + + await waitFor(() => { + expect(mockedFormChange).toHaveBeenCalledWith(TITLE_LEVEL_REQUESTS.TLR_ENABLED, true); + }); + }); + }); +}); diff --git a/src/deprecated/settings/TitleLevelRequests/constants.js b/src/deprecated/settings/TitleLevelRequests/constants.js new file mode 100644 index 00000000..70da6959 --- /dev/null +++ b/src/deprecated/settings/TitleLevelRequests/constants.js @@ -0,0 +1,13 @@ +import { + NOT_SELECTED, + TITLE_LEVEL_REQUESTS, +} from '../../../constants'; + +export const TITLE_LEVEL_REQUESTS_DEFAULT_VALUES = { + [TITLE_LEVEL_REQUESTS.TLR_ENABLED]: false, + [TITLE_LEVEL_REQUESTS.CREATE_TLR_BY_DEFAULT]: false, + [TITLE_LEVEL_REQUESTS.TLR_HOLD_SHOULD_FOLLOW_CIRCULATION_RULES]: false, + [TITLE_LEVEL_REQUESTS.CONFIRMATION_TEMPLATE]: NOT_SELECTED, + [TITLE_LEVEL_REQUESTS.CANCELLATION_TEMPLATE]: NOT_SELECTED, + [TITLE_LEVEL_REQUESTS.EXPIRATION_TEMPLATE]: NOT_SELECTED, +}; diff --git a/src/deprecated/settings/TitleLevelRequests/index.js b/src/deprecated/settings/TitleLevelRequests/index.js new file mode 100644 index 00000000..62d94875 --- /dev/null +++ b/src/deprecated/settings/TitleLevelRequests/index.js @@ -0,0 +1 @@ +export { default } from './TitleLevelRequests'; diff --git a/src/deprecated/settings/TitleLevelRequests/utils/getInitialValues.js b/src/deprecated/settings/TitleLevelRequests/utils/getInitialValues.js new file mode 100644 index 00000000..7dc20a1f --- /dev/null +++ b/src/deprecated/settings/TitleLevelRequests/utils/getInitialValues.js @@ -0,0 +1,33 @@ +import { + isEmpty, + head, +} from 'lodash'; + +import { + NOT_SELECTED, + TLR_FIELDS_FOR_RESET, +} from '../../../../constants'; +import { + TITLE_LEVEL_REQUESTS_DEFAULT_VALUES, +} from '../constants'; + +const getInitialValues = (settings) => { + if (isEmpty(settings)) { + return TITLE_LEVEL_REQUESTS_DEFAULT_VALUES; + } + + const settingsForReturn = { + ...TITLE_LEVEL_REQUESTS_DEFAULT_VALUES, + ...JSON.parse(head(settings).value), + }; + + TLR_FIELDS_FOR_RESET.forEach(field => { + if (settingsForReturn[field] === null) { + settingsForReturn[field] = NOT_SELECTED; + } + }); + + return settingsForReturn; +}; + +export default getInitialValues; diff --git a/src/deprecated/settings/TitleLevelRequests/utils/getInitialValues.test.js b/src/deprecated/settings/TitleLevelRequests/utils/getInitialValues.test.js new file mode 100644 index 00000000..1463d8b1 --- /dev/null +++ b/src/deprecated/settings/TitleLevelRequests/utils/getInitialValues.test.js @@ -0,0 +1,33 @@ +import getInitialValues from './getInitialValues'; +import { + TITLE_LEVEL_REQUESTS, +} from '../../../../constants'; +import { + TITLE_LEVEL_REQUESTS_DEFAULT_VALUES, +} from '../constants'; + +describe('deprecated getInitialValues', () => { + it('should return default config if nothing found in database', () => { + expect(getInitialValues()).toEqual(TITLE_LEVEL_REQUESTS_DEFAULT_VALUES); + }); + + it('should return config with values from database', () => { + const testData = [ + { + value: JSON.stringify({ + [TITLE_LEVEL_REQUESTS.TLR_ENABLED]: true, + [TITLE_LEVEL_REQUESTS.CONFIRMATION_TEMPLATE]: 'testId', + [TITLE_LEVEL_REQUESTS.EXPIRATION_TEMPLATE]: null, + [TITLE_LEVEL_REQUESTS.CANCELLATION_TEMPLATE]: null, + }), + }, + ]; + const expectedData = { + ...TITLE_LEVEL_REQUESTS_DEFAULT_VALUES, + [TITLE_LEVEL_REQUESTS.TLR_ENABLED]: true, + [TITLE_LEVEL_REQUESTS.CONFIRMATION_TEMPLATE]: 'testId', + }; + + expect(getInitialValues(testData)).toEqual(expectedData); + }); +}); diff --git a/src/deprecated/settings/TitleLevelRequests/utils/index.js b/src/deprecated/settings/TitleLevelRequests/utils/index.js new file mode 100644 index 00000000..77f927b7 --- /dev/null +++ b/src/deprecated/settings/TitleLevelRequests/utils/index.js @@ -0,0 +1,2 @@ +export { default as normalizeData } from './normalizeData'; +export { default as getInitialValues } from './getInitialValues'; diff --git a/src/deprecated/settings/TitleLevelRequests/utils/normalizeData.js b/src/deprecated/settings/TitleLevelRequests/utils/normalizeData.js new file mode 100644 index 00000000..5564fe50 --- /dev/null +++ b/src/deprecated/settings/TitleLevelRequests/utils/normalizeData.js @@ -0,0 +1,24 @@ +import { + TITLE_LEVEL_REQUESTS, + TLR_FIELDS_FOR_RESET, + NOT_SELECTED, +} from '../../../../constants'; +import { + TITLE_LEVEL_REQUESTS_DEFAULT_VALUES, +} from '../constants'; + +const normalizeData = (value) => { + const configForReturn = value[TITLE_LEVEL_REQUESTS.TLR_ENABLED] + ? value + : TITLE_LEVEL_REQUESTS_DEFAULT_VALUES; + + TLR_FIELDS_FOR_RESET.forEach(field => { + if (configForReturn[field] === NOT_SELECTED) { + configForReturn[field] = null; + } + }); + + return JSON.stringify(configForReturn); +}; + +export default normalizeData; diff --git a/src/deprecated/settings/TitleLevelRequests/utils/normalizeData.test.js b/src/deprecated/settings/TitleLevelRequests/utils/normalizeData.test.js new file mode 100644 index 00000000..89a40f5d --- /dev/null +++ b/src/deprecated/settings/TitleLevelRequests/utils/normalizeData.test.js @@ -0,0 +1,41 @@ +import normalizeData from './normalizeData'; +import { + TITLE_LEVEL_REQUESTS, + NOT_SELECTED, +} from '../../../../constants'; +import { + TITLE_LEVEL_REQUESTS_DEFAULT_VALUES, +} from '../constants'; + +describe('deprecated normalizeData', () => { + const testId = 'testId'; + + it('should return modified passed config if "TLR" is allowed', () => { + const testData = { + titleLevelRequestsFeatureEnabled: true, + someData: 'test', + [TITLE_LEVEL_REQUESTS.CONFIRMATION_TEMPLATE]: NOT_SELECTED, + [TITLE_LEVEL_REQUESTS.CANCELLATION_TEMPLATE]: NOT_SELECTED, + [TITLE_LEVEL_REQUESTS.EXPIRATION_TEMPLATE]: testId, + }; + + const expectedResult = { + titleLevelRequestsFeatureEnabled: true, + someData: 'test', + [TITLE_LEVEL_REQUESTS.CONFIRMATION_TEMPLATE]: null, + [TITLE_LEVEL_REQUESTS.CANCELLATION_TEMPLATE]: null, + [TITLE_LEVEL_REQUESTS.EXPIRATION_TEMPLATE]: testId, + }; + + expect(normalizeData(testData)).toBe(JSON.stringify(expectedResult)); + }); + + it('should return modified default config if "TLR" is not allowed', () => { + const testData = { + titleLevelRequestsFeatureEnabled: false, + someData: 'test', + }; + + expect(normalizeData(testData)).toBe(JSON.stringify(TITLE_LEVEL_REQUESTS_DEFAULT_VALUES)); + }); +}); diff --git a/src/index.js b/src/index.js index d6c73cfa..334db8db 100644 --- a/src/index.js +++ b/src/index.js @@ -22,6 +22,7 @@ import RequestPolicySettings from './settings/RequestPolicy'; import TitleLevelRequests from './settings/TitleLevelRequests'; import PrintHoldRequests from './settings/PrintHoldRequests'; import TLRPatronNotices from './settings/TLRPatronNotices'; +import DeprecatedTitleLevelRequests from './deprecated/settings/TitleLevelRequests'; import ConsortiumTLR from './settings/ConsortiumTLR'; import { getConsortiumTlrPermission } from './settings/utils/utils'; import ViewPrintDetails from './settings/ViewPrintDetails'; @@ -34,6 +35,9 @@ class Circulation extends Component { constructor(props) { super(props); + + const isEnabledEcsRequests = props.stripes?.config?.enableEcsRequests; + this.sections = [ { label: , @@ -56,18 +60,6 @@ class Circulation extends Component { component: StaffSlips, perm: 'ui-circulation.settings.view-staff-slips', }, - { - route: 'title-level-requests', - label: , - component: TitleLevelRequests, - perm: 'ui-circulation.settings.view-titleLevelRequests', - }, - { - route: 'consortium-title-level-requests', - label: , - component: ConsortiumTLR, - perm: getConsortiumTlrPermission(props.stripes), - }, ], }, { @@ -142,12 +134,6 @@ class Circulation extends Component { component: RequestPolicySettings, perm: 'ui-circulation.settings.view-request-policies', }, - { - route: 'tlr-patron-notice-templates', - label: , - component: TLRPatronNotices, - perm: 'ui-circulation.settings.view-titleLevelRequests', - }, { route: 'print-hold-requests', label: , @@ -163,6 +149,34 @@ class Circulation extends Component { ], }, ]; + + if (isEnabledEcsRequests === true) { + this.sections[0].pages.push({ + route: 'title-level-requests', + label: , + component: TitleLevelRequests, + perm: 'ui-circulation.settings.view-titleLevelRequests', + }, + { + route: 'consortium-title-level-requests', + label: , + component: ConsortiumTLR, + perm: getConsortiumTlrPermission(props.stripes), + }); + this.sections[4].pages.splice(2, 0, { + route: 'tlr-patron-notice-templates', + label: , + component: TLRPatronNotices, + perm: 'ui-circulation.settings.view-titleLevelRequests', + }); + } else { + this.sections[4].pages.splice(2, 0, { + route: 'title-level-requests', + label: , + component: DeprecatedTitleLevelRequests, + perm: 'ui-circulation.settings.view-titleLevelRequests', + }); + } } render() {