Skip to content

Commit

Permalink
ERM-2533: Refactor interfaces code to react-query (#1174)
Browse files Browse the repository at this point in the history
* feat: Interfaces (!WIP!)

Initial steps to moving interfaces over to react-query, currently not functional -- DO NOT MERGE AS IS

refs ERM-2533

* feat: Interfaces

Wired up interfaces to new hooks, avoiding stripes-connect

ERM-2533

* test: Tests

Fixed tests

ERM-2533
  • Loading branch information
EthanFreestone committed Jan 24, 2023
1 parent 4be434b commit f22546e
Show file tree
Hide file tree
Showing 6 changed files with 14 additions and 376 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@ export default class Organizations extends React.Component {
}),
),
}).isRequired,
handlers: PropTypes.shape({
onFetchCredentials: PropTypes.func,
}),
id: PropTypes.string,
};

Expand All @@ -52,7 +49,6 @@ export default class Organizations extends React.Component {
<ViewOrganizationCard
key={`${org.orgsUuid}`}
data-test-organizations-org
fetchCredentials={this.props.handlers.onFetchCredentials}
headerStart={
<span>
<AppIcon app="organizations" size="small">
Expand All @@ -66,6 +62,7 @@ export default class Organizations extends React.Component {
}
interfaces={interfaces}
note={note}
org={org}
roles={roles}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,6 @@ const agreement = {
]
};

const handlers = {
onFetchCredentials: () => { }
};

let renderComponent;

describe('Organizations', () => {
Expand All @@ -174,7 +170,6 @@ describe('Organizations', () => {
renderComponent = renderWithIntl(
<Organizations
agreement={agreement}
handlers={handlers}
id="organizations"
/>,
translationsProperties
Expand All @@ -196,7 +191,6 @@ describe('Organizations', () => {
renderComponent = renderWithIntl(
<Organizations
agreement={{}}
handlers={handlers}
id="organizations"
/>,
translationsProperties
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
88 changes: 13 additions & 75 deletions src/routes/AgreementViewRoute/AgreementViewRoute.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 { 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();

Expand All @@ -52,6 +47,11 @@ 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']))
Expand Down Expand Up @@ -200,32 +200,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 */
})),
}));

Expand Down Expand Up @@ -281,10 +267,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}`);
};
Expand Down Expand Up @@ -319,7 +301,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 }),
Expand All @@ -331,36 +312,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({
Expand All @@ -374,19 +325,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;
47 changes: 0 additions & 47 deletions src/routes/AgreementViewRoute/AgreementViewRoute.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -39,10 +28,6 @@ const FilterEResourceButton = (props) => {
return <Button onClick={props.handlers.onFilterEResources}>FilterEResourceButton</Button>;
};

const FetchCredentialsButton = (props) => {
return <Button onClick={props.handlers.onFetchCredentials}>FetchCredentialsButton</Button>;
};

const EditButton = (props) => {
return <Button onClick={props.handlers.onEdit}>EditButton</Button>;
};
Expand Down Expand Up @@ -89,12 +74,6 @@ FilterEResourceButton.propTypes = {
}),
};

FetchCredentialsButton.propTypes = {
handlers: PropTypes.shape({
onFetchCredentials: PropTypes.func,
}),
};

EditButton.propTypes = {
handlers: PropTypes.shape({
onEdit: PropTypes.func,
Expand Down Expand Up @@ -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'),
Expand All @@ -152,7 +130,6 @@ jest.mock('../../components/views/Agreement', () => {
<AgreementLineButton {...props} />
<NeedMoreLinesButton {...props} />
<FilterEResourceButton {...props} />
<FetchCredentialsButton {...props} />
<EditButton {...props} />
<NeedMoreEResourcesButton {...props} />
<ToggleTagsButton {...props} />
Expand All @@ -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 }));
Expand Down Expand Up @@ -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();
Expand Down
Loading

0 comments on commit f22546e

Please sign in to comment.