Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vocabulary item view #347

Open
wants to merge 41 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
d77a180
register new route
karkraeg May 13, 2024
0b5aaaa
Implemented first Admin view based on mock API
karkraeg May 14, 2024
4d3365b
add copyright
karkraeg May 14, 2024
f7404c0
remove WIP import
karkraeg May 14, 2024
009be0a
remove more imports
karkraeg May 14, 2024
fb36717
provide API endpoint with aggregated counts for all types of vocabula…
karkraeg May 16, 2024
c0377de
add missing invenio-administration dependency
karkraeg May 17, 2024
dd1420d
Add and update docstrings
SarahW91 May 17, 2024
ebd3363
dirty commit, added resources
karkraeg May 22, 2024
9bf7e2a
fix imports and cleanup
karkraeg May 22, 2024
ff50270
cleanup
karkraeg May 23, 2024
8965685
overwrite api endpoint
karkraeg May 23, 2024
f405b4b
Fixes after review. Take out additional list view for now until it is…
SarahW91 May 24, 2024
3601b15
Fixed formatting and doc strings.
SarahW91 May 24, 2024
b2a3c93
Fixed formatting
SarahW91 May 24, 2024
0fc61ae
vocabulary types: Implement query functionality
SarahW91 May 28, 2024
43f25da
vocabulary types: Show count in list view
SarahW91 May 28, 2024
9de7fd2
vocabulary types: Implement sorting
SarahW91 May 28, 2024
a5e1f90
vocabulary type endpoint: fix formatting
SarahW91 Jun 13, 2024
78bec3d
vocabulary types endpoint: split implementation for service, config a…
SarahW91 Jun 13, 2024
fe43685
services: fix service proxy
karkraeg Jun 14, 2024
edfdf53
vocabulary types administration: Fix sidebar menu name and remove cre…
SarahW91 Jun 17, 2024
22f7835
vocabulary types administration: Add Uni Münster copyright notice.
SarahW91 Jun 17, 2024
5657042
vocabulary types administration tests: Use correct service for tests
SarahW91 Jun 17, 2024
2555b8e
Merge branch 'master' into all_vocabularies_endpoint
SarahW91 Jun 19, 2024
842f5c3
vocabulary types: cleanup
SarahW91 Jun 24, 2024
6c79b8b
vocabulary types items: add vocabulary items list view
SarahW91 Jun 25, 2024
ba10dcb
vocabulary types items: account for different sort options on differe…
SarahW91 Jun 25, 2024
b0a4bb7
vocabulary types items: add display fields for items
SarahW91 Jun 25, 2024
f210d7c
vocabulary types items: add subject column
SarahW91 Jun 25, 2024
9056ac3
Merge branch 'inveniosoftware:master' into vocabulary_item_view
SarahW91 Jun 26, 2024
1cbf807
Capitalize vocabulary type name in items view
SarahW91 Jun 25, 2024
8cf3e43
vocabulary item list view: Fixed formatting and pydocstyle
SarahW91 Jun 26, 2024
99f299d
vocabulary types: remove schema property from VocabularyTypeService
SarahW91 Jun 25, 2024
7475321
vocabulary types: remove unused read response handler from Vocabulari…
SarahW91 Jun 25, 2024
9d4ccbb
vocabulary types: rename route and response handler of VocabulariesAd…
SarahW91 Jun 25, 2024
9a2a0d7
vocabulary item list view: Avoid code duplication by overwriting get …
SarahW91 Jul 4, 2024
c9f79e8
vocabulary item list view: make view ui customizable via config.py
SarahW91 Jul 16, 2024
75240e9
vocabulary item list view: add resource name to config
SarahW91 Jul 16, 2024
8147305
Merge branch 'master' into vocabulary_item_view
SarahW91 Jul 16, 2024
f6ba1dc
formatting: run isort and black
SarahW91 Jul 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions invenio_vocabularies/administration/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2024 CERN.
# Copyright (C) 2024 Uni Münster.
#
# Invenio-Vocabularies is free software; you can redistribute it and/or
# modify it under the terms of the MIT License; see LICENSE file for more
# details.

"""Invenio administration views module for vocabularies."""
10 changes: 10 additions & 0 deletions invenio_vocabularies/administration/views/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2020-2021 CERN.
# Copyright (C) 2024 Uni Münster.
#
# Invenio-Vocabularies is free software; you can redistribute it and/or
# modify it under the terms of the MIT License; see LICENSE file for more
# details.

"""Invenio administration views module for Vocabularies."""
118 changes: 118 additions & 0 deletions invenio_vocabularies/administration/views/vocabularies.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2020-2021 CERN.
# Copyright (C) 2024 Uni Münster.
#
# Invenio-Vocabularies is free software; you can redistribute it and/or
# modify it under the terms of the MIT License; see LICENSE file for more
# details.

"""Vocabularies admin interface."""
from flask import current_app
from invenio_administration.views.base import AdminResourceListView


class VocabulariesListView(AdminResourceListView):
"""Configuration for vocabularies list view."""

