From 54fca502477b4360e41c1bc7d4399d158c819015 Mon Sep 17 00:00:00 2001 From: Priyanka Terala Date: Tue, 23 Apr 2024 12:34:18 +0530 Subject: [PATCH 01/15] UITEN-278 - create reading room from tenant settings --- CHANGELOG.md | 3 + package.json | 6 + .../ReadingRoomAccess/ReadingRoomAccess.js | 146 ++++++++++++++++++ .../ReadingRoomAccess.test.js | 122 +++++++++++++++ 4 files changed, 277 insertions(+) create mode 100644 src/settings/ReadingRoomAccess/ReadingRoomAccess.js create mode 100644 src/settings/ReadingRoomAccess/ReadingRoomAccess.test.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 261199c4..718ca706 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ * [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-277](https://issues.folio.org/browse/UITEN-277) Ensure Reading Room Access settings page is wrapped by `Title Manager`. +* [UITEN-276](https://issues.folio.org/browse/UITEN-276) Reading Room Access (settings): Basic Layout. +* [UITEN-278] (https://issues.folio.org/browse/UITEN-278) Reading Room Access (settings): Create new reading room. ## [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 57c5dfb5..0305ef20 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,13 @@ "route": "/tenant-settings", "okapiInterfaces": { "configuration": "2.0", +<<<<<<< Updated upstream "users": "15.0 16.0" +======= + "login-saml": "2.0", + "users": "15.0 16.0", + "reading-room": "1.0" +>>>>>>> Stashed changes }, "optionalOkapiInterfaces": { "location-units": "2.0", diff --git a/src/settings/ReadingRoomAccess/ReadingRoomAccess.js b/src/settings/ReadingRoomAccess/ReadingRoomAccess.js new file mode 100644 index 00000000..20603e80 --- /dev/null +++ b/src/settings/ReadingRoomAccess/ReadingRoomAccess.js @@ -0,0 +1,146 @@ +import React from 'react'; +import { useIntl } from 'react-intl'; +import { Field } from 'redux-form'; +import _ from 'lodash'; + +import { TitleManager, useStripes } from '@folio/stripes/core'; +import { + Checkbox, + Label, + MultiSelection, +} from '@folio/stripes/components'; +import { ControlledVocab } from '@folio/stripes/smart-components'; + +const hiddenFields = ['numberOfObjects', 'lastUpdated']; +const visibleFields = ['name', 'isPublic', 'servicePoints']; +const formatter = { + 'isPublic': (record) => , + 'servicePoints': (record) => { + const asp = record.servicePoints || []; + const items = asp.map(a =>
  • {a.label}
  • ); + return ; + } +}; +const translations = { + cannotDeleteTermHeader: 'ui-tenant-settings.settings.addresses.cannotDeleteTermHeader', + cannotDeleteTermMessage: 'ui-tenant-settings.settings.addresses.cannotDeleteTermMessage', + deleteEntry: 'ui-tenant-settings.settings.reading-room-access.deleteEntry', + termDeleted: 'ui-tenant-settings.settings.reading-room-access.termDeleted', + termWillBeDeleted: 'ui-tenant-settings.settings.reading-room-access.termWillBeDeleted', +}; + +const ReadingRoomAccess = (props) => { + const intl = useIntl(); + const stripes = useStripes(); + const { resources } = props; + // service points defined in the tenant + const servicePoints = _.get(resources, ['RRAServicePoints', 'records', 0, 'servicepoints'], []); + /** + * A reading room can have more than one service points assigned to it. + * but a servicepoint cannot be mapped to more than one reading room + */ + const sps = []; + const rrs = _.get(resources, ['values', 'records']); + rrs.forEach(rr => { + const asp = rr.servicePoints || []; + asp.forEach(s => { + if (!sps.includes(s.value)) { + sps.push(s.value); + } + }); + }); + + const options = []; + servicePoints.forEach(s => { + if (!sps.includes(s.id) || s.name === 'None') { + options.push({ value: s.id, label: s.name }); + } + }); + + const columnMapping = { + name: ( + ), + isPublic: intl.formatMessage({ id:'ui-tenant-settings.settings.reading-room-access.public' }), + servicePoints: ( + ), + }; + + const fieldComponents = { + isPublic: ({ fieldProps }) => ( + + ), + servicePoints: ({ fieldProps }) => { + return ( + e.preventDefault()} + /> + ); + } + }; + + const editable = true; // stripes.hasPerm('ui-users.settings.reading-room-access.all'); + + return ( + + true, + delete: () => true, + }} + /> + + ); +}; + +ReadingRoomAccess.manifest = Object.freeze({ + values: { + type: 'okapi', + records: 'readingRooms', + path: 'reading-room', + GET: { + path: 'reading-room?query=cql.allRecords=1 sortby name&limit=100' + } + }, + updaterIds: [], + RRAServicePoints: { + type: 'okapi', + resource: 'service-points', + path: 'service-points?limit=200', + }, +}); + +export default ReadingRoomAccess; diff --git a/src/settings/ReadingRoomAccess/ReadingRoomAccess.test.js b/src/settings/ReadingRoomAccess/ReadingRoomAccess.test.js new file mode 100644 index 00000000..27f82cfb --- /dev/null +++ b/src/settings/ReadingRoomAccess/ReadingRoomAccess.test.js @@ -0,0 +1,122 @@ +import { screen } from '@testing-library/react'; + +import '../../../test/jest/__mocks__'; +import buildStripes from '../../../test/jest/__new_mocks__/stripesCore.mock'; + +import { + renderWithRouter, + renderWithReduxForm, +} from '../../../test/jest/helpers'; + +import ReadingRoomAccess from './ReadingRoomAccess'; + +const STRIPES = buildStripes(); + +const mutatorMock = { + values: { + // PUT: jest.fn(() => Promise.resolve()), + // DELETE: jest.fn(() => Promise.resolve()), + GET: jest.fn(() => Promise.resolve()), + POST: jest.fn(() => Promise.resolve()), + }, +}; + +const resourcesMock = { + values: { + dataKey: 'reading-room', + failed: false, + hasLoaded: true, + httpStatus: 200, + isPending: false, + module: '@folio/tenant-settings', + records: [ + { + 'id': '04efd73f-f7e3-4c19-8614-861941dd1d8e', + 'name': 'readingroom-422', + 'isPublic': true, + 'servicePoints': [ + { + 'value': '7c5abc9f-f3d7-4856-b8d7-6712462ca007', + 'label': 'Online' + } + ], + 'metadata': { + 'createdDate': '2024-04-22T11:41:52.904334', + 'createdByUserId': '2db30b15-7a36-4f02-9c77-999dbb470874' + } + }, + { + 'id': '75e44262-f68c-418c-ab4c-88c9198669c1', + 'name': 'reading-room-4221', + 'isPublic': true, + 'servicePoints': [ + { + 'value': '3a40852d-49fd-4df2-a1f9-6e2641a6e91f', + 'label': 'Circ Desk 1' + } + ], + 'metadata': { + 'createdDate': '2024-04-22T11:48:50.255863', + 'createdByUserId': '2db30b15-7a36-4f02-9c77-999dbb470874' + } + }, + { + 'id': '7c5abc9f-f3d7-4856-b8d7-6712462ca009', + 'name': 'reading-room-555', + 'isPublic': false, + 'servicePoints': [ + { + 'value': 'c4c90014-c8c9-4ade-8f24-b5e313319f4b', + 'label': 'Circ Desk 4' + } + ], + 'metadata': { + 'createdDate': '2024-04-19T11:56:15.192057', + 'createdByUserId': '2db30b15-7a36-4f02-9c77-999dbb470874', + 'updatedDate': '2024-04-22T04:38:00.75285', + 'updatedByUserId': '2db30b15-7a36-4f02-9c77-999dbb470874' + } + } + ], + }, +}; + +const renderReadingRoomAccess = (props) => { + const component = () => ( + + ); + + return renderWithRouter(renderWithReduxForm(component)); +}; + +describe('Reading Room Access', () => { + describe('when records exist', () => { + const props = { + mutator: mutatorMock, + resources: resourcesMock, + stripes:{ STRIPES } + }; + + beforeEach(() => { + renderReadingRoomAccess(props); + }); + + it('should render a Pane with title "Reading room access"', () => { + expect(screen.getByLabelText('ui-tenant-settings.settings.reading-room-access.label')).toBeInTheDocument(); + }); + + it('should render new button', () => { + expect(screen.getByRole('button', { name: 'stripes-core.button.new' })).toBeVisible(); + }); + + it('should render correct result column', () => { + const columnHeaders = [ + /settings.reading-room-access.name/, + /settings.reading-room-access.public/, + /settings.reading-room-access.asp/ + ]; + + columnHeaders.forEach((el) => expect(screen.getByRole('columnheader', { name: el })).toBeVisible()); + }); + }); +}); From b17a1b75ecb3e7dc542d80e57d130330cae89ccf Mon Sep 17 00:00:00 2001 From: Priyanka Terala Date: Tue, 23 Apr 2024 12:37:43 +0530 Subject: [PATCH 02/15] UITEN-278 - update package.json --- package.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/package.json b/package.json index 0305ef20..a51e1a68 100644 --- a/package.json +++ b/package.json @@ -17,13 +17,8 @@ "route": "/tenant-settings", "okapiInterfaces": { "configuration": "2.0", -<<<<<<< Updated upstream - "users": "15.0 16.0" -======= - "login-saml": "2.0", "users": "15.0 16.0", "reading-room": "1.0" ->>>>>>> Stashed changes }, "optionalOkapiInterfaces": { "location-units": "2.0", From 4a8c63f5533d690dafea859fd1ae91c59d5471cd Mon Sep 17 00:00:00 2001 From: Priyanka Terala Date: Tue, 23 Apr 2024 12:50:30 +0530 Subject: [PATCH 03/15] UITEN-278 - Add prop type validation --- src/settings/ReadingRoomAccess/ReadingRoomAccess.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/settings/ReadingRoomAccess/ReadingRoomAccess.js b/src/settings/ReadingRoomAccess/ReadingRoomAccess.js index 20603e80..54b83557 100644 --- a/src/settings/ReadingRoomAccess/ReadingRoomAccess.js +++ b/src/settings/ReadingRoomAccess/ReadingRoomAccess.js @@ -1,4 +1,5 @@ import React from 'react'; +import PropTypes from 'prop-types'; import { useIntl } from 'react-intl'; import { Field } from 'redux-form'; import _ from 'lodash'; @@ -143,4 +144,9 @@ ReadingRoomAccess.manifest = Object.freeze({ }, }); +ReadingRoomAccess.propTypes = { + resources: PropTypes.object, + mutator: PropTypes.object +}; + export default ReadingRoomAccess; From 68180b220320fab80e8e7bcae0fff05db31463ab Mon Sep 17 00:00:00 2001 From: Priyanka Terala Date: Tue, 23 Apr 2024 13:22:15 +0530 Subject: [PATCH 04/15] UITEN-278 - update jest config --- jest.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/jest.config.js b/jest.config.js index 98599830..22988ec5 100644 --- a/jest.config.js +++ b/jest.config.js @@ -19,6 +19,7 @@ module.exports = { moduleNameMapper: { '^.+\\.(css)$': 'identity-obj-proxy', '^.+\\.(svg)$': 'identity-obj-proxy', + '^.+\\.(png)$': 'identity-obj-proxy', 'ky': 'ky/umd', }, testMatch: ['**/(lib|src)/**/?(*.)test.{js,jsx}'], From eaae5df6d542ca49a3c1c2f0cef0f57d1442fe76 Mon Sep 17 00:00:00 2001 From: Priyanka Terala Date: Tue, 23 Apr 2024 14:28:23 +0530 Subject: [PATCH 05/15] UITEN-278 - add unit test --- .../ReadingRoomAccess.test.js | 64 ++++++++++++------- 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/src/settings/ReadingRoomAccess/ReadingRoomAccess.test.js b/src/settings/ReadingRoomAccess/ReadingRoomAccess.test.js index 27f82cfb..3450af23 100644 --- a/src/settings/ReadingRoomAccess/ReadingRoomAccess.test.js +++ b/src/settings/ReadingRoomAccess/ReadingRoomAccess.test.js @@ -1,5 +1,5 @@ -import { screen } from '@testing-library/react'; - +import { screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import '../../../test/jest/__mocks__'; import buildStripes from '../../../test/jest/__new_mocks__/stripesCore.mock'; @@ -90,33 +90,49 @@ const renderReadingRoomAccess = (props) => { }; describe('Reading Room Access', () => { - describe('when records exist', () => { - const props = { - mutator: mutatorMock, - resources: resourcesMock, - stripes:{ STRIPES } - }; - - beforeEach(() => { - renderReadingRoomAccess(props); - }); + const props = { + mutator: mutatorMock, + resources: resourcesMock, + stripes:{ STRIPES } + }; - it('should render a Pane with title "Reading room access"', () => { - expect(screen.getByLabelText('ui-tenant-settings.settings.reading-room-access.label')).toBeInTheDocument(); - }); + beforeEach(() => { + renderReadingRoomAccess(props); + }); + + it('should render a Pane with title "Reading room access"', () => { + expect(screen.getByLabelText('ui-tenant-settings.settings.reading-room-access.label')).toBeInTheDocument(); + }); + + it('should render new button', () => { + expect(screen.getByRole('button', { name: 'stripes-core.button.new' })).toBeVisible(); + }); + + it('should render correct result column', () => { + const columnHeaders = [ + /settings.reading-room-access.name/, + /settings.reading-room-access.public/, + /settings.reading-room-access.asp/ + ]; + + columnHeaders.forEach((el) => expect(screen.getByRole('columnheader', { name: el })).toBeVisible()); + }); - it('should render new button', () => { - expect(screen.getByRole('button', { name: 'stripes-core.button.new' })).toBeVisible(); + it('create reading room', async () => { + const newButton = screen.getByRole('button', { name: 'stripes-core.button.new' }); + await userEvent.click(newButton); + await waitFor(() => { + expect(screen.getByText('stripes-core.button.save')).toBeInTheDocument(); + expect(document.querySelector('[name="items[0].name"]')).toBeInTheDocument(); }); - it('should render correct result column', () => { - const columnHeaders = [ - /settings.reading-room-access.name/, - /settings.reading-room-access.public/, - /settings.reading-room-access.asp/ - ]; + await userEvent.type(document.querySelector('[name="items[0].name"]'), 'test'); + await userEvent.click(document.querySelectorAll("[class^='multiSelectToggleButton']")[0]); + await userEvent.click(document.querySelectorAll('[class^="multiSelectOption"]')[0]); + await userEvent.click(screen.getByText('stripes-core.button.save')); - columnHeaders.forEach((el) => expect(screen.getByRole('columnheader', { name: el })).toBeVisible()); + await waitFor(() => { + expect(screen.queryByText('stripes-core.button.save')).not.toBeInTheDocument(); }); }); }); From fbf242c7abbfbf5e52f7ca790ad61110630307bf Mon Sep 17 00:00:00 2001 From: Priyanka Terala Date: Tue, 23 Apr 2024 19:08:14 +0530 Subject: [PATCH 06/15] UITEN-278 - update to final form --- src/settings/ReadingRoomAccess/ReadingRoomAccess.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/settings/ReadingRoomAccess/ReadingRoomAccess.js b/src/settings/ReadingRoomAccess/ReadingRoomAccess.js index 54b83557..f46607c5 100644 --- a/src/settings/ReadingRoomAccess/ReadingRoomAccess.js +++ b/src/settings/ReadingRoomAccess/ReadingRoomAccess.js @@ -1,7 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { useIntl } from 'react-intl'; -import { Field } from 'redux-form'; +import { Field } from 'react-final-form'; import _ from 'lodash'; import { TitleManager, useStripes } from '@folio/stripes/core'; @@ -80,6 +80,7 @@ const ReadingRoomAccess = (props) => { {...fieldProps} component={Checkbox} type="checkbox" + initialValue={false} /> ), servicePoints: ({ fieldProps }) => { @@ -122,6 +123,7 @@ const ReadingRoomAccess = (props) => { edit: () => true, delete: () => true, }} + formType="final-form" /> ); From 38524391d6562ab996ee92fbd2092a34eca55709 Mon Sep 17 00:00:00 2001 From: Priyanka Terala Date: Tue, 23 Apr 2024 19:53:33 +0530 Subject: [PATCH 07/15] UITEN-278 - update uni test --- .../ReadingRoomAccess.test.js | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/src/settings/ReadingRoomAccess/ReadingRoomAccess.test.js b/src/settings/ReadingRoomAccess/ReadingRoomAccess.test.js index 3450af23..d95a44a3 100644 --- a/src/settings/ReadingRoomAccess/ReadingRoomAccess.test.js +++ b/src/settings/ReadingRoomAccess/ReadingRoomAccess.test.js @@ -79,6 +79,83 @@ const resourcesMock = { } ], }, + RRAServicePoints: { + 'hasLoaded': true, + 'isPending': false, + 'failed': false, + 'records': [ + { + 'servicepoints': [ + { + 'id': 'c4c90014-c8c9-4ade-8f24-b5e313319f4b', + 'name': 'Circ Desk 2', + 'code': 'cd2', + 'discoveryDisplayName': 'Circulation Desk -- Back Entrance', + 'pickupLocation': true, + 'holdShelfExpiryPeriod': { + 'duration': 5, + 'intervalId': 'Days' + }, + 'holdShelfClosedLibraryDateManagement': 'Keep_the_current_due_date', + 'staffSlips': [], + 'metadata': { + 'createdDate': '2024-04-23T01:53:59.590+00:00', + 'updatedDate': '2024-04-23T01:53:59.590+00:00' + } + }, + { + 'id': '3a40852d-49fd-4df2-a1f9-6e2641a6e91f', + 'name': 'Circ Desk 1', + 'code': 'cd1', + 'discoveryDisplayName': 'Circulation Desk -- Hallway', + 'pickupLocation': true, + 'holdShelfExpiryPeriod': { + 'duration': 3, + 'intervalId': 'Weeks' + }, + 'holdShelfClosedLibraryDateManagement': 'Keep_the_current_due_date', + 'staffSlips': [], + 'metadata': { + 'createdDate': '2024-04-23T01:53:59.598+00:00', + 'updatedDate': '2024-04-23T01:53:59.598+00:00' + } + }, + { + 'id': '7c5abc9f-f3d7-4856-b8d7-6712462ca007', + 'name': 'Online', + 'code': 'Online', + 'discoveryDisplayName': 'Online', + 'shelvingLagTime': 0, + 'pickupLocation': false, + 'holdShelfClosedLibraryDateManagement': 'Keep_the_current_due_date', + 'staffSlips': [], + 'metadata': { + 'createdDate': '2024-04-23T01:53:59.593+00:00', + 'updatedDate': '2024-04-23T01:53:59.593+00:00' + } + }, + { + 'id': '9d1b77e8-f02e-4b7f-b296-3f2042ddac54', + 'name': 'DCB', + 'code': '000', + 'discoveryDisplayName': 'DCB', + 'pickupLocation': true, + 'holdShelfExpiryPeriod': { + 'duration': 3, + 'intervalId': 'Days' + }, + 'holdShelfClosedLibraryDateManagement': 'Keep_the_current_due_date', + 'staffSlips': [], + 'metadata': { + 'createdDate': '2024-04-23T01:56:03.899+00:00', + 'updatedDate': '2024-04-23T01:56:03.899+00:00' + } + } + ], + 'totalRecords': 4 + } + ], + } }; const renderReadingRoomAccess = (props) => { From 2afad54b4ab04141948119c7319de4d6f96a60f2 Mon Sep 17 00:00:00 2001 From: Priyanka Terala Date: Wed, 24 Apr 2024 08:40:14 +0530 Subject: [PATCH 08/15] UITEN-278 - refinement --- .../ReadingRoomAccess/ReadingRoomAccess.js | 54 ++++++++++--------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/src/settings/ReadingRoomAccess/ReadingRoomAccess.js b/src/settings/ReadingRoomAccess/ReadingRoomAccess.js index f46607c5..0de57d5b 100644 --- a/src/settings/ReadingRoomAccess/ReadingRoomAccess.js +++ b/src/settings/ReadingRoomAccess/ReadingRoomAccess.js @@ -67,41 +67,43 @@ const ReadingRoomAccess = (props) => { ), isPublic: intl.formatMessage({ id:'ui-tenant-settings.settings.reading-room-access.public' }), servicePoints: ( -