Skip to content

Commit 1454d47

Browse files
UIREQMED-3: Add Search field for Mediated requests activity page
1 parent ea35535 commit 1454d47

27 files changed

+564
-21
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
* Add landing page actions: Confirm item arrival, Mediated requests activities and Send item in transit. Refs UIREQMED-2.
66
* Hide permission that should not be visible. Refs UIREQMED-20.
77
* Add caret to `react` peer dependency. Refs UIREQMED-23.
8+
* Add Search field for Mediated requests activity page. Refs UIREQMED-3.
9+
* Add Filters for Mediated requests actions page. Refs UIREQMED-4.
810

911
## 1.0.0
1012
* New app created with stripes-cli. Updated module after created with stripes-cli. Refs UIREQMED-1.

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@
8383
"displayName": "Mediated requests: View",
8484
"subPermissions": [
8585
"module.requests-mediated.enabled",
86+
"settings.circulation.enabled",
87+
"mod-settings.global.read.circulation",
88+
"mod-settings.entries.collection.get",
89+
"mod-settings.entries.item.get",
8690
"settings.requests-mediated.enabled"
8791
],
8892
"visible": true

src/components/MediatedRequestsActivities/MediatedRequestsActivities.js

Lines changed: 62 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,22 @@
1+
import { useState } from 'react';
2+
13
import { FormattedMessage } from 'react-intl';
24

35
import { AppIcon } from '@folio/stripes/core';
46

57
import {
68
Pane,
9+
PaneMenu,
710
Paneset,
811
} from '@folio/stripes/components';
12+
import {
13+
SearchAndSortQuery,
14+
ExpandFilterPaneButton,
15+
CollapseFilterPaneButton,
16+
} from '@folio/stripes/smart-components';
917

1018
import NavigationMenu from '../NavigationMenu';
19+
import MediatedRequestsFilters from './components/MediatedRequestsFilters';
1120

