From 9b9ede257753b1e3fd19bbf90a5895de5db18504 Mon Sep 17 00:00:00 2001 From: Bryan Newbold Date: Fri, 11 Feb 2022 11:14:07 -0800 Subject: containers: progress on browse interface --- python/fatcat_web/routes.py | 92 ++++++++++++++++++++-- python/fatcat_web/search.py | 7 +- .../templates/container_view_browse.html | 71 ++++++++++++----- python/fatcat_web/templates/entity_macros.html | 4 +- 4 files changed, 146 insertions(+), 28 deletions(-) (limited to 'python/fatcat_web') diff --git a/python/fatcat_web/routes.py b/python/fatcat_web/routes.py index 0afc189f..6e3e9b57 100644 --- a/python/fatcat_web/routes.py +++ b/python/fatcat_web/routes.py @@ -287,8 +287,6 @@ def generic_entity_view(entity_type: str, ident: str, view_template: str) -> Any entity._type_preservation = get_elastic_preservation_by_type( ReleaseQuery(container_id=ident), ) - if view_template == "container_view_browse.html": - entity._browse_volume_year = get_elastic_container_browse_year_volume(entity.ident) return render_template( view_template, entity_type=entity_type, entity=entity, editgroup_id=None @@ -350,9 +348,93 @@ def container_view_coverage(ident: str) -> AnyResponse: @app.route("/container//browse", methods=["GET"]) -def container_view_browser(ident: str) -> AnyResponse: - # note: there is a special hack to add entity._type_preservation for this endpoint - return generic_entity_view("container", ident, "container_view_browse.html") +def container_view_browse(ident: str) -> AnyResponse: + entity = generic_get_entity("container", ident) + + if entity.state == "redirect": + return redirect(f"/container/{entity.redirect}") + elif entity.state == "deleted": + return render_template("deleted_entity.html", entity_type="container", entity=entity) + + query_sort: Optional[List[str]] + if request.args.get('year') and 'volume' in request.args and 'issue' in request.args: + # year, volume, issue specified; browse-by-page + year = int(request.args.get('year')) + volume = request.args.get('volume', '') + issue = request.args.get('issue', '') + if volume: + volume = f'volume:"{volume}"' + else: + volume = "!volume:*" + if issue: + issue = f'issue:"{issue}"' + else: + issue = "!issue:*" + query_string = f'year:{year} {volume} {issue}' + query_sort = ["first_page", "release_date"] + elif request.args.get('year') and 'volume' in request.args: + # year, volume specified (no issue); browse-by-page + year = int(request.args.get('year')) + volume = request.args.get('volume', '') + if volume: + volume = f'volume:"{volume}"' + else: + volume = "!volume:*" + query_string = f'year:{year} {volume}' + query_sort = ["issue", "first_page", "release_date"] + elif request.args.get('year'): + # year specified, not anything else; browse-by-date + year = int(request.args.get('year')) + query_string = f"year:{year}" + query_sort = ["release_date"] + else: + entity._browse_volume_year = get_elastic_container_browse_year_volume(entity.ident) + return render_template( + "container_view_browse.html", entity_type="container", entity=entity, editgroup_id=None + ) + + print(query_string) + query = ReleaseQuery( + q=query_string, + limit=200, + offset=0, + container_id=ident, + fulltext_only=False, + recent=False, + exclude_stubs=True, + sort=query_sort, + ) + + try: + found = do_release_search(query) + except FatcatSearchError as fse: + return ( + render_template( + "container_view_search.html", + query=query, + es_error=fse, + entity_type="container", + entity=entity, + editgroup_id=None, + ), + fse.status_code, + ) + + # HACK: re-sort by first page *numerically* + if found.results and query_sort and 'first_page' in query_sort: + for doc in found.results: + if doc.get('first_page') and doc['first_page'].isdigit(): + doc['first_page'] = int(doc['first_page']) + found.results = sorted(found.results, key=lambda d: d.get('first_page') or 99999999) + + return render_template( + "container_view_browse.html", + query=query, + releases_found=found, + entity_type="container", + entity=entity, + editgroup_id=None, + ) @app.route("/container//metadata", methods=["GET"]) diff --git a/python/fatcat_web/search.py b/python/fatcat_web/search.py index b19b57e6..3f4a216c 100644 --- a/python/fatcat_web/search.py +++ b/python/fatcat_web/search.py @@ -29,6 +29,7 @@ class ReleaseQuery: container_id: Optional[str] = None recent: bool = False exclude_stubs: bool = False + sort: Optional[List[str]] = None @staticmethod def from_args(args: Dict[str, Any]) -> "ReleaseQuery": @@ -45,6 +46,7 @@ class ReleaseQuery: container_id=args.get("container_id"), recent=bool(args.get("recent")), exclude_stubs=bool(args.get("exclude_stubs")), + sort=None, ) @@ -182,6 +184,9 @@ def do_release_search(query: ReleaseQuery, deep_page_limit: int = 2000) -> Searc negative_boost=0.5, ) + if query.sort: + search = search.sort(*query.sort) + # Sanity checks limit = min((int(query.limit or 25), 100)) offset = max((int(query.offset or 0), 0)) @@ -299,7 +304,7 @@ def get_elastic_container_browse_year_volume(ident: str) -> Dict[int, Dict[str, for year in year_nums: year_dicts[year] = {} for row in buckets: - year_dicts[int(row["key"]["year"])][row["key"]["volume"] or "_unknown"] = int( + year_dicts[int(row["key"]["year"])][row["key"]["volume"] or "000_unknown"] = int( row["doc_count"] ) # return sorted(year_dicts.values(), key=lambda x: x["year"]) diff --git a/python/fatcat_web/templates/container_view_browse.html b/python/fatcat_web/templates/container_view_browse.html index b5691899..aa88b666 100644 --- a/python/fatcat_web/templates/container_view_browse.html +++ b/python/fatcat_web/templates/container_view_browse.html @@ -4,28 +4,59 @@ {% import "entity_macros.html" as entity_macros %} {% extends "entity_base.html" %} -{% block entity_main %} - -{% if entity._browse_volume_year %} -

Browse by Year and Volume

-
    -{% for year in entity._browse_volume_year.keys()|sort|reverse %} - {% for volume in entity._browse_volume_year[year].keys()|sort|reverse %} - {% if volume == '_unknown' %} -
  • {{ year }} ({{ entity._browse_volume_year[year][volume] }} releases) - {% else %} -
  • {{ year }} | Vol. {{ volume }} ({{ entity._browse_volume_year[year][volume] }} releases) - {% endif %} +{% macro browse_year_volume_table(entity, data) %} + + + {% for year in data.keys()|sort|reverse %} + {% for volume in data[year].keys()|sort|reverse %} + + {% if loop.first %} + + {% endif %} + {% if volume == '000_unknown' %} + + + + {% endfor %} {% endfor %} -{% endfor %} - -{% elif entity._browse_issues %} -{% for issue in entity._browse_issues.keys()|sort|reverse %} -

    {{ issue }}

    - {% for paper in entity._browse_issues[issue] %} - {{ paper.title }}
    + +
    + {{ year }} + {% if data[year]|length > 1 %}n/a{% endif %}{{ data[year][volume] }} releases + {% else %} + Vol. {{ volume }}{{ data[year][volume] }} releases + {% endif %} +
    +{% endmacro %} + +{% macro browse_releases(found) %} + {% for release_doc in found.results %} +
    +
    + {% if release_doc.pages %} + {{ release_doc.pages }} + {# + {% elif release_doc.release_date %} + {{ release_doc.release_date }} + #} + {% endif %} +
    +
    + {{ entity_macros.release_search_result_row(release_doc, margin_top=False) }} +
    +
    {% endfor %} -{% endfor %} +{% endmacro %} + +{% block entity_main %} + +{% if releases_found %} + {{ browse_releases(releases_found) }} +{% elif entity._browse_volume_year %} +
    +

    Contents by Year and Volume

    + {{ browse_year_volume_table(entity, entity._browse_volume_year) }} +
    {% endif %} {% endblock %} diff --git a/python/fatcat_web/templates/entity_macros.html b/python/fatcat_web/templates/entity_macros.html index 6ad63a14..163af3e0 100644 --- a/python/fatcat_web/templates/entity_macros.html +++ b/python/fatcat_web/templates/entity_macros.html @@ -142,9 +142,9 @@ {%- endmacro %} -{% macro release_search_result_row(paper) -%} +{% macro release_search_result_row(paper, margin_top=True) -%}