diff --git a/oarepo_model_builder/datatypes/components/model/facets.py b/oarepo_model_builder/datatypes/components/model/facets.py index c5dda28..2a6e07a 100644 --- a/oarepo_model_builder/datatypes/components/model/facets.py +++ b/oarepo_model_builder/datatypes/components/model/facets.py @@ -24,6 +24,16 @@ class Meta: ) generate = ma.fields.Boolean() skip = ma.fields.Boolean() + facet_groups = ma.fields.Dict( + attribute="facet-groups", + data_key="facet-groups", + keys=ma.fields.String(), + values=ma.fields.Dict(keys=ma.fields.String(), values=ma.fields.Integer()), + metadata={ + "doc": "Groups of facets in the form of {group_name: {facet_path: priority}}. Will merge with facet " + "groups declared on the individual fields." + }, + ) class FacetsModelComponent(ObjectFacetsComponent): @@ -45,6 +55,7 @@ def before_model_prepare(self, datatype, *, context, **__kwargs): facets.setdefault("module", f"{module}.services.{profile_module}.facets") facets.setdefault("extra-code", "") + facets.setdefault("groups", True) def build_facet_definition( self, diff --git a/oarepo_model_builder/invenio/invenio_record_search_options.py b/oarepo_model_builder/invenio/invenio_record_search_options.py index bf55b3e..e9b6134 100644 --- a/oarepo_model_builder/invenio/invenio_record_search_options.py +++ b/oarepo_model_builder/invenio/invenio_record_search_options.py @@ -1,3 +1,4 @@ +from collections import defaultdict from typing import List from ..datatypes.components.facets import FacetDefinition @@ -21,6 +22,18 @@ def finish(self, **extra_kwargs): for f in facets: facet_group_names.update(f.facet_groups.keys()) + # there might be a definition of facet groups on the model's facets -> facet-groups + # if there is, we need to merge those + top_level_facet_groups = self.current_model.definition.get("facets", {}).get( + "facet-groups", {} + ) + facet_group_names.update(top_level_facet_groups.keys()) + path_to_facet_group = defaultdict(dict) + + for group, group_def in top_level_facet_groups.items(): + for path, priority in group_def.items(): + path_to_facet_group[group][path] = priority + # for each group name, gather all facets with that group name # sort them by their order in the group # and add them to the facet_groups dict @@ -35,6 +48,11 @@ def finish(self, **extra_kwargs): if group in f.facet_groups: group_members.append((f, f.facet_groups[group])) + # if there is a definition of facet groups on the model's facets -> add the selected facets as well + for path, priority in path_to_facet_group.get(group, {}).items(): + if f.dot_path.startswith(path): + group_members.append((f, priority)) + # sort the group members by their order in the facet_group group_members.sort(key=lambda x: x[1]) diff --git a/tests/test_search_options.py b/tests/test_search_options.py index 2aab57a..2b8e868 100644 --- a/tests/test_search_options.py +++ b/tests/test_search_options.py @@ -425,6 +425,76 @@ def test_facet_groups_ordering(): ) +def test_top_level_facet_groups_ordering(): + schema = load_model( + DUMMY_YAML, + model_content={ + "record": { + "use": "invenio", + "module": {"qualified": "test"}, + "search-options": { + "base-classes": ["BaseSearchOptions"], + "imports": [{"import": "blah.BaseSearchOptions"}], + }, + "facets": { + "facet-groups": { + "curator": { + "a": 2, + "b": 3, + "c": 1, + } + } + }, + "properties": { + "a": { + "type": "keyword", + }, + "b": { + "type": "keyword", + }, + "c": { + "type": "keyword", + }, + }, + }, + }, + isort=False, + black=False, + autoflake=False, + ) + + filesystem = InMemoryFileSystem() + builder = create_builder_from_entrypoints(filesystem=filesystem) + + builder.build(schema, "record", ["record"], "") + + data = builder.filesystem.open( + os.path.join("test", "services", "records", "search.py") + ).read() + print(data) + data2 = builder.filesystem.open( + os.path.join("test", "services", "records", "facets.py") + ).read() + print(data2) + data3 = builder.filesystem.read( + os.path.join("test", "records", "mappings", "os-v2", "test", "test-1.0.0.json") + ) + import json + + data3 = json.loads(data3) + print(data3) + assert ( + strip_whitespaces( + """ + 'c': facets.c, + 'a': facets.a, + 'b': facets.b, + """ + ) + in strip_whitespaces(data) + ) + + def test_replace_sort_options(): schema = load_model( DUMMY_YAML,