1221
import {
1322
APP_ICON_NAME,
@@ -16,21 +25,60 @@ import {
1625
} from '../../constants';
1726

1827
const MediatedRequestsActivities = () => {
28+
const [filterPaneIsVisible, setFilterPaneIsVisible] = useState(true);
29+
30+
const toggleFilterPane = () => {
31+
setFilterPaneIsVisible(!filterPaneIsVisible);
32+
};
33+
34+
const renderResultsFirstMenu = () => {
35+
if (filterPaneIsVisible) {
36+
return null;
37+
}
38+
39+
return (
40+
<PaneMenu>
41+
<ExpandFilterPaneButton
42+
onClick={toggleFilterPane}
43+
/>
44+
</PaneMenu>
45+
);
46+
};
47+
1948
return (
20-
<Paneset data-testid="mediatedRequestsActivitiesPaneSet">
21-
<Pane
22-
data-testid="mediatedRequestsActivitiesPane"
23-
defaultWidth={FILTER_PANE_WIDTH}
24-
paneTitle={<FormattedMessage id="ui-requests-mediated.app.filterPane.selectActivity" />}
25-
>
26-
<NavigationMenu value={getMediatedRequestsActivitiesUrl()} />
27-
</Pane>
28-
<Pane
29-
defaultWidth="fill"
30-
appIcon={<AppIcon app={APP_ICON_NAME} />}
31-
paneTitle={<FormattedMessage id="ui-requests-mediated.app.mediatedRequestsActivities.paneTitle" />}
32-
/>
33-
</Paneset>
49+
<SearchAndSortQuery data-testid="mediatedRequestsActivitiesSearchAndSortQuery">
50+
{() => (
51+
<Paneset data-testid="mediatedRequestsActivitiesPaneSet">
52+
{filterPaneIsVisible &&
53+
<Pane
54+
data-testid="mediatedRequestsActivitiesPane"
55+
defaultWidth={FILTER_PANE_WIDTH}
56+
paneTitle={<FormattedMessage id="ui-requests-mediated.app.filterPane.selectActivity" />}
57+
lastMenu={
58+
<PaneMenu>
59+
<CollapseFilterPaneButton
60+
data-testid="mediatedRequestsActivitiesCollapseFilterPaneButton"
61+
onClick={toggleFilterPane}
62+
/>
63+
</PaneMenu>
64+
}
65+
>
66+
<NavigationMenu
67+
value={getMediatedRequestsActivitiesUrl()}
68+
separator
69+
/>
70+
<MediatedRequestsFilters />
71+
</Pane>
72+
}
73+
<Pane
74+
defaultWidth="fill"
75+
appIcon={<AppIcon app={APP_ICON_NAME} />}
76+
paneTitle={<FormattedMessage id="ui-requests-mediated.app.mediatedRequestsActivities.paneTitle" />}
77+
firstMenu={renderResultsFirstMenu()}
78+
/>
79+
</Paneset>
80+
)}
81+
</SearchAndSortQuery>
3482
);
3583
};
3684

src/components/MediatedRequestsActivities/MediatedRequestsActivities.test.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,18 @@ import {
55

66
import MediatedRequestsActivities from './MediatedRequestsActivities';
77
import NavigationMenu from '../NavigationMenu';
8+
import MediatedRequestsFilters from './components/MediatedRequestsFilters';
89

910
import { getMediatedRequestsActivitiesUrl } from '../../constants';
1011

1112
jest.mock('../NavigationMenu', () => jest.fn((props) => (<div {...props} />)));
13+
jest.mock('./components/MediatedRequestsFilters', () => jest.fn((props) => (<div {...props} />)));
1214

1315
const testIds = {
16+
mediatedRequestsActivitiesSearchAndSortQuery: 'mediatedRequestsActivitiesSearchAndSortQuery',
1417
mediatedRequestsActivitiesPaneSet: 'mediatedRequestsActivitiesPaneSet',
1518
mediatedRequestsActivitiesPane: 'mediatedRequestsActivitiesPane',
19+
mediatedRequestsActivitiesCollapseFilterPaneButton: 'mediatedRequestsActivitiesCollapseFilterPaneButton',
1620
};
1721
const labelIds = {
1822
paneTitle: 'ui-requests-mediated.app.mediatedRequestsActivities.paneTitle',
@@ -23,6 +27,10 @@ describe('MediatedRequestsActivities', () => {
2327
render(<MediatedRequestsActivities />);
2428
});
2529

30+
it('should render search and sort query', () => {
31+
expect(screen.getByTestId(testIds.mediatedRequestsActivitiesSearchAndSortQuery)).toBeInTheDocument();
32+
});
33+
2634
it('should render pane set', () => {
2735
expect(screen.getByTestId(testIds.mediatedRequestsActivitiesPaneSet)).toBeInTheDocument();
2836
});
@@ -40,4 +48,12 @@ describe('MediatedRequestsActivities', () => {
4048
value: getMediatedRequestsActivitiesUrl(),
4149
}), {});
4250
});
51+
52+
it('should trigger MediatedRequestsFilters with correct props', () => {
53+
expect(MediatedRequestsFilters).toHaveBeenCalledWith(expect.objectContaining({}), {});
54+
});
55+
56+
it('should render CollapseFilterPaneButton', () => {
57+
expect(screen.getByTestId(testIds.mediatedRequestsActivitiesCollapseFilterPaneButton)).toBeInTheDocument();
58+
});
4359
});
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import PropTypes from 'prop-types';
2+
3+
import { stripesConnect } from '@folio/stripes/core';
4+
5+
import {
6+
MediatedRequestLevelFilter,
7+
MediatedRequestStatusFilter,
8+
Search,
9+
} from './components';
10+
11+
import {
12+
getIsTitleLevelRequestsFeatureEnabled,
13+
} from '../../../../utils';
14+
15+
const SETTINGS_SCOPES = {
16+
CIRCULATION: 'circulation',
17+
};
18+
const SETTINGS_KEYS = {
19+
GENERAL_TLR: 'generalTlr',
20+
};
21+
22+
const MediatedRequestsFilters = ({
23+
resources,
24+
}) => {
25+
const isTitleLevelRequestsFeatureEnabled = getIsTitleLevelRequestsFeatureEnabled(resources);
26+
27+
return (
28+
<form
29+
data-testid="MediatedRequestsFiltersForm"
30+
>
31+
<Search
32+
data-testid="MediatedRequestsFiltersSearch"
33+
/>
34+
<MediatedRequestStatusFilter
35+
data-testid="mediatedRequestFiltersStatusFilter"
36+
/>
37+
{isTitleLevelRequestsFeatureEnabled && (
38+
<MediatedRequestLevelFilter
39+
data-testid="mediatedRequestFiltersLevelFilter"
40+
/>
41+
)}
42+
</form>
43+
);
44+
};
45+
46+
MediatedRequestsFilters.manifest = {
47+
configs: {
48+
type: 'okapi',
49+
records: 'items',
50+
path: 'settings/entries',
51+
params: {
52+
query: `(scope==${SETTINGS_SCOPES.CIRCULATION} and key==${SETTINGS_KEYS.GENERAL_TLR})`,
53+
},
54+
},
55+
};
56+
57+
MediatedRequestsFilters.propTypes = {
58+
resources: PropTypes.object.isRequired,
59+
};
60+
61+
export default stripesConnect(MediatedRequestsFilters);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import {
2+
render,
3+
screen,
4+
} from '@folio/jest-config-stripes/testing-library/react';
5+
6+
import MediatedRequestsFilters from './MediatedRequestsFilters';
7+
8+
import {
9+
MediatedRequestLevelFilter,
10+
MediatedRequestStatusFilter,
11+
Search,
12+
} from './components';
13+
import NavigationMenu from '../../../NavigationMenu';
14+
import { getMediatedRequestsActivitiesUrl } from '../../../../constants';
15+
16+
jest.mock('./components', () => ({
17+
MediatedRequestLevelFilter: jest.fn((props) => (<div {...props} />)),
18+
MediatedRequestStatusFilter: jest.fn((props) => (<div {...props} />)),
19+
Search: jest.fn((props) => (<div {...props} />)),
20+
}));
21+
22+
const testIds = {
23+
mediatedRequestsFiltersForm: 'MediatedRequestsFiltersForm',
24+
mediatedRequestsFiltersSearch: 'MediatedRequestsFiltersSearch',
25+
mediatedRequestFiltersStatusFilter: 'mediatedRequestFiltersStatusFilter',
26+
mediatedRequestFiltersLevelFilter: 'mediatedRequestFiltersLevelFilter',
27+
};
28+
29+
describe('MediatedRequestsFilters', () => {
30+
beforeEach(() => {
31+
render(<MediatedRequestsFilters />);
32+
});
33+
34+
it('should render form', () => {
35+
expect(screen.getByTestId(testIds.mediatedRequestsFiltersForm)).toBeInTheDocument();
36+
});
37+
38+
it('should render search', () => {
39+
expect(screen.getByTestId(testIds.mediatedRequestsFiltersSearch)).toBeInTheDocument();
40+
});
41+
42+
it('should trigger search with correct props', () => {
43+
expect(Search).toHaveBeenCalledWith(expect.objectContaining({}), {});
44+
});
45+
46+
it('should render status filter', () => {
47+
expect(screen.getByTestId(testIds.mediatedRequestFiltersStatusFilter)).toBeInTheDocument();
48+
});
49+
50+
it('should trigger status filter with correct props', () => {
51+
expect(MediatedRequestStatusFilter).toHaveBeenCalledWith(expect.objectContaining({}), {});
52+
});
53+
54+
it('should not render status filter', () => {
55+
expect(screen.queryByTestId(testIds.mediatedRequestFiltersLevelFilter)).not.toBeInTheDocument();
56+
});
57+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { useIntl } from 'react-intl';
2+
3+
import {
4+
Accordion,
5+
AccordionSet,
6+
FilterAccordionHeader,
7+
} from '@folio/stripes/components';
8+
import {
9+
CheckboxFilter,
10+
} from '@folio/stripes/smart-components';
11+
12+
import {
13+
transformRequestFilterOptions,
14+
} from '../../../../../../utils';
15+
import {
16+
MEDIATED_REQUEST_FILTER_TYPES,
17+
MEDIATED_REQUEST_LEVEL_TRANSLATIONS,
18+
} from '../../../../../../constants';
19+
20+
const MediatedRequestLevelFilter = () => {
21+
const { formatMessage } = useIntl();
22+
23+
return (
24+
<AccordionSet
25+
data-testid={`${MEDIATED_REQUEST_FILTER_TYPES.MEDIATED_REQUEST_LEVELS}Set`}
26+
>
27+
<Accordion
28+
id={MEDIATED_REQUEST_FILTER_TYPES.MEDIATED_REQUEST_LEVELS}
29+
data-testid={MEDIATED_REQUEST_FILTER_TYPES.MEDIATED_REQUEST_LEVELS}
30+
header={FilterAccordionHeader}
31+
label={formatMessage({ id:'ui-requests-mediated.filters.mediatedRequestLevel.accordionTitle' })}
32+
name={MEDIATED_REQUEST_FILTER_TYPES.MEDIATED_REQUEST_LEVELS}
33+
separator={false}
34+
onClearFilter={() => {}}
35+
>
36+
<CheckboxFilter
37+
data-testid={`${MEDIATED_REQUEST_FILTER_TYPES.MEDIATED_REQUEST_LEVELS}Filter`}
38+
dataOptions={transformRequestFilterOptions(MEDIATED_REQUEST_LEVEL_TRANSLATIONS, formatMessage)}
39+
name={MEDIATED_REQUEST_FILTER_TYPES.MEDIATED_REQUEST_LEVELS}
40+
onChange={() => {}}
41+
/>
42+
</Accordion>
43+
</AccordionSet>
44+
);
45+
};
46+
47+
export default MediatedRequestLevelFilter;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import {
2+
render,
3+
screen,
4+
} from '@folio/jest-config-stripes/testing-library/react';
5+
6+
import MediatedRequestLevelFilter from './MediatedRequestLevelFilter';
7+
8+
import { MEDIATED_REQUEST_FILTER_TYPES } from '../../../../../../constants';
9+
10+
const testIds = {
11+
accordionSet: `${MEDIATED_REQUEST_FILTER_TYPES.MEDIATED_REQUEST_LEVELS}Set`,
12+
accordion: MEDIATED_REQUEST_FILTER_TYPES.MEDIATED_REQUEST_LEVELS,
13+
checkboxFilter: `${MEDIATED_REQUEST_FILTER_TYPES.MEDIATED_REQUEST_LEVELS}Filter`,
14+
};
15+
16+
describe('MediatedRequestLevelFilter', () => {
17+
beforeEach(() => {
18+
render(<MediatedRequestLevelFilter />);
19+
});
20+
21+
it('should render accordion set', () => {
22+
expect(screen.getByTestId(testIds.accordionSet)).toBeInTheDocument();
23+
});
24+
25+
it('should render accordion', () => {
26+
expect(screen.getByTestId(testIds.accordion)).toBeInTheDocument();
27+
});
28+
29+
it('should render checkbox filter', () => {
30+
expect(screen.getByTestId(testIds.checkboxFilter)).toBeInTheDocument();
31+
});
32+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default } from './MediatedRequestLevelFilter';

0 commit comments

Comments
 (0)