Skip to content

Commit

Permalink
UISACQCOMP-194 ECS - Support central ordering in the acq modules (#784)
Browse files Browse the repository at this point in the history
* UISACQCOMP-194 ECS - Support central ordering in the acq modules

* update part of components and hooks to support central ordering

* update filters to support tenant id prop

* update hooks and filters to support tenant id option

* Updates tests according to changes

* add unit test

* fix issue with closing the lookup

* update changelog

* remove redundant code

* update react query hook

* adapt more hooks and components to work with central ordering

* fix test

* tests

* remove unused imports

* one more hook adapted to central ordering enabled

* fix test

* resolve code smells
  • Loading branch information
usavkov-epam authored Jul 2, 2024
1 parent e6ed48a commit 05f04cf
Show file tree
Hide file tree
Showing 85 changed files with 1,389 additions and 599 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
* Correctly manage state setting in the `toggle` function of the `useToggle` hook. Refs UISACQCOMP-189.
* ECS - Support affiliations select for the inventory field (`<ConsortiumFieldInventory>`). Refs UISACQCOMP-190.
* Add Print routing list functionality. Refs UISACQCOMP-191.
* ECS - Support central ordering in the acq modules. Refs UISACQCOMP-194.

## [5.1.1](https://github.com/folio-org/stripes-acq-components/tree/v5.1.1) (2024-04-22)
[Full Changelog](https://github.com/folio-org/stripes-acq-components/compare/v5.1.0...v5.1.1)
Expand Down
39 changes: 19 additions & 20 deletions lib/AcqTagsFilter/AcqTagsFilter.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import React, { useMemo } from 'react';
import { useMemo } from 'react';
import PropTypes from 'prop-types';
import { get } from 'lodash';

import { MultiSelectionFilter } from '@folio/stripes/smart-components';
import { stripesConnect } from '@folio/stripes/core';

import { FilterAccordion } from '../FilterAccordion';
import {
configTags,
tagsResource,
} from '../manifests';
useTags,
useTagsConfigs,
} from '../hooks';

const getTagsOptions = resources => {
return get(resources, 'tagsFilter.records', []).map(tag => ({
const getTagsOptions = (tags) => {
return tags.map(tag => ({
label: tag.label,
value: tag.label,
}));
Expand All @@ -26,12 +24,18 @@ const AcqTagsFilter = ({
labelId,
name,
onChange,
resources,
tenantId,
}) => {
const tags = useMemo(() => getTagsOptions(resources), [resources]);
const { configs, isFetched } = useTagsConfigs({ tenantId });

const tagSettings = get(resources, ['configTags', 'records'], []);
const tagsEnabled = !tagSettings.length || tagSettings[0].value === 'true';
const tagsEnabled = isFetched && (!configs.length || configs[0].value === 'true');

const { tags } = useTags({
tenantId,
enabled: tagsEnabled,
});

const tagsOptions = useMemo(() => getTagsOptions(tags), [tags]);

if (!tagsEnabled) return false;

Expand All @@ -47,7 +51,7 @@ const AcqTagsFilter = ({
>
<MultiSelectionFilter
ariaLabelledBy={`accordion-toggle-button-${id}`}
dataOptions={tags}
dataOptions={tagsOptions}
disabled={disabled}
id="acq-tags-filter"
name={name}
Expand All @@ -58,11 +62,6 @@ const AcqTagsFilter = ({
);
};

AcqTagsFilter.manifest = Object.freeze({
tagsFilter: tagsResource,
configTags,
});

AcqTagsFilter.propTypes = {
activeFilters: PropTypes.arrayOf(PropTypes.string),
closedByDefault: PropTypes.bool,
Expand All @@ -71,7 +70,7 @@ AcqTagsFilter.propTypes = {
labelId: PropTypes.string,
name: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
resources: PropTypes.object.isRequired,
tenantId: PropTypes.string,
};

AcqTagsFilter.defaultProps = {
Expand All @@ -80,4 +79,4 @@ AcqTagsFilter.defaultProps = {
labelId: 'stripes-acq-components.filter.tags',
};

export default stripesConnect(AcqTagsFilter);
export default AcqTagsFilter;
26 changes: 22 additions & 4 deletions lib/AcqTagsFilter/AcqTagsFilter.test.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,46 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import {
render,
screen,
} from '@testing-library/react';
import user from '@testing-library/user-event';

import {
useTags,
useTagsConfigs,
} from '../hooks';
import AcqTagsFilter from './AcqTagsFilter';

jest.mock('../hooks', () => ({
...jest.requireActual('../hooks'),
useTags: jest.fn(),
useTagsConfigs: jest.fn(),
}));

const TAGS_FILTER_LABEL = 'stripes-acq-components.filter.tags';
const TAGS = [{
id: 'tag1',
label: 'tag 1',
}];

const renderAcqTagsFilter = (props = {}) => (render(
const renderAcqTagsFilter = (props = {}) => render(
<AcqTagsFilter
id="tags-filter"
name="tags-filter"
{...props}
/>,
));
);

describe('AcqTagsFilter', () => {
const onChange = jest.fn();

beforeEach(() => {
onChange.mockClear();
useTags
.mockClear()
.mockReturnValue({ tags: TAGS });
useTagsConfigs
.mockClear()
.mockReturnValue({ configs: [], isFetched: true });
});

it('should display Tags filter', () => {
Expand Down
19 changes: 6 additions & 13 deletions lib/AcqUnitFilter/AcqUnitFilterContainer.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,22 @@
import React from 'react';
import PropTypes from 'prop-types';

import { stripesConnect } from '@folio/stripes/core';

import { acqUnitsManifest } from '../manifests';
import { useAcquisitionUnits } from '../hooks';
import AcqUnitFilter from './AcqUnitFilter';

const AcqUnitFilterContainer = ({ resources, ...rest }) => {
const acqUnitsRecords = resources.acqUnits?.records;
const AcqUnitFilterContainer = ({ tenantId, ...rest }) => {
const { acquisitionsUnits } = useAcquisitionUnits({ tenantId });

return (
<AcqUnitFilter
labelId="stripes-acq-components.filter.acqUnit"
{...rest}
acqUnits={acqUnitsRecords}
acqUnits={acquisitionsUnits}
/>
);
};

AcqUnitFilterContainer.manifest = Object.freeze({
acqUnits: acqUnitsManifest,
});

AcqUnitFilterContainer.propTypes = {
resources: PropTypes.object.isRequired,
tenantId: PropTypes.string,
};

export default stripesConnect(AcqUnitFilterContainer);
export default AcqUnitFilterContainer;
91 changes: 30 additions & 61 deletions lib/AcqUnits/AcqUnitsField/AcqUnitsFieldContainer.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
import React, { useEffect, useState } from 'react';
import compact from 'lodash/compact';
import difference from 'lodash/difference';
import uniq from 'lodash/uniq';
import PropTypes from 'prop-types';
import { get, uniq, compact, difference } from 'lodash';

import {
stripesConnect,
stripesShape,
} from '@folio/stripes/core';

import { LIMIT_MAX } from '../../constants';
import { baseManifest } from '../../manifests';
import { usePrevious } from '../../utils';
import { useStripes } from '@folio/stripes/core';

import { useAcquisitionUnits } from '../../hooks';
import { useAcqUnitsMemberships } from '../hooks';
import AcqUnitsField from './AcqUnitsField';

export const buildAcqUnitsQuery = (memberUnits, preselectedUnits, isEdit) => {
Expand All @@ -32,76 +28,49 @@ export const buildAcqUnitsQuery = (memberUnits, preselectedUnits, isEdit) => {
};

const AcqUnitsFieldContainer = ({
name, mutator, stripes, preselectedUnits, perm, isEdit, isFinal, id,
name,
preselectedUnits,
perm,
isEdit,
isFinal,
id,
tenantId,
}) => {
const userId = get(stripes, 'user.user.id');
const prevUserId = usePrevious(userId);
const [units, setUnits] = useState([]);

useEffect(() => {
if (userId !== prevUserId) {
mutator.acqUnitMemberships.reset();
mutator.acqUnitsEdit.reset();
const stripes = useStripes();
const userId = stripes?.user?.user?.id;

mutator.acqUnitMemberships.GET({
params: {
limit: LIMIT_MAX,
query: `userId==${userId}`,
},
}).then(memberships => {
const query = buildAcqUnitsQuery(
memberships.map(({ acquisitionsUnitId }) => acquisitionsUnitId),
preselectedUnits,
isEdit,
);
const { acquisitionsUnitMemberships } = useAcqUnitsMemberships(userId, { tenantId });

if (query.length) {
mutator.acqUnitsEdit.GET({
params: {
limit: LIMIT_MAX,
query,
},
}).then(setUnits);
}
});
}
const { acquisitionsUnits } = useAcquisitionUnits({
tenantId,
searchParams: {
query: buildAcqUnitsQuery(
acquisitionsUnitMemberships.map(({ acquisitionsUnitId }) => acquisitionsUnitId),
preselectedUnits,
isEdit,
),
},
});

return (
<AcqUnitsField
id={id}
name={name}
units={units}
units={acquisitionsUnits}
disabled={perm ? !stripes.hasPerm(perm) : false}
isFinal={isFinal}
/>
);
};

AcqUnitsFieldContainer.manifest = Object.freeze({
acqUnitMemberships: {
...baseManifest,
path: 'acquisitions-units/memberships',
records: 'acquisitionsUnitMemberships',
accumulate: true,
},
acqUnitsEdit: {
...baseManifest,
path: 'acquisitions-units/units',
records: 'acquisitionsUnits',
accumulate: true,
},
});

AcqUnitsFieldContainer.propTypes = {
stripes: stripesShape.isRequired,
mutator: PropTypes.object.isRequired,
name: PropTypes.string,
preselectedUnits: PropTypes.arrayOf(PropTypes.string),
perm: PropTypes.string,
preselectedUnits: PropTypes.arrayOf(PropTypes.string),
id: PropTypes.string,
isEdit: PropTypes.bool,
isFinal: PropTypes.bool,
id: PropTypes.string,
tenantId: PropTypes.string,
};

AcqUnitsFieldContainer.defaultProps = {
Expand All @@ -112,4 +81,4 @@ AcqUnitsFieldContainer.defaultProps = {
isFinal: false,
};

export default stripesConnect(AcqUnitsFieldContainer);
export default AcqUnitsFieldContainer;
51 changes: 30 additions & 21 deletions lib/AcqUnits/AcqUnitsField/AcqUnitsFieldContainer.test.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
import React from 'react';
import { render, waitFor } from '@testing-library/react';
import { render } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';

import { useAcquisitionUnits } from '../../hooks';
import { useAcqUnitsMemberships } from '../hooks';
import AcqUnitsField from './AcqUnitsField';
import AcqUnitsFieldContainer from './AcqUnitsFieldContainer';

jest.mock('../../hooks', () => ({
...jest.requireActual('../../hooks'),
useAcquisitionUnits: jest.fn(),
}));
jest.mock('../hooks', () => ({
...jest.requireActual('../hooks'),
useAcqUnitsMemberships: jest.fn(),
}));
jest.mock('./AcqUnitsField', () => {
return jest.fn(() => 'AcqUnitsField');
});

const MEMBERSHIP = [{
'id': '3b552ce3-da49-49be-a1f8-a7a6617f16cc',
'userId': 'e5e96ab2-694f-5222-b616-34befa6125bb',
Expand All @@ -20,40 +33,36 @@ const UNITS = [{
'protectDelete': true,
}];

jest.mock('./AcqUnitsField', () => {
return jest.fn(() => 'AcqUnitsField');
});
const defaultProps = {
id: 'units',
name: 'units',
};

const renderComponent = (props = {}) => (render(
<MemoryRouter>
<AcqUnitsFieldContainer
id="units"
name="units"
{...defaultProps}
{...props}
/>
</MemoryRouter>,
));

describe('AcqUnitsFieldContainer', () => {
const mutator = {
acqUnitMemberships: {
GET: jest.fn().mockResolvedValue(MEMBERSHIP),
reset: jest.fn(),
},
acqUnitsEdit: {
GET: jest.fn().mockResolvedValue(UNITS),
reset: jest.fn(),
},
};

beforeEach(() => {
AcqUnitsField.mockClear();
useAcquisitionUnits
.mockClear()
.mockReturnValue({ acquisitionsUnits: UNITS });
useAcqUnitsMemberships
.mockClear()
.mockReturnValue({ acquisitionsUnitMemberships: MEMBERSHIP });
});

it('should load and pass units', async () => {
it('should load and pass units', () => {
const preselectedUnits = ['1ed3cc28-c0da-423e-b9d4-5b9917b2fa69'];

renderComponent({ mutator, preselectedUnits });
await waitFor(() => expect(AcqUnitsField.mock.calls[1][0].units).toEqual(UNITS));
renderComponent({ preselectedUnits });

expect(AcqUnitsField.mock.calls[0][0].units).toEqual(UNITS);
});
});
Loading

0 comments on commit 05f04cf

Please sign in to comment.