api_endpoint = "/vocabularies/"
name = "vocabulary-types"
menu_label = "Vocabulary Types"
resource_config = "vocabulary_admin_resource"
search_request_headers = {"Accept": "application/json"}
title = "Vocabulary Types"
category = "Site management"

pid_path = "id"
icon = "exchange"
template = "invenio_administration/search.html"

display_search = True
display_delete = False
display_edit = False
display_create = False

item_field_list = {
"id": {"text": "Name", "order": 1},
"count": {"text": "Number of entries", "order": 2},
}

search_config_name = "VOCABULARIES_TYPES_SEARCH"
search_facets_config_name = "VOCABULARIES_TYPES_FACETS"
search_sort_config_name = "VOCABULARIES_TYPES_SORT_OPTIONS"


class VocabularyDetailsListView(AdminResourceListView):
Copy link
Contributor

@kpsherva kpsherva Jul 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you considered inheriting from both Details and List views?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not yet. Could you explain how that might help with our issues?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would ensure less ambiguity on where the methods are actually coming from, this class now only imitates the interface of AdminResourceDetails view in order to use some of its frontend functionalities, while it does not actually inherit from the class itself. It might create divergence on the implementation of these "virtually" inherited methods the code it will be harder to maintain.
So to answer your question, it does not solve immediate problems but prevents ambiguity in the future

"""Configuration for vocabularies list view."""

def get_api_endpoint(self, pid_value=None):
"""Overwrite get_api_endpoint to accept pid_value."""
if pid_value in current_app.config.get(
"VOCABULARIES_CUSTOM_VOCABULARY_TYPES", []
):
return f"/api/{pid_value}"
else:
return f"/api/vocabularies/{pid_value}"

def get_context(self, **kwargs):
SarahW91 marked this conversation as resolved.
Show resolved Hide resolved
"""Create details view context."""
search_conf = self.init_search_config(**kwargs)
schema = self.get_service_schema()
serialized_schema = self._schema_to_json(schema)
pid_value = kwargs.get("pid_value", "")
return {
"search_config": search_conf,
"title": f"{pid_value.capitalize()} vocabulary items",
"name": self.name,
"resource_schema": serialized_schema,
"fields": self.item_field_list,
"display_search": self.display_search,
"display_create": self.display_create,
"display_edit": self.display_edit,
"display_delete": self.display_delete,
"display_read": self.display_read,
"actions": self.serialize_actions(),
"pid_path": self.pid_path,
"pid_value": pid_value,
"create_ui_endpoint": self.get_create_view_endpoint(),
"list_ui_endpoint": self.get_list_view_endpoint(),
"resource_name": (
self.resource_name if self.resource_name else self.pid_path
),
}
SarahW91 marked this conversation as resolved.
Show resolved Hide resolved

name = "vocabulary-type-items"
url = "/vocabulary-types/<pid_value>"

api_endpoint = "/vocabularies/"

# INFO name of the resource's list view name, enables navigation between items view and types view.
list_view_name = "vocabulary-types"

resource_config = "vocabulary_admin_resource"
search_request_headers = {"Accept": "application/json"}

pid_path = "id"

# INFO only if disabled() (as a function) it's not in the sidebar, see https://github.com/inveniosoftware/invenio-administration/blob/main/invenio_administration/menu/menu.py#L54
disabled = lambda _: True

template = "invenio_administration/search.html"

display_delete = False
display_create = False
display_edit = True
display_search = True

# TODO: It would be nicer to choose the correct column depending on the vocabulary
# TODO: It would ne nicer to use the title's translation in the currently selected language and fall back to English if this doesn't exist
item_field_list = {
"name": {"text": "Name", "order": 0},
"title['en']": {"text": "Title [en]", "order": 1},
"subject": {"text": "Subject", "order": 2},
"created": {"text": "Created", "order": 3},
}

search_config_name = "VOCABULARIES_TYPES_ITEMS_SEARCH"
search_facets_config_name = "VOCABULARIES_TYPES_ITEMS_FACETS"
search_sort_config_name = "VOCABULARIES_TYPES_ITEMS_SORT_OPTIONS"
55 changes: 53 additions & 2 deletions invenio_vocabularies/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
)
from .datastreams.transformers import XMLTransformer
from .datastreams.writers import ServiceWriter, YamlWriter
from .resources.resource import VocabulariesResourceConfig
from .services.service import VocabulariesServiceConfig
from .resources import VocabulariesResourceConfig
from .services.config import VocabulariesServiceConfig

VOCABULARIES_RESOURCE_CONFIG = VocabulariesResourceConfig
"""Configure the resource."""
Expand Down Expand Up @@ -103,6 +103,15 @@
}
"""Names allowed identifier schemes."""

# configure CUSTOM_VOCABULARY_TYPES to differentiate output. Is used in VocabulariesServiceConfig
VOCABULARIES_CUSTOM_VOCABULARY_TYPES = [
"names",
"affiliations",
"awards",
"funders",
"subjects",
]

VOCABULARIES_DATASTREAM_READERS = {
"csv": CSVReader,
"json": JsonReader,
Expand All @@ -126,3 +135,45 @@
"yaml": YamlWriter,
}
"""Data Streams writers."""

VOCABULARIES_TYPES_SORT_OPTIONS = {
"name": dict(
title=_("Name"),
fields=["id"],
),
"count": dict(
title=_("Number of entries"),
fields=["count"],
),
}
"""Definitions of available Vocabulary types sort options. """

VOCABULARIES_TYPES_SEARCH = {
"facets": [],
"sort": ["name", "count"],
}
"""Vocabulary type search configuration."""

VOCABULARIES_TYPES_ITEMS_SORT_OPTIONS = {
"name": dict(
title=_("Name"),
fields=["id"],
),
"title": dict(
title=_("Title"),
fields=["title"],
),
"subject": dict(
title=_("Subject"),
fields=["subject"],
),
"created": dict(
title=_("Created"),
fields=["created"],
),
}

VOCABULARIES_TYPES_ITEMS_SEARCH = {
"facets": [],
"sort": ["name", "title", "subject", "created"],
}
27 changes: 21 additions & 6 deletions invenio_vocabularies/ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,14 @@
SubjectsService,
SubjectsServiceConfig,
)
from .resources.resource import VocabulariesResource
from .services.service import VocabulariesService
from .resources import (
VocabulariesAdminResource,
VocabulariesResource,
VocabulariesResourceConfig,
VocabularyTypeResourceConfig,
)
from .services.config import VocabularyTypesServiceConfig
from .services.service import VocabulariesService, VocabularyTypeService


class InvenioVocabularies(object):
Expand Down Expand Up @@ -76,6 +82,7 @@ class ServiceConfigs:
funders = FundersServiceConfig
names = NamesServiceConfig
subjects = SubjectsServiceConfig
vocabulary_types = VocabularyTypesServiceConfig

return ServiceConfigs

Expand All @@ -93,9 +100,12 @@ def init_services(self, app):
self.funders_service = FundersService(config=service_configs.funders)
self.names_service = NamesService(config=service_configs.names)
self.subjects_service = SubjectsService(config=service_configs.subjects)
self.service = VocabulariesService(
self.vocabularies_service = VocabulariesService(
config=app.config["VOCABULARIES_SERVICE_CONFIG"],
)
self.vocabulary_types_service = VocabularyTypeService(
config=service_configs.vocabulary_types
)

def init_resource(self, app):
"""Initialize vocabulary resources."""
Expand All @@ -121,9 +131,13 @@ def init_resource(self, app):
config=SubjectsResourceConfig,
)
self.resource = VocabulariesResource(
service=self.service,
service=self.vocabularies_service,
config=app.config["VOCABULARIES_RESOURCE_CONFIG"],
)
self.vocabulary_admin_resource = VocabulariesAdminResource(
service=self.vocabulary_types_service,
config=VocabularyTypeResourceConfig,
)


def finalize_app(app):
Expand Down Expand Up @@ -153,12 +167,13 @@ def init(app):
sregistry.register(ext.funders_service, service_id="funders")
sregistry.register(ext.names_service, service_id="names")
sregistry.register(ext.subjects_service, service_id="subjects")
sregistry.register(ext.service, service_id="vocabularies")
sregistry.register(ext.vocabularies_service, service_id="vocabularies")
sregistry.register(ext.vocabulary_types_service, service_id="vocabulary-types")
# Register indexers
iregistry = app.extensions["invenio-indexer"].registry
iregistry.register(ext.affiliations_service.indexer, indexer_id="affiliations")
iregistry.register(ext.awards_service.indexer, indexer_id="awards")
iregistry.register(ext.funders_service.indexer, indexer_id="funders")
iregistry.register(ext.names_service.indexer, indexer_id="names")
iregistry.register(ext.subjects_service.indexer, indexer_id="subjects")
iregistry.register(ext.service.indexer, indexer_id="vocabularies")
iregistry.register(ext.vocabularies_service.indexer, indexer_id="vocabularies")
2 changes: 1 addition & 1 deletion invenio_vocabularies/proxies.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def _ext_proxy(attr):
)


current_service = _ext_proxy("service")
current_service = _ext_proxy("vocabularies_service")
"""Proxy to the instantiated vocabulary service."""


Expand Down
7 changes: 7 additions & 0 deletions invenio_vocabularies/resources/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,14 @@
"""Resources module."""
from invenio_vocabularies.resources.schema import L10NString, VocabularyL10Schema

from .config import VocabulariesResourceConfig, VocabularyTypeResourceConfig
from .resource import VocabulariesAdminResource, VocabulariesResource

__all__ = (
"VocabularyL10Schema",
"L10NString",
"VocabulariesResourceConfig",
"VocabularyTypeResourceConfig",
"VocabulariesAdminResource",
"VocabulariesResource",
)
Loading
Loading