Skip to content

Commit

Permalink
config: add document advanced seach flag
Browse files Browse the repository at this point in the history
* Adds configuration for enabled/disabled advanced search.
* Adds a new field in the document schema to group
  call number for holdings and items.
* Adds a new endpoint for advanced search config.

Co-Authored-by: Bertrand Zuchuat <bertrand.zuchuat@rero.ch>
  • Loading branch information
Garfield-fr committed Oct 25, 2023
1 parent 07a8796 commit 1947830
Show file tree
Hide file tree
Showing 6 changed files with 215 additions and 7 deletions.
110 changes: 109 additions & 1 deletion rero_ils/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ def _(x):
RERO_ILS_ILL_REQUEST_ON_GLOBAL_VIEW = True
RERO_ILS_ILL_DEFAULT_SOURCE = 'RERO +'

# DOCUMENT ADVANCED SEARCH
RERO_ILS_APP_DOCUMENT_ADVANCED_SEARCH = True

# Rate limiting
# =============
#: Storage for ratelimiter.
Expand Down Expand Up @@ -3038,7 +3041,7 @@ def _(x):
'base_url': os.environ.get('RERO_ILS_MEF_CONCEPTS_URL', 'https://mef.rero.ch/api/concepts'),
'sources': ['idref'],
'filters': [
{'idref.bnf_type': 'genre/forme Rameau'}
{'idref.bnf_type': 'genre/forme Rameau'}
]
},
'places': {
Expand Down Expand Up @@ -3632,3 +3635,108 @@ def _(x):
RERO_ILS_PASSWORD_SPECIAL_CHAR = False
RERO_ILS_PASSWORD_GENERATOR = 'rero_ils.modules.utils:password_generator'
RERO_ILS_PASSWORD_VALIDATOR = 'rero_ils.modules.utils:password_validator'

# ADVANCED SEARCH CONFIG
# ======================
RERO_ILS_APP_ADVANCED_SEARCH_CONFIG = [
{
'label': 'Title',
'value': 'title',
'field': 'title.*',
},
{
'label': 'Responsibility statement',
'value': 'responsibilityStatement',
'field': 'responsibilityStatement.value',
},
{
'label': 'Contribution',
'value': 'contribution',
'field': 'contribution.entity.*',
},
{
'label': 'Country',
'value': 'country',
'field': 'provisionActivity.country',
},
{
'label': 'Canton',
'value': 'canton',
'field': 'provisionActivity.canton',
},
{
'label': 'Provision activity statement',
'value': 'provisionActivityStatement',
'field': 'provisionActivity.statement.label',
},
{
'label': 'Series statement',
'value': 'seriesStatement',
'field': 'seriesStatement.*',
},
{
'label': 'Identifier',
'value': 'identifiedBy',
'field': 'identifiedBy.value',
},
{
'label': 'ISBN',
'value': 'isbn',
'field': 'isbn',
},
{
'label': 'ISSN',
'value': 'issn',
'field': 'issn',
},
{
'label': 'Genre, form',
'value': 'genreForm',
'field': 'genreForm.entity.*',
},
{
'label': 'Subject',
'value': 'subjects',
'field': 'subjects.entity.*',
},
{
'label': 'Call number',
'value': 'callNumber',
'field': 'call_numbers',
},
{
'label': 'Holdings local fields',
'value': 'holdingsLocalFields',
'field': 'holdings.local_fields.*',
},
{
'label': 'Classification',
'value': 'classification',
'field': 'classification.*',
},
{
'label': 'Item local fields',
'value': 'itemLocalFields',
'field': 'holdings.items.local_fields.*',
},
{
'label': 'Document local fields',
'value': 'documentLocalFields',
'field': 'local_fields.*',
},
{
'label': 'RDA content type',
'value': 'rdaContentType',
'field': 'contentmediaCarrier.contentType',
},
{
'label': 'RDA media type',
'value': 'rdaMediaType',
'field': 'contentmediaCarrier.mediaType',
},
{
'label': 'RDA carrier type',
'value': 'rdaCarrierType',
'field': 'contentmediaCarrier.carrierType',
},
]
56 changes: 54 additions & 2 deletions rero_ils/modules/documents/api_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,16 @@

"""Blueprint for document api."""

from flask import Blueprint, abort, jsonify
from functools import cmp_to_key

from flask import Blueprint, abort, current_app, jsonify
from flask import request as flask_request

from rero_ils.modules.decorators import check_logged_as_librarian

from .api import Document
from .utils import get_remote_cover
from ..utils import cached
from ..utils import cached, read_json_file

api_blueprint = Blueprint(
'api_documents',
Expand All @@ -50,3 +54,51 @@ def document_availability(pid):
return jsonify({
'available': Document.is_available(pid, view_code)
})


@api_blueprint.route('/advanced-search-config')
# @cached(timeout=300, query_string=True)
@check_logged_as_librarian
def advanced_search_config():
"""Advanced search config."""

def sort_medias(a, b):
"""Sort only media start with rda in label."""
a, b = a['label'], b['label']
if a.startswith('rda') and b.startswith('rda'):
return a > b
elif a.startswith('rda'):
return -1
elif b.startswith('rda'):
return 1
else:
return a > b

cantons = read_json_file('jsonschemas/common/cantons-v0.0.1.json')
countries = read_json_file('jsonschemas/common/countries-v0.0.1.json')
medias = read_json_file('modules/documents/jsonschemas/documents'
'/document_content_media_carrier-v0.0.1.json')
media_items = medias['contentMediaCarrier']['items']['oneOf']
media_types = []
carrier_types = []
for item in media_items:
if rda_type := item.get('properties', {}).get('mediaType', {}):
data = rda_type.get('title')
media_types.append({'label': data, 'value': data})
if rda_type := item.get('properties', {}).get('carrierType', {}):
for option in rda_type.get('form', {}).get('options'):
if option not in carrier_types:
carrier_types.append(option)
return jsonify({
'fieldsConfig': current_app.config.get(
'RERO_ILS_APP_ADVANCED_SEARCH_CONFIG', []),
'fieldsData': {
'country': countries['country']['form']['options'],
'canton': cantons['canton']['form']['options'],
'rdaContentType': medias['definitions']['contentType']['items']
['form']['options'],
'rdaMediaType': sorted(media_types, key=cmp_to_key(sort_medias)),
'rdaCarrierType': sorted(
carrier_types, key=cmp_to_key(sort_medias))
}
})
Original file line number Diff line number Diff line change
Expand Up @@ -1139,10 +1139,12 @@
}
},
"call_number": {
"type": "text"
"type": "text",
"copy_to": "call_numbers"
},
"second_call_number": {
"type": "text"
"type": "text",
"copy_to": "call_numbers"
},
"index": {
"type": "text"
Expand All @@ -1166,10 +1168,12 @@
"type": "keyword"
},
"call_number": {
"type": "text"
"type": "text",
"copy_to": "call_numbers"
},
"second_call_number": {
"type": "text"
"type": "text",
"copy_to": "call_numbers"
},
"status": {
"type": "keyword"
Expand Down Expand Up @@ -2135,6 +2139,9 @@
}
}
},
"call_numbers": {
"type": "text"
},
"_draft": {
"type": "boolean"
},
Expand Down
2 changes: 2 additions & 0 deletions rero_ils/modules/patrons/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ def logged_user():
'agentLabelOrder': config.get('RERO_ILS_AGENTS_LABEL_ORDER', {}),
'agentSources': config.get('RERO_ILS_AGENTS_SOURCES', []),
'operationLogs': config.get('RERO_ILS_ENABLE_OPERATION_LOG', []),
'documentAdvancedSearch': config.get(
'RERO_ILS_APP_DOCUMENT_ADVANCED_SEARCH', False),
'userProfile': {
'readOnly': config.get(
'RERO_PUBLIC_USERPROFILES_READONLY', False),
Expand Down
11 changes: 11 additions & 0 deletions rero_ils/modules/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"""Utilities for rero-ils editor."""

import cProfile
import json
import os
import pstats
import random
Expand Down Expand Up @@ -1300,3 +1301,13 @@ def password_generator(length=8, special_char=False):

random.shuffle(password)
return ''.join(password)


def read_json_file(file_path):
"""Read json file with full path.
:param file_path: the relative path.
:returns: the contents of the json file.
"""
path = os.path.dirname(os.path.realpath('__file__'))
return json.load(open(f'{path}/rero_ils/{file_path}'))
28 changes: 28 additions & 0 deletions tests/api/documents/test_documents_rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -728,3 +728,31 @@ def test_document_current_library_on_request_parameter(
.scan())
assert oplg.library.value == lib_martigny_bourg.pid
db.session.rollback()


def test_document_advanced_search_config(app, db, client,
system_librarian_martigny, document):
"""Test for advanced search config."""
config_url = url_for('api_documents.advanced_search_config')

res = client.get(config_url)
assert res.status_code == 401

login_user_via_session(client, system_librarian_martigny.user)

res = client.get(config_url)
assert res.status_code == 200

json = res.json
assert 'fieldsConfig' in json
assert 'fieldsData' in json
field_data = json.get('fieldsData')
data_keys = [
'canton', 'country', 'rdaCarrierType',
'rdaContentType', 'rdaMediaType'
]
assert data_keys == list(field_data.keys())

assert 0 < len(json.get('fieldsConfig'))
for key in data_keys:
assert 0 < len(field_data.get(key))

0 comments on commit 1947830

Please sign in to comment.