From de2602a34d69bc35e7c01239cadc55386ed4aa22 Mon Sep 17 00:00:00 2001 From: Dmitriy-Litvinenko Date: Wed, 3 Jan 2024 11:49:17 +0200 Subject: [PATCH 1/2] UIREQMED-2: Add pages: Confirm item arrival, Mediated requests activities and Send item in transit --- CHANGELOG.md | 2 +- README.md | 27 ++-- package.json | 36 ++++- .../ConfirmItemArrival/ConfirmItemArrival.js | 46 ++++++ .../ConfirmItemArrival.test.js | 32 ++++ src/components/ConfirmItemArrival/index.js | 1 + .../MediatedRequestsActivities.js | 50 ++++++ .../MediatedRequestsActivities.test.js | 32 ++++ .../MediatedRequestsActivities/index.js | 1 + .../NavigationMenu/NavigationMenu.js | 68 +++++++++ .../NavigationMenu/NavigationMenu.test.js | 144 ++++++++++++++++++ src/components/NavigationMenu/index.js | 1 + .../SendItemInTransit/SendItemInTransit.js | 46 ++++++ .../SendItemInTransit.test.js | 32 ++++ src/components/SendItemInTransit/index.js | 1 + src/constants/api.js | 9 ++ src/constants/base.js | 4 + src/constants/index.js | 2 + src/index.js | 35 +++-- src/routes/MediatedRequests.js | 22 --- src/routes/MediatedRequests.test.js | 37 ----- src/settings/General.test.js | 5 - test/jest/__mock__/stripesComponents.mock.js | 38 +++-- translations/ui-requests-mediated/en.json | 15 +- 24 files changed, 578 insertions(+), 108 deletions(-) create mode 100644 src/components/ConfirmItemArrival/ConfirmItemArrival.js create mode 100644 src/components/ConfirmItemArrival/ConfirmItemArrival.test.js create mode 100644 src/components/ConfirmItemArrival/index.js create mode 100644 src/components/MediatedRequestsActivities/MediatedRequestsActivities.js create mode 100644 src/components/MediatedRequestsActivities/MediatedRequestsActivities.test.js create mode 100644 src/components/MediatedRequestsActivities/index.js create mode 100644 src/components/NavigationMenu/NavigationMenu.js create mode 100644 src/components/NavigationMenu/NavigationMenu.test.js create mode 100644 src/components/NavigationMenu/index.js create mode 100644 src/components/SendItemInTransit/SendItemInTransit.js create mode 100644 src/components/SendItemInTransit/SendItemInTransit.test.js create mode 100644 src/components/SendItemInTransit/index.js create mode 100644 src/constants/api.js create mode 100644 src/constants/base.js create mode 100644 src/constants/index.js delete mode 100644 src/routes/MediatedRequests.js delete mode 100644 src/routes/MediatedRequests.test.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 1646c31..4685bc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## 1.1.0 (IN PROGRESS) * Update github actions. Refs UIREQMED-14. +* Add landing page actions: Confirm item arrival, Mediated requests activities and Send item in transit. Refs UIREQMED-2. ## 1.0.0 - * New app created with stripes-cli. Updated module after created with stripes-cli. Refs UIREQMED-1. diff --git a/README.md b/README.md index 4c7b2b3..2a743e3 100644 --- a/README.md +++ b/README.md @@ -4,16 +4,6 @@ Copyright (C) 2023 The Open Library Foundation This software is distributed under the terms of the Apache License, Version 2.0. See the file "[LICENSE](LICENSE)" for more information. -## Introduction - -Congratulations on creating a new Stripes UI app module! Follow the instructions below to run ui-requests-mediated and start your development. - -TODO: Modify this README to replace these sections about getting started. - -## Prerequisites - -In order to view and log into the platform being served up, a suitable Okapi backend will need to be running. The [testing-backend](https://app.vagrantup.com/folio/boxes/testing-backend) Vagrant box should work if your app does not yet have its own backend module. - ## Run your new app Run the following from the ui-requests-mediated directory to serve your new app using a development server: @@ -35,18 +25,19 @@ stripes serve --okapi http://my-okapi.example.com:9130 --tenant my-tenant-id Run the included UI tests with the following command: ``` -stripes test karma +yarn run test:jest" ``` -## What to do next? - -Now that your new app is running, search the code for "`new-app`" to find comments and subbed placeholders that may need your attention. +## Introduction -Please remove or customize the sample strings in `en.json` (lines 3-10) before merging this file to master; the translators do not need to be providing translations for these sample strings. +This is a [Stripes](https://github.com/folio-org/stripes-core/) UI module +for making requests on items. -Read the [Stripes Module Developer's Guide](https://github.com/folio-org/stripes/blob/master/doc/dev-guide.md). +## Additional information -When your new UI app is ready and being built by CI, then adjust its Jenkinsfile to remove the `npmDeploy = 'no'` parameter (which is then superfluous). +Other [modules](https://dev.folio.org/source-code/#client-side). -TODO: Modify this README to replace these sections about getting started, link to your issue tracker, etc. +See project [UIREQMED](https://issues.folio.org/browse/UIREQMED) +at the [FOLIO issue tracker](https://dev.folio.org/guidelines/issue-tracker). +Other FOLIO Developer documentation is at [dev.folio.org](https://dev.folio.org/) diff --git a/package.json b/package.json index 9fb11aa..c1b935f 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,8 @@ "regenerator-runtime": "^0.13.3" }, "dependencies": { - "prop-types": "^15.6.0" + "prop-types": "^15.6.0", + "react-router-prop-types": "^1.0.4" }, "peerDependencies": { "@folio/stripes": "^9.0.0", @@ -79,6 +80,39 @@ "settings.enabled" ], "visible": true + }, + { + "permissionName": "ui-requests-mediated.view", + "displayName": "Mediated requests: View", + "subPermissions": [ + "module.requests-mediated.enabled", + "settings.requests-mediated.enabled" + ], + "visible": true + }, + { + "permissionName": "ui-requests-mediated.view-create", + "displayName": "Mediated requests: View, create", + "subPermissions": [ + "ui-requests-mediated.view" + ], + "visible": true + }, + { + "permissionName": "ui-requests-mediated.view-edit-cancel", + "displayName": "Mediated requests: View, edit, cancel", + "subPermissions": [ + "ui-requests-mediated.view-create" + ], + "visible": true + }, + { + "permissionName": "ui-requests-mediated.all", + "displayName": "Mediated requests: All permissions", + "subPermissions": [ + "ui-requests-mediated.view-edit-cancel" + ], + "visible": true } ] } diff --git a/src/components/ConfirmItemArrival/ConfirmItemArrival.js b/src/components/ConfirmItemArrival/ConfirmItemArrival.js new file mode 100644 index 0000000..1a34290 --- /dev/null +++ b/src/components/ConfirmItemArrival/ConfirmItemArrival.js @@ -0,0 +1,46 @@ +import ReactRouterPropTypes from 'react-router-prop-types'; +import { FormattedMessage } from 'react-intl'; + +import { + Pane, + Paneset, +} from '@folio/stripes/components'; + +import NavigationMenu from '../NavigationMenu'; + +import { + FILTER_PANE_WIDTH, + getConfirmItemArrivalUrl, +} from '../../constants'; + +const ConfirmItemArrival = ({ + history, + location, +}) => { + return ( + + } + > + + + } + /> + + ); +}; + +ConfirmItemArrival.propTypes = { + history: ReactRouterPropTypes.history.isRequired, + location: ReactRouterPropTypes.location.isRequired, +}; + +export default ConfirmItemArrival; diff --git a/src/components/ConfirmItemArrival/ConfirmItemArrival.test.js b/src/components/ConfirmItemArrival/ConfirmItemArrival.test.js new file mode 100644 index 0000000..def818d --- /dev/null +++ b/src/components/ConfirmItemArrival/ConfirmItemArrival.test.js @@ -0,0 +1,32 @@ +import { + render, + screen, +} from '@folio/jest-config-stripes/testing-library/react'; + +import ConfirmItemArrival from './ConfirmItemArrival'; + +const testIds = { + confirmItemArrivalPaneSet: 'confirmItemArrivalPaneSet', + confirmItemArrivalPane: 'confirmItemArrivalPane', +}; +const labelIds = { + paneTitle: 'ui-requests-mediated.app.confirmItemArrival.paneTitle', +}; + +describe('ConfirmItemArrival', () => { + beforeEach(() => { + render(); + }); + + it('should render pane set', () => { + expect(screen.getByTestId(testIds.confirmItemArrivalPaneSet)).toBeInTheDocument(); + }); + + it('should render pane', () => { + expect(screen.getByTestId(testIds.confirmItemArrivalPane)).toBeInTheDocument(); + }); + + it('should render pane title', () => { + expect(screen.getByText(labelIds.paneTitle)).toBeVisible(); + }); +}); diff --git a/src/components/ConfirmItemArrival/index.js b/src/components/ConfirmItemArrival/index.js new file mode 100644 index 0000000..e44e27e --- /dev/null +++ b/src/components/ConfirmItemArrival/index.js @@ -0,0 +1 @@ +export { default } from './ConfirmItemArrival'; diff --git a/src/components/MediatedRequestsActivities/MediatedRequestsActivities.js b/src/components/MediatedRequestsActivities/MediatedRequestsActivities.js new file mode 100644 index 0000000..234c261 --- /dev/null +++ b/src/components/MediatedRequestsActivities/MediatedRequestsActivities.js @@ -0,0 +1,50 @@ +import ReactRouterPropTypes from 'react-router-prop-types'; +import { FormattedMessage } from 'react-intl'; + +import { AppIcon } from '@folio/stripes/core'; + +import { + Pane, + Paneset, +} from '@folio/stripes/components'; + +import NavigationMenu from '../NavigationMenu'; + +import { + APP_ICON_NAME, + FILTER_PANE_WIDTH, + getMediatedRequestsActivitiesUrl, +} from '../../constants'; + +const MediatedRequestsActivities = ({ + history, + location, +}) => { + return ( + + } + > + + + } + paneTitle={} + /> + + ); +}; + +MediatedRequestsActivities.propTypes = { + history: ReactRouterPropTypes.history.isRequired, + location: ReactRouterPropTypes.location.isRequired, +}; + +export default MediatedRequestsActivities; diff --git a/src/components/MediatedRequestsActivities/MediatedRequestsActivities.test.js b/src/components/MediatedRequestsActivities/MediatedRequestsActivities.test.js new file mode 100644 index 0000000..3acd77d --- /dev/null +++ b/src/components/MediatedRequestsActivities/MediatedRequestsActivities.test.js @@ -0,0 +1,32 @@ +import { + render, + screen, +} from '@folio/jest-config-stripes/testing-library/react'; + +import MediatedRequestsActivities from './MediatedRequestsActivities'; + +const testIds = { + mediatedRequestsActivitiesPaneSet: 'mediatedRequestsActivitiesPaneSet', + mediatedRequestsActivitiesPane: 'mediatedRequestsActivitiesPane', +}; +const labelIds = { + paneTitle: 'ui-requests-mediated.app.mediatedRequestsActivities.paneTitle', +}; + +describe('MediatedRequestsActivities', () => { + beforeEach(() => { + render(); + }); + + it('should render pane set', () => { + expect(screen.getByTestId(testIds.mediatedRequestsActivitiesPaneSet)).toBeInTheDocument(); + }); + + it('should render pane', () => { + expect(screen.getByTestId(testIds.mediatedRequestsActivitiesPane)).toBeInTheDocument(); + }); + + it('should render pane title', () => { + expect(screen.getByText(labelIds.paneTitle)).toBeVisible(); + }); +}); diff --git a/src/components/MediatedRequestsActivities/index.js b/src/components/MediatedRequestsActivities/index.js new file mode 100644 index 0000000..6e0b47e --- /dev/null +++ b/src/components/MediatedRequestsActivities/index.js @@ -0,0 +1 @@ +export { default } from './MediatedRequestsActivities'; diff --git a/src/components/NavigationMenu/NavigationMenu.js b/src/components/NavigationMenu/NavigationMenu.js new file mode 100644 index 0000000..d9d933f --- /dev/null +++ b/src/components/NavigationMenu/NavigationMenu.js @@ -0,0 +1,68 @@ +import PropTypes from 'prop-types'; +import { useIntl } from 'react-intl'; + +import { Select } from '@folio/stripes/components'; + +import { + getConfirmItemArrivalUrl, + getMediatedRequestsActivitiesUrl, + getSendItemInTransitUrl, +} from '../../constants'; + +export const getDataOptions = (intl) => ([ + { + label: intl.formatMessage({ id: 'ui-requests-mediated.app.mediatedRequestsActivities.navigation' }), + value: getMediatedRequestsActivitiesUrl(), + }, + { + label: intl.formatMessage({ id: 'ui-requests-mediated.app.confirmItemArrival.navigation' }), + value: getConfirmItemArrivalUrl(), + }, + { + label: intl.formatMessage({ id: 'ui-requests-mediated.app.sendItemInTransit.navigation' }), + value: getSendItemInTransitUrl(), + }, +]); + +export const handleChangeMenu = (event, location, history) => { + const pathname = event.target.value; + const destination = { + pathname, + state: location.state, + }; + + if (pathname === getMediatedRequestsActivitiesUrl()) { + destination.search = location.state; + } else { + destination.state = location.search; + } + + history.push(destination); +}; + +const NavigationMenu = ({ + history, + location, + value, +}) => { + const intl = useIntl(); + + return ( + - {dataOptions.forEach((option, i) => ( - ))} - - {children} - - )), + Select: jest.fn(({ + children, + 'data-testid': testId, + dataOptions, + }) => { + const selectTestId = testId || 'selectTestId'; + const selectOptionTestId = `${selectTestId}selectOption`; + + return ( +
+ + {children} +
+ ); + }), })); diff --git a/translations/ui-requests-mediated/en.json b/translations/ui-requests-mediated/en.json index faebe7d..cfc6cc8 100644 --- a/translations/ui-requests-mediated/en.json +++ b/translations/ui-requests-mediated/en.json @@ -1,7 +1,20 @@ { "meta.title": "Mediated requests", - "app.index.paneTitle": "Mediated requests", + "permission.view": "Mediated requests: View", + "permission.view-create": "Mediated requests: View, create", + "permission.view-create-edit": "Mediated requests: View, edit, cancel", + "permission.all": "Mediated requests: All permissions", + + "app.filterPane.selectActivity": "Select activity", + + "app.confirmItemArrival.navigation": "Confirm item arrival", + "app.mediatedRequestsActivities.navigation": "Mediated requests activities", + "app.sendItemInTransit.navigation": "Send item in transit", + + "app.confirmItemArrival.paneTitle": "Confirm item arrival", + "app.mediatedRequestsActivities.paneTitle": "Mediated requests", + "app.sendItemInTransit.paneTitle": "Send item in transit", "settings.index.paneTitle": "Mediated requests", "settings.general": "General", From 0d21078126fd7d7ed10521f2efe14da982e7df96 Mon Sep 17 00:00:00 2001 From: Dmitriy-Litvinenko Date: Tue, 16 Jan 2024 19:01:13 +0200 Subject: [PATCH 2/2] UIREQMED-2: Add pages: Confirm item arrival, Mediated requests activities and Send item in transit --- package.json | 3 +-- .../ConfirmItemArrival/ConfirmItemArrival.js | 17 ++--------------- .../ConfirmItemArrival.test.js | 11 +++++++++++ .../MediatedRequestsActivities.js | 17 ++--------------- .../MediatedRequestsActivities.test.js | 11 +++++++++++ .../NavigationMenu/NavigationMenu.js | 12 ++++++------ .../NavigationMenu/NavigationMenu.test.js | 18 +++++++++++------- .../SendItemInTransit/SendItemInTransit.js | 17 ++--------------- .../SendItemInTransit.test.js | 11 +++++++++++ 9 files changed, 57 insertions(+), 60 deletions(-) diff --git a/package.json b/package.json index c1b935f..57cebc3 100644 --- a/package.json +++ b/package.json @@ -42,8 +42,7 @@ "regenerator-runtime": "^0.13.3" }, "dependencies": { - "prop-types": "^15.6.0", - "react-router-prop-types": "^1.0.4" + "prop-types": "^15.6.0" }, "peerDependencies": { "@folio/stripes": "^9.0.0", diff --git a/src/components/ConfirmItemArrival/ConfirmItemArrival.js b/src/components/ConfirmItemArrival/ConfirmItemArrival.js index 1a34290..2c04838 100644 --- a/src/components/ConfirmItemArrival/ConfirmItemArrival.js +++ b/src/components/ConfirmItemArrival/ConfirmItemArrival.js @@ -1,4 +1,3 @@ -import ReactRouterPropTypes from 'react-router-prop-types'; import { FormattedMessage } from 'react-intl'; import { @@ -13,10 +12,7 @@ import { getConfirmItemArrivalUrl, } from '../../constants'; -const ConfirmItemArrival = ({ - history, - location, -}) => { +const ConfirmItemArrival = () => { return ( } > - + jest.fn((props) => (
))); const testIds = { confirmItemArrivalPaneSet: 'confirmItemArrivalPaneSet', @@ -29,4 +34,10 @@ describe('ConfirmItemArrival', () => { it('should render pane title', () => { expect(screen.getByText(labelIds.paneTitle)).toBeVisible(); }); + + it('should trigger NavigationMenu with correct props', () => { + expect(NavigationMenu).toHaveBeenCalledWith(expect.objectContaining({ + value: getConfirmItemArrivalUrl(), + }), {}); + }); }); diff --git a/src/components/MediatedRequestsActivities/MediatedRequestsActivities.js b/src/components/MediatedRequestsActivities/MediatedRequestsActivities.js index 234c261..3b734b0 100644 --- a/src/components/MediatedRequestsActivities/MediatedRequestsActivities.js +++ b/src/components/MediatedRequestsActivities/MediatedRequestsActivities.js @@ -1,4 +1,3 @@ -import ReactRouterPropTypes from 'react-router-prop-types'; import { FormattedMessage } from 'react-intl'; import { AppIcon } from '@folio/stripes/core'; @@ -16,10 +15,7 @@ import { getMediatedRequestsActivitiesUrl, } from '../../constants'; -const MediatedRequestsActivities = ({ - history, - location, -}) => { +const MediatedRequestsActivities = () => { return ( } > - + jest.fn((props) => (
))); const testIds = { mediatedRequestsActivitiesPaneSet: 'mediatedRequestsActivitiesPaneSet', @@ -29,4 +34,10 @@ describe('MediatedRequestsActivities', () => { it('should render pane title', () => { expect(screen.getByText(labelIds.paneTitle)).toBeVisible(); }); + + it('should trigger NavigationMenu with correct props', () => { + expect(NavigationMenu).toHaveBeenCalledWith(expect.objectContaining({ + value: getMediatedRequestsActivitiesUrl(), + }), {}); + }); }); diff --git a/src/components/NavigationMenu/NavigationMenu.js b/src/components/NavigationMenu/NavigationMenu.js index d9d933f..bb6b89f 100644 --- a/src/components/NavigationMenu/NavigationMenu.js +++ b/src/components/NavigationMenu/NavigationMenu.js @@ -1,5 +1,9 @@ import PropTypes from 'prop-types'; import { useIntl } from 'react-intl'; +import { + useHistory, + useLocation, +} from 'react-router-dom'; import { Select } from '@folio/stripes/components'; @@ -41,11 +45,11 @@ export const handleChangeMenu = (event, location, history) => { }; const NavigationMenu = ({ - history, - location, value, }) => { const intl = useIntl(); + const history = useHistory(); + const location = useLocation(); return (