aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--python/fatcat_web/forms.py4
-rw-r--r--python/fatcat_web/routes.py214
-rw-r--r--python/fatcat_web/search.py9
-rw-r--r--python/fatcat_web/templates/400.html2
-rw-r--r--python/fatcat_web/templates/base.html13
-rw-r--r--python/fatcat_web/templates/container_view.html20
-rw-r--r--python/fatcat_web/templates/coverage_search.html7
-rw-r--r--python/fatcat_web/templates/entity_macros.html2
-rw-r--r--python/tests/import_file_meta.py2
-rw-r--r--python/tests/web_entity_views.py10
10 files changed, 159 insertions, 124 deletions
diff --git a/python/fatcat_web/forms.py b/python/fatcat_web/forms.py
index ff885fcb..1c9fb199 100644
--- a/python/fatcat_web/forms.py
+++ b/python/fatcat_web/forms.py
@@ -476,5 +476,9 @@ class EntityTomlForm(EntityEditForm):
pop_fields = ['ident', 'state', 'revision', 'redirect']
else:
pop_fields = ['ident', 'state']
+
+ # remove "expand" fields
+ pop_fields += ['releases', 'container', 'work', 'creators', 'files', 'filesets', 'webcaptures']
+
etf.toml.data = entity_to_toml(entity, pop_fields=pop_fields)
return etf
diff --git a/python/fatcat_web/routes.py b/python/fatcat_web/routes.py
index 9ae2eaa9..02b5258a 100644
--- a/python/fatcat_web/routes.py
+++ b/python/fatcat_web/routes.py
@@ -1,6 +1,7 @@
import os
import json
+import citeproc_styles
from flask import render_template, make_response, send_from_directory, \
request, url_for, abort, redirect, jsonify, session, flash, Response
from flask_login import login_required
@@ -22,7 +23,7 @@ from fatcat_web.forms import SavePaperNowForm
### Generic Entity Views ####################################################
-@app.route('/container/<ident>/history', methods=['GET'])
+@app.route('/container/<string(length=26):ident>/history', methods=['GET'])
def container_history(ident):
try:
entity = api.get_container(ident)
@@ -35,7 +36,7 @@ def container_history(ident):
entity=entity,
history=history)
-@app.route('/creator/<ident>/history', methods=['GET'])
+@app.route('/creator/<string(length=26):ident>/history', methods=['GET'])
def creator_history(ident):
try:
entity = api.get_creator(ident)
@@ -47,7 +48,7 @@ def creator_history(ident):
entity=entity,
history=history)
-@app.route('/file/<ident>/history', methods=['GET'])
+@app.route('/file/<string(length=26):ident>/history', methods=['GET'])
def file_history(ident):
try:
entity = api.get_file(ident)
@@ -59,7 +60,7 @@ def file_history(ident):
entity=entity,
history=history)
-@app.route('/fileset/<ident>/history', methods=['GET'])
+@app.route('/fileset/<string(length=26):ident>/history', methods=['GET'])
def fileset_history(ident):
try:
entity = api.get_fileset(ident)
@@ -71,7 +72,7 @@ def fileset_history(ident):
entity=entity,
history=history)
-@app.route('/webcapture/<ident>/history', methods=['GET'])
+@app.route('/webcapture/<string(length=26):ident>/history', methods=['GET'])
def webcapture_history(ident):
try:
entity = api.get_webcapture(ident)
@@ -83,7 +84,7 @@ def webcapture_history(ident):
entity=entity,
history=history)
-@app.route('/release/<ident>/history', methods=['GET'])
+@app.route('/release/<string(length=26):ident>/history', methods=['GET'])
def release_history(ident):
try:
entity = api.get_release(ident)
@@ -95,7 +96,7 @@ def release_history(ident):
entity=entity,
history=history)
-@app.route('/work/<ident>/history', methods=['GET'])
+@app.route('/work/<string(length=26):ident>/history', methods=['GET'])
def work_history(ident):
try:
entity = api.get_work(ident)
@@ -238,241 +239,241 @@ def generic_editgroup_entity_view(editgroup_id, entity_type, ident, view_templat
return render_template(view_template, entity_type=entity_type, entity=entity, editgroup=editgroup)
-@app.route('/container/<ident>', methods=['GET'])
+@app.route('/container/<string(length=26):ident>', methods=['GET'])
def container_view(ident):
return generic_entity_view('container', ident, 'container_view.html')
-@app.route('/container_<ident>', methods=['GET'])
+@app.route('/container_<string(length=26):ident>', methods=['GET'])
def container_underscore_view(ident):
return redirect('/container/{}'.format(ident))
-@app.route('/container/<ident>/coverage', methods=['GET'])
+@app.route('/container/<string(length=26):ident>/coverage', methods=['GET'])
def container_view_coverage(ident):
# note: there is a special hack to add entity._type_preservation for this endpoint
return generic_entity_view('container', ident, 'container_view_coverage.html')
-@app.route('/container/<ident>/metadata', methods=['GET'])
+@app.route('/container/<string(length=26):ident>/metadata', methods=['GET'])
def container_view_metadata(ident):
return generic_entity_view('container', ident, 'entity_view_metadata.html')
-@app.route('/container/rev/<revision_id>', methods=['GET'])
+@app.route('/container/rev/<uuid:revision_id>', methods=['GET'])
def container_revision_view(revision_id):
- return generic_entity_revision_view('container', revision_id, 'container_view.html')
+ return generic_entity_revision_view('container', str(revision_id), 'container_view.html')
-@app.route('/container/rev/<revision_id>/metadata', methods=['GET'])
+@app.route('/container/rev/<uuid:revision_id>/metadata', methods=['GET'])
def container_revision_view_metadata(revision_id):
- return generic_entity_revision_view('container', revision_id, 'entity_view_metadata.html')
+ return generic_entity_revision_view('container', str(revision_id), 'entity_view_metadata.html')
-@app.route('/editgroup/<editgroup_id>/container/<ident>', methods=['GET'])
+@app.route('/editgroup/<editgroup_id>/container/<string(length=26):ident>', methods=['GET'])
def container_editgroup_view(editgroup_id, ident):
return generic_editgroup_entity_view(editgroup_id, 'container', ident, 'container_view.html')
-@app.route('/editgroup/<editgroup_id>/container/<ident>/metadata', methods=['GET'])
+@app.route('/editgroup/<editgroup_id>/container/<string(length=26):ident>/metadata', methods=['GET'])
def container_editgroup_view_metadata(editgroup_id, ident):
return generic_editgroup_entity_view(editgroup_id, 'container', ident, 'entity_view_metadata.html')
-@app.route('/creator/<ident>', methods=['GET'])
+@app.route('/creator/<string(length=26):ident>', methods=['GET'])
def creator_view(ident):
return generic_entity_view('creator', ident, 'creator_view.html')
-@app.route('/creator_<ident>', methods=['GET'])
+@app.route('/creator_<string(length=26):ident>', methods=['GET'])
def creator_underscore_view(ident):
return redirect('/creator/{}'.format(ident))
-@app.route('/creator/<ident>/metadata', methods=['GET'])
+@app.route('/creator/<string(length=26):ident>/metadata', methods=['GET'])
def creator_view_metadata(ident):
return generic_entity_view('creator', ident, 'entity_view_metadata.html')
-@app.route('/creator/rev/<revision_id>', methods=['GET'])
+@app.route('/creator/rev/<uuid:revision_id>', methods=['GET'])
def creator_revision_view(revision_id):
- return generic_entity_revision_view('creator', revision_id, 'creator_view.html')
+ return generic_entity_revision_view('creator', str(revision_id), 'creator_view.html')
-@app.route('/creator/rev/<revision_id>/metadata', methods=['GET'])
+@app.route('/creator/rev/<uuid:revision_id>/metadata', methods=['GET'])
def creator_revision_view_metadata(revision_id):
- return generic_entity_revision_view('creator', revision_id, 'entity_view_metadata.html')
+ return generic_entity_revision_view('creator', str(revision_id), 'entity_view_metadata.html')
-@app.route('/editgroup/<editgroup_id>/creator/<ident>', methods=['GET'])
+@app.route('/editgroup/<editgroup_id>/creator/<string(length=26):ident>', methods=['GET'])
def creator_editgroup_view(editgroup_id, ident):
return generic_editgroup_entity_view(editgroup_id, 'creator', ident, 'creator_view.html')
-@app.route('/editgroup/<editgroup_id>/creator/<ident>/metadata', methods=['GET'])
+@app.route('/editgroup/<editgroup_id>/creator/<string(length=26):ident>/metadata', methods=['GET'])
def creator_editgroup_view_metadata(editgroup_id, ident):
return generic_editgroup_entity_view(editgroup_id, 'creator', ident, 'entity_view_metadata.html')
-@app.route('/file/<ident>', methods=['GET'])
+@app.route('/file/<string(length=26):ident>', methods=['GET'])
def file_view(ident):
return generic_entity_view('file', ident, 'file_view.html')
-@app.route('/file_<ident>', methods=['GET'])
+@app.route('/file_<string(length=26):ident>', methods=['GET'])
def file_underscore_view(ident):
return redirect('/file/{}'.format(ident))
-@app.route('/file/<ident>/metadata', methods=['GET'])
+@app.route('/file/<string(length=26):ident>/metadata', methods=['GET'])
def file_view_metadata(ident):
return generic_entity_view('file', ident, 'entity_view_metadata.html')
-@app.route('/file/rev/<revision_id>', methods=['GET'])
+@app.route('/file/rev/<uuid:revision_id>', methods=['GET'])
def file_revision_view(revision_id):
- return generic_entity_revision_view('file', revision_id, 'file_view.html')
+ return generic_entity_revision_view('file', str(revision_id), 'file_view.html')
-@app.route('/file/rev/<revision_id>/metadata', methods=['GET'])
+@app.route('/file/rev/<uuid:revision_id>/metadata', methods=['GET'])
def file_revision_view_metadata(revision_id):
- return generic_entity_revision_view('file', revision_id, 'entity_view_metadata.html')
+ return generic_entity_revision_view('file', str(revision_id), 'entity_view_metadata.html')
-@app.route('/editgroup/<editgroup_id>/file/<ident>', methods=['GET'])
+@app.route('/editgroup/<editgroup_id>/file/<string(length=26):ident>', methods=['GET'])
def file_editgroup_view(editgroup_id, ident):
return generic_editgroup_entity_view(editgroup_id, 'file', ident, 'file_view.html')
-@app.route('/editgroup/<editgroup_id>/file/<ident>/metadata', methods=['GET'])
+@app.route('/editgroup/<editgroup_id>/file/<string(length=26):ident>/metadata', methods=['GET'])
def file_editgroup_view_metadata(editgroup_id, ident):
return generic_editgroup_entity_view(editgroup_id, 'file', ident, 'entity_view_metadata.html')
-@app.route('/fileset/<ident>', methods=['GET'])
+@app.route('/fileset/<string(length=26):ident>', methods=['GET'])
def fileset_view(ident):
return generic_entity_view('fileset', ident, 'fileset_view.html')
-@app.route('/fileset_<ident>', methods=['GET'])
+@app.route('/fileset_<string(length=26):ident>', methods=['GET'])
def fileset_underscore_view(ident):
return redirect('/fileset/{}'.format(ident))
-@app.route('/fileset/<ident>/metadata', methods=['GET'])
+@app.route('/fileset/<string(length=26):ident>/metadata', methods=['GET'])
def fileset_view_metadata(ident):
return generic_entity_view('fileset', ident, 'entity_view_metadata.html')
-@app.route('/fileset/rev/<revision_id>', methods=['GET'])
+@app.route('/fileset/rev/<uuid:revision_id>', methods=['GET'])
def fileset_revision_view(revision_id):
- return generic_entity_revision_view('fileset', revision_id, 'fileset_view.html')
+ return generic_entity_revision_view('fileset', str(revision_id), 'fileset_view.html')
-@app.route('/fileset/rev/<revision_id>/metadata', methods=['GET'])
+@app.route('/fileset/rev/<uuid:revision_id>/metadata', methods=['GET'])
def fileset_revision_view_metadata(revision_id):
- return generic_entity_revision_view('fileset', revision_id, 'entity_view_metadata.html')
+ return generic_entity_revision_view('fileset', str(revision_id), 'entity_view_metadata.html')
-@app.route('/editgroup/<editgroup_id>/fileset/<ident>', methods=['GET'])
+@app.route('/editgroup/<editgroup_id>/fileset/<string(length=26):ident>', methods=['GET'])
def fileset_editgroup_view(editgroup_id, ident):
return generic_editgroup_entity_view(editgroup_id, 'fileset', ident, 'fileset_view.html')
-@app.route('/editgroup/<editgroup_id>/fileset/<ident>/metadata', methods=['GET'])
+@app.route('/editgroup/<editgroup_id>/fileset/<string(length=26):ident>/metadata', methods=['GET'])
def fileset_editgroup_view_metadata(editgroup_id, ident):
return generic_editgroup_entity_view(editgroup_id, 'fileset', ident, 'entity_view_metadata.html')
-@app.route('/webcapture/<ident>', methods=['GET'])
+@app.route('/webcapture/<string(length=26):ident>', methods=['GET'])
def webcapture_view(ident):
return generic_entity_view('webcapture', ident, 'webcapture_view.html')
-@app.route('/webcapture_<ident>', methods=['GET'])
+@app.route('/webcapture_<string(length=26):ident>', methods=['GET'])
def webcapture_underscore_view(ident):
return redirect('/webcapture/{}'.format(ident))
-@app.route('/webcapture/<ident>/metadata', methods=['GET'])
+@app.route('/webcapture/<string(length=26):ident>/metadata', methods=['GET'])
def webcapture_view_metadata(ident):
return generic_entity_view('webcapture', ident, 'entity_view_metadata.html')
-@app.route('/webcapture/rev/<revision_id>', methods=['GET'])
+@app.route('/webcapture/rev/<uuid:revision_id>', methods=['GET'])
def webcapture_revision_view(revision_id):
- return generic_entity_revision_view('webcapture', revision_id, 'webcapture_view.html')
+ return generic_entity_revision_view('webcapture', str(revision_id), 'webcapture_view.html')
-@app.route('/webcapture/rev/<revision_id>/metadata', methods=['GET'])
+@app.route('/webcapture/rev/<uuid:revision_id>/metadata', methods=['GET'])
def webcapture_revision_view_metadata(revision_id):
- return generic_entity_revision_view('webcapture', revision_id, 'entity_view_metadata.html')
+ return generic_entity_revision_view('webcapture', str(revision_id), 'entity_view_metadata.html')
-@app.route('/editgroup/<editgroup_id>/webcapture/<ident>', methods=['GET'])
+@app.route('/editgroup/<editgroup_id>/webcapture/<string(length=26):ident>', methods=['GET'])
def webcapture_editgroup_view(editgroup_id, ident):
return generic_editgroup_entity_view(editgroup_id, 'webcapture', ident, 'webcapture_view.html')
-@app.route('/editgroup/<editgroup_id>/webcapture/<ident>/metadata', methods=['GET'])
+@app.route('/editgroup/<editgroup_id>/webcapture/<string(length=26):ident>/metadata', methods=['GET'])
def webcapture_editgroup_view_metadata(editgroup_id, ident):
return generic_editgroup_entity_view(editgroup_id, 'webcapture', ident, 'entity_view_metadata.html')
-@app.route('/release/<ident>', methods=['GET'])
+@app.route('/release/<string(length=26):ident>', methods=['GET'])
def release_view(ident):
return generic_entity_view('release', ident, 'release_view.html')
-@app.route('/release_<ident>', methods=['GET'])
+@app.route('/release_<string(length=26):ident>', methods=['GET'])
def release_underscore_view(ident):
return redirect('/release/{}'.format(ident))
-@app.route('/release/<ident>/contribs', methods=['GET'])
+@app.route('/release/<string(length=26):ident>/contribs', methods=['GET'])
def release_view_contribs(ident):
return generic_entity_view('release', ident, 'release_view_contribs.html')
-@app.route('/release/<ident>/references', methods=['GET'])
+@app.route('/release/<string(length=26):ident>/references', methods=['GET'])
def release_view_references(ident):
return generic_entity_view('release', ident, 'release_view_references.html')
-@app.route('/release/<ident>/metadata', methods=['GET'])
+@app.route('/release/<string(length=26):ident>/metadata', methods=['GET'])
def release_view_metadata(ident):
return generic_entity_view('release', ident, 'entity_view_metadata.html')
-@app.route('/release/rev/<revision_id>', methods=['GET'])
+@app.route('/release/rev/<uuid:revision_id>', methods=['GET'])
def release_revision_view(revision_id):
- return generic_entity_revision_view('release', revision_id, 'release_view.html')
+ return generic_entity_revision_view('release', str(revision_id), 'release_view.html')
-@app.route('/release/rev/<revision_id>/contribs', methods=['GET'])
+@app.route('/release/rev/<uuid:revision_id>/contribs', methods=['GET'])
def release_revision_view_contribs(revision_id):
- return generic_entity_revision_view('release', revision_id, 'release_view_contribs.html')
+ return generic_entity_revision_view('release', str(revision_id), 'release_view_contribs.html')
-@app.route('/release/rev/<revision_id>/references', methods=['GET'])
+@app.route('/release/rev/<uuid:revision_id>/references', methods=['GET'])
def release_revision_view_references(revision_id):
- return generic_entity_revision_view('release', revision_id, 'release_view_references.html')
+ return generic_entity_revision_view('release', str(revision_id), 'release_view_references.html')
-@app.route('/release/rev/<revision_id>/metadata', methods=['GET'])
+@app.route('/release/rev/<uuid:revision_id>/metadata', methods=['GET'])
def release_revision_view_metadata(revision_id):
- return generic_entity_revision_view('release', revision_id, 'entity_view_metadata.html')
+ return generic_entity_revision_view('release', str(revision_id), 'entity_view_metadata.html')
-@app.route('/editgroup/<editgroup_id>/release/<ident>', methods=['GET'])
+@app.route('/editgroup/<editgroup_id>/release/<string(length=26):ident>', methods=['GET'])
def release_editgroup_view(editgroup_id, ident):
return generic_editgroup_entity_view(editgroup_id, 'release', ident, 'release_view.html')
-@app.route('/editgroup/<editgroup_id>/release/<ident>/contribs', methods=['GET'])
+@app.route('/editgroup/<editgroup_id>/release/<string(length=26):ident>/contribs', methods=['GET'])
def release_editgroup_view_contribs(editgroup_id, ident):
return generic_editgroup_entity_view(editgroup_id, 'release', ident, 'release_view_contribs.html')
-@app.route('/editgroup/<editgroup_id>/release/<ident>/references', methods=['GET'])
+@app.route('/editgroup/<editgroup_id>/release/<string(length=26):ident>/references', methods=['GET'])
def release_editgroup_view_references(editgroup_id, ident):
return generic_editgroup_entity_view(editgroup_id, 'release', ident, 'release_view_references.html')
-@app.route('/editgroup/<editgroup_id>/release/<ident>/metadata', methods=['GET'])
+@app.route('/editgroup/<editgroup_id>/release/<string(length=26):ident>/metadata', methods=['GET'])
def release_editgroup_view_metadata(editgroup_id, ident):
return generic_editgroup_entity_view(editgroup_id, 'release', ident, 'entity_view_metadata.html')
-@app.route('/work/<ident>', methods=['GET'])
+@app.route('/work/<string(length=26):ident>', methods=['GET'])
def work_view(ident):
return generic_entity_view('work', ident, 'work_view.html')
-@app.route('/work_<ident>', methods=['GET'])
+@app.route('/work_<string(length=26):ident>', methods=['GET'])
def work_underscore_view(ident):
return redirect('/work/{}'.format(ident))
-@app.route('/work/<ident>/metadata', methods=['GET'])
+@app.route('/work/<string(length=26):ident>/metadata', methods=['GET'])
def work_view_metadata(ident):
return generic_entity_view('work', ident, 'entity_view_metadata.html')
-@app.route('/work/rev/<revision_id>', methods=['GET'])
+@app.route('/work/rev/<uuid:revision_id>', methods=['GET'])
def work_revision_view(revision_id):
- return generic_entity_revision_view('work', revision_id, 'work_view.html')
+ return generic_entity_revision_view('work', str(revision_id), 'work_view.html')
-@app.route('/work/rev/<revision_id>/metadata', methods=['GET'])
+@app.route('/work/rev/<uuid:revision_id>/metadata', methods=['GET'])
def work_revision_view_metadata(revision_id):
- return generic_entity_revision_view('work', revision_id, 'entity_view_metadata.html')
+ return generic_entity_revision_view('work', str(revision_id), 'entity_view_metadata.html')
-@app.route('/editgroup/<editgroup_id>/work/<ident>', methods=['GET'])
+@app.route('/editgroup/<editgroup_id>/work/<string(length=26):ident>', methods=['GET'])
def work_editgroup_view(editgroup_id, ident):
return generic_editgroup_entity_view(editgroup_id, 'work', ident, 'work_view.html')
-@app.route('/editgroup/<editgroup_id>/work/<ident>/metadata', methods=['GET'])
+@app.route('/editgroup/<editgroup_id>/work/<string(length=26):ident>/metadata', methods=['GET'])
def work_editgroup_view_metadata(editgroup_id, ident):
return generic_editgroup_entity_view(editgroup_id, 'work', ident, 'entity_view_metadata.html')
### Views ###################################################################
-@app.route('/editgroup/<ident>', methods=['GET'])
+@app.route('/editgroup/<string(length=26):ident>', methods=['GET'])
def editgroup_view(ident):
try:
eg = api.get_editgroup(str(ident))
@@ -498,7 +499,7 @@ def editgroup_view(ident):
return render_template('editgroup_view.html', editgroup=eg,
auth_to=auth_to)
-@app.route('/editgroup/<ident>/annotation', methods=['POST'])
+@app.route('/editgroup/<string(length=26):ident>/annotation', methods=['POST'])
@login_required
def editgroup_create_annotation(ident):
if not app.testing:
@@ -523,7 +524,7 @@ def editgroup_create_annotation(ident):
raise ae
return redirect('/editgroup/{}'.format(ident))
-@app.route('/editgroup/<ident>/accept', methods=['POST'])
+@app.route('/editgroup/<string(length=26):ident>/accept', methods=['POST'])
@login_required
def editgroup_accept(ident):
if not app.testing:
@@ -540,7 +541,7 @@ def editgroup_accept(ident):
abort(ae.status)
return redirect('/editgroup/{}'.format(ident))
-@app.route('/editgroup/<ident>/unsubmit', methods=['POST'])
+@app.route('/editgroup/<string(length=26):ident>/unsubmit', methods=['POST'])
@login_required
def editgroup_unsubmit(ident):
if not app.testing:
@@ -557,7 +558,7 @@ def editgroup_unsubmit(ident):
abort(ae.status)
return redirect('/editgroup/{}'.format(ident))
-@app.route('/editgroup/<ident>/submit', methods=['POST'])
+@app.route('/editgroup/<string(length=26):ident>/submit', methods=['POST'])
@login_required
def editgroup_submit(ident):
if not app.testing:
@@ -574,7 +575,7 @@ def editgroup_submit(ident):
abort(ae.status)
return redirect('/editgroup/{}'.format(ident))
-@app.route('/editor/<ident>', methods=['GET'])
+@app.route('/editor/<string(length=26):ident>', methods=['GET'])
def editor_view(ident):
try:
entity = api.get_editor(ident)
@@ -582,7 +583,7 @@ def editor_view(ident):
abort(ae.status)
return render_template('editor_view.html', editor=entity)
-@app.route('/editor/<ident>/editgroups', methods=['GET'])
+@app.route('/editor/<string(length=26):ident>/editgroups', methods=['GET'])
def editor_editgroups(ident):
try:
editor = api.get_editor(ident)
@@ -595,7 +596,7 @@ def editor_editgroups(ident):
return render_template('editor_editgroups.html', editor=editor,
editgroups=editgroups)
-@app.route('/editor/<ident>/annotations', methods=['GET'])
+@app.route('/editor/<string(length=26):ident>/annotations', methods=['GET'])
def editor_annotations(ident):
try:
editor = api.get_editor(ident)
@@ -634,7 +635,7 @@ def reviewable_view():
abort(ae.status)
return render_template('editgroup_reviewable.html', entries=entries)
-@app.route('/release/<ident>/save', methods=['GET', 'POST'])
+@app.route('/release/<string(length=26):ident>/save', methods=['GET', 'POST'])
def release_save(ident):
form = SavePaperNowForm()
@@ -745,7 +746,18 @@ def coverage_search():
)
query = ReleaseQuery.from_args(request.args)
- coverage_stats = get_elastic_search_coverage(query)
+ try:
+ coverage_stats = get_elastic_search_coverage(query)
+ except FatcatSearchError as fse:
+ return render_template(
+ 'coverage_search.html',
+ query=query,
+ coverage_stats=None,
+ coverage_type_preservation=None,
+ year_histogram_svg=None,
+ date_histogram_svg=None,
+ es_error=fse,
+ ), fse.status_code
year_histogram_svg = None
date_histogram_svg = None
coverage_type_preservation = None
@@ -820,7 +832,7 @@ def container_issnl_stats(issnl):
abort(503)
return jsonify(stats)
-@app.route('/container/<ident>/stats.json', methods=['GET', 'OPTIONS'])
+@app.route('/container/<string(length=26):ident>/stats.json', methods=['GET', 'OPTIONS'])
@crossdomain(origin='*',headers=['access-control-allow-origin','Content-Type'])
def container_ident_stats(ident):
try:
@@ -834,7 +846,7 @@ def container_ident_stats(ident):
abort(503)
return jsonify(stats)
-@app.route('/container/<ident>/ia_coverage_years.json', methods=['GET', 'OPTIONS'])
+@app.route('/container/<string(length=26):ident>/ia_coverage_years.json', methods=['GET', 'OPTIONS'])
@crossdomain(origin='*',headers=['access-control-allow-origin','Content-Type'])
def container_ident_ia_coverage_years_json(ident):
try:
@@ -849,7 +861,7 @@ def container_ident_ia_coverage_years_json(ident):
histogram = [dict(year=h[0], in_ia=h[1], count=h[2]) for h in histogram]
return jsonify({'container_id': ident, "histogram": histogram})
-@app.route('/container/<ident>/ia_coverage_years.svg', methods=['GET', 'OPTIONS'])
+@app.route('/container/<string(length=26):ident>/ia_coverage_years.svg', methods=['GET', 'OPTIONS'])
@crossdomain(origin='*',headers=['access-control-allow-origin','Content-Type'])
def container_ident_ia_coverage_years_svg(ident):
try:
@@ -863,7 +875,7 @@ def container_ident_ia_coverage_years_svg(ident):
abort(503)
return ia_coverage_histogram(histogram).render_response()
-@app.route('/container/<ident>/preservation_by_year.json', methods=['GET', 'OPTIONS'])
+@app.route('/container/<string(length=26):ident>/preservation_by_year.json', methods=['GET', 'OPTIONS'])
@crossdomain(origin='*',headers=['access-control-allow-origin','Content-Type'])
def container_ident_preservation_by_year_json(ident):
try:
@@ -878,7 +890,7 @@ def container_ident_preservation_by_year_json(ident):
abort(503)
return jsonify({'container_id': ident, "histogram": histogram})
-@app.route('/container/<ident>/preservation_by_year.svg', methods=['GET', 'OPTIONS'])
+@app.route('/container/<string(length=26):ident>/preservation_by_year.svg', methods=['GET', 'OPTIONS'])
@crossdomain(origin='*',headers=['access-control-allow-origin','Content-Type'])
def container_ident_preservation_by_year_svg(ident):
try:
@@ -896,7 +908,7 @@ def container_ident_preservation_by_year_svg(ident):
merge_shadows=Config.FATCAT_MERGE_SHADOW_PRESERVATION,
).render_response()
-@app.route('/container/<ident>/preservation_by_volume.json', methods=['GET', 'OPTIONS'])
+@app.route('/container/<string(length=26):ident>/preservation_by_volume.json', methods=['GET', 'OPTIONS'])
@crossdomain(origin='*',headers=['access-control-allow-origin','Content-Type'])
def container_ident_preservation_by_volume_json(ident):
try:
@@ -910,7 +922,7 @@ def container_ident_preservation_by_volume_json(ident):
abort(503)
return jsonify({'container_id': ident, "histogram": histogram})
-@app.route('/container/<ident>/preservation_by_volume.svg', methods=['GET', 'OPTIONS'])
+@app.route('/container/<string(length=26):ident>/preservation_by_volume.svg', methods=['GET', 'OPTIONS'])
@crossdomain(origin='*',headers=['access-control-allow-origin','Content-Type'])
def container_ident_preservation_by_volume_svg(ident):
try:
@@ -927,7 +939,7 @@ def container_ident_preservation_by_volume_svg(ident):
merge_shadows=Config.FATCAT_MERGE_SHADOW_PRESERVATION,
).render_response()
-@app.route('/release/<ident>.bib', methods=['GET'])
+@app.route('/release/<string(length=26):ident>.bib', methods=['GET'])
def release_bibtex(ident):
try:
entity = api.get_release(ident)
@@ -937,7 +949,7 @@ def release_bibtex(ident):
bibtex = citeproc_csl(csl, 'bibtex')
return Response(bibtex, mimetype="text/plain")
-@app.route('/release/<ident>/citeproc', methods=['GET'])
+@app.route('/release/<string(length=26):ident>/citeproc', methods=['GET'])
def release_citeproc(ident):
style = request.args.get('style', 'harvard1')
is_html = request.args.get('html', False)
@@ -951,7 +963,10 @@ def release_citeproc(ident):
except ApiException as ae:
raise ae
csl = release_to_csl(entity)
- cite = citeproc_csl(csl, style, is_html)
+ try:
+ cite = citeproc_csl(csl, style, is_html)
+ except citeproc_styles.StyleNotFoundError as e:
+ abort(400, e)
if is_html:
return Response(cite)
elif style == "csl-json":
@@ -1171,4 +1186,3 @@ def page_sitemap_xml():
return send_from_directory(os.path.join(app.root_path, 'static'),
"sitemap.xml",
mimetype='text/xml')
-
diff --git a/python/fatcat_web/search.py b/python/fatcat_web/search.py
index 7d9ce69f..755b303a 100644
--- a/python/fatcat_web/search.py
+++ b/python/fatcat_web/search.py
@@ -604,10 +604,11 @@ def get_elastic_preservation_by_year(query) -> List[dict]:
buckets = resp.aggregations.year_preservation.buckets
year_nums = set([int(h['key']['year']) for h in buckets])
year_dicts = dict()
- for num in range(min(year_nums), max(year_nums)+1):
- year_dicts[num] = dict(year=num, bright=0, dark=0, shadows_only=0, none=0)
- for row in buckets:
- year_dicts[int(row['key']['year'])][row['key']['preservation']] = int(row['doc_count'])
+ if year_nums:
+ for num in range(min(year_nums), max(year_nums)+1):
+ year_dicts[num] = dict(year=num, bright=0, dark=0, shadows_only=0, none=0)
+ for row in buckets:
+ year_dicts[int(row['key']['year'])][row['key']['preservation']] = int(row['doc_count'])
if app.config['FATCAT_MERGE_SHADOW_PRESERVATION']:
for k in year_dicts.keys():
year_dicts[k]['none'] += year_dicts[k]['shadows_only']
diff --git a/python/fatcat_web/templates/400.html b/python/fatcat_web/templates/400.html
index 21f98aad..c0a00652 100644
--- a/python/fatcat_web/templates/400.html
+++ b/python/fatcat_web/templates/400.html
@@ -12,6 +12,8 @@
<div class="header"></div>
{% if err and err.description %}
<p>{{ err.description }}
+ {% elif err %}
+ <p>{{ err }}
{% else %}
<p>Wasn't able to handle the request, either due to incorrect or unexpected
input. Usually more context should be available; if you hit this page it means
diff --git a/python/fatcat_web/templates/base.html b/python/fatcat_web/templates/base.html
index 2c18ec44..b858728d 100644
--- a/python/fatcat_web/templates/base.html
+++ b/python/fatcat_web/templates/base.html
@@ -17,7 +17,18 @@
<link rel="stylesheet"
type="text/css"
href="https://cdn.jsdelivr.net/npm/fomantic-ui@2.8.6/dist/semantic.min.css"
+ type="text/css"
+ crossorigin="anonymous">
+ <link rel="preload"
+ href="https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic&subset=latin&display=swap"
+ as="style">
+ <link rel="preload"
+ href="https://cdn.jsdelivr.net/npm/fomantic-ui@2.8.6/dist/themes/default/assets/fonts/icons.woff2"
+ as="font"
+ type="font/woff2"
crossorigin="anonymous">
+ <link rel="icon" href="data:,">
+
<style>
{# bnewbold: fix light grey bars in header #}
.ui.inverted.menu .item:before { background: none; }
@@ -131,10 +142,12 @@
<script
src="https://cdn.jsdelivr.net/npm/jquery@3.3.1/dist/jquery.min.js"
+ integrity="sha256=FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous">
</script>
<script
src="https://cdn.jsdelivr.net/npm/fomantic-ui@2.8.6/dist/semantic.min.js"
+ integrity="sha256=9H3HWYnPJ2bEHgkOrw+48KheOqYzTvJd1hbeU9sEDFk="
crossorigin="anonymous">
</script>
{% block postscript %}{% endblock %}
diff --git a/python/fatcat_web/templates/container_view.html b/python/fatcat_web/templates/container_view.html
index 2d3ef036..32c06a53 100644
--- a/python/fatcat_web/templates/container_view.html
+++ b/python/fatcat_web/templates/container_view.html
@@ -48,11 +48,7 @@
<div class="ui segment top attached">
{% if container._es and container._es.is_oa == True %}
- <i class="icon unlock huge orange"></i><b>Open Access Publisher</b>
- {% elif container._es and container._es.is_oa == False %}
- <i class="icon lock huge black"></i><b>Not Open Access</b>
- {% else %}
- <i class="icon question huge grey"></i><b>Unknown OA Status</b>
+ <i class="icon unlock huge orange"></i><b>Open Access Publication</b>
{% endif %}
</div>
@@ -65,15 +61,12 @@
</div>
</div>
</div>
-<div class="ui segment attached">
- <b>Preservation Status</b><br>
- {% if container._stats.total >= 1 %}
- {{ entity_macros.preservation_bar(container._stats.preservation) }}
- {{ entity_macros.preservation_small_table(container._stats.preservation) }}
- {% endif %}
-</div>
{% if container._stats.total >= 1 %}
-{% endif %}
+ <div class="ui segment attached">
+ <b>Preservation Status</b><br>
+ {{ entity_macros.preservation_bar(container._stats.preservation) }}
+ {{ entity_macros.preservation_small_table(container._stats.preservation) }}
+ </div>
<div class="ui segment attached">
<b>Work Types</b><br>
<table class="ui very basic very compact collapsing table">
@@ -92,6 +85,7 @@
</table>
</div>
{% endif %}
+{% endif %}
{% if container.issnl != None or container.wikidata_qid != None %}
<div class="ui segment attached">
diff --git a/python/fatcat_web/templates/coverage_search.html b/python/fatcat_web/templates/coverage_search.html
index 1e0f8327..b1db6a9a 100644
--- a/python/fatcat_web/templates/coverage_search.html
+++ b/python/fatcat_web/templates/coverage_search.html
@@ -1,4 +1,5 @@
{% import "entity_macros.html" as entity_macros %}
+{% import "search_macros.html" as search_macros %}
{% extends "base.html" %}
{% block title %}
@@ -32,6 +33,12 @@
<div class="ui container" style="margin-top: 2em;">
+{% if es_error %}
+ <div class="ui container text">
+ {{ search_macros.es_error_msg(es_error) }}
+ </div>
+{% endif %}
+
{% if coverage_stats != None %}
<div class="ui centered grid">
<div class="row">
diff --git a/python/fatcat_web/templates/entity_macros.html b/python/fatcat_web/templates/entity_macros.html
index 0ce646bf..d5ecd9b6 100644
--- a/python/fatcat_web/templates/entity_macros.html
+++ b/python/fatcat_web/templates/entity_macros.html
@@ -302,7 +302,7 @@ yellow
<td style="background-color: #21ba45;">
<td class="right aligned" >{{ "{:,}".format(stats.bright) }}
<td class="right aligned" >{{ (frac_bright*100)|round(2,method='ceil') }}%
- <td>preserved and publicly available (bright)
+ <td>preserved and publicly accessible (bright)
<tr>
<td style="background-color: darkgreen;">
<td class="right aligned" >{{ "{:,}".format(stats.dark) }}
diff --git a/python/tests/import_file_meta.py b/python/tests/import_file_meta.py
index b59356b6..e6d1a59f 100644
--- a/python/tests/import_file_meta.py
+++ b/python/tests/import_file_meta.py
@@ -31,8 +31,6 @@ def test_file_meta_importer_basic(file_meta_importer):
))
api.accept_editgroup(eg.editgroup_id)
- last_index = file_meta_importer.api.get_changelog(limit=1)[0].index
-
with open('tests/files/example_file_meta.json', 'r') as f:
counts = JsonLinePusher(file_meta_importer, f).run()
diff --git a/python/tests/web_entity_views.py b/python/tests/web_entity_views.py
index 7b973ef2..4068a0c7 100644
--- a/python/tests/web_entity_views.py
+++ b/python/tests/web_entity_views.py
@@ -48,7 +48,7 @@ def test_entity_basics(app, mocker):
rv = app.get('/{}/rev/{}'.format(entity_type, revision))
assert rv.status_code == 200
rv = app.get('/{}/rev/{}_something'.format(entity_type, revision))
- assert rv.status_code == 400
+ assert rv.status_code == 404
rv = app.get('/{}/rev/{}/metadata'.format(entity_type, revision))
assert rv.status_code == 200
print('/editgroup/aaaaaaaaaaaabo53aaaaaaaaaq/{}/{}'.format(entity_type, ident))
@@ -59,11 +59,13 @@ def test_entity_basics(app, mocker):
# bad requests
rv = app.get('/{}/9999999999'.format(entity_type))
- assert rv.status_code == 400
+ assert rv.status_code == 404
rv = app.get('/{}/9999999999/history'.format(entity_type))
- assert rv.status_code == 400
+ assert rv.status_code == 404
rv = app.get('/{}/f1f046a3-45c9-ffff-ffff-ffffffffffff'.format(entity_type))
- assert rv.status_code == 400
+ assert rv.status_code == 404
+ rv = app.get('/{}/rev/f1f046a3-45c9-ffff-ffff-fffffffff'.format(entity_type))
+ assert rv.status_code == 404
rv = app.get('/{}/ccccccccccccccccccccccccca'.format(entity_type))
assert rv.status_code == 404