aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--python/fatcat_web/routes.py11
-rw-r--r--python/fatcat_web/search.py64
-rw-r--r--python/fatcat_web/templates/container_view_browse.html32
-rw-r--r--python/fatcat_web/templates/entity_base.html1
4 files changed, 107 insertions, 1 deletions
diff --git a/python/fatcat_web/routes.py b/python/fatcat_web/routes.py
index b25cd37c..9f46c674 100644
--- a/python/fatcat_web/routes.py
+++ b/python/fatcat_web/routes.py
@@ -60,6 +60,7 @@ from fatcat_web.search import (
ReleaseQuery,
do_container_search,
do_release_search,
+ get_elastic_container_browse_year_volume,
get_elastic_container_histogram_legacy,
get_elastic_container_preservation_by_volume,
get_elastic_container_random_releases,
@@ -286,6 +287,8 @@ 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
@@ -346,6 +349,12 @@ def container_view_coverage(ident: str) -> AnyResponse:
return generic_entity_view("container", ident, "container_view_coverage.html")
+@app.route("/container/<string(length=26):ident>/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")
+
+
@app.route("/container/<string(length=26):ident>/metadata", methods=["GET"])
def container_view_metadata(ident: str) -> AnyResponse:
return generic_entity_view("container", ident, "entity_view_metadata.html")
@@ -1079,7 +1088,7 @@ def coverage_search() -> AnyResponse:
)
-@app.route("/container/<ident>/search", methods=["GET", "POST"])
+@app.route("/container/<string(length=26):ident>/search", methods=["GET", "POST"])
def container_view_search(ident: str) -> AnyResponse:
entity = generic_get_entity("container", ident)
diff --git a/python/fatcat_web/search.py b/python/fatcat_web/search.py
index 9e9376cc..ac4dc34e 100644
--- a/python/fatcat_web/search.py
+++ b/python/fatcat_web/search.py
@@ -327,6 +327,70 @@ def get_elastic_container_random_releases(ident: str, limit: int = 5) -> List[Di
return results
+def get_elastic_container_browse_year_volume(ident: str) -> List[Dict[int, Any]]:
+ """
+ Returns a set of histogram buckets:
+
+ container_ident: str
+ years{}
+ volumes{}
+ """
+
+ search = Search(using=app.es_client, index=app.config["ELASTICSEARCH_RELEASE_INDEX"])
+ search = search.query(
+ "bool",
+ filter=[Q("bool", must_not=[Q("match", release_type="stub")])],
+ )
+ search = search.filter("term", container_id=ident)
+ search.aggs.bucket(
+ "year_volume",
+ "composite",
+ size=1500,
+ sources=[
+ {
+ "year": {
+ "histogram": {
+ "field": "release_year",
+ "interval": 1,
+ "missing_bucket": True,
+ # TODO: es-public-proxy support?
+ # "order": "asc",
+ # "missing_order": "last",
+ },
+ }
+ },
+ {
+ "volume": {
+ "terms": {
+ "field": "volume",
+ "missing_bucket": True,
+ # TODO: es-public-proxy support?
+ # "order": "asc",
+ # "missing_order": "last",
+ },
+ }
+ },
+ ],
+ )
+ search = search[:0]
+ search = search.params(request_cache=True)
+ resp = wrap_es_execution(search)
+ buckets = resp.aggregations.year_volume.buckets
+ # print(buckets)
+ buckets = [h for h in buckets if h["key"]["year"]]
+ year_nums = set([int(h["key"]["year"]) for h in buckets])
+ year_dicts: Dict[int, Dict[str, Any]] = dict()
+ if year_nums:
+ for year in year_nums:
+ year_dicts[year] = {}
+ for row in buckets:
+ year_dicts[int(row["key"]["year"])][row["key"]["volume"] or "_unknown"] = int(
+ row["doc_count"]
+ )
+ # return sorted(year_dicts.values(), key=lambda x: x["year"])
+ return year_dicts
+
+
def get_elastic_entity_stats() -> dict:
"""
TODO: files, filesets, webcaptures (no schema yet)
diff --git a/python/fatcat_web/templates/container_view_browse.html b/python/fatcat_web/templates/container_view_browse.html
new file mode 100644
index 00000000..b5691899
--- /dev/null
+++ b/python/fatcat_web/templates/container_view_browse.html
@@ -0,0 +1,32 @@
+{% set container = entity %}
+{% set entity_view = "browse" %}
+{% set entity_type = "container" %}
+{% import "entity_macros.html" as entity_macros %}
+{% extends "entity_base.html" %}
+
+{% block entity_main %}
+
+{% if entity._browse_volume_year %}
+<h2>Browse by Year and Volume</h2>
+<ul>
+{% for year in entity._browse_volume_year.keys()|sort|reverse %}
+ {% for volume in entity._browse_volume_year[year].keys()|sort|reverse %}
+ {% if volume == '_unknown' %}
+ <li><a href="/container/{{ entity.ident }}/browse?year={{ year }}&volume=">{{ year }}</a> ({{ entity._browse_volume_year[year][volume] }} releases)
+ {% else %}
+ <li><a href="/container/{{ entity.ident }}/browse?year={{ year }}&volume={{ volume }}">{{ year }} | Vol. {{ volume }}</a> ({{ entity._browse_volume_year[year][volume] }} releases)
+ {% endif %}
+ {% endfor %}
+{% endfor %}
+</ul>
+{% elif entity._browse_issues %}
+{% for issue in entity._browse_issues.keys()|sort|reverse %}
+ <h4>{{ issue }}</h4>
+ {% for paper in entity._browse_issues[issue] %}
+ {{ paper.title }}<br>
+ {% endfor %}
+{% endfor %}
+{% endif %}
+
+{% endblock %}
+
diff --git a/python/fatcat_web/templates/entity_base.html b/python/fatcat_web/templates/entity_base.html
index 2782edd5..633f3aee 100644
--- a/python/fatcat_web/templates/entity_base.html
+++ b/python/fatcat_web/templates/entity_base.html
@@ -82,6 +82,7 @@
<div class="ui small tabular compact menu">
{{ entity_tab("overview", "Overview", "") }}
{% if entity_type == "container" and entity.state == 'active' and not editgroup %}
+ {{ entity_tab("browse", "Browse", "/browse") }}
{{ entity_tab("coverage", "Preservation", "/coverage") }}
{{ entity_tab("search", "Search", "/search") }}
{% elif entity_type == "release" and entity.state != 'deleted' %}