diff --git a/pyproject.toml b/pyproject.toml
index d27487cf6d..71209ca4db 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -186,7 +186,7 @@ rero-ils = "rero_ils.modules.ext:REROILSAPP"
[tool.poetry.plugins."invenio_base.blueprints"]
circ_policies = "rero_ils.modules.circ_policies.views:blueprint"
collections = "rero_ils.modules.collections.views:blueprint"
-remote_entities = "rero_ils.modules.entities.remote_entities.views:blueprint"
+entities = "rero_ils.modules.entities.views:blueprint"
documents = "rero_ils.modules.documents.views:blueprint"
holdings = "rero_ils.modules.holdings.views:blueprint"
ill_requests = "rero_ils.modules.ill_requests.views:blueprint"
diff --git a/rero_ils/config.py b/rero_ils/config.py
index f8dc528b39..6fe9bb5053 100644
--- a/rero_ils/config.py
+++ b/rero_ils/config.py
@@ -40,7 +40,7 @@
ItemOnLoanToItemReturned, PendingToItemAtDesk, \
PendingToItemInTransitPickup, ToCancelled, ToItemOnLoan
from invenio_records_rest.facets import range_filter, terms_filter
-from invenio_records_rest.utils import deny_all, allow_all
+from invenio_records_rest.utils import allow_all, deny_all
from rero_ils.modules.acquisition.acq_accounts.api import AcqAccount
from rero_ils.modules.acquisition.acq_accounts.permissions import \
@@ -63,6 +63,12 @@
from rero_ils.modules.acquisition.budgets.api import Budget
from rero_ils.modules.acquisition.budgets.permissions import \
BudgetPermissionPolicy
+from rero_ils.modules.entities.local_entities.api import LocalEntity
+from rero_ils.modules.entities.local_entities.permissions import \
+ LocalEntityPermissionPolicy
+from rero_ils.modules.entities.remote_entities.api import RemoteEntity
+from rero_ils.modules.entities.remote_entities.permissions import \
+ RemoteEntityPermissionPolicy
from .modules.circ_policies.api import CircPolicy
from .modules.circ_policies.permissions import \
@@ -73,9 +79,6 @@
from .modules.documents.permissions import DocumentPermissionPolicy
from .modules.documents.query import acquisition_filter, \
nested_identified_filter
-from rero_ils.modules.entities.remote_entities.api import RemoteEntity
-from rero_ils.modules.entities.remote_entities.permissions import \
- RemoteEntityPermissionPolicy
from .modules.holdings.api import Holding
from .modules.holdings.models import HoldingCirculationAction
from .modules.holdings.permissions import HoldingsPermissionPolicy
@@ -98,9 +101,6 @@
get_extension_params, is_item_available_for_checkout, \
loan_build_document_ref, loan_build_item_ref, loan_build_patron_ref, \
validate_item_pickup_transaction_locations, validate_loan_duration
-from rero_ils.modules.entities.local_entities.api import LocalEntity
-from rero_ils.modules.entities.local_entities.permissions import \
- LocalEntityPermissionPolicy
from .modules.local_fields.api import LocalField
from .modules.local_fields.permissions import LocalFieldPermissionPolicy
from .modules.locations.api import Location
@@ -3060,6 +3060,7 @@ def _(x):
#: Entities
RERO_ILS_AGENTS_SOURCES = ['idref', 'gnd', 'rero']
+RERO_ILS_AGENTS_SOURCES_EXCLUDE_LINK = ['rero']
RERO_ILS_AGENTS_LABEL_ORDER = {
'fallback': 'fr',
'fr': ['idref', 'rero', 'gnd'],
diff --git a/rero_ils/filter.py b/rero_ils/filter.py
index 6c461061f0..162b47fbe3 100644
--- a/rero_ils/filter.py
+++ b/rero_ils/filter.py
@@ -25,6 +25,7 @@
import dateparser
from babel.dates import format_date, format_datetime, format_time
from flask import current_app, render_template
+from flask_babelex import gettext as _
from invenio_i18n.ext import current_i18n
from jinja2 import TemplateNotFound
from markupsafe import Markup
@@ -102,6 +103,10 @@ def format_date_filter(
if not locale:
locale = current_i18n.locale.language
+ # Date formatting in GB English (DD/MM/YYYY)
+ if locale == 'en':
+ locale += '_GB'
+
if timezone:
tzinfo = timezone
else:
@@ -184,3 +189,19 @@ def message_filter(key):
:return: none or a json (check structure into the class Message).
"""
return Message.get(key)
+
+
+def translate(data, prefix='', separator=', '):
+ """Translate data.
+
+ :param data: the data to translate
+ :param prefix: A prefix as a character string
+ :param separator: A character string separator.
+ :return: The translated string
+ """
+ if data:
+ if isinstance(data, list):
+ translated = [_(f'{prefix}{item}') for item in data]
+ return separator.join(translated)
+ elif isinstance(data, str):
+ return _(f'{prefix}{data}')
diff --git a/rero_ils/modules/documents/api.py b/rero_ils/modules/documents/api.py
index 170b8fcaa1..96bd65e5b5 100644
--- a/rero_ils/modules/documents/api.py
+++ b/rero_ils/modules/documents/api.py
@@ -73,6 +73,30 @@ class Meta:
default_filter = None
+ def by_entity(self, entity, subjects=True, imported_subjects=True,
+ genre_forms=True):
+ """Build a search to get hits related to an entity.
+
+ :param entity: the entity record to search.
+ :param subjects: search on `subject` field.
+ :param imported_subjects: search on `imported_subject` field.
+ :param genre_forms: search on `genre_forms` field.
+ :returns: An ElasticSearch query to get hits related the entity.
+ :rtype: `elasticsearch_dsl.Search`
+ """
+ field = f'contribution.entity.pids.{entity.resource_type}'
+ filters = Q('term', **{field: entity.pid})
+ if subjects:
+ field = f'subjects.entity.pids.{entity.resource_type}'
+ filters |= Q('term', **{field: entity.pid})
+ if imported_subjects:
+ field = f'subjects_imported.pids.{entity.resource_type}'
+ filters |= Q('term', **{field: entity.pid})
+ if genre_forms:
+ field = f'genreForm.entity.pids.{entity.resource_type}'
+ filters |= Q('term', **{field: entity.pid})
+ return self.filter(filters)
+
class Document(IlsRecord):
"""Document class."""
@@ -244,6 +268,7 @@ def index_contributions(self, bulk=False):
"""Index all attached contributions."""
from rero_ils.modules.entities.remote_entities.api import \
RemoteEntitiesIndexer, RemoteEntity
+
from ..tasks import process_bulk_queue
contributions_ids = []
for contribution in self.get('contribution', []):
diff --git a/rero_ils/modules/documents/dojson/contrib/jsontomarc21/model.py b/rero_ils/modules/documents/dojson/contrib/jsontomarc21/model.py
index 8425537921..aa7ab42e03 100644
--- a/rero_ils/modules/documents/dojson/contrib/jsontomarc21/model.py
+++ b/rero_ils/modules/documents/dojson/contrib/jsontomarc21/model.py
@@ -26,8 +26,8 @@
from rero_ils.modules.documents.utils import display_alternate_graphic_first
from rero_ils.modules.documents.views import create_title_responsibilites
from rero_ils.modules.entities.models import EntityType
-from rero_ils.modules.entities.remote_entities.api import RemoteEntity, \
- RemoteEntitiesSearch
+from rero_ils.modules.entities.remote_entities.api import \
+ RemoteEntitiesSearch, RemoteEntity
from rero_ils.modules.holdings.api import Holding, HoldingsSearch
from rero_ils.modules.items.api import Item, ItemsSearch
from rero_ils.modules.libraries.api import Library
diff --git a/rero_ils/modules/documents/dumpers/replace_refs.py b/rero_ils/modules/documents/dumpers/replace_refs.py
index 609192974d..6abc939c96 100644
--- a/rero_ils/modules/documents/dumpers/replace_refs.py
+++ b/rero_ils/modules/documents/dumpers/replace_refs.py
@@ -20,8 +20,7 @@
from invenio_records.dumpers import Dumper
from rero_ils.modules.commons.exceptions import RecordNotFound
-from rero_ils.modules.entities.dumpers import \
- document_dumper
+from rero_ils.modules.entities.dumpers import document_dumper
from rero_ils.modules.entities.remote_entities.utils import \
extract_data_from_mef_uri
from rero_ils.modules.utils import extracted_data_from_ref
diff --git a/rero_ils/modules/documents/extensions/provision_activities.py b/rero_ils/modules/documents/extensions/provision_activities.py
index ff8e6ab616..598f8cd410 100644
--- a/rero_ils/modules/documents/extensions/provision_activities.py
+++ b/rero_ils/modules/documents/extensions/provision_activities.py
@@ -22,9 +22,9 @@
from invenio_records.extensions import RecordExtension
from rero_ils.dojson.utils import remove_trailing_punctuation
+from rero_ils.modules.entities.models import EntityType
from ..utils import display_alternate_graphic_first
-from rero_ils.modules.entities.models import EntityType
class ProvisionActivitiesExtension(RecordExtension):
diff --git a/rero_ils/modules/documents/serializers/base.py b/rero_ils/modules/documents/serializers/base.py
index d4cebcd233..7b510d2963 100644
--- a/rero_ils/modules/documents/serializers/base.py
+++ b/rero_ils/modules/documents/serializers/base.py
@@ -24,10 +24,10 @@
from rero_ils.modules.commons.identifiers import IdentifierFactory, \
IdentifierStatus, IdentifierType
+from rero_ils.modules.entities.models import EntityType
from rero_ils.modules.utils import get_base_url
from ..api import DocumentsSearch
-from rero_ils.modules.entities.models import EntityType
CREATOR_ROLES = [
'aut', 'cmp', 'cre', 'dub', 'pht', 'ape', 'aqt', 'arc', 'art', 'aus',
diff --git a/rero_ils/modules/documents/templates/rero_ils/detailed_view_documents.html b/rero_ils/modules/documents/templates/rero_ils/detailed_view_documents.html
index 83c1c6bb09..dad7691285 100644
--- a/rero_ils/modules/documents/templates/rero_ils/detailed_view_documents.html
+++ b/rero_ils/modules/documents/templates/rero_ils/detailed_view_documents.html
@@ -2,6 +2,7 @@
RERO ILS
Copyright (C) 2019-2023 RERO
+ Copyright (C) 2019-2023 UCLouvain
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
@@ -218,7 +219,18 @@
{% for subject in record.subjects %}
{% if 'entity' in subject %}
- {{ subject.entity | doc_entity_label(language=current_i18n.language) }}
+ {% set type, value, label = subject.entity | doc_entity_label(language=current_i18n.language) %}
+ {% if 'textual' == type %}
+ {% set query = 'subjects.entity.authorized_access_point_' ~ current_i18n.language ~ ':"' ~ value ~ '"' %}
+ {% elif type in ['local', 'remote'] %}
+ {% set query = 'subjects.entity.pids.' ~ type ~ ':' ~ value %}
+ {% endif %}
+
+ {% if query %}
+ {{ label }}
+ {% else %}
+ {{ label }}
+ {% endif %}
{% endif %}
{% endfor %}
@@ -230,16 +242,25 @@
{% for genreForm in record.genreForm %}
{% if 'entity' in genreForm %}
+ {% set type, value, label = genreForm.entity | doc_entity_label(language=current_i18n.language) %}
+ {% if 'textual' == type %}
+ {% set query = 'genreForm.entity.authorized_access_point_' ~ current_i18n.language ~ ':"' ~ value ~ '"' %}
+ {% elif type in ['local', 'remote'] %}
+ {% set query = 'genreForm.entity.pids.' ~ type ~ ':' ~ value %}
+ {% endif %}
- {{ genreForm.entity | doc_entity_label(language=current_i18n.language) }}
+ {% if query %}
+ {{ label }}
+ {% else %}
+ {{ label }}
+ {% endif %}
{% endif %}
{% endfor %}
{% endif %}
-
{% if linked_documents_count and linked_documents_count > 0 %}
{text}'
else:
default_key = 'authorized_access_point'
- localized_key = f'{default_key}_{language}'
- label = contrib['entity'].get(localized_key) or \
+ localized_key = f'authorized_access_point_{language}'
+ text = contrib['entity'].get(localized_key) or \
contrib['entity'].get(default_key)
+ args = {
+ 'viewcode': viewcode,
+ 'recordType': 'documents',
+ 'q': f'contribution.entity.{localized_key}:"{text}"',
+ 'simple': 0
+ }
+ url = url_for('rero_ils.search', **args)
+ label = f'{text}'
if with_roles:
if roles := [_(role) for role in contrib.get('role', [])]:
@@ -288,7 +295,7 @@ def contribution_format(contributions, language, viewcode, with_roles=False):
label += f' ({roles_str})'
output.append(label)
- return ' ; '.join(output)
+ return ' ; '.join(output)
@blueprint.app_template_filter()
@@ -301,20 +308,28 @@ def doc_entity_label(entity, language=None, part_separator=' - ') -> str:
:returns: the best possible label to display.
"""
parts = []
- if 'pid' in entity:
- entity = RemoteEntity.get_record_by_pid(entity['pid'])
- parts.append(entity.get_authorized_access_point(language=language))
+ if '$ref' in entity:
+ # Local or remote entity
+ if entity := Entity.get_record_by_ref(entity['$ref']):
+ entity_type = entity.resource_type
+ value = entity.pid
+ parts.append(entity.get_authorized_access_point(language=language))
else:
+ # Textual entity
+ entity_type = 'textual'
default_key = 'authorized_access_point'
localized_key = f'{default_key}_{language}'
- parts.append(entity.get(localized_key) or entity.get(default_key))
+ value = entity.get(localized_key) or entity.get(default_key)
+ parts.append(value)
+ # Subdivisions (only for textual entity)
for subdivision in entity.get('subdivisions', []):
if sub_entity := subdivision.get('entity'):
- parts.append(
- doc_entity_label(sub_entity, language, part_separator))
+ _, _, label = doc_entity_label(
+ sub_entity, language, part_separator)
+ parts.append(label)
- return part_separator.join(filter(None, parts))
+ return entity_type, value, part_separator.join(filter(None, parts))
@blueprint.app_template_filter()
diff --git a/rero_ils/modules/entities/api.py b/rero_ils/modules/entities/api.py
index 906763202a..a8b6498a99 100644
--- a/rero_ils/modules/entities/api.py
+++ b/rero_ils/modules/entities/api.py
@@ -20,16 +20,42 @@
from abc import ABC, abstractmethod
-from elasticsearch_dsl import Q, A
+from elasticsearch_dsl import A
from flask import current_app
-from rero_ils.modules.api import IlsRecord
+from rero_ils.modules.api import IlsRecord, IlsRecordsSearch
from rero_ils.modules.documents.api import DocumentsSearch
+from rero_ils.modules.entities.remote_entities.utils import \
+ extract_data_from_mef_uri
+from rero_ils.modules.utils import extracted_data_from_ref, sorted_pids
+
+
+class EntitiesSearch(IlsRecordsSearch):
+ """Entities search class."""
+
+ class Meta:
+ """Meta class."""
+
+ index = 'entities'
+ doc_types = None
+ fields = ('*', )
+ facets = {}
+
+ default_filter = None
class Entity(IlsRecord, ABC):
"""Entity class."""
+ @classmethod
+ def get_record_by_ref(cls, ref):
+ """."""
+ from .remote_entities.api import RemoteEntity
+ if entity := extracted_data_from_ref(ref, 'record'):
+ return entity
+ _, _type, _pid = extract_data_from_mef_uri(ref)
+ return RemoteEntity.get_entity(_type, _pid)
+
@abstractmethod
def get_authorized_access_point(self, language):
"""Get localized authorized_access_point.
@@ -39,6 +65,30 @@ def get_authorized_access_point(self, language):
"""
raise NotImplementedError
+ @abstractmethod
+ def get_links_to_me(self, get_pids=False):
+ """Get links to other resources.
+
+ :param get_pids: related resource pids are included into response ;
+ otherwise the count of related resources are specified.
+ :returns: list of related resource to this entity.
+ :rtype: dict.
+ """
+ document_query = DocumentsSearch().by_entity(self)
+ documents = sorted_pids(document_query) if get_pids \
+ else document_query.count()
+ links = {
+ 'documents': documents
+ }
+ return {k: v for k, v in links.items() if v}
+
+ def reasons_not_to_delete(self):
+ """Get reasons not to delete record."""
+ cannot_delete = {}
+ if links := self.get_links_to_me():
+ cannot_delete['links'] = links
+ return cannot_delete
+
@property
@abstractmethod
def resource_type(self):
@@ -47,8 +97,8 @@ def resource_type(self):
@property
def organisation_pids(self):
- """Get organisations pids."""
- search = self._search_documents()
+ """Get organisation pids related with this entity."""
+ search = DocumentsSearch().by_entity(self)[:0]
agg = A(
'terms',
field='holdings.organisation.organisation_pid',
@@ -64,39 +114,25 @@ def organisation_pids(self):
for result in results.aggregations.organisation.buckets
})
- def _search_documents(
+ def documents_pids(
self, with_subjects=True, with_subjects_imported=True,
with_genre_forms=True
):
- """Get ES query to search documents containing this entity.
+ """Get documents pids related to this entity.
- :param with_subjects: search also on `subjects` ?
- :param with_subjects_imported: search also on `subject_imported` ?
- :param with_genre_forms: search also on `genreForm` ?
+ :param with_subjects: is the document `subject` field must be analyzed.
+ :param with_subjects_imported: is the document `subject_imported` field
+ must be analyzed.
+ :param with_genre_forms: is the document `genre_forms` field must be
+ analyzed.
+ :returns: document pids related to this entity.
+ :rtype: list
"""
- contribution_key = f'contribution.entity.pids.{self.resource_type}'
- filters = Q('term', **{contribution_key: self.pid})
- if with_subjects:
- search_field = f'subjects.entity.pids.{self.resource_type}'
- filters |= Q('term', **{search_field: self.pid})
- if with_subjects_imported:
- search_field = f'subjects_imported.pids.{self.resource_type}'
- filters |= Q('term', **{search_field: self.pid})
- if with_genre_forms:
- search_field = f'genreForm.entity.pids.{self.resource_type}'
- filters |= Q('term', **{search_field: self.pid})
-
- return DocumentsSearch().filter(filters)
-
- def documents_pids(
- self, with_subjects=True, with_subjects_imported=True,
- with_genre_forms=True
- ):
- """Get documents pids."""
- search = self._search_documents(
- with_subjects=with_subjects,
- with_subjects_imported=with_subjects_imported,
- with_genre_forms=with_genre_forms
+ search = DocumentsSearch().by_entity(
+ self,
+ subjects=with_subjects,
+ imported_subjects=with_subjects_imported,
+ genre_forms=with_genre_forms
).source('pid')
return [hit.pid for hit in search.scan()]
@@ -104,10 +140,20 @@ def documents_ids(
self, with_subjects=True, with_subjects_imported=True,
with_genre_forms=True
):
- """Get documents ids."""
- search = self._search_documents(
- with_subjects=with_subjects,
- with_subjects_imported=with_subjects_imported,
- with_genre_forms=with_genre_forms
+ """Get document ID's/UUID related to this entity.
+
+ :param with_subjects: is the document `subject` field must be analyzed.
+ :param with_subjects_imported: is the document `subject_imported` field
+ must be analyzed.
+ :param with_genre_forms: is the document `genre_forms` field must be
+ analyzed.
+ :returns: document ID's/UUID related to this entity.
+ :rtype: list
+ """
+ search = DocumentsSearch().by_entity(
+ self,
+ subjects=with_subjects,
+ imported_subjects=with_subjects_imported,
+ genre_forms=with_genre_forms
).source(False)
return [hit.meta.id for hit in search.scan()]
diff --git a/rero_ils/modules/entities/local_entities/api.py b/rero_ils/modules/entities/local_entities/api.py
index 955b1a33f4..6d847d6e64 100644
--- a/rero_ils/modules/entities/local_entities/api.py
+++ b/rero_ils/modules/entities/local_entities/api.py
@@ -21,7 +21,6 @@
from functools import partial
from rero_ils.modules.api import IlsRecordsSearch
-from rero_ils.modules.utils import sorted_pids
from rero_ils.modules.fetchers import id_fetcher
from rero_ils.modules.minters import id_minter
from rero_ils.modules.operation_logs.extensions import \
@@ -113,24 +112,3 @@ def resolve(self):
# The links will be stored as a `$ref` and `replace_refs_dumper`
# will be used.
return self.dumps(replace_refs_dumper)
-
- def get_links_to_me(self, get_pids=False):
- """Record links.
-
- :param get_pids: if True list of linked pids
- if False count of linked records
- """
- document_query = self._search_documents()
- documents = sorted_pids(document_query) if get_pids \
- else document_query.count()
- links = {
- 'documents': documents
- }
- return {k: v for k, v in links.items() if v}
-
- def reasons_not_to_delete(self):
- """Get reasons not to delete record."""
- cannot_delete = {}
- if links := self.get_links_to_me():
- cannot_delete['links'] = links
- return cannot_delete
diff --git a/rero_ils/modules/entities/local_entities/indexer.py b/rero_ils/modules/entities/local_entities/indexer.py
index fe0cc33b6b..0bdfc97ca1 100644
--- a/rero_ils/modules/entities/local_entities/indexer.py
+++ b/rero_ils/modules/entities/local_entities/indexer.py
@@ -17,14 +17,15 @@
# along with this program. If not, see .
"""Local entity indexer APIs."""
-from celery import shared_task
from datetime import datetime
+from celery import shared_task
from flask import current_app
-from rero_ils.modules.utils import get_record_class_by_resource, \
- get_indexer_class_by_resource
from rero_ils.modules.api import IlsRecordsIndexer, ReferencedRecordsIndexer
+from rero_ils.modules.utils import get_indexer_class_by_resource, \
+ get_record_class_by_resource
+
from .api import LocalEntity
from ..dumpers import indexer_dumper
diff --git a/rero_ils/modules/entities/local_entities/jsonschemas/local_entities/local_entity_organisation-v0.0.1.json b/rero_ils/modules/entities/local_entities/jsonschemas/local_entities/local_entity_organisation-v0.0.1.json
index 0a9f437161..8f24ac20ae 100644
--- a/rero_ils/modules/entities/local_entities/jsonschemas/local_entities/local_entity_organisation-v0.0.1.json
+++ b/rero_ils/modules/entities/local_entities/jsonschemas/local_entities/local_entity_organisation-v0.0.1.json
@@ -14,10 +14,10 @@
"type",
"name",
"subordinate_units",
- "conference",
"conference_numbering",
"conference_date",
"conference_place",
+ "conference",
"start_date",
"end_date",
"alternative_names",
@@ -116,8 +116,7 @@
"type": "string",
"minLength": 1,
"form": {
- "placeholder": "Example: Paris",
- "hideExpression": "!field?.parent?.model || !field.parent.model.conference || field.parent.model.conference == false"
+ "placeholder": "Example: Paris"
}
},
"conference_numbering": {
@@ -125,8 +124,7 @@
"type": "string",
"minLength": 1,
"form": {
- "placeholder": "Example: 23e",
- "hideExpression": "!field?.parent?.model || !field.parent.model.conference || field.parent.model.conference == false"
+ "placeholder": "Example: 23e"
}
},
"conference_date": {
@@ -135,8 +133,7 @@
"type": "string",
"minLength": 1,
"form": {
- "placeholder": "Example: 2022",
- "hideExpression": "!field?.parent?.model || !field.parent.model.conference || field.parent.model.conference == false"
+ "placeholder": "Example: 2022"
}
},
"alternative_names": {
diff --git a/rero_ils/modules/entities/local_entities/mappings/v7/local_entities/local_entity-v0.0.1.json b/rero_ils/modules/entities/local_entities/mappings/v7/local_entities/local_entity-v0.0.1.json
index 7c96955e5c..f28776ac0c 100644
--- a/rero_ils/modules/entities/local_entities/mappings/v7/local_entities/local_entity-v0.0.1.json
+++ b/rero_ils/modules/entities/local_entities/mappings/v7/local_entities/local_entity-v0.0.1.json
@@ -124,10 +124,16 @@
"type": "text"
},
"alternative_names": {
- "type": "text"
+ "type": "text",
+ "copy_to": [
+ "autocomplete_name"
+ ]
},
"fuller_form_of_name": {
- "type": "text"
+ "type": "text",
+ "copy_to": [
+ "autocomplete_name"
+ ]
},
"gender": {
"type": "keyword"
diff --git a/rero_ils/modules/entities/local_entities/permissions.py b/rero_ils/modules/entities/local_entities/permissions.py
index 1a10524e94..6af2cd6d83 100644
--- a/rero_ils/modules/entities/local_entities/permissions.py
+++ b/rero_ils/modules/entities/local_entities/permissions.py
@@ -19,8 +19,8 @@
"""Permissions for `Local Entity` records."""
from invenio_access import action_factory
-from rero_ils.modules.permissions import RecordPermissionPolicy, \
- AllowedByAction
+from rero_ils.modules.permissions import AllowedByAction, \
+ RecordPermissionPolicy
# Actions to control local entity policies for CRUD operations
search_action = action_factory('locent-search')
diff --git a/rero_ils/modules/entities/local_entities/proxy.py b/rero_ils/modules/entities/local_entities/proxy.py
index 75ea3b18b0..ec93ee5a03 100644
--- a/rero_ils/modules/entities/local_entities/proxy.py
+++ b/rero_ils/modules/entities/local_entities/proxy.py
@@ -22,7 +22,6 @@
from .api import LocalEntitiesSearch
from ..models import EntityType
-
CATEGORY_FILTERS = {
'agents': Q('terms', type=[EntityType.PERSON, EntityType.ORGANISATION]),
'person': Q('term', type=EntityType.PERSON),
diff --git a/rero_ils/modules/entities/remote_entities/__init__.py b/rero_ils/modules/entities/remote_entities/__init__.py
index ff7065b145..aba233d747 100644
--- a/rero_ils/modules/entities/remote_entities/__init__.py
+++ b/rero_ils/modules/entities/remote_entities/__init__.py
@@ -1,7 +1,8 @@
# -*- coding: utf-8 -*-
#
# RERO ILS
-# Copyright (C) 2019-2022 RERO
+# Copyright (C) 2019-2023 RERO
+# Copyright (C) 2019-2023 UCLouvain
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
@@ -15,4 +16,4 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-"""Mef Contributions Records."""
+"""Remote entities Records."""
diff --git a/rero_ils/modules/entities/remote_entities/api.py b/rero_ils/modules/entities/remote_entities/api.py
index 7d69f12eca..76fa5d2303 100644
--- a/rero_ils/modules/entities/remote_entities/api.py
+++ b/rero_ils/modules/entities/remote_entities/api.py
@@ -32,10 +32,9 @@
from rero_ils.modules.minters import id_minter
from rero_ils.modules.providers import Provider
-from .models import RemoteEntityIdentifier, RemoteEntityMetadata, \
- EntityUpdateAction
+from .models import EntityUpdateAction, RemoteEntityIdentifier, \
+ RemoteEntityMetadata
from .utils import extract_data_from_mef_uri, get_mef_data_by_type
-
from ..api import Entity
from ..dumpers import indexer_dumper, replace_refs_dumper
from ..models import EntityResourceType
diff --git a/rero_ils/modules/entities/remote_entities/sync.py b/rero_ils/modules/entities/remote_entities/sync.py
index 1733c7fe76..2be3f64dfa 100644
--- a/rero_ils/modules/entities/remote_entities/sync.py
+++ b/rero_ils/modules/entities/remote_entities/sync.py
@@ -29,11 +29,12 @@
from rero_ils.modules.commons.exceptions import RecordNotFound
from rero_ils.modules.documents.api import Document
-from rero_ils.modules.entities.remote_entities.api import \
- RemoteEntitiesSearch, RemoteEntity
from rero_ils.modules.utils import get_mef_url, get_timestamp, \
requests_retry_session, set_timestamp
+from .api import RemoteEntitiesSearch, RemoteEntity
+from ..logger import create_logger
+
class SyncEntity:
"""Entity MEF synchronization."""
diff --git a/rero_ils/modules/entities/remote_entities/templates/rero_ils/_entity_by_source.html b/rero_ils/modules/entities/remote_entities/templates/rero_ils/_entity_by_source.html
deleted file mode 100644
index 3eb2fe35ce..0000000000
--- a/rero_ils/modules/entities/remote_entities/templates/rero_ils/_entity_by_source.html
+++ /dev/null
@@ -1,55 +0,0 @@
-{# -*- coding: utf-8 -*-
-
- RERO ILS
- Copyright (C) 2019-2023 RERO
- Copyright (C) 2019-2023 UCLouvain
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, version 3 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see .
-
-#}
-
-
-{% for agency in ["rero", "gnd", "idref"] %}
-{% if record[agency] %}
-
-
-
-
-
-
-
-
-
- {% with data=record[agency], source_name='agency', source=agency %}
- {% include('rero_ils/_entity_by_source_data.html') %}
- {% endwith %}
-
-
-
-
-
-{% endif %}
-{% endfor %}
diff --git a/rero_ils/modules/entities/remote_entities/templates/rero_ils/_entity_unified.html b/rero_ils/modules/entities/remote_entities/templates/rero_ils/_entity_unified.html
deleted file mode 100644
index cf6305d56c..0000000000
--- a/rero_ils/modules/entities/remote_entities/templates/rero_ils/_entity_unified.html
+++ /dev/null
@@ -1,45 +0,0 @@
-{# -*- coding: utf-8 -*-
-
- RERO ILS
- Copyright (C) 2019-2023 RERO
- Copyright (C) 2019-2023 UCLouvain
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, version 3 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see .
-
-#}
-
-{% from 'rero_ils/macros/entity.html' import dl, dl_bool, dl_permalink %}
-{% set record = record %}
-{% set data = record | entity_merge_data_values %}
-
-
- {{ dl(_('Birth date'), data.date_of_birth) }}
- {{ dl(_('Death date'), data.date_of_death) }}
- {% if data.language %}
- {{ dl(_('Language'), data.language|translat_unified('lang_')) }}
- {% endif %}
- {{ dl(_('Gender'), data.gender) }}
- {{ dl(_('Biographical information'), data.biographical_information | biographicaUrl) }}
- {{ dl(_('Qualifier'), data.qualifier) }}
- {{ dl(_('Numeration'), data.numeration) }}
- {{ dl(_('Date establishment'), data.date_of_establishment) }}
- {{ dl(_('Death termination'), data.date_of_termination) }}
- {{ dl_bool(_('Conference'), data.conference) }}
- {% if data.country_associated %}
- {{ dl(_('Associated country'), data.country_associated|translat_unified('country_')) }}
- {% endif %}
- {{ dl_permalink(_('ID'), data) }}
- {{ dl(_('Authorized access point'), data.authorized_access_point) }}
- {{ dl(_('Variant access point'), data.variant_access_point) }}
- {{ dl(_('Parallel access point'), data.parallel_access_point) }}
-
diff --git a/rero_ils/modules/entities/remote_entities/templates/rero_ils/detailed_view_entity.html b/rero_ils/modules/entities/remote_entities/templates/rero_ils/detailed_view_entity.html
deleted file mode 100644
index 5541cbe30d..0000000000
--- a/rero_ils/modules/entities/remote_entities/templates/rero_ils/detailed_view_entity.html
+++ /dev/null
@@ -1,82 +0,0 @@
-{# -*- coding: utf-8 -*-
-
- RERO ILS
- Copyright (C) 2019-2022 RERO
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, version 3 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see .
-
-#}
-
-{%- extends 'rero_ils/page.html' %}
-
-{%- block body %}
-
-
-
-
-
- {% include('rero_ils/_entity_unified.html') %}
-
-
- {% include('rero_ils/_entity_by_source.html') %}
-
-
-
-
-{%- if record.documents %}
-
-{% endif %}
-
-{% endblock body %}
diff --git a/rero_ils/modules/entities/remote_entities/views.py b/rero_ils/modules/entities/remote_entities/views.py
index ac34a6cc9a..a2b5229d52 100644
--- a/rero_ils/modules/entities/remote_entities/views.py
+++ b/rero_ils/modules/entities/remote_entities/views.py
@@ -20,95 +20,18 @@
from __future__ import absolute_import, print_function
-import typing
-
-from flask import Blueprint, abort, current_app, render_template
-from flask_babelex import gettext as translate
-from invenio_records_ui.signals import record_viewed
+from flask import Blueprint, abort
from rero_ils.modules.decorators import check_logged_as_librarian
-from rero_ils.modules.documents.api import DocumentsSearch
-from rero_ils.modules.organisations.api import Organisation
-from rero_ils.theme.views import url_active
-from .api import RemoteEntity
-from ..models import EntityType
from .proxy import MEFProxyFactory
-blueprint = Blueprint(
- 'remote_entities',
- __name__,
- url_prefix='/',
- template_folder='templates',
- static_folder='static',
-)
-
api_blueprint = Blueprint(
'api_remote_entities',
__name__
)
-def remote_entity_proxy(viewcode, pid, entity_type):
- """Proxy for entities.
-
- :param viewcode: viewcode of html request
- :param pid: pid of contribution
- :param entity_type: type of the entity
- :returns: entity template
- """
- entity = RemoteEntity.get_record_by_pid(pid)
- if not entity or entity.get('type') != entity_type:
- abort(404, 'Record not found')
- return remote_entity_view_method(
- pid=entity.persistent_identifier,
- record=entity,
- template='rero_ils/detailed_view_entity.html',
- viewcode=viewcode
- )
-
-
-def remote_entity_view_method(pid, record, template=None, **kwargs):
- """Display default view.
-
- Sends record_viewed signal and renders template.
-
- :param pid: PID object.
- :param record: the `Entity` record,
- :param template: the template to use to render the entity
- """
- record_viewed.send(
- current_app._get_current_object(), pid=pid, record=record)
-
- # Get contribution persons documents
- search = DocumentsSearch()\
- .filter('term', contribution__entity__pid=pid.pid_value)
-
- viewcode = kwargs['viewcode']
- if viewcode != current_app.config.get('RERO_ILS_SEARCH_GLOBAL_VIEW_CODE'):
- org_pid = Organisation.get_record_by_viewcode(viewcode)['pid']
- search = search \
- .filter('term', holdings__organisation__organisation_pid=org_pid)
- search = search \
- .params(preserve_order=True)\
- .sort({'sort_title': {'order': 'asc'}})
-
- record['documents'] = list(search.scan())
- return render_template(template, record=record, viewcode=viewcode)
-
-
-@blueprint.route('/persons/', methods=['GET'])
-def persons_proxy(viewcode, pid):
- """Proxy person for entity."""
- return remote_entity_proxy(viewcode, pid, EntityType.PERSON)
-
-
-@blueprint.route('/corporate-bodies/', methods=['GET'])
-def corporate_bodies_proxy(viewcode, pid):
- """Proxy corporate bodies for entity."""
- return remote_entity_proxy(viewcode, pid, EntityType.ORGANISATION)
-
-
@api_blueprint.route('/remote_entities/search/',
defaults={'entity_type': 'agents'})
@api_blueprint.route('/remote_entities/search//')
@@ -128,79 +51,3 @@ def remote_search_proxy(entity_type, term):
return MEFProxyFactory.create_proxy(entity_type).search(term)
except ValueError as err:
abort(400, str(err))
-
-
-# TEMPLATE JINJA FILTERS ======================================================
-@blueprint.app_template_filter()
-def entity_merge_data_values(data):
- """Create merged data for values."""
- sources = current_app.config.get('RERO_ILS_AGENTS_SOURCES', [])
- result = {}
- for source in sources:
- if data.get(source):
- result[source] = {
- 'pid': data[source]['pid'],
- 'identifier': data[source]['identifier']
- }
- for key, values in data.get(source, {}).items():
- if key == 'conference':
- result['conference'] = data[source]['conference']
- else:
- if key not in result:
- result[key] = {}
- if isinstance(values, str):
- values = [values]
- for value in values:
- if isinstance(value, typing.Hashable):
- if value in result[key]:
- result[key][value].append(source)
- else:
- result[key][value] = [source]
- return result
-
-
-@blueprint.app_template_filter()
-def entity_label(data, language):
- """Create contribution label."""
- order = current_app.config.get('RERO_ILS_AGENTS_LABEL_ORDER', [])
- source_order = order.get(language, order.get(order['fallback'], []))
- for source in source_order:
- if label := data.get(source, {}).get('authorized_access_point', None):
- return label
- return '-'
-
-
-@blueprint.app_template_filter()
-def translat_unified(data, prefix=''):
- """Translate the keys of an dictionary.
-
- :param data: dictionary to translate
- :param prefix: prefix to add to keys
- :returns: dictionary with translated keys
- """
- return {
- translate(f'{prefix}{key}'): value
- for key, value
- in data.items()
- }
-
-
-@blueprint.app_template_filter()
-@api_blueprint.app_template_filter()
-def translat(data, prefix='', seperator=', '):
- """Translate data."""
- if data:
- if isinstance(data, list):
- translated = [translate(f'{prefix}{item}') for item in data]
- return seperator.join(translated)
- elif isinstance(data, str):
- return translate(f'{prefix}{data}')
-
-
-@blueprint.app_template_filter('biographicaUrl')
-def biographical_url(biographicals):
- """Add link url on text if http detected."""
- return {
- url_active(biographical, '_blank'): biographicals[biographical]
- for biographical in biographicals
- }
diff --git a/rero_ils/modules/entities/serializers/__init__.py b/rero_ils/modules/entities/serializers/__init__.py
index 14c3a11f45..f74f406517 100644
--- a/rero_ils/modules/entities/serializers/__init__.py
+++ b/rero_ils/modules/entities/serializers/__init__.py
@@ -18,8 +18,8 @@
"""RERO Unified entities serialization."""
-from rero_ils.modules.serializers import RecordSchemaJSONV1, \
- search_responsify
+from rero_ils.modules.serializers import RecordSchemaJSONV1, search_responsify
+
from .base import EntityJSONSerializer
# Serializers
diff --git a/rero_ils/modules/entities/templates/rero_ils/_local_organisation.html b/rero_ils/modules/entities/templates/rero_ils/_local_organisation.html
new file mode 100644
index 0000000000..a88976f481
--- /dev/null
+++ b/rero_ils/modules/entities/templates/rero_ils/_local_organisation.html
@@ -0,0 +1,28 @@
+{# -*- coding: utf-8 -*-
+
+ RERO ILS
+ Copyright (C) 2019-2023 RERO
+ Copyright (C) 2019-2023 UCLouvain
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, version 3 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+
+#}
+{{ dl(_('Name'), record.name) }}
+{{ dl(_('Subordinate units'), record.subordinate_units) }}
+{{ dl(_('Conference place'), record.conference_place) }}
+{{ dl(_('Conference numbering'), record.conference_numbering) }}
+{{ dl(_('Conference date'), record.conference_date) }}
+{{ dl_bool(_('Conference'), record.conference) }}
+{{ dl(_('Start date'), record.start_date) }}
+{{ dl(_('End date'), record.end_date) }}
+{{ dl(_('Alternative names'), record.alternative_names) }}
diff --git a/rero_ils/modules/entities/templates/rero_ils/_local_person.html b/rero_ils/modules/entities/templates/rero_ils/_local_person.html
new file mode 100644
index 0000000000..89a4ea4067
--- /dev/null
+++ b/rero_ils/modules/entities/templates/rero_ils/_local_person.html
@@ -0,0 +1,26 @@
+{# -*- coding: utf-8 -*-
+
+ RERO ILS
+ Copyright (C) 2019-2023 RERO
+ Copyright (C) 2019-2023 UCLouvain
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, version 3 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+
+#}
+{{ dl(_('Name'), record.name) }}
+{{ dl(_('Birth date'), record.date_of_birth) }}
+{{ dl(_('Death date'), record.date_of_death) }}
+{{ dl(_('Numeration'), record.numeration) }}
+{{ dl(_('Qualifier'), record.qualifier) }}
+{{ dl(_('Fuller form of name'), record.fuller_form_of_name) }}
+{{ dl(_('Alternative names'), record.alternative_names) }}
diff --git a/rero_ils/modules/entities/templates/rero_ils/_local_place.html b/rero_ils/modules/entities/templates/rero_ils/_local_place.html
new file mode 100644
index 0000000000..8c281c2318
--- /dev/null
+++ b/rero_ils/modules/entities/templates/rero_ils/_local_place.html
@@ -0,0 +1,21 @@
+{# -*- coding: utf-8 -*-
+
+ RERO ILS
+ Copyright (C) 2019-2023 RERO
+ Copyright (C) 2019-2023 UCLouvain
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, version 3 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+
+#}
+{{ dl(_('Name'), record.name) }}
+{{ dl(_('Alternative names'), record.alternative_names) }}
diff --git a/rero_ils/modules/entities/templates/rero_ils/_local_temporal.html b/rero_ils/modules/entities/templates/rero_ils/_local_temporal.html
new file mode 100644
index 0000000000..8c281c2318
--- /dev/null
+++ b/rero_ils/modules/entities/templates/rero_ils/_local_temporal.html
@@ -0,0 +1,21 @@
+{# -*- coding: utf-8 -*-
+
+ RERO ILS
+ Copyright (C) 2019-2023 RERO
+ Copyright (C) 2019-2023 UCLouvain
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, version 3 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+
+#}
+{{ dl(_('Name'), record.name) }}
+{{ dl(_('Alternative names'), record.alternative_names) }}
diff --git a/rero_ils/modules/entities/templates/rero_ils/_local_topic.html b/rero_ils/modules/entities/templates/rero_ils/_local_topic.html
new file mode 100644
index 0000000000..327fe585b6
--- /dev/null
+++ b/rero_ils/modules/entities/templates/rero_ils/_local_topic.html
@@ -0,0 +1,22 @@
+{# -*- coding: utf-8 -*-
+
+ RERO ILS
+ Copyright (C) 2019-2023 RERO
+ Copyright (C) 2019-2023 UCLouvain
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, version 3 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+
+#}
+{{ dl(_('Name'), record.name) }}
+{{ dl_bool(_('Genre form'), record.genreForm) }}
+{{ dl(_('Alternative names'), record.alternative_names) }}
diff --git a/rero_ils/modules/entities/templates/rero_ils/_local_work.html b/rero_ils/modules/entities/templates/rero_ils/_local_work.html
new file mode 100644
index 0000000000..5d534f4ef0
--- /dev/null
+++ b/rero_ils/modules/entities/templates/rero_ils/_local_work.html
@@ -0,0 +1,21 @@
+{# -*- coding: utf-8 -*-
+
+ RERO ILS
+ Copyright (C) 2019-2023 RERO
+ Copyright (C) 2019-2023 UCLouvain
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, version 3 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+
+#}
+{{ dl(_('Title'), record.title) }}
+{{ dl(_('Creator'), record.creator) }}
diff --git a/rero_ils/modules/entities/remote_entities/templates/rero_ils/_entity_by_source_data.html b/rero_ils/modules/entities/templates/rero_ils/_remote_organisation.html
similarity index 62%
rename from rero_ils/modules/entities/remote_entities/templates/rero_ils/_entity_by_source_data.html
rename to rero_ils/modules/entities/templates/rero_ils/_remote_organisation.html
index 0086768e61..c25c78cde8 100644
--- a/rero_ils/modules/entities/remote_entities/templates/rero_ils/_entity_by_source_data.html
+++ b/rero_ils/modules/entities/templates/rero_ils/_remote_organisation.html
@@ -18,24 +18,20 @@
#}
-{% from 'rero_ils/macros/entity.html' import dl, dl_bool, dl_permalink_by_source %}
-
-{{ dl(_('Birth date'), data.date_of_birth) }}
-{{ dl(_('Death date'), data.date_of_death) }}
-{% if data.language %}
- {{ dl(_('Language'), data.language|translat('lang_')) }}
-{% endif %}
-{{ dl(_('Gender'), data.gender) }}
-{{ dl(_('Biographical information'), data.biographical_information | join('\n') | urlActive('_blank') | nl2br | safe ) }}
-{{ dl(_('Qualifier'), data.qualifier) }}
-{{ dl(_('Numeration'), data.numeration) }}
+
{{ dl(_('Date establishment'), data.date_of_establishment) }}
+
{{ dl(_('Death termination'), data.date_of_termination) }}
-{{ dl_bool(_('Conference'), data.conference) }}
+
+{% if data.language %}
+ {{ dl(_('Language'), data.language|translate('lang_')) }}
+{% endif %}
+
{% if data.country_associated %}
- {{ dl(_('Associated country'), data.country_associated|translat('country_')) }}
+ {{ dl(_('Associated country'), data.country_associated|translate('country_')) }}
{% endif %}
-{{ dl_permalink_by_source(_('ID'), data, source) }}
+
{{ dl(_('Authorized access point'), data.authorized_access_point) }}
+
{{ dl(_('Variant access point'), data.variant_access_point) }}
-{{ dl(_('Parallel access point'), data.parallel_access_point) }}
+
diff --git a/rero_ils/modules/entities/templates/rero_ils/_remote_person.html b/rero_ils/modules/entities/templates/rero_ils/_remote_person.html
new file mode 100644
index 0000000000..c2b6eebad1
--- /dev/null
+++ b/rero_ils/modules/entities/templates/rero_ils/_remote_person.html
@@ -0,0 +1,44 @@
+{# -*- coding: utf-8 -*-
+
+ RERO ILS
+ Copyright (C) 2019-2023 RERO
+ Copyright (C) 2019-2023 UCLouvain
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, version 3 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+
+#}
+
+
+{% if data.date_of_birth %}
+ {{ dl(_('Birth date'), data.date_of_birth | format_date(date_format='short', time_format=None)) }}
+{% endif %}
+
+{% if data.date_of_death %}
+ {{ dl(_('Death date'), data.date_of_death | format_date(date_format='short', time_format=None)) }}
+{% endif %}
+
+{% if data.language %}
+ {{ dl(_('Language'), data.language|translate('lang_')) }}
+{% endif %}
+
+{{ dl(_('Gender'), data.gender) }}
+
+{% if data.biographical_information %}
+{{ dl(_('Biographical information'), data.biographical_information | join('\n') | urlActive('_blank') | nl2br | safe ) }}
+{% endif %}
+
+{{ dl(_('Name'), data.name) }}
+
+{{ dl(_('Variant access point'), data.variant_access_point) }}
+
+{{ dl(_('Authorized access point'), data.authorized_access_point) }}
diff --git a/rero_ils/modules/entities/templates/rero_ils/_remote_topic.html b/rero_ils/modules/entities/templates/rero_ils/_remote_topic.html
new file mode 100644
index 0000000000..e11561c534
--- /dev/null
+++ b/rero_ils/modules/entities/templates/rero_ils/_remote_topic.html
@@ -0,0 +1,71 @@
+{# -*- coding: utf-8 -*-
+
+ RERO ILS
+ Copyright (C) 2019-2023 RERO
+ Copyright (C) 2019-2023 UCLouvain
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, version 3 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+
+#}
+
+
+{% if data.bnf_type %}
+ {{ dl(_('Type'), data.bnf_type) }}
+{% endif %}
+
+{% if data.variant_access_point %}
+ {{ dl(_('Variant access point(s)'), data.variant_access_point) }}
+{% endif %}
+
+{% if data.broader %}
+ {{ _('Broader') }}
+
+
+ {% for broader in data.broader %}
+ - {{ broader.authorized_access_point }}
+ {% endfor %}
+
+
+{% endif %}
+
+{% if data.related %}
+ {{ _('Related') }}
+
+
+ {% for related in data.related %}
+ - {{ related.authorized_access_point }}
+ {% endfor %}
+
+
+{% endif %}
+
+{% if data.classification %}
+{{ _('Classification(s)') }}
+
+
+ {% for classification in data.classification %}
+ -
+ {% if classification.classificationPortion %}
+ {{ classification.classificationPortion }}
+ {% endif %}
+ {% if classification.name %}
+ {{ classification.name }}
+ {% endif %}
+ {% if classification.type %}
+ {{ _(classification.type) }}
+ {% endif %}
+
+ {% endfor %}
+
+
+{% endif %}
diff --git a/rero_ils/modules/entities/templates/rero_ils/_search_link.html b/rero_ils/modules/entities/templates/rero_ils/_search_link.html
new file mode 100644
index 0000000000..67c06af6cc
--- /dev/null
+++ b/rero_ils/modules/entities/templates/rero_ils/_search_link.html
@@ -0,0 +1,24 @@
+{# -*- coding: utf-8 -*-
+
+ RERO ILS
+ Copyright (C) 2019-2023 RERO
+ Copyright (C) 2019-2023 UCLouvain
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, version 3 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+
+#}
+
+
+
+ {{ _('Search documents') }}
+
diff --git a/rero_ils/modules/entities/templates/rero_ils/entity_local.html b/rero_ils/modules/entities/templates/rero_ils/entity_local.html
new file mode 100644
index 0000000000..e13b98bca5
--- /dev/null
+++ b/rero_ils/modules/entities/templates/rero_ils/entity_local.html
@@ -0,0 +1,64 @@
+{# -*- coding: utf-8 -*-
+
+ RERO ILS
+ Copyright (C) 2019-2023 RERO
+ Copyright (C) 2019-2023 UCLouvain
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, version 3 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+
+#}
+{% from 'rero_ils/macros/entity.html' import dl, dl_bool, dl_permalink_by_source %}
+
+{% extends 'rero_ils/page.html' %}
+
+{% set pid = record.pid %}
+
+{%- block body %}
+
+
+
+
+ {{ record.authorized_access_point }}
+
+ {{ _('LOCAL ID') }}: {{ pid }}
+
+
+ {% include 'rero_ils/_search_link.html' %}
+
+
+
+ {% if record['type'] == 'bf:Organisation' %}
+ {% include 'rero_ils/_local_organisation.html' %}
+ {% elif record['type'] == 'bf:Person' %}
+ {% include 'rero_ils/_local_person.html' %}
+ {% elif record['type'] == 'bf:Place' %}
+ {% include 'rero_ils/_local_place.html' %}
+ {% elif record['type'] == 'bf:Temporal' %}
+ {% include 'rero_ils/_local_temporal.html' %}
+ {% elif record['type'] == 'bf:Topic' %}
+ {% include 'rero_ils/_local_topic.html' %}
+ {% elif record['type'] == 'bf:Work' %}
+ {% include 'rero_ils/_local_work.html' %}
+ {% endif %}
+
+
+ {{ dl(_('Source catalog'), record.source_catalog) }}
+ {% if record.identifier %}
+ - {{ _('Identifier') }}
+ -
+ {{ _(record.identifier.type) }} - {{ record.identifier.value }}
+ {% if record.identifier.source %}({{ record.identifier.source }}){% endif %}
+
+ {% endif %}
+
+{%- endblock body %}
diff --git a/rero_ils/modules/entities/templates/rero_ils/entity_remote.html b/rero_ils/modules/entities/templates/rero_ils/entity_remote.html
new file mode 100644
index 0000000000..97f2efbe88
--- /dev/null
+++ b/rero_ils/modules/entities/templates/rero_ils/entity_remote.html
@@ -0,0 +1,64 @@
+{# -*- coding: utf-8 -*-
+
+ RERO ILS
+ Copyright (C) 2019-2023 RERO
+ Copyright (C) 2019-2023 UCLouvain
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, version 3 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+
+#}
+{% from 'rero_ils/macros/entity.html' import dl, dl_bool, dl_permalink_by_source %}
+
+{% extends 'rero_ils/page.html' %}
+
+{% set source, data = record|extract_data_from_remote_entity %}
+{% set pid = record.pid %}
+
+{%- block body %}
+
+
+
+
+ {{ record | entity_label(current_i18n.language) }}
+
+ MEF ID: {{ pid }}
+
+
+ {% include 'rero_ils/_search_link.html' %}
+
+
+
+ {% if record['type'] == 'bf:Organisation' %}
+ {% include 'rero_ils/_remote_organisation.html' %}
+ {% elif record['type'] == 'bf:Person' %}
+ {% include 'rero_ils/_remote_person.html' %}
+ {% elif record['type'] == 'bf:Topic' %}
+ {% include 'rero_ils/_remote_topic.html' %}
+ {% endif %}
+
+ {% set links = record|sources_link %}
+ {% if links != {} %}
+ - {{ _('Source(s)') }}
+ -
+
+ {% for source, link in links.items() %}
+ -
+ {{ source }}
+ {{ "; " if not loop.last else "" }}
+
+ {% endfor %}
+
+
+ {% endif %}
+
+{%- endblock body %}
diff --git a/rero_ils/modules/entities/remote_entities/templates/rero_ils/macros/entity.html b/rero_ils/modules/entities/templates/rero_ils/macros/entity.html
similarity index 72%
rename from rero_ils/modules/entities/remote_entities/templates/rero_ils/macros/entity.html
rename to rero_ils/modules/entities/templates/rero_ils/macros/entity.html
index 9bd81f1392..8dd8572b9e 100644
--- a/rero_ils/modules/entities/remote_entities/templates/rero_ils/macros/entity.html
+++ b/rero_ils/modules/entities/templates/rero_ils/macros/entity.html
@@ -20,10 +20,10 @@
{% macro dl(name, value, prefix) %}
{% if value %}
-
+
{{ name }}:
-
+
{% if value is string %}
{% if prefix %}
{{ _(prefix.format(v=value)) }}
@@ -56,33 +56,11 @@
{{ name }}:
-
+
{% endif %}
{% endmacro %}
-{% macro dl_permalink(name, record) %}
-
- {{ _(name) }}:
-
-
-
- {% for source in config.RERO_ILS_AGENTS_SOURCES %}
- {% if record[source] %}
- -
- {% if source != 'rero' %}
- {{ record[source].pid }}
- {% else %}
- {{ record[source].pid }}
- {% endif %}
- {{ source }}
-
- {% endif %}
- {% endfor %}
-
-
-{% endmacro %}
-
{% macro dl_permalink_by_source(name, data, source) %}
{% if data.pid %}
diff --git a/rero_ils/modules/entities/views.py b/rero_ils/modules/entities/views.py
new file mode 100644
index 0000000000..b6e9f481f8
--- /dev/null
+++ b/rero_ils/modules/entities/views.py
@@ -0,0 +1,148 @@
+# -*- coding: utf-8 -*-
+#
+# RERO ILS
+# Copyright (C) 2019-2023 RERO
+# Copyright (C) 2019-2023 UCLouvain
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, version 3 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+"""Blueprint used for entities."""
+from flask import Blueprint, abort, current_app, render_template
+from flask_babelex import gettext as _
+from invenio_i18n.ext import current_i18n
+
+from rero_ils.modules.entities.models import EntityType
+
+from .local_entities.api import LocalEntity
+from .remote_entities.api import RemoteEntity
+
+blueprint = Blueprint(
+ 'entities',
+ __name__,
+ url_prefix='//entities',
+ template_folder='templates',
+ static_folder='static',
+)
+
+
+@blueprint.route('//')
+def entity_detailed_view(viewcode, type, pid):
+ """Display entity view (local or remote).
+
+ :param: viewcode: The current view code.
+ :param: type: Resource type.
+ :param: pid: Resource PID.
+ :returns: The html rendering of the resource.
+ """
+ entity_class = LocalEntity if type == 'local' else RemoteEntity
+ if not (record := entity_class.get_record_by_pid(pid)):
+ abort(404, _('Entity not found.'))
+
+ return render_template(
+ f'rero_ils/entity_{type}.html',
+ record=record,
+ viewcode=viewcode,
+ search_link=search_link(record)
+ )
+
+
+@blueprint.app_template_filter()
+def entity_icon(type):
+ """Selects the right icon according to type.
+
+ :param: type: Resource type.
+ :returns: string, The class of the selected icon.
+ """
+ icons = {
+ EntityType.ORGANISATION: 'fa-building-o',
+ EntityType.PERSON: 'fa-user-o',
+ EntityType.PLACE: 'fa-map-marker',
+ EntityType.TEMPORAL: 'fa-calendar',
+ EntityType.TOPIC: 'fa-tag',
+ EntityType.WORK: 'fa-book'
+ }
+ return icons.get(type, 'fa-question-circle-o')
+
+
+@blueprint.app_template_filter()
+def extract_data_from_remote_entity(record):
+ """Data extraction based on language and resource type.
+
+ Used only on remote entity.
+
+ :param: record: the json record
+ :returns: source and the dictionary of the resource selected.
+ """
+ locale = current_i18n.locale.language
+ agent_order = current_app.config.get('RERO_ILS_AGENTS_LABEL_ORDER')
+ if locale not in agent_order:
+ locale = agent_order.get('fallback', {})
+ sources = agent_order.get(locale)
+ for source in sources:
+ if data := record.get(source):
+ return source, data
+
+
+@blueprint.app_template_filter()
+def entity_label(data, language):
+ """Create contribution label.
+
+ :param data: The record metadata.
+ :param language: The current language.
+ :returns: The contribution label.
+ """
+ order = current_app.config.get('RERO_ILS_AGENTS_LABEL_ORDER', [])
+ source_order = order.get(language, order.get(order['fallback'], []))
+ for source in source_order:
+ if label := data.get(source, {}).get('authorized_access_point', None):
+ return label
+ return '-'
+
+
+@blueprint.app_template_filter()
+def sources_link(data):
+ """Extract sources link.
+
+ :param data: The record metadata.
+ :returns A dict with the source and link.
+ """
+ links = {}
+ sources_link = list(filter(lambda source: source not in
+ current_app.config.get(
+ 'RERO_ILS_AGENTS_SOURCES_EXCLUDE_LINK', []),
+ data.get('sources', [])))
+
+ for source in sources_link:
+ if identifier := data.get(source, {}).get('identifier'):
+ links[source] = identifier
+ return links
+
+
+def search_link(metadata):
+ """Generate Link for search entities.
+
+ :param metadata: the record metadata.
+ :returns: the search link.
+ """
+ queries = []
+ for field in ['contribution', 'subjects', 'genreForm']:
+ if 'sources' in metadata:
+ # Remote entities
+ source, data = extract_data_from_remote_entity(metadata)
+ entity_id = data.get('pid')
+ else:
+ # Local entities
+ source = 'local'
+ entity_id = metadata.get('pid')
+ queries.append(f'{field}.entity.pids.{source}:{entity_id}')
+ return " OR ".join(queries) + "&simple=0"
diff --git a/rero_ils/modules/ext.py b/rero_ils/modules/ext.py
index 186083cb1c..cddd0d56db 100644
--- a/rero_ils/modules/ext.py
+++ b/rero_ils/modules/ext.py
@@ -42,7 +42,7 @@
from rero_ils.filter import address_block, empty_data, format_date_filter, \
get_record_by_ref, jsondumps, message_filter, node_assets, text_to_id, \
- to_pretty_json
+ to_pretty_json, translate
from rero_ils.modules.acquisition.acq_accounts.listener import \
enrich_acq_account_data
from rero_ils.modules.acquisition.acq_order_lines.listener import \
@@ -175,6 +175,7 @@ def __init__(self, app=None):
app.add_template_filter(address_block)
app.add_template_filter(message_filter, name='message')
app.add_template_filter(issue_client_reference)
+ app.add_template_filter(translate)
app.jinja_env.add_extension('jinja2.ext.do')
app.jinja_env.globals['version'] = __version__
self.register_signals(app)
diff --git a/rero_ils/modules/monitoring/api.py b/rero_ils/modules/monitoring/api.py
index d72a304f79..f8ebbc7cb6 100644
--- a/rero_ils/modules/monitoring/api.py
+++ b/rero_ils/modules/monitoring/api.py
@@ -68,7 +68,7 @@ class Monitoring(object):
times of selected functions.
"""
- has_no_db = ['oplg']
+ has_no_db = ['oplg', 'ent']
def __init__(self, time_delta=1):
"""Constructor.
diff --git a/rero_ils/theme/templates/rero_ils/address_block/eng.tpl.txt b/rero_ils/theme/templates/rero_ils/address_block/eng.tpl.txt
index 16820da98c..c4c01298c5 100644
--- a/rero_ils/theme/templates/rero_ils/address_block/eng.tpl.txt
+++ b/rero_ils/theme/templates/rero_ils/address_block/eng.tpl.txt
@@ -1,7 +1,7 @@
{{ data.name }}
{{ data.address.street }}
{{ data.address.zip_code }} - {{ data.address.city }}
-{{ data.address.country | translat('country_') }}
+{{ data.address.country | translate('country_') }}
{%- if data.email %}
Email: {{ data.email }}
{%- endif %}
diff --git a/rero_ils/theme/templates/rero_ils/address_block/fre.tpl.txt b/rero_ils/theme/templates/rero_ils/address_block/fre.tpl.txt
index 4bb3d15337..5583059424 100644
--- a/rero_ils/theme/templates/rero_ils/address_block/fre.tpl.txt
+++ b/rero_ils/theme/templates/rero_ils/address_block/fre.tpl.txt
@@ -1,7 +1,7 @@
{{ data.name }}
{{ data.address.street }}
{{ data.address.zip_code }} - {{ data.address.city }}
-{{ data.address.country | translat('country_') }}
+{{ data.address.country | translate('country_') }}
{%- if data.email %}
E-mail: {{ data.email }}
{%- endif %}
diff --git a/rero_ils/theme/templates/rero_ils/address_block/ger.tpl.txt b/rero_ils/theme/templates/rero_ils/address_block/ger.tpl.txt
index 2dd13d4009..b1e49c29c2 100644
--- a/rero_ils/theme/templates/rero_ils/address_block/ger.tpl.txt
+++ b/rero_ils/theme/templates/rero_ils/address_block/ger.tpl.txt
@@ -1,7 +1,7 @@
{{ data.name }}
{{ data.address.street }}
{{ data.address.zip_code }} - {{ data.address.city }}
-{{ data.address.country | translat('country_') }}
+{{ data.address.country | translate('country_') }}
{%- if data.email %}
E-mail: {{ data.email }}
{%- endif %}
diff --git a/rero_ils/theme/templates/rero_ils/address_block/ita.tpl.txt b/rero_ils/theme/templates/rero_ils/address_block/ita.tpl.txt
index 3454e4259d..60cca2d6b6 100644
--- a/rero_ils/theme/templates/rero_ils/address_block/ita.tpl.txt
+++ b/rero_ils/theme/templates/rero_ils/address_block/ita.tpl.txt
@@ -1,7 +1,7 @@
{{ data.name }}
{{ data.address.street }}
{{ data.address.zip_code }} - {{ data.address.city }}
-{{ data.address.country | translat('country_') }}
+{{ data.address.country | translate('country_') }}
{%- if data.email %}
E-mail: {{ data.email }}
{%- endif %}
diff --git a/tests/api/entities/local_entities/test_local_entities_rest.py b/tests/api/entities/local_entities/test_local_entities_rest.py
index 4f37ae8d84..23ae3c21ab 100644
--- a/tests/api/entities/local_entities/test_local_entities_rest.py
+++ b/tests/api/entities/local_entities/test_local_entities_rest.py
@@ -19,15 +19,16 @@
"""Tests `LocalEntity` resource REST API."""
import json
+
import mock
from flask import url_for
-from utils import get_json, postdata, to_relative_url, \
- VerifyRecordPermissionPatch
+from utils import VerifyRecordPermissionPatch, get_json, postdata, \
+ to_relative_url
from rero_ils.modules.documents.dumpers import document_replace_refs_dumper
-from rero_ils.modules.entities.models import EntityType
-from rero_ils.modules.entities.local_entities.api import LocalEntity
from rero_ils.modules.entities.dumpers import indexer_dumper
+from rero_ils.modules.entities.local_entities.api import LocalEntity
+from rero_ils.modules.entities.models import EntityType
from rero_ils.modules.utils import get_ref_for_pid
diff --git a/tests/api/entities/remote_entities/test_remote_entities_rest.py b/tests/api/entities/remote_entities/test_remote_entities_rest.py
index bb0be4bf80..f6a7de963d 100644
--- a/tests/api/entities/remote_entities/test_remote_entities_rest.py
+++ b/tests/api/entities/remote_entities/test_remote_entities_rest.py
@@ -22,8 +22,8 @@
from flask import url_for
from utils import get_json, mock_response, postdata, to_relative_url
-from rero_ils.modules.entities.models import EntityType
from rero_ils.modules.entities.dumpers import indexer_dumper
+from rero_ils.modules.entities.models import EntityType
def test_remote_entities_permissions(client, entity_person, json_header):
diff --git a/tests/fixtures/mef.py b/tests/fixtures/mef.py
index dfe90981c9..d713ddfef0 100644
--- a/tests/fixtures/mef.py
+++ b/tests/fixtures/mef.py
@@ -20,8 +20,10 @@
from copy import deepcopy
import pytest
-from rero_ils.modules.entities.remote_entities.api import RemoteEntity, \
- RemoteEntitiesSearch
+
+from rero_ils.modules.entities.remote_entities.api import \
+ RemoteEntitiesSearch, RemoteEntity
+
@pytest.fixture(scope="module")
def mef_concept1_data(mef_entities):
diff --git a/tests/fixtures/metadata.py b/tests/fixtures/metadata.py
index cc23e158fc..06f2f60286 100644
--- a/tests/fixtures/metadata.py
+++ b/tests/fixtures/metadata.py
@@ -27,12 +27,12 @@
from utils import flush_index, mock_response
from rero_ils.modules.documents.api import Document, DocumentsSearch
+from rero_ils.modules.entities.local_entities.api import LocalEntitiesSearch, \
+ LocalEntity
from rero_ils.modules.entities.remote_entities.api import \
RemoteEntitiesSearch, RemoteEntity
from rero_ils.modules.holdings.api import Holding, HoldingsSearch
from rero_ils.modules.items.api import Item, ItemsSearch
-from rero_ils.modules.entities.local_entities.api import LocalEntitiesSearch, \
- LocalEntity
from rero_ils.modules.local_fields.api import LocalField, LocalFieldsSearch
from rero_ils.modules.operation_logs.api import OperationLog
from rero_ils.modules.templates.api import Template, TemplatesSearch
diff --git a/tests/ui/documents/test_documents_api.py b/tests/ui/documents/test_documents_api.py
index 18125b5b2b..0ee5a57f2a 100644
--- a/tests/ui/documents/test_documents_api.py
+++ b/tests/ui/documents/test_documents_api.py
@@ -182,8 +182,9 @@ def test_document_linked_subject(
in subject['entity']['variant_access_point']
# reset fixtures
- entity.delete()
+ doc.delete_from_index()
doc.delete()
+ entity.delete()
def test_document_add_cover_url(db, document):
diff --git a/tests/ui/documents/test_documents_filter.py b/tests/ui/documents/test_documents_filter.py
index 210e991964..e7dc724623 100644
--- a/tests/ui/documents/test_documents_filter.py
+++ b/tests/ui/documents/test_documents_filter.py
@@ -400,15 +400,26 @@ def test_contribution_format(db, entity_organisation):
'authorized_access_point_fr': 'author_fr'
}
}]
- assert contribution_format(contributions, 'en', 'global') == 'author_def'
- assert contribution_format(contributions, 'fr', 'global') == 'author_fr'
- assert contribution_format(contributions, 'zh', 'global') == 'author_def'
+ # ---- Textual contribution
+ # With english language
+ link_part = '/global/search/documents?q=' \
+ 'contribution.entity.authorized_access_point_en%3A' \
+ '%22author_def%22'
+ assert link_part in contribution_format(contributions, 'en', 'global')
+
+ # With french language
+ link_part = '/global/search/documents?q=' \
+ 'contribution.entity.authorized_access_point_fr%3A' \
+ '%22author_fr%22'
+ assert link_part in contribution_format(contributions, 'fr', 'global')
+
+ # ---- Remote contribution
contributions = [{
'entity': {'pid': entity.pid}
}]
- link_part = f'/global/search/documents?q' \
- f'=contribution.entity.pids.{entity.resource_type}%3A' \
+ link_part = f'/global/search/documents?q=' \
+ f'contribution.entity.pids.{entity.resource_type}%3A' \
f'{entity.pid}'
assert link_part in contribution_format(contributions, 'en', 'global')
@@ -550,46 +561,71 @@ def test_main_title_text():
assert extract[0].get('_text') is not None
-def test_doc_entity_label_filter(entity_person):
+def test_doc_entity_label_filter(entity_person, local_entity_person):
"""Test entity label filter."""
+
+ # Remote entity
+ remote_pid = entity_person['idref']['pid']
data = {
'entity': {
- 'authorized_access_point': 'subject topic',
- 'type': EntityType.TOPIC
+ '$ref': f'https://mef.rero.ch/api/concepts/idref/{remote_pid}',
+ 'pid': remote_pid
}
}
- assert doc_entity_label(data['entity'], None) == 'subject topic'
- assert doc_entity_label(data['entity'], 'fr') == 'subject topic'
+ entity_type, value, label = doc_entity_label(data['entity'], 'fr')
+ assert 'remote' == entity_type
+ assert 'ent_pers' == value
+ assert 'Loy, Georg, 1885-19..' == label
+ # Local entity
+ pid = local_entity_person['pid']
data = {
'entity': {
- 'authorized_access_point': 'topic_default',
- 'authorized_access_point_fr': 'topic_fr',
- 'type': EntityType.TOPIC
+ '$ref': f'https://bib.rero.ch/api/local_entities/{pid}'
}
}
- assert doc_entity_label(data['entity'], 'fr') == 'topic_fr'
- assert doc_entity_label(data['entity'], 'en') == 'topic_default'
- assert doc_entity_label(data['entity'], None) == 'topic_default'
+ entity_type, value, label = doc_entity_label(data['entity'], 'fr')
+ assert 'local' == entity_type
+ assert 'locent_pers' == value
+ assert 'Loy, Georg (1881-1968)' == label
+ entity_type, value, label = doc_entity_label(data['entity'], 'en')
+ assert 'local' == entity_type
+ assert 'locent_pers' == value
+ assert 'Loy, Georg (1881-1968)' == label
+
+ # Textual
data = {
'entity': {
- 'authorized_access_point': 'topic_default',
- 'subdivisions': [{
- 'entity': {
- 'authorized_access_point': 'sub_default',
- 'authorized_access_point_fr': 'sub_fr'
- }
- }],
- 'type': EntityType.TOPIC
+ 'authorized_access_point': 'subject topic'
}
}
- assert doc_entity_label(data['entity'], 'fr') == 'topic_default - sub_fr'
- assert doc_entity_label(
- data['entity'], 'en') == 'topic_default - sub_default'
- assert doc_entity_label(
- data['entity'], None) == 'topic_default - sub_default'
-
- data = {'entity': {'pid': entity_person.pid}}
- assert doc_entity_label(data['entity'], 'fr') == 'Loy, Georg, 1885-19..'
- assert doc_entity_label(data['entity'], 'de') == 'Loy, Georg, 1885'
+ entity_type, value, label = doc_entity_label(data['entity'], None)
+ assert 'textual' == entity_type
+ assert 'subject topic' == value
+ assert 'subject topic' == label
+
+ entity_type, value, label = doc_entity_label(data['entity'], 'fr')
+ assert 'textual' == entity_type
+ assert 'subject topic' == value
+ assert 'subject topic' == label
+
+ # Textual with subdivision
+ data['entity']['subdivisions'] = [
+ {
+ 'entity': {
+ 'authorized_access_point': 'Sub 1',
+ 'type': EntityType.TOPIC
+ }
+ },
+ {
+ 'entity': {
+ 'authorized_access_point': 'Sub 2',
+ 'type': EntityType.TOPIC
+ }
+ }
+ ]
+ entity_type, value, label = doc_entity_label(data['entity'], 'fr')
+ assert 'textual' == entity_type
+ assert 'subject topic' == value
+ assert 'subject topic - Sub 1 - Sub 2' == label
diff --git a/tests/ui/entities/local_entities/test_local_entities_api.py b/tests/ui/entities/local_entities/test_local_entities_api.py
index ecfbf9c3f1..296c2ea0b7 100644
--- a/tests/ui/entities/local_entities/test_local_entities_api.py
+++ b/tests/ui/entities/local_entities/test_local_entities_api.py
@@ -22,6 +22,7 @@
import time
from datetime import timedelta
+
from utils import flush_index
from rero_ils.modules.documents.api import Document, DocumentsSearch
diff --git a/tests/ui/entities/remote_entities/test_remote_entities_api.py b/tests/ui/entities/remote_entities/test_remote_entities_api.py
index 4ffc13edce..311a117a3b 100644
--- a/tests/ui/entities/remote_entities/test_remote_entities_api.py
+++ b/tests/ui/entities/remote_entities/test_remote_entities_api.py
@@ -125,6 +125,10 @@ def test_sync_contribution(
)
flush_index(DocumentsSearch.Meta.index)
+ # Test that entity could not be deleted
+ assert pers.get_links_to_me(True)['documents'] == [doc.pid]
+ assert pers.reasons_not_to_delete()['links']['documents'] == 1
+
# === nothing to update
sync_entity._get_latest = mock.MagicMock(
return_value=entity_person_data_tmp
diff --git a/tests/ui/entities/remote_entities/test_remote_entities_filter.py b/tests/ui/entities/remote_entities/test_remote_entities_filter.py
deleted file mode 100644
index 6080a26cd0..0000000000
--- a/tests/ui/entities/remote_entities/test_remote_entities_filter.py
+++ /dev/null
@@ -1,108 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# RERO ILS
-# Copyright (C) 2019-2023 RERO
-# Copyright (C) 2019-2023 UCLouvain
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, version 3 of the License.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-
-"""Jinja2 filters tests."""
-
-from rero_ils.modules.entities.remote_entities.views import entity_label, \
- entity_merge_data_values
-
-
-def test_remote_entity_label(app, entity_person_data):
- """Test entity label."""
- app.config['RERO_ILS_AGENTS_LABEL_ORDER'] = {
- 'fallback': 'fr',
- 'fr': ['rero', 'idref', 'gnd'],
- 'de': ['gnd', 'rero', 'idref'],
- }
- label = entity_label(entity_person_data, 'fr')
- assert label == 'Loy, Georg, 1885-19..'
- label = entity_label(entity_person_data, 'it')
- assert label == 'Loy, Georg, 1885-19..'
-
-
-def test_remote_entity_merge_data_values(app, entity_person_data):
- """Test entities merge data."""
- app.config['RERO_ILS_AGENTS_SOURCES'] = ['idref', 'gnd', 'rero']
- data = entity_merge_data_values(entity_person_data)
- assert data == {
- '$schema': {
- 'https://mef.test.rero.ch/schemas/gnd/'
- 'gnd-contribution-v0.0.1.json': ['gnd'],
- 'https://mef.test.rero.ch/schemas/idref/'
- 'idref-contribution-v0.0.1.json': ['idref'],
- 'https://mef.test.rero.ch/schemas/rero/'
- 'rero-contribution-v0.0.1.json': ['rero']
- },
- 'authorized_access_point': {
- 'Loy, Georg, 1885': ['gnd'],
- 'Loy, Georg, 1885-19..': ['idref', 'rero']
- },
- 'bf:Agent': {
- 'bf:Person': ['idref', 'gnd', 'rero']
- },
- 'biographical_information': {
- 'Diss. philosophische Fakultät': ['gnd']
- },
- 'country_associated': {
- 'gw': ['idref', 'rero']
- },
- 'date_of_birth': {
- '1885': ['gnd'],
- '1885-05-14': ['idref', 'rero']
- },
- 'date_of_death': {
- '19..': ['idref', 'rero']
- },
- 'identifier': {
- 'http://d-nb.info/gnd/13343771X': ['gnd'],
- 'http://www.idref.fr/223977268': ['idref'],
- 'http://data.rero.ch/02-A017671081': ['rero']
- },
- 'language': {
- 'ger': ['idref', 'rero']
- },
- 'md5': {
- '3dd3788c64af4200676a35a5ea35b180': ['idref'],
- '3dd3788c64af4200676a35a5ea35b181': ['rero'],
- '5dad1e77d5a47d39e87bb0ec37aaf51e': ['gnd']
- },
- 'pid': {
- '13343771X': ['gnd'],
- '223977268': ['idref'],
- 'A017671081': ['rero']
- },
- 'preferred_name': {
- 'Loy, Georg': ['idref', 'gnd', 'rero']
- },
- 'variant_name': {
- 'Loy, George, di Madeiros': ['gnd']
- },
- 'gnd': {
- 'identifier': 'http://d-nb.info/gnd/13343771X',
- 'pid': '13343771X'
- },
- 'idref': {
- 'identifier': 'http://www.idref.fr/223977268',
- 'pid': '223977268'
- },
- 'rero': {
- 'identifier': 'http://data.rero.ch/02-A017671081',
- 'pid': 'A017671081'
- }
-
- }
diff --git a/tests/ui/entities/remote_entities/test_remote_entities_ui.py b/tests/ui/entities/remote_entities/test_remote_entities_ui.py
index 3303ff713d..51a0a04a91 100644
--- a/tests/ui/entities/remote_entities/test_remote_entities_ui.py
+++ b/tests/ui/entities/remote_entities/test_remote_entities_ui.py
@@ -16,22 +16,19 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-"""Tests UI view for entities."""
+"""Jinja2 filters tests."""
-from flask import url_for
+from rero_ils.modules.entities.views import entity_label
-def test_remote_entity_person_detailed_view(client, entity_person):
- """Test entity person detailed view."""
- res = client.get(url_for(
- 'remote_entities.persons_proxy',
- viewcode='global', pid=entity_person.pid))
- assert res.status_code == 200
-
-
-def test_remote_entity_organisation_detailed_view(client, entity_organisation):
- """Test entity organisation detailed view."""
- res = client.get(url_for(
- 'remote_entities.corporate_bodies_proxy',
- viewcode='global', pid='ent_org'))
- assert res.status_code == 200
+def test_remote_entity_label(app, entity_person_data):
+ """Test entity label."""
+ app.config['RERO_ILS_AGENTS_LABEL_ORDER'] = {
+ 'fallback': 'fr',
+ 'fr': ['rero', 'idref', 'gnd'],
+ 'de': ['gnd', 'rero', 'idref'],
+ }
+ label = entity_label(entity_person_data, 'fr')
+ assert label == 'Loy, Georg, 1885-19..'
+ label = entity_label(entity_person_data, 'it')
+ assert label == 'Loy, Georg, 1885-19..'
diff --git a/tests/ui/entities/test_entities_ui.py b/tests/ui/entities/test_entities_ui.py
new file mode 100644
index 0000000000..1a040238f1
--- /dev/null
+++ b/tests/ui/entities/test_entities_ui.py
@@ -0,0 +1,137 @@
+# -*- coding: utf-8 -*-
+#
+# RERO ILS
+# Copyright (C) 2019-2023 RERO
+# Copyright (C) 2019-2023 UCLouvain
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, version 3 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+"""Tests UI view for entities."""
+
+from flask import url_for
+from invenio_i18n.ext import current_i18n
+
+from rero_ils.modules.entities.models import EntityType
+from rero_ils.modules.entities.views import entity_icon, \
+ extract_data_from_remote_entity, search_link, sources_link
+
+
+def test_view(client, entity_person, local_entity_person):
+ """Entity detailed view test."""
+
+ # Check unauthorized type value in url
+ res = client.get(url_for(
+ 'entities.entity_detailed_view',
+ viewcode='global',
+ type='foo',
+ pid='foo'
+ ))
+ assert res.status_code == 404
+
+ # Check 404 error if entity does not exist
+ res = client.get(url_for(
+ 'entities.entity_detailed_view',
+ viewcode='global',
+ type='remote',
+ pid='foo'
+ ))
+ assert res.status_code == 404
+
+ # Remote entity
+ res = client.get(url_for(
+ 'entities.entity_detailed_view',
+ viewcode='global',
+ type='remote',
+ pid=entity_person.get('pid')
+ ))
+ assert res.status_code == 200
+
+ # Local entity
+ res = client.get(url_for(
+ 'entities.entity_detailed_view',
+ viewcode='global',
+ type='local',
+ pid=local_entity_person.get('pid')
+ ))
+ assert res.status_code == 200
+
+
+def test_entity_icon():
+ """Entity icon test."""
+ assert 'fa-building-o' == entity_icon(EntityType.ORGANISATION)
+ # Default icon if type not found
+ assert 'fa-question-circle-o' == entity_icon('foo')
+
+
+def test_extract_data_from_record(app):
+ """Extract data from record test."""
+ contrib_data = {
+ 'idref': {'data': 'idref'},
+ 'rero': {'data': 'rero'},
+ 'gnd': {'data': 'gnd'}
+ }
+ current_i18n.locale.language = 'fr'
+ source, data = extract_data_from_remote_entity(contrib_data)
+ assert source == 'idref'
+ assert contrib_data.get(source) == data
+
+ current_i18n.locale.language = 'de'
+ source, data = extract_data_from_remote_entity(contrib_data)
+ assert source == 'gnd'
+ assert contrib_data.get(source) == data
+
+ # Fallback test
+ current_i18n.locale.language = 'it'
+ source, data = extract_data_from_remote_entity(contrib_data)
+ assert source == 'idref'
+ assert contrib_data.get(source) == data
+
+ # Control the selection cascade
+ contrib_data.pop('idref')
+ contrib_data.pop('gnd')
+ source, data = extract_data_from_remote_entity(contrib_data)
+ assert source == 'rero'
+ assert contrib_data.get(source) == data
+
+
+def test_sources_link(app):
+ """Sources link test."""
+ data = {
+ 'idref': {'identifier': 'http://www.idref.fr/066924502'},
+ 'gnd': {'identifier': 'http://d-nb.info/gnd/118754688'},
+ 'rero': {'identifier': 'http://data.rero.ch/02-A003795108'},
+ 'sources': ['idref', 'gnd', 'rero']
+ }
+ result = {
+ 'idref': 'http://www.idref.fr/066924502',
+ 'gnd': 'http://d-nb.info/gnd/118754688'
+ }
+ assert result == sources_link(data)
+ assert {} == sources_link({})
+
+
+def test_search_link(app, entity_organisation, local_entity_org):
+ """Search link test."""
+
+ # test remote link
+ link = search_link(entity_organisation)
+ assert link == 'contribution.entity.pids.rero:A027711299 ' \
+ 'OR subjects.entity.pids.rero:A027711299 ' \
+ 'OR genreForm.entity.pids.rero:A027711299' \
+ '&simple=0'
+ # test local link
+ link = search_link(local_entity_org)
+ assert link == 'contribution.entity.pids.local:locent_org ' \
+ 'OR subjects.entity.pids.local:locent_org ' \
+ 'OR genreForm.entity.pids.local:locent_org' \
+ '&simple=0'
diff --git a/tests/ui/test_filters.py b/tests/ui/test_filters.py
index b4cef0d6c8..7af95a3dd4 100644
--- a/tests/ui/test_filters.py
+++ b/tests/ui/test_filters.py
@@ -31,7 +31,7 @@ def test_get_record_by_ref(document_data, document):
def test_date_filter_format_timestamp_en(app):
"""Test full english date and tile filter."""
datestring = format_date_filter('2018-06-06T09:29:55.947149+00:00')
- assert 'Wednesday, June 6, 2018, 11:29:55 AM' in datestring
+ assert 'Wednesday, 6 June 2018, 11:29:55' in datestring
datestring = format_date_filter(
'2018-06-06T09:29:55.947149+00:00', locale='fr')
@@ -46,28 +46,28 @@ def test_date_filter_format_default_en(app):
"""Test medium english date filter."""
datestring = format_date_filter(
'1950-01-01', date_format='short', time_format=None)
- assert '1/1/50' in datestring
+ assert '01/01/1950' in datestring
def test_date_filter_timezone(app):
"""Test medium english date filter."""
datestring = format_date_filter(
'2018-06-06T09:29:55.947149+00:00', timezone='Europe/Helsinki')
- assert 'Wednesday, June 6, 2018, 12:29:55 PM' in datestring
+ assert 'Wednesday, 6 June 2018, 12:29:55' in datestring
def test_date_filter_format_medium_date_en(app):
"""Test medium_date english date filter."""
datestring = format_date_filter(
'1950-01-01', date_format='medium', time_format=None)
- assert 'Jan 1, 1950' in datestring
+ assert '1 Jan 1950' in datestring
def test_date_filter_format_full_en(app):
"""Test full english date filter."""
datestring = format_date_filter(
'1950-01-01', date_format='full', time_format=None)
- assert 'Sunday, January 1, 1950' in datestring
+ assert 'Sunday, 1 January 1950' in datestring
def test_date_filter_format_full_fr(app):
@@ -88,7 +88,7 @@ def test_time_filter_format_default(app):
"""Test default time."""
datestring = format_date_filter(
'2018-06-06T09:29:55.947149+00:00', date_format=None)
- assert datestring == '11:29:55 AM'
+ assert datestring == '11:29:55'
def test_time_filter_format_fr(app):
@@ -102,7 +102,7 @@ def test_time_filter_format_delimiter(app):
"""Test default time."""
datestring = format_date_filter(
'2018-06-06T09:29:55.947149+00:00', delimiter=' - ')
- assert datestring == 'Wednesday, June 6, 2018 - 11:29:55 AM'
+ assert datestring == 'Wednesday, 6 June 2018 - 11:29:55'
def test_to_pretty():
diff --git a/tests/unit/conftest.py b/tests/unit/conftest.py
index 32b0f29d1f..c08f6d91a7 100644
--- a/tests/unit/conftest.py
+++ b/tests/unit/conftest.py
@@ -25,9 +25,9 @@
from pkg_resources import resource_string
from utils import get_schema
+from rero_ils.modules.entities.remote_entities.api import \
+ RemoteEntitiesSearch, RemoteEntity
from rero_ils.modules.patrons.api import Patron
-from rero_ils.modules.entities.remote_entities.api import RemoteEntity, \
- RemoteEntitiesSearch
@pytest.fixture(scope='module')