From 7e4ca5da9d9a8657842d8fdde90fd85ed4301025 Mon Sep 17 00:00:00 2001 From: Chris Topaloudis Date: Wed, 1 Apr 2020 02:00:31 +0200 Subject: [PATCH] loans: date range search - filters loans_from_date and loans_to_date on loan start date - datepickers for ui - depends on react-searchkit release 0.18.0 - closes #168 --- invenio_app_ils/config.py | 7 +- invenio_app_ils/facets.py | 12 ++- ui/package-lock.json | 6 +- ui/package.json | 2 +- .../backoffice/Loan/LoanSearch/LoanSearch.js | 6 +- .../Loan/LoanSearch/SearchDateRange.js | 77 +++++++++++++++++++ 6 files changed, 101 insertions(+), 9 deletions(-) create mode 100644 ui/src/pages/backoffice/Loan/LoanSearch/SearchDateRange.js diff --git a/invenio_app_ils/config.py b/invenio_app_ils/config.py index f9bf52162..78c21aefb 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,8 @@ def _(x): ), filters={ "returns.end_date": overdue_loans_filter("end_date"), + "loans_from_date": date_range_filter("start_date", "gte"), + "loans_to_date": date_range_filter("start_date", "lte"), }, post_filters=dict( state=terms_filter("state"), diff --git a/invenio_app_ils/facets.py b/invenio_app_ils/facets.py index d68c62918..6566d5854 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,14 @@ def overdue_agg(): ) ) ) + + +def date_range_filter(field, comparator): + """Create a range filter. + + :param field: Field name. + :param comparator: Comparison we want with the supplied date. + """ + def inner(values): + return Range(**{field: {comparator: str(arrow.get(values[0]).date())}}) + 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..fe75c1e19 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.18.0", "react-show-more": "^2.0.0", "react-tagcloud": "^2.0.0", "redux": "^4.0.4", diff --git a/ui/src/pages/backoffice/Loan/LoanSearch/LoanSearch.js b/ui/src/pages/backoffice/Loan/LoanSearch/LoanSearch.js index d13ef651e..914b008c4 100644 --- a/ui/src/pages/backoffice/Loan/LoanSearch/LoanSearch.js +++ b/ui/src/pages/backoffice/Loan/LoanSearch/LoanSearch.js @@ -23,10 +23,11 @@ import { SearchAggregationsCards, } from '@components/SearchControls'; +import { SearchDateRange } from './SearchDateRange'; + export class LoanSearch extends Component { searchApi = new InvenioSearchApi({ - url: loanApi.searchBaseURL, - withCredentials: true, + axios: { url: loanApi.searchBaseURL, withCredentials: true }, interceptors: { response: { reject: responseRejectInterceptor }, }, @@ -87,6 +88,7 @@ export class LoanSearch extends Component {
+ diff --git a/ui/src/pages/backoffice/Loan/LoanSearch/SearchDateRange.js b/ui/src/pages/backoffice/Loan/LoanSearch/SearchDateRange.js new file mode 100644 index 000000000..3aa501424 --- /dev/null +++ b/ui/src/pages/backoffice/Loan/LoanSearch/SearchDateRange.js @@ -0,0 +1,77 @@ +import React, { Component } from 'react'; +import { Card } from 'semantic-ui-react'; +import { DatePicker } from '@components'; +import { withState } from 'react-searchkit'; +import _isEmpty from 'lodash/isEmpty'; + +class _SearchDateRange extends Component { + getCurrentDates() { + const { filters } = this.props.currentQueryState; + let loans_from_date = ''; + let loans_to_date = ''; + + filters.forEach(([name, value]) => { + if (name === 'loans_from_date') loans_from_date = value; + if (name === 'loans_to_date') loans_to_date = value; + }); + return [loans_from_date, loans_to_date]; + } + + onDateChange = newFilter => { + const [name, value] = newFilter; + let result = newFilter; + + if (_isEmpty(value)) { + this.props.updateQueryState({ filters: result }); + return; + } + + const { filters } = this.props.currentQueryState; + const existingFilters = filters.filter(filter => filter[0] === name); + + if (!_isEmpty(existingFilters)) { + result = existingFilters.push(newFilter); + } + // NOTE: react-searchkit allows having the same filter multiple times. + // For the range dates filters we want each filter one time only so we have + // to we have to add also the existing filters we want to remove. + this.props.updateQueryState({ filters: result }); + }; + + render() { + const [fromDate, toDate] = this.getCurrentDates(); + + return ( + + + Date + + *Loan start date + + + + + this.onDateChange(['loans_from_date', value]) + } + /> + + + + this.onDateChange(['loans_to_date', value]) + } + /> + + + ); + } +} + +export const SearchDateRange = withState(_SearchDateRange);