diff --git a/invenio_app_ils/config.py b/invenio_app_ils/config.py
index f9bf52162..349008e65 100644
--- a/invenio_app_ils/config.py
+++ b/invenio_app_ils/config.py
@@ -53,8 +53,9 @@
from .documents.api import DOCUMENT_PID_FETCHER, DOCUMENT_PID_MINTER, \
DOCUMENT_PID_TYPE, Document
from .documents.search import DocumentSearch
-from .facets import default_value_when_missing_filter, keyed_range_filter, \
- not_empty_object_or_list_filter, overdue_agg, overdue_loans_filter
+from .facets import date_range_filter, default_value_when_missing_filter, \
+ keyed_range_filter, not_empty_object_or_list_filter, overdue_agg, \
+ overdue_loans_filter
from .records.views import UserInfoResource
from .api import ( # isort:skip
@@ -1191,6 +1192,7 @@ def _(x):
),
filters={
"returns.end_date": overdue_loans_filter("end_date"),
+ "loan.start_date": date_range_filter("start_date"),
},
post_filters=dict(
state=terms_filter("state"),
diff --git a/invenio_app_ils/facets.py b/invenio_app_ils/facets.py
index d68c62918..a07f0b01a 100644
--- a/invenio_app_ils/facets.py
+++ b/invenio_app_ils/facets.py
@@ -6,7 +6,6 @@
# it under the terms of the MIT License; see LICENSE file for more details.
"""Facets and factories for result filtering and aggregation."""
-from datetime import timedelta
import arrow
from elasticsearch_dsl.query import Bool, Q, Range
@@ -113,3 +112,22 @@ def overdue_agg():
)
)
)
+
+
+# loan.start_date:2020-02-02,2020-12-30
+def date_range_filter(field):
+ """Create a range filter.
+
+ :param field: Field name.
+ :param values[0]: string with comma separated fromDate and toDate.
+ """
+ def inner(values):
+ fromDate, toDate = values[0].split(',')
+ params = {}
+ if fromDate:
+ params["gte"] = str(arrow.get(fromDate).date())
+ if toDate:
+ params["lte"] = str(arrow.get(toDate).date())
+ return Range(**{field: params})
+
+ return inner
diff --git a/ui/package-lock.json b/ui/package-lock.json
index 023e4a281..c6e5154ae 100644
--- a/ui/package-lock.json
+++ b/ui/package-lock.json
@@ -14418,9 +14418,9 @@
}
},
"react-searchkit": {
- "version": "0.16.0",
- "resolved": "https://registry.npmjs.org/react-searchkit/-/react-searchkit-0.16.0.tgz",
- "integrity": "sha512-tFfHdUa1Nih61XHaUr46KF7ksmA3N8oCq8Xc+w/+eJF0apMaHFxERfa8CK3HDcYahNzQPL056KmRfsN6+xkM+g=="
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/react-searchkit/-/react-searchkit-0.17.0.tgz",
+ "integrity": "sha512-RKzD32VDvJCHkfRt9PDJR4ghrq2amnPR5z0SMBoWESJB2q+IqsDqo+KPw3svphm5+C/i70X9NKwzdCHcbrX4SA=="
},
"react-show-more": {
"version": "2.0.0",
diff --git a/ui/package.json b/ui/package.json
index 521269dfb..2979b2efb 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -30,7 +30,7 @@
"react-router-dom": "^5.1.2",
"react-scripts": "^3.4.0",
"react-scroll": "^1.7.16",
- "react-searchkit": "^0.16.0",
+ "react-searchkit": "^0.17.0",
"react-show-more": "^2.0.0",
"react-tagcloud": "^2.0.0",
"redux": "^4.0.4",
diff --git a/ui/src/components/SearchControls/components/SearchDateRange/SearchDateRange.js b/ui/src/components/SearchControls/components/SearchDateRange/SearchDateRange.js
new file mode 100644
index 000000000..40066c28d
--- /dev/null
+++ b/ui/src/components/SearchControls/components/SearchDateRange/SearchDateRange.js
@@ -0,0 +1,72 @@
+import React, { Component } from 'react';
+import { Card } from 'semantic-ui-react';
+import { DatePicker } from '@components';
+import { withState, onQueryChanged } from 'react-searchkit';
+import _fromPairs from 'lodash/fromPairs';
+import _toPairs from 'lodash/toPairs';
+import _cloneDeep from 'lodash/cloneDeep';
+
+class _SearchDateRange extends Component {
+ constructor(props) {
+ super(props);
+ const [fromDate, toDate] = this.parseUrlDates();
+ this.state = { fromDate, toDate };
+ }
+
+ parseUrlDates = () => {
+ const { filters } = this.props.currentQueryState;
+ const filtersObj = _fromPairs(filters);
+ const dateFilter = filtersObj['loan.start_date'];
+ if (dateFilter) return dateFilter.split(',');
+ return ['', ''];
+ };
+
+ updateFilters = () => {
+ const newQuery = _cloneDeep(this.props.currentQueryState);
+ const filtersObj = _fromPairs(newQuery.filters);
+ filtersObj[
+ 'loan.start_date'
+ ] = `${this.state.fromDate},${this.state.toDate}`;
+ newQuery.filters = _toPairs(filtersObj);
+
+ // NOTE: since its wrapped with `withState` when the pr is merged
+ // (https://github.com/inveniosoftware/react-searchkit/pull/100) we could
+ // use this.props.updateStateQuery(newQuery) instead of the events.
+ onQueryChanged({ searchQuery: newQuery });
+ };
+
+ render() {
+ return (
+
+
+ Date
+
+ *Loan start date
+
+
+
+
+ this.setState({ fromDate: value }, this.updateFilters)
+ }
+ />
+
+
+
+ this.setState({ toDate: value }, this.updateFilters)
+ }
+ />
+
+
+ );
+ }
+}
+
+export const SearchDateRange = withState(_SearchDateRange);
diff --git a/ui/src/components/SearchControls/components/SearchDateRange/index.js b/ui/src/components/SearchControls/components/SearchDateRange/index.js
new file mode 100644
index 000000000..20d0ef835
--- /dev/null
+++ b/ui/src/components/SearchControls/components/SearchDateRange/index.js
@@ -0,0 +1 @@
+export { SearchDateRange } from './SearchDateRange';
diff --git a/ui/src/components/SearchControls/components/index.js b/ui/src/components/SearchControls/components/index.js
index 6059743d0..d8c85747c 100644
--- a/ui/src/components/SearchControls/components/index.js
+++ b/ui/src/components/SearchControls/components/index.js
@@ -1,5 +1,6 @@
export { SearchAggregationsCards } from './SearchAggregations';
export { SearchAggregationsMenu } from './SearchAggregations';
+export { SearchDateRange } from './SearchDateRange';
export { SearchFooter } from './SearchFooter';
export { SearchPagination } from './SearchPagination';
export { SearchEmptyResults } from './SearchEmptyResults';
diff --git a/ui/src/pages/backoffice/Loan/LoanSearch/LoanSearch.js b/ui/src/pages/backoffice/Loan/LoanSearch/LoanSearch.js
index d13ef651e..17269d665 100644
--- a/ui/src/pages/backoffice/Loan/LoanSearch/LoanSearch.js
+++ b/ui/src/pages/backoffice/Loan/LoanSearch/LoanSearch.js
@@ -23,6 +23,8 @@ import {
SearchAggregationsCards,
} from '@components/SearchControls';
+import { SearchDateRange } from '@components/SearchControls/components';
+
export class LoanSearch extends Component {
searchApi = new InvenioSearchApi({
url: loanApi.searchBaseURL,
@@ -77,7 +79,11 @@ export class LoanSearch extends Component {
<>
-
+
@@ -87,6 +93,7 @@ export class LoanSearch extends Component {
+