diff --git a/CHANGELOG.md b/CHANGELOG.md index a6e33f548..0744082e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Change history for ui-agreements +## 8.3.3 2023-01-24 +* ERM-2547 On agreement and license user details do not display when more than one user linked to agreement/license as Internal contact +* ERM-2538 On agreement and license view not all linked Org interfaces displaying + ## 8.3.2 2022-12-01 * ERM-2489 Reduce number of eresources retrieved to 25 rather than 100 diff --git a/package.json b/package.json index 6131c4682..261801778 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@folio/agreements", - "version": "8.3.2", + "version": "8.3.3", "description": "ERM agreement functionality for Stripes", "main": "src/index.js", "publishConfig": { @@ -32,7 +32,7 @@ "@folio/eslint-config-stripes": "^6.3.0", "@folio/stripes": "^7.3.1", "@folio/stripes-cli": "^2.6.1", - "@folio/stripes-erm-components": "^7.0.1", + "@folio/stripes-erm-components": "^7.0.5", "@folio/stripes-testing": "^4.2.0", "@formatjs/cli": "^4.2.31", "@interactors/html": "^1.0.0-rc1.2", @@ -74,7 +74,7 @@ }, "dependencies": { "@folio/stripes-acq-components": "^3.1.0", - "@k-int/stripes-kint-components": "^3.0.2", + "@k-int/stripes-kint-components": "^3.2.2", "@rehooks/local-storage": "2.4.4", "compose-function": "^3.0.3", "final-form": "^4.18.4", @@ -89,7 +89,7 @@ }, "peerDependencies": { "@folio/stripes": "^7.3.1", - "@folio/stripes-erm-components": "^7.0.1", + "@folio/stripes-erm-components": "^7.0.5", "moment": "^2.29.3", "react": "^17.0.2", "react-dom": "^17.0.2", diff --git a/src/components/AgreementSections/Organizations/Organizations.js b/src/components/AgreementSections/Organizations/Organizations.js index 0f15089c4..2effad0e7 100644 --- a/src/components/AgreementSections/Organizations/Organizations.js +++ b/src/components/AgreementSections/Organizations/Organizations.js @@ -35,9 +35,6 @@ export default class Organizations extends React.Component { }), ), }).isRequired, - handlers: PropTypes.shape({ - onFetchCredentials: PropTypes.func, - }), id: PropTypes.string, }; @@ -52,7 +49,6 @@ export default class Organizations extends React.Component { @@ -66,6 +62,7 @@ export default class Organizations extends React.Component { } interfaces={interfaces} note={note} + org={org} roles={roles} /> ); diff --git a/src/components/AgreementSections/Organizations/Organizations.test.js b/src/components/AgreementSections/Organizations/Organizations.test.js index d1c628879..4a8f10a70 100644 --- a/src/components/AgreementSections/Organizations/Organizations.test.js +++ b/src/components/AgreementSections/Organizations/Organizations.test.js @@ -162,10 +162,6 @@ const agreement = { ] }; -const handlers = { - onFetchCredentials: () => { } -}; - let renderComponent; describe('Organizations', () => { @@ -174,7 +170,6 @@ describe('Organizations', () => { renderComponent = renderWithIntl( , translationsProperties @@ -196,7 +191,6 @@ describe('Organizations', () => { renderComponent = renderWithIntl( , translationsProperties diff --git a/src/routes/AgreementLineCreateRoute/AgreementLineCreateRoute.js b/src/routes/AgreementLineCreateRoute/AgreementLineCreateRoute.js index d5bd2e62f..be9b7d42a 100644 --- a/src/routes/AgreementLineCreateRoute/AgreementLineCreateRoute.js +++ b/src/routes/AgreementLineCreateRoute/AgreementLineCreateRoute.js @@ -125,13 +125,6 @@ AgreementLineCreateRoute.propTypes = { agreementId: PropTypes.string.isRequired, }).isRequired }).isRequired, - resources: PropTypes.shape({ - basket: PropTypes.arrayOf(PropTypes.object), - }).isRequired, - stripes: PropTypes.shape({ - hasInterface: PropTypes.func.isRequired, - hasPerm: PropTypes.func.isRequired, - }).isRequired, }; export default stripesConnect(AgreementLineCreateRoute); diff --git a/src/routes/AgreementViewRoute/AgreementViewRoute.js b/src/routes/AgreementViewRoute/AgreementViewRoute.js index b1466326e..9fb00455f 100644 --- a/src/routes/AgreementViewRoute/AgreementViewRoute.js +++ b/src/routes/AgreementViewRoute/AgreementViewRoute.js @@ -4,32 +4,27 @@ import PropTypes from 'prop-types'; import { useMutation, useQuery, useQueryClient } from 'react-query'; import { FormattedMessage, useIntl } from 'react-intl'; -import { get, flatten, uniqBy } from 'lodash'; +import { flatten } from 'lodash'; -import { CalloutContext, stripesConnect, useOkapiKy } from '@folio/stripes/core'; -import { useAgreement, useInfiniteFetch, useUsers } from '@folio/stripes-erm-components'; +import { CalloutContext, useOkapiKy } from '@folio/stripes/core'; +import { useAgreement, useInfiniteFetch, useInterfaces, useUsers } from '@folio/stripes-erm-components'; import { generateKiwtQueryParams } from '@k-int/stripes-kint-components'; import View from '../../components/views/Agreement'; import { parseMclPageSize, urls } from '../../components/utilities'; -import { errorTypes, resultCount } from '../../constants'; +import { errorTypes } from '../../constants'; import { joinRelatedAgreements } from '../utilities/processRelatedAgreements'; import { useAgreementsHelperApp, useAgreementsSettings, useChunkedOrderLines } from '../../hooks'; import { AGREEMENT_ENDPOINT, AGREEMENT_ERESOURCES_ENDPOINT, AGREEMENT_LINES_ENDPOINT } from '../../constants/endpoints'; -const { RECORDS_PER_REQUEST_MEDIUM } = resultCount; - -const credentialsArray = []; const AgreementViewRoute = ({ handlers = {}, history, location, match: { params: { id: agreementId } }, - mutator, - resources, }) => { const queryClient = useQueryClient(); @@ -52,6 +47,10 @@ const AgreementViewRoute = ({ const { agreement, isAgreementLoading } = useAgreement({ agreementId }); + const interfaces = useInterfaces({ + interfaceIds: flatten((agreement?.orgs ?? []).map(o => o?.org?.orgsUuid_object?.interfaces ?? [])) + }) ?? []; + const { mutateAsync: deleteAgreement } = useMutation( [agreementPath, 'ui-agreements', 'AgreementViewRoute', 'deleteAgreement'], () => ky.delete(agreementPath).then(() => queryClient.invalidateQueries(['ERM', 'Agreements'])) @@ -200,32 +199,18 @@ const AgreementViewRoute = ({ } ); - const getRecord = (id, resourceType) => { - return get(resources, `${resourceType}.records`, []) - .find(i => i.id === id); - }; - const getCompositeAgreement = () => { const contacts = agreement.contacts.map(c => ({ ...c, user: users?.find(user => user?.id === c.user) || c.user, })); - const interfacesCredentials = uniqBy(get(resources, 'interfacesCredentials.records', []), 'id'); - - if (interfacesCredentials[0]) { - const index = credentialsArray.findIndex(object => object.id === interfacesCredentials[0].id); - if (index === -1) { - credentialsArray.push(interfacesCredentials[0]); - } - } - const orgs = agreement.orgs.map(o => ({ ...o, - interfaces: get(o, 'org.orgsUuid_object.interfaces', []) + interfaces: (o?.org?.orgsUuid_object?.interfaces ?? []) .map(id => ({ - ...getRecord(id, 'interfaces') || {}, - credentials: credentialsArray.find(cred => cred.interfaceId === id) + ...(interfaces?.find(int => int?.id === id) ?? {}), + /* Credentials are now handled by ViewOrganizationCard directly */ })), })); @@ -281,10 +266,6 @@ const AgreementViewRoute = ({ history.push(`${urls.agreementEdit(agreementId)}${location.search}`); }; - const handleFetchCredentials = (id) => { - mutator.interfaceRecord.replace({ id }); - }; - const handleViewAgreementLine = (lineId) => { history.push(`${urls.agreementLineView(agreementId, lineId)}${location.search}`); }; @@ -319,7 +300,6 @@ const AgreementViewRoute = ({ onExportAgreement: exportAgreement, onExportEResourcesAsJSON: exportEresourcesAsJson, onExportEResourcesAsKBART: exportEresourcesAsKBART, - onFetchCredentials: handleFetchCredentials, onFilterEResources: handleFilterEResources, onNeedMoreEResources: (_askAmount, index) => fetchNextEresourcePage({ pageParam: index }), onNeedMoreLines: (_askAmount, index) => fetchNextLinesPage({ pageParam: index }), @@ -331,36 +311,6 @@ const AgreementViewRoute = ({ ); }; -AgreementViewRoute.manifest = Object.freeze({ - interfaces: { // We can and shouold migrate these to react-query at some point as a separate task - type: 'okapi', - path: 'organizations-storage/interfaces', - perRequest: RECORDS_PER_REQUEST_MEDIUM, - params: (_q, _p, _r, _l, props) => { - const orgs = get(props.resources, 'agreement.records[0].orgs', []); - const interfaces = flatten(orgs.map(o => get(o, 'org.orgsUuid_object.interfaces', []))); - const query = [ - ...new Set(interfaces.map(i => `id==${i}`)) - ].join(' or '); - - return query ? { query } : {}; - }, - fetch: props => !!props.stripes.hasInterface('organizations-storage.interfaces', '2.0'), - permissionsRequired: 'organizations-storage.interfaces.collection.get', - records: 'interfaces', - }, - interfacesCredentials: { - clientGeneratePk: false, - throwErrors: false, - path: 'organizations-storage/interfaces/%{interfaceRecord.id}/credentials', - type: 'okapi', - pk: 'FAKE_PK', // it's done to fool stripes-connect not to add cred id to the path's end. - permissionsRequired: 'organizations-storage.interfaces.credentials.item.get', - fetch: props => !!props.stripes.hasInterface('organizations-storage.interfaces', '1.0 2.0'), - }, - interfaceRecord: {}, -}); - AgreementViewRoute.propTypes = { handlers: PropTypes.object, history: PropTypes.shape({ @@ -374,19 +324,6 @@ AgreementViewRoute.propTypes = { id: PropTypes.string.isRequired, }).isRequired }).isRequired, - mutator: PropTypes.shape({ - interfaceRecord: PropTypes.shape({ - replace: PropTypes.func, - }), - }), - resources: PropTypes.shape({ - interfaces: PropTypes.object, - query: PropTypes.object, - }).isRequired, - stripes: PropTypes.shape({ - hasInterface: PropTypes.func.isRequired, - hasPerm: PropTypes.func.isRequired, - }).isRequired, }; -export default stripesConnect(AgreementViewRoute); +export default AgreementViewRoute; diff --git a/src/routes/AgreementViewRoute/AgreementViewRoute.test.js b/src/routes/AgreementViewRoute/AgreementViewRoute.test.js index b9e919fd3..cc8d29a45 100644 --- a/src/routes/AgreementViewRoute/AgreementViewRoute.test.js +++ b/src/routes/AgreementViewRoute/AgreementViewRoute.test.js @@ -10,19 +10,8 @@ import { Button } from '@folio/stripes/components'; import { Button as ButtonInteractor } from '@folio/stripes-testing'; import { agreement, - agreementLines, - agreementEresources, - eresourcesFilterPath, - interfaces, - orderLines, - query, - settings, - users, - tagsEnabled, location, - handlers, match, - intl } from './testResources'; import translationsProperties from '../../../test/helpers'; import AgreementViewRoute from './AgreementViewRoute'; @@ -39,10 +28,6 @@ const FilterEResourceButton = (props) => { return ; }; -const FetchCredentialsButton = (props) => { - return ; -}; - const EditButton = (props) => { return ; }; @@ -89,12 +74,6 @@ FilterEResourceButton.propTypes = { }), }; -FetchCredentialsButton.propTypes = { - handlers: PropTypes.shape({ - onFetchCredentials: PropTypes.func, - }), -}; - EditButton.propTypes = { handlers: PropTypes.shape({ onEdit: PropTypes.func, @@ -138,7 +117,6 @@ CloneButton.propTypes = { }; const historyPushMock = jest.fn(); -const mutatorFetchReplaceMock = jest.fn(); jest.mock('@folio/stripes-erm-components', () => ({ ...jest.requireActual('@folio/stripes-erm-components'), @@ -152,7 +130,6 @@ jest.mock('../../components/views/Agreement', () => { - @@ -165,30 +142,11 @@ jest.mock('../../components/views/Agreement', () => { }); const data = { - handlers, history:{ push: historyPushMock, }, - intl, location, match, - mutator:{ - interfaceRecord:{ - replace: mutatorFetchReplaceMock, - }, - }, - resources: { - agreement, - agreementLines, - agreementEresources, - eresourcesFilterPath, - interfaces, - orderLines, - query, - settings, - users, - }, - tagsEnabled }; useQuery.mockImplementation(() => ({ data: agreement, isLoading: false })); @@ -230,11 +188,6 @@ describe('AgreementViewRoute', () => { expect(historyPushMock).toHaveBeenCalled(); }); - test('triggers the FetchCredentialsButton callback', async () => { - await ButtonInteractor('FetchCredentialsButton').click(); - expect(mutatorFetchReplaceMock).toHaveBeenCalled(); - }); - test('triggers the CloseButton callback', async () => { await ButtonInteractor('CloseButton').click(); expect(historyPushMock).toHaveBeenCalled(); diff --git a/src/routes/AgreementViewRoute/testResources.js b/src/routes/AgreementViewRoute/testResources.js index c709b958e..fddddfa35 100644 --- a/src/routes/AgreementViewRoute/testResources.js +++ b/src/routes/AgreementViewRoute/testResources.js @@ -1,14 +1,3 @@ -const tagsEnabled = true; - -const handlers = { - 'onDownloadFile': () => {}, - 'onUploadFile': () => {}, -}; - -const history = { - push: () => {}, -}; - const location = { 'pathname': '/erm/agreements/d5b622c5-2564-4d59-bed6-16fdb7c925f1', 'search': '?filters=agreementStatus.active%2CagreementStatus.draft%2CagreementStatus.in_negotiation%2CagreementStatus.requested&sort=name', @@ -25,10 +14,6 @@ const match = { } }; -const intl = { - 'formatMessage': jest.fn(), -}; - const agreement = { 'id': 'd5b622c5-2564-4d59-bed6-16fdb7c925f1', 'cancellationDeadline': '2021-10-10', @@ -72,230 +57,8 @@ const agreement = { 'relatedAgreements': [] }; -const agreementLines = { - 'hasLoaded': true, - 'isPending': false, - 'failed': false, - 'records': [], - 'successfulMutations': [], - 'failedMutations': [], - 'pendingMutations': [], - 'loadedAt': 'Fri Oct 22 2021 13:36:48 GMT+0100 (British Summer Time)', - 'url': 'https://folio-snapshot-okapi.dev.folio.org/erm/entitlements?filters=owner%3Dd5b622c5-2564-4d59-bed6-16fdb7c925f1&perPage=10&sort=resource.name&stats=true', - 'headers': 'Headers(undefined) {"content-type" => "application/json;charset=UTF-8"}', - 'httpStatus': 200, - 'other': { - 'pageSize': 10, - 'page': 1, - 'totalPages': 0, - 'meta': '{}', - 'totalRecords': 0, - 'total': 0 - }, - 'resource': 'agreementLines', - 'module': '@folio/agreements', - 'throwErrors': true -}; - -const agreementEresources = { - 'hasLoaded': true, - 'isPending': false, - 'failed': false, - 'records': [], - 'successfulMutations': [], - 'failedMutations': [], - 'pendingMutations': [], - 'loadedAt': 'Fri Oct 22 2021 13:36:48 GMT+0100 (British Summer Time)', - 'url': 'https://folio-snapshot-okapi.dev.folio.org/erm/sas/d5b622c5-2564-4d59-bed6-16fdb7c925f1/resources/current?perPage=10&sort=pti.titleInstance.name%3Basc&stats=true', - 'headers': 'Headers(undefined) {"content-type" => "application/json;charset=UTF-8"}', - 'httpStatus': 200, - 'other': { - 'pageSize': 10, - 'page': 1, - 'totalPages': 0, - 'meta': '{}', - 'totalRecords': 0, - 'total': 0 - }, - 'resource': 'agreementEresources', - 'module': '@folio/agreements', - 'throwErrors': true -}; - -const eresourcesFilterPath = 'current'; - -const interfaces = { - 'hasLoaded': false, - 'isPending': false, - 'failed': false, - 'records': [], - 'successfulMutations': [], - 'failedMutations': [], - 'pendingMutations': [] -}; - -const orderLines = { - 'hasLoaded': false, - 'isPending': false, - 'failed': false, - 'records': [], - 'successfulMutations': [], - 'failedMutations': [], - 'pendingMutations': [] -}; - -const settings = { - 'hasLoaded': true, - 'isPending': false, - 'failed': false, - 'records': [], - 'successfulMutations': [], - 'failedMutations': [], - 'pendingMutations': [], - 'loadedAt': 'Fri Oct 22 2021 13:36:48 GMT+0100 (British Summer Time)', - 'url': 'https://folio-snapshot-okapi.dev.folio.org/configurations/entries?query=(module=AGREEMENTS%20and%20configName=general)', - 'headers': 'Headers(undefined) {"content-type" => "application/json"}', - 'httpStatus': 200, - 'other': { - 'totalRecords': 0, - 'resultInfo': '{diagnostics: Array(0), facets: Array(0), totalReco…}' - }, - 'resource': 'settings', - 'module': '@folio/agreements', - 'throwErrors': true -}; - -const users = { - 'hasLoaded': false, - 'isPending': false, - 'failed': false, - 'records': [], - 'successfulMutations': [], - 'failedMutations': [], - 'pendingMutations': [] -}; - -const interfacesCredentials = { - 'hasLoaded': false, - 'isPending': false, - 'failed': false, - 'records': [], - 'successfulMutations': [], - 'failedMutations': [], - 'pendingMutations': [] -}; - -const query = { - 'query': '', - 'filters': 'agreementStatus.active,agreementStatus.draft,agreementStatus.in_negotiation,agreementStatus.requested', - 'sort': 'name' -}; - -const mutator = { - 'agreement': { - DELETE: () => {}, - PUT: () => {}, - POST: () => {}, - cancel: () => {}, - }, - 'agreementLines': { - DELETE: () => {}, - PUT: () => {}, - POST: () => {}, - cancel: () => {}, - }, - 'agreementEresources': { - DELETE: () => {}, - PUT: () => {}, - POST: () => {}, - cancel: () => {}, - }, - 'eresourcesFilterPath': { - update: () => {}, - replace: () => {}, - }, - 'interfaces': { - DELETE: () => {}, - PUT: () => {}, - POST: () => {}, - cancel: () => {}, - }, - 'orderLines': { - DELETE: () => {}, - PUT: () => {}, - POST: () => {}, - cancel: () => {}, - }, - 'settings': { - DELETE: () => {}, - PUT: () => {}, - POST: () => {}, - cancel: () => {}, - }, - 'supplementaryProperties': { - DELETE: () => {}, - PUT: () => {}, - POST: () => {}, - cancel: () => {}, - }, - 'terms': { - DELETE: () => {}, - PUT: () => {}, - POST: () => {}, - cancel: () => {}, - }, - 'users': { - DELETE: () => {}, - PUT: () => {}, - POST: () => {}, - cancel: () => {}, - }, - 'interfacesCredentials': { - DELETE: () => {}, - PUT: () => {}, - POST: () => {}, - cancel: () => {}, - }, - 'interfaceRecord': { - update: () => {}, - replace: () => {}, - }, - 'agreementEresourcesOffset': { - update: () => {}, - replace: () => {}, - }, - 'agreementLinesOffset': { - update: () => {}, - replace: () => {} - }, - 'query': { - update: () => {}, - replace: () => {}, - }, - 'tagSettings': { - DELETE: () => {}, - PUT: () => {}, - POST: () => {}, - cancel: () => {}, - } -}; - export { agreement, - agreementLines, - agreementEresources, - eresourcesFilterPath, - interfaces, - orderLines, - query, - settings, - users, - history, - tagsEnabled, location, - handlers, match, - intl, - interfacesCredentials, - mutator };