Skip to content

Commit 806f4be

Browse files
authored
Merge pull request #1372 from folio-org/release/11.1.1
Release 11.1.1
2 parents ce9bd04 + 80dd6e4 commit 806f4be

File tree

24 files changed

+245
-180
lines changed

24 files changed

+245
-180
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Change history for ui-agreements
22

3+
## 11.1.1 2024-11-29
4+
* ERM-3449 The Agreement content filter is not set back to original empty selection state
5+
* ERM-3392 Agreements: Changes to the field content type are not saved, but a success message is displayed
6+
* ERM 3390 Agreements > Show columns: Name column should not be in the list of unselectable columns
7+
38
## 11.1.0 2024-10-31
49
* ERM-3375 Update module license and guidance for ui-agreements
510
* ERM-3365 UI Agreements does not display monograph information if TitleInstance.Type.label is changed

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@folio/agreements",
3-
"version": "11.1.0",
3+
"version": "11.1.1",
44
"description": "ERM agreement functionality for Stripes",
55
"main": "src/index.js",
66
"publishConfig": {
@@ -344,5 +344,8 @@
344344
"title": "Print title"
345345
}
346346
]
347+
},
348+
"resolutions": {
349+
"nwsapi" : "2.2.13"
347350
}
348351
}

src/components/AgreementContentFilter/AgreementContentFilter.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ const AgreementContentFieldArray = ({ handleSubmit }) => {
7878
}}
7979
/>
8080
<Field
81+
key={values?.agreementContent[index]?.content}
8182
component={MultiSelection}
8283
dataOptions={translatedContentOptions}
8384
id={`${filter}-content-multi-select`}

src/components/AgreementSections/ContentTypesFieldArray/ContentTypesFieldArray.js

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
import PropTypes from 'prop-types';
21
import { useEffect, useState, useRef } from 'react';
2+
import PropTypes from 'prop-types';
3+
4+
import isEqual from 'lodash/isEqual';
5+
36
import { FormattedMessage } from 'react-intl';
47
import { Field } from 'react-final-form';
5-
import { getRefdataValuesByDesc, requiredValidator, usePrevious } from '@folio/stripes-erm-components';
8+
69
import {
710
Button,
811
Col,
@@ -13,18 +16,9 @@ import {
1316
} from '@folio/stripes/components';
1417
import { useKiwtFieldArray } from '@k-int/stripes-kint-components';
1518

16-
import { useAgreementsRefdata } from '../../../hooks';
17-
18-
// Utility function to check if two arrays of scalars contain the same items (Order does not count)
19-
const arraysAreEqual = (a, b) => {
20-
if (a.length !== b.length) {
21-
return false;
22-
}
19+
import { getRefdataValuesByDesc, requiredValidator, usePrevious } from '@folio/stripes-erm-components';
2320

24-
return a.every(element => {
25-
return b.includes(element);
26-
});
27-
};
21+
import { useAgreementsRefdata } from '../../../hooks';
2822

2923
const [
3024
AGREEMENT_CONTENT_TYPE
@@ -40,8 +34,12 @@ const ContentTypesFieldArray = ({
4034
AGREEMENT_CONTENT_TYPE,
4135
]
4236
});
43-
const contentTypeValues = getRefdataValuesByDesc(refdata, AGREEMENT_CONTENT_TYPE);
44-
const agreementContentType = contentTypeValues.map(ct => ({ value: ct.value, label: ct.label }));
37+
const contentTypeSelectOptions = getRefdataValuesByDesc(refdata, AGREEMENT_CONTENT_TYPE)
38+
.map(ct => ({
39+
value: ct.id, // Map to id for submittal purposes
40+
label: ct.label
41+
}));
42+
4543
const { items, onAddField, onDeleteField } = useKiwtFieldArray(name);
4644
const [contentTypeInUse, setContentTypeInUse] = useState([]);
4745
const contentTypeRefs = useRef([]);
@@ -51,12 +49,13 @@ const ContentTypesFieldArray = ({
5149
const previousCount = usePrevious(itemsLength);
5250

5351
useEffect(() => {
54-
const newContentTypeInUse = items.map(i => i?.contentType?.value).filter(x => !!x);
55-
if (!arraysAreEqual(contentTypeInUse, newContentTypeInUse)) {
52+
const newContentTypeInUse = items.map(i => i?.contentType?.id).filter(x => !!x);
53+
if (!isEqual(contentTypeInUse, newContentTypeInUse)) {
5654
setContentTypeInUse(newContentTypeInUse);
5755
}
5856
}, [items, contentTypeInUse]);
5957

58+
6059
useEffect(() => {
6160
// the second conditional is checking if the current field to be focused is the default content type field.
6261
if (contentTypeRefs.current.length > 1 || (contentTypeRefs.current.length > 0 && previousCount - itemsLength === 1)) {
@@ -73,21 +72,29 @@ const ContentTypesFieldArray = ({
7372

7473
const renderContentTypes = () => (
7574
items.map((act, index) => {
76-
const dataOptions = agreementContentType.filter(ct => !contentTypeInUse.includes(ct.value) || ct.value === act.contentType?.value);
75+
const dataOptions = contentTypeSelectOptions.filter(ct => !contentTypeInUse.includes(ct.value) || ct.value === act.contentType?.id);
76+
7777
return (
7878
<div
7979
key={`${act?.contentType?.id}`}
8080
data-testid={`contentTypesFieldArray[${index}]`}
8181
>
8282
<Row>
8383
<Col xs={11}>
84+
{/*
85+
* This select will ONLY change the id of the refdata,
86+
* and the bind will happen from that. That will make
87+
* the PUT look a little funky as it will have the old
88+
* label/value information, but prevents us from having
89+
* to do loads of eaxtra tweaking at the field level
90+
*/}
8491
<Field
8592
component={Select}
8693
dataOptions={dataOptions}
8794
id="content-type-field-array"
8895
index={index}
8996
inputRef={addToRefs}
90-
name={`${name}[${index}].contentType.value`}
97+
name={`${name}[${index}].contentType.id`}
9198
placeholder=" "
9299
validate={requiredValidator}
93100
/>
Lines changed: 48 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,85 @@
1-
21
import { waitFor } from '@folio/jest-config-stripes/testing-library/react';
2+
33
import { Button, Dropdown, MultiColumnList, renderWithIntl } from '@folio/stripes-erm-testing';
4-
import { MemoryRouter } from 'react-router-dom';
4+
55
import translationsProperties from '../../../../test/helpers';
66
import CoveredEResourcesList from './CoveredEResourcesList';
77
import agreement from './testResources';
88

9-
jest.mock('../../IfEResourcesEnabled', () => ({ children }) => {
10-
return typeof children === 'function' ? children({ isEnabled: true }) : children;
11-
});
12-
13-
// Use manual mocks set up in hooks/__mocks__ folder
14-
jest.mock('../../../hooks');
9+
// Use manual mocks set up in hooks/__mocks__ folder (small correction to the way this was done before)
10+
jest.mock('../../../hooks/useAgreementsSettings');
11+
jest.mock('../../../hooks/useEresourcesEnabled');
1512

1613
const handlers = {
1714
onFilterEResources: jest.fn(),
1815
onExportEResourcesAsJSON: jest.fn().mockImplementation(() => Promise.resolve()),
1916
onExportEResourcesAsKBART: jest.fn().mockImplementation(() => Promise.resolve()),
2017
};
2118

19+
// TODO there are 2 warnings when running this test... contentData ends up as a boolean not an array --
20+
// maybe needs mocking fetchMultiplePages
21+
// received NaN for the children attribute within PrevNextPagination, better mocking needed there too?
2222
describe('CoveredEResourcesList', () => {
23-
beforeEach(() => {
24-
renderWithIntl(
25-
<MemoryRouter>
23+
beforeEach(async () => {
24+
// This is blowing my mind... I do not understand why this needs to be wrapped in a waitFor
25+
await waitFor(() => {
26+
renderWithIntl(
2627
<CoveredEResourcesList
2728
agreement={agreement}
2829
eresourcesFilterPath="current"
2930
{...handlers}
30-
/>
31-
</MemoryRouter>,
32-
translationsProperties
33-
);
34-
});
35-
36-
test('renders the expected filter buttons', async () => {
37-
await Button('Current').exists();
38-
await Button('Future').exists();
39-
await Button('Dropped').exists();
40-
await Button('All').exists();
31+
/>,
32+
translationsProperties
33+
);
34+
});
4135
});
4236

43-
test('clicking the filter buttons should call the onFilterEResources callback', async () => {
44-
await waitFor(async () => {
45-
await Button('Future').click();
37+
describe.each(['Future', 'Current', 'Dropped', 'All'])('%s filter button', (filterLabel) => {
38+
test(`renders the ${filterLabel} button`, async () => {
39+
await waitFor(async () => {
40+
await Button(filterLabel).exists();
41+
});
4642
});
4743

48-
await waitFor(async () => {
49-
expect(handlers.onFilterEResources.mock.calls.length).toBe(1);
50-
});
51-
52-
await waitFor(async () => {
53-
await Button('Dropped').click();
54-
});
44+
describe(`clicking the ${filterLabel} button`, () => {
45+
beforeEach(async () => {
46+
handlers.onFilterEResources.mockClear();
5547

56-
await waitFor(async () => {
57-
expect(handlers.onFilterEResources.mock.calls.length).toBe(2);
58-
});
48+
expect(handlers.onFilterEResources.mock.calls.length).toBe(0);
5949

60-
await waitFor(async () => {
61-
await Button('All').click();
62-
});
50+
await waitFor(async () => {
51+
await Button(filterLabel).click();
52+
});
53+
});
6354

64-
await waitFor(async () => {
65-
expect(handlers.onFilterEResources.mock.calls.length).toBe(3);
55+
test('onFilterEResources callback called', async () => {
56+
await waitFor(async () => {
57+
expect(handlers.onFilterEResources.mock.calls.length).toBe(1);
58+
});
59+
});
6660
});
6761
});
6862

6963
test('renders the Export dropdown', async () => {
70-
await Dropdown('Export as...').exists();
71-
});
72-
73-
test('choosing the dropdown options', async () => {
7464
await waitFor(async () => {
75-
await Dropdown('Export as...').choose('JSON');
65+
await Dropdown('Export as...').exists();
7666
});
67+
});
7768

78-
await waitFor(async () => {
79-
expect(handlers.onExportEResourcesAsJSON.mock.calls.length).toBe(1);
69+
describe.each([
70+
{ dropdownChoice: 'JSON', mockHandler: handlers.onExportEResourcesAsJSON },
71+
{ dropdownChoice: 'KBART', mockHandler: handlers.onExportEResourcesAsKBART }
72+
])('choosing export as $dropdownChoice', ({ dropdownChoice, mockHandler }) => {
73+
beforeEach(async () => {
74+
await waitFor(async () => {
75+
await Dropdown('Export as...').choose(dropdownChoice);
76+
});
8077
});
8178

82-
await waitFor(async () => {
83-
await Dropdown('Export as...').choose('KBART');
84-
});
85-
86-
await waitFor(async () => {
87-
expect(handlers.onExportEResourcesAsKBART.mock.calls.length).toBe(1);
79+
test('correct onExportResources handler called', async () => {
80+
await waitFor(async () => {
81+
expect(mockHandler.mock.calls.length).toBe(1);
82+
});
8883
});
8984
});
9085

@@ -100,4 +95,3 @@ describe('CoveredEResourcesList', () => {
10095
await MultiColumnList({ columns: ['Name', 'eISSN/ISSN', 'Platform', 'Package', 'Coverage', ' ', 'Access start', 'Access end'] }).exists();
10196
});
10297
});
103-

src/components/AgreementSections/Lines/Lines.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ const Lines = ({
7171
</Button>
7272
<ColumnManagerMenu
7373
columnMapping={LINE_LISTING_COLUMN_MAPPING}
74+
excludeColumns={['name']}
7475
prefix="line-listing"
7576
toggleColumn={toggleColumn}
7677
visibleColumns={visibleColumns}

src/components/views/AgreementLines/AgreementLines.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ const AgreementLines = ({
9090
return (
9191
<ColumnManagerMenu
9292
columnMapping={AGREEMENT_LINES_COLUMN_MAPPING}
93+
excludeColumns={['name']}
9394
prefix="agreement-lines"
9495
toggleColumn={toggleColumn}
9596
visibleColumns={visibleColumns}

src/components/views/Agreements/Agreements.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ const Agreements = ({
142142
</IfPermission>
143143
<ColumnManagerMenu
144144
columnMapping={AGREEMENTS_COLUMN_MAPPING}
145+
excludeColumns={['name']}
145146
prefix="agreements-list"
146147
toggleColumn={toggleColumn}
147148
visibleColumns={visibleColumns}

src/hooks/__mocks__/index.js

Lines changed: 0 additions & 7 deletions
This file was deleted.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
module.exports = jest.fn(() => {
2+
return (
3+
{
4+
parsedSettings: {
5+
pageSize: {
6+
agreementEresources: 12
7+
}
8+
}
9+
}
10+
);
11+
});

0 commit comments

Comments
 (0)