diff --git a/invenio_records_resources/services/base/config.py b/invenio_records_resources/services/base/config.py index 7bd6d2a0..1546c540 100644 --- a/invenio_records_resources/services/base/config.py +++ b/invenio_records_resources/services/base/config.py @@ -61,10 +61,14 @@ def customize(cls, opts): attrs = {} if opts.facets: attrs["facets"] = opts.facets + # these are the selected sort options if opts.sort_options: attrs["sort_options"] = opts.sort_options attrs["sort_default"] = opts.sort_default attrs["sort_default_no_query"] = opts.sort_default_no_query + # store all available sort options + if opts.available_sort_options: + attrs["available_sort_options"] = opts.available_sort_options if opts.query_parser_cls: attrs["query_parser_cls"] = opts.query_parser_cls return _make_cls(cls, attrs) if attrs else cls @@ -128,13 +132,18 @@ def __init__(self, available_options, selected_options): # Ensure all selected options are availabe. for o in selected_options: assert o in available_options, f"Selected option '{o}' is undefined." + self.iterate_all_options = False self.available_options = available_options self.selected_options = selected_options def __iter__(self): """Iterate over options to produce RSK options.""" - for o in self.selected_options: + for o in ( + self.selected_options + if not self.iterate_all_options + else self.available_options + ): yield self.map_option(o, self.available_options[o]) def map_option(self, key, option): @@ -142,6 +151,11 @@ def map_option(self, key, option): # This interface is used in Invenio-App-RDM. return (key, option) + def __call__(self): + """Control if we iterate through all or selected sort options.""" + self.iterate_all_options = True + return self + class SortOptionsSelector(OptionsSelector): """Sort options for the search configuration.""" @@ -194,6 +208,11 @@ def sort_options(self): """Get sort options for search.""" return {k: v for (k, v) in self._sort} + @property + def available_sort_options(self): + """Get sort options for search.""" + return {k: v for (k, v) in self._sort()} + @property def sort_default(self): """Get default sort method for search.""" diff --git a/invenio_records_resources/services/records/params/sort.py b/invenio_records_resources/services/records/params/sort.py index b870cbab..2c038fe0 100644 --- a/invenio_records_resources/services/records/params/sort.py +++ b/invenio_records_resources/services/records/params/sort.py @@ -39,7 +39,16 @@ def apply(self, identity, search, params): def _compute_sort_fields(self, params): """Compute sort fields.""" - options = deepcopy(self.config.sort_options) + # validate sort options in the following order + # 1. search all available options if set in the search config. This will be + # added automatically if `SearchOptionsMixin` is used. + # 2. selected sort options otherwise. These are also the sort options that the + # UI displays. + options = deepcopy( + self.config.available_sort_options + if hasattr(self.config, "available_sort_options") + else self.config.sort_options + ) if "sort" not in params: params["sort"] = self._default_sort(params, options)