diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9102524b..4563b84b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,7 @@
* COUNTER statistics: Show the COUNTER release version for reports in an additional column ([UIEUS-368](https://folio-org.atlassian.net/browse/UIEUS-368))
* Leverage `yarn.lock` ([UIEUS-377](https://folio-org.atlassian.net/browse/UIEUS-377))
* COUNTER 5.1 Support: Harvesting configuration for usage data providers ([UIEUS-357](https://folio-org.atlassian.net/browse/UIEUS-357))
+* Add filter for COUNTER report release ([UIEUS-374](https://folio-org.atlassian.net/browse/UIEUS-374))
## [9.0.0](https://github.com/folio-org/ui-erm-usage/tree/v9.0.0) (2024-04-17)
* *BREAKING* Use `multipart/form-data` to upload COUNTER reports ([UIEUS-353](https://folio-org.atlassian.net/browse/UIEUS-353))
diff --git a/src/components/UDPFilters/UDPFilters.js b/src/components/UDPFilters/UDPFilters.js
index 00d26ec4..fabc0dc6 100644
--- a/src/components/UDPFilters/UDPFilters.js
+++ b/src/components/UDPFilters/UDPFilters.js
@@ -30,6 +30,7 @@ const UDPFilters = ({
tags: [],
errorCodes: [],
reportTypes: [],
+ reportReleases: [],
});
const isFilterDefinedLocally = filter => {
@@ -134,94 +135,31 @@ const UDPFilters = ({
);
};
- const renderTagsFilter = () => {
- const tagFilters = activeFilters.tags || [];
-
- return (
- 0}
- header={FilterAccordionHeader}
- label={}
- onClearFilter={() => {
- filterHandlers.clearGroup('tags');
- }}
- separator={false}
- >
- filterHandlers.state({
- ...activeFilters,
- tags: e.values
- })
- }
- selectedValues={tagFilters}
- />
-
- );
- };
-
- const renderErrorCodesFilter = () => {
- const errorCodesFilters = activeFilters.errorCodes || [];
-
- return (
- 0}
- header={FilterAccordionHeader}
- label={}
- onClearFilter={() => {
- filterHandlers.clearGroup('errorCodes');
- }}
- separator={false}
- >
- filterHandlers.state({
- ...activeFilters,
- errorCodes: e.values
- })
- }
- selectedValues={errorCodesFilters}
- />
-
- );
- };
-
- const renderReportTypesFiler = () => {
- const reportTypesFilters = activeFilters.reportTypes || [];
+ const renderMultiSelectionFilter = (key, closedByDefault = true) => {
+ const groupFilters = activeFilters[key] || [];
return (
0}
+ closedByDefault={closedByDefault}
+ displayClearButton={groupFilters.length > 0}
header={FilterAccordionHeader}
- label={}
- onClearFilter={() => {
- filterHandlers.clearGroup('reportTypes');
- }}
+ id={`filter-accordion-${key}`}
+ label={}
+ onClearFilter={() => { filterHandlers.clearGroup(key); }}
separator={false}
>
filterHandlers.state({
- ...activeFilters,
- reportTypes: e.values
- })
- }
- selectedValues={reportTypesFilters}
+ ariaLabelledBy={`clickable-filter-${key}`}
+ dataOptions={filterState[key]}
+ id={`filter-${key}`}
+ name={key}
+ onChange={group => {
+ filterHandlers.state({
+ ...activeFilters,
+ [group.name]: group.values
+ });
+ }}
+ selectedValues={groupFilters}
/>
);
@@ -232,10 +170,11 @@ const UDPFilters = ({
{renderCheckboxFilter('harvestingStatus')}
{renderCheckboxFilter('harvestVia')}
{renderCheckboxFilter('aggregators', true)}
- {renderReportTypesFiler()}
+ {renderMultiSelectionFilter('reportTypes')}
+ {renderMultiSelectionFilter('reportReleases')}
{renderCheckboxFilter('hasFailedReport', true)}
- {renderTagsFilter()}
- {renderErrorCodesFilter()}
+ {renderMultiSelectionFilter('tags')}
+ {renderMultiSelectionFilter('errorCodes')}
);
};
diff --git a/src/components/views/UDPs.test.js b/src/components/views/UDPs.test.js
index 9dbca2bb..c2f16122 100644
--- a/src/components/views/UDPs.test.js
+++ b/src/components/views/UDPs.test.js
@@ -1,4 +1,4 @@
-import { screen } from '@folio/jest-config-stripes/testing-library/react';
+import { screen, within } from '@folio/jest-config-stripes/testing-library/react';
import userEvent from '@folio/jest-config-stripes/testing-library/user-event';
import { MemoryRouter } from 'react-router-dom';
@@ -32,6 +32,7 @@ const renderUDPs = (stripes, props, udpsData, rerender) => renderWithIntl(
tags: [],
errorCodes: ['3030', '3031', 'other'],
reportTypes: ['BR', 'TR'],
+ reportReleases: ['5.0', '4'],
}}
selectedRecordId=""
onNeedMoreData={jest.fn()}
@@ -136,28 +137,36 @@ describe('UDPs SASQ View', () => {
});
describe('check filters', () => {
- it('harvesting status filter should be present', () => {
- expect(document.querySelector('#filter-accordion-harvestingStatus')).toBeInTheDocument();
+ it('should be present the harvesting status filter', () => {
+ expect(screen.getByRole('button', { name: 'Harvesting status filter list' })).toBeInTheDocument();
});
- it('harvestVia filter should be present', () => {
- expect(document.querySelector('#filter-accordion-harvestVia')).toBeInTheDocument();
+ it('should be present the harvestVia filter', () => {
+ expect(screen.getByRole('button', { name: 'Harvest via filter list' })).toBeInTheDocument();
});
- it('aggregators filter should be present', () => {
- expect(document.querySelector('#filter-accordion-aggregators')).toBeInTheDocument();
+ it('should be present the aggregators filter', () => {
+ expect(screen.getByRole('button', { name: 'Aggregators filter list' })).toBeInTheDocument();
});
- it('report types filter should be present', () => {
- expect(document.querySelector('#clickable-report-types-filter')).toBeInTheDocument();
+ it('should be present the report types filter', () => {
+ expect(screen.getByRole('button', { name: 'Report types filter list' })).toBeInTheDocument();
});
- it('has failed reports filter should be present', () => {
- expect(document.querySelector('#filter-accordion-hasFailedReport')).toBeInTheDocument();
+ it('should be present the report releases filter', () => {
+ expect(screen.getByRole('button', { name: 'Report releases filter list' })).toBeInTheDocument();
});
- it('error codes filter should be present', () => {
- expect(document.querySelector('#clickable-error-codes-filter')).toBeInTheDocument();
+ it('should be present the has failed reports filter', () => {
+ expect(screen.getByRole('button', { name: 'Has failed report(s) filter list' })).toBeInTheDocument();
+ });
+
+ it('should be present the tags filter', () => {
+ expect(screen.getByRole('button', { name: 'Tags filter list' })).toBeInTheDocument();
+ });
+
+ it('should be present the error codes filter', () => {
+ expect(screen.getByRole('button', { name: 'Error codes filter list' })).toBeInTheDocument();
});
it('reset all button should be present', () => {
@@ -172,6 +181,35 @@ describe('UDPs SASQ View', () => {
expect(document.querySelector('#clickable-search-udps')).toBeInTheDocument();
});
+ test('select and clear report release filter values', async () => {
+ const reportReleaseAccordion = screen.getByRole('button', { name: 'Report releases filter list' });
+ expect(reportReleaseAccordion).toBeInTheDocument();
+ await userEvent.click(reportReleaseAccordion);
+
+ const multiselects = screen.getAllByLabelText('open menu');
+ const multiselectReportReleases = multiselects.find(btn => btn.getAttribute('aria-controls') === 'multiselect-option-list-filter-reportReleases');
+ expect(multiselectReportReleases).toBeInTheDocument();
+ await userEvent.click(multiselectReportReleases);
+
+ const listboxes = screen.getAllByRole('listbox');
+ const reportReleasesList = listboxes.find(ul => ul.getAttribute('id') === 'multiselect-option-list-filter-reportReleases');
+ expect(within(reportReleasesList).getByRole('option', { name: /5.0/ })).toBeInTheDocument();
+ expect(within(reportReleasesList).getByRole('option', { name: /4/ })).toBeInTheDocument();
+ await userEvent.click(within(reportReleasesList).getByRole('option', { name: /4/ }));
+
+ const searchboxes = screen.getAllByRole('searchbox');
+ const searchboxReportReleases = searchboxes.find(btn => btn.getAttribute('aria-describedby') === 'multi-describe-control-filter-reportReleases');
+ expect(searchboxReportReleases).toBeInTheDocument();
+ expect(within(searchboxReportReleases).getByText('4')).toBeInTheDocument();
+ expect(within(searchboxReportReleases).queryByText('5.0')).not.toBeInTheDocument();
+
+ const clearReportReleasesButton = screen.getByRole('button', { name: /Clear selected Report releases filters/i });
+ expect(clearReportReleasesButton).toBeInTheDocument();
+ await userEvent.click(clearReportReleasesButton);
+
+ expect(within(searchboxReportReleases).queryByText('4')).not.toBeInTheDocument();
+ });
+
it('columns of MCL should be present', async () => {
const searchFieldInput = document.querySelector('#input-udp-search');
expect(searchFieldInput).toBeInTheDocument();
diff --git a/src/routes/UDPsRoute.js b/src/routes/UDPsRoute.js
index f0de70ca..85a8e8e8 100644
--- a/src/routes/UDPsRoute.js
+++ b/src/routes/UDPsRoute.js
@@ -62,6 +62,11 @@ class UDPsRoute extends React.Component {
path: 'counter-reports/reports/types',
records: 'reportTypes'
},
+ reportReleases: {
+ type: 'okapi',
+ path: 'counter-reports/reports/releases',
+ records: 'reportReleases'
+ },
numFiltersLoaded: { initialValue: 1 }, // will be incremented as each filter loads
initializedFilterConfig: { initialValue: false },
query: {
@@ -193,7 +198,8 @@ class UDPsRoute extends React.Component {
aggregators: get(resources, 'aggregatorSettings.records', []),
tags: get(resources, 'tags.records', []),
errorCodes: get(resources, 'errorCodes.records', []),
- reportTypes: get(resources, 'reportTypes.records', [])
+ reportTypes: get(resources, 'reportTypes.records', []),
+ reportReleases: get(resources, 'reportReleases.records', []),
}}
selectedRecordId={match.params.id}
onNeedMoreData={this.handleNeedMoreData}
diff --git a/src/util/data/filterGroups.js b/src/util/data/filterGroups.js
index 54937d3f..8a11313b 100644
--- a/src/util/data/filterGroups.js
+++ b/src/util/data/filterGroups.js
@@ -55,6 +55,13 @@ const filterGroups = [
cql: 'reportTypes',
operator: '=',
values: [],
+ },
+ {
+ label: 'Report Releases',
+ name: 'reportReleases',
+ cql: 'reportReleases',
+ operator: '=',
+ values: [],
}
];
diff --git a/translations/ui-erm-usage/en.json b/translations/ui-erm-usage/en.json
index b5615f55..88fdce07 100644
--- a/translations/ui-erm-usage/en.json
+++ b/translations/ui-erm-usage/en.json
@@ -35,6 +35,7 @@
"general.tags": "Tags",
"general.errorCodes": "Error codes",
"general.reportTypes": "Report types",
+ "general.reportReleases": "Report releases",
"general.edit": "Edit",
"general.note": "Note",
"general.year": "Year",