From d21cfdaafc2bb8ad55b43b0784b31b7407c3193c Mon Sep 17 00:00:00 2001 From: ange Date: Tue, 12 Jun 2018 19:55:56 +0200 Subject: [PATCH] changes to annotations --- app/getannot.py | 85 ++++++++++++------ app/static/css/style.css | 9 ++ app/static/viewer/web/viewer.html | 85 +++++++++++------- app/templates/annotations.html | 108 ++++++----------------- app/templates/header.html | 1 + app/templates/results_annot.html | 56 ++++++++++++ app/templates/show_book_detail.html | 61 +++++++------ app/templates/show_stack_detail.html | 1 + app/views.py | 123 ++++++++------------------- run.py | 10 --- 10 files changed, 274 insertions(+), 265 deletions(-) create mode 100644 app/templates/results_annot.html diff --git a/app/getannot.py b/app/getannot.py index c24b522..895200a 100644 --- a/app/getannot.py +++ b/app/getannot.py @@ -1,38 +1,75 @@ -#https://gist.github.com/mjlavin80/186a6395c5819dbe25a8a0e001d5acfd + + +# #https://gist.github.com/mjlavin80/186a6395c5819dbe25a8a0e001d5acfd +# import requests +# import json + + + +# # This script demonstrates how to query annotations for a particular URL using the hypothes.is API. An API key is required. +# # The end result of this script is a Python dictionary with annotation data in it. Top save to csv or other format, further parsing would be required +# def get_annotations(): + + + import requests import json +# This script demonstrates how to query annotations for a particular URL using the hypothes.is API. An API key is required. +# The end result of this script is a Python dictionary with annotation data in it. Top save to csv or other format, further parsing would be required def get_annotations(): - KEY = "6879-rwfbfodYqhBn2OK2ODnNGkzlWUa4bPCoJi2U8pgTYHg" + KEY = "6879-n8AksBoSB7kYoQ3eEwzpEr3nFQEmSp3XN-0PcKL_Sik" + # URL = "https://monoskop.org/Monoskop" + + #a dictionary containing necessary http headers + headers = { + "Host": "hypothes.is", + "Accept": "application/json", + "Authorization": "Bearer %s" % KEY + } - headers = { - "Host": "xppl", - "Accept": "application/json", - "Content-Type": "application/json", - "Authorization": "Bearer %s" % KEY - } + base_url = "https://hypothes.is/api/search?user=xpub@hypothes.is" - search_url = "".join("http://localhost:5000/api/search") + search_url = "".join([base_url]) - r = requests.get(search_url, headers=headers) - data = json.loads(r.text) - return data + r = requests.get(search_url, headers=headers) + #data is a python dictionary + data = json.loads(r.text) - # extract=[] - # for item in data['rows']: - # # if 'exact' in item['target'][0]['selector'][2]: - # if 'selector' in item['target'][0]: - # if len(item['target'][0]['selector']) > 2: - # extract.append('extract:' + (item['target'][0]['selector'][2]['exact'])) - # extract.append('annotation:' + item['text']) - # extract.append ('-----------') - # else: - # extract.append('annotation:' + item['text']) - # extract.append ('-----------') - # return extract + # r = requests.get(search_url, headers=headers) + # data = json.loads(r.text) + return data +def get_annot_results(annot,name): + res=[] + annot=get_annotations() + for item in annot['rows']: + if 'selector' in item['target'][0]: + if len(item['target'][0]['selector'])>2: + if name in item['text'] or name in item['target'][0]['selector'][2]['exact']: + data={'text': item['text'],'extract':item['target'][0]['selector'][2]['exact'],'title':item['document']['title']} + res.append(data) + else: + if name in item['text'] or name in item['target'][0]['selector'][1]['exact']: + data={'text': item['text'],'extract':item['target'][0]['selector'][1]['exact'],'title':item['document']['title']} + res.append(data) + return res +def get_annot_book(annot,name): + bannot=[] + annot=get_annotations() + for item in annot['rows']: + if 'selector' in item['target'][0]: + if len(item['target'][0]['selector'])>2: + if name==item['uri']: + data={'text': item['text'],'extract':item['target'][0]['selector'][2]['exact'],'title':item['document']['title']} + bannot.append(data) + else: + if name in item['uri']: + data={'text': item['text'],'extract':item['target'][0]['selector'][1]['exact'],'title':item['document']['title']} + bannot.append(data) + return bannot diff --git a/app/static/css/style.css b/app/static/css/style.css index 6ae5dd1..2f6aa8c 100755 --- a/app/static/css/style.css +++ b/app/static/css/style.css @@ -437,3 +437,12 @@ box-sizing: border-box; text-decoration: none; cursor: pointer; } + + +body { font-family: "Archivo Narrow"} +nav { font-size: .7em } + +@page { size: A5; margin: 1cm } +@media print { + nav { display: none } +} \ No newline at end of file diff --git a/app/static/viewer/web/viewer.html b/app/static/viewer/web/viewer.html index 9d75574..ab725c9 100755 --- a/app/static/viewer/web/viewer.html +++ b/app/static/viewer/web/viewer.html @@ -413,25 +413,35 @@ http://sourceforge.net/adobe/cmap/wiki/License/ - - - + + + + + @@ -465,12 +475,15 @@ window.hypothesisConfig = function () { --> - --> + - - - --> + + diff --git a/app/templates/annotations.html b/app/templates/annotations.html index d707af2..77bbc7e 100644 --- a/app/templates/annotations.html +++ b/app/templates/annotations.html @@ -1,57 +1,55 @@ +{% extends 'base.html' %} + {% block main %} -

Annotations

- - -

+

Annotations of XPPL

+







- +{% for row in annot.rows %} + {% if 'selector' in row.target[0] %} + {%for book in books%} + {%if book.file == row.uri%} +

{{book.title}}


+ {% endif %} + {% endfor %} - -{% for row in annot.rows %} - {% if 'selector' in row.target[0] %} {% if row.target[0].selector|length > 2%} -

{{row.document.title}}


- -
- "{{row.target[0].selector[2].exact}}"

- - {%if 'https://www.youtube.com'in row.text %} +

Extracts:

+
"{{row.target[0].selector[2].exact}}"

+

Annotations:

+ {%if 'https://www.youtube.com' in row.text %} - {{row.text}}
+ {{row.text}}
{%elif '.jpg' in row.text%} {{row.document.title}} + {%elif '.mp3' in row.text %} + + {{row.text}}
{%else%} -
{{row.text}}

+
{{row.text}}

{% endif %}
{%else%} -

{{row.document.title}}


- -
+
"{{row.target[0].selector[1].exact}}"

{%if 'https://www.youtube.com'in row.text %} - - {{row.text}}
+ {{row.text}}
{%elif '.jpg' in row.text%} {{row.document.title}} {%else%} -
{{row.text}}

+
{{row.text}}

{% endif %} -
{% endif %} {%else%} - {{row.document.title}}
-

{{row.text}}


+

{{row.text}}




{% endif %} {% endfor %} @@ -60,63 +58,7 @@ - - - - - - - - - - - - - - - + --> diff --git a/app/templates/header.html b/app/templates/header.html index 0d8b33d..3a70af6 100755 --- a/app/templates/header.html +++ b/app/templates/header.html @@ -5,6 +5,7 @@
  • Stacks
  • Add Book
  • Add Stack
  • +
  • Annotations
  • About
  • Instances
  • diff --git a/app/templates/results_annot.html b/app/templates/results_annot.html new file mode 100644 index 0000000..a9f47f1 --- /dev/null +++ b/app/templates/results_annot.html @@ -0,0 +1,56 @@ +{% extends 'base.html' %} + +{% block main %} +


    + + +
    + Browse annotations:
    + + +
    +




    + + All + + +



    +{% for row in res %} + {%for book in books%} + {%if book.file == row.uri%} +

    {{book.title}}


    + {% endif %} + {% endfor %} + +

    {{row.title}}


    + +

    Extracts:

    +
    + "{{ row.extract }}"

    + +

    Annotations:

    +{%if 'https://www.youtube.com'in row.text %} + {{row.text}}
    +
    + {%elif '.jpg' in row.text%} + +
    + {%else%} +
    {{row.text}}

    +
    + {% endif %} + + + +{% endfor %} + + + + + + + + +{% endblock %} \ No newline at end of file diff --git a/app/templates/show_book_detail.html b/app/templates/show_book_detail.html index b27dad3..f9b73a8 100755 --- a/app/templates/show_book_detail.html +++ b/app/templates/show_book_detail.html @@ -66,35 +66,6 @@ -<<<<<<< HEAD -<<<<<<< HEAD - download {{ book.fileformat }} - -
    - --> Feel free to annotate
    - - - - -
    -
    - edit -======= -{% if book.file %} - - -{% else %} -{% endif %} ->>>>>>> stack_stuff -======= - download {{ book.fileformat }}

    Instances:

    @@ -124,11 +95,11 @@ ×

    A message from the uploading librarian:

    "{{book.message or 'Happy reading.'}}"
    -

    >>>> Link to file <<<<

    +

    >>>> Link to file <<<<

    {% else %} {% endif %} ->>>>>>> master + @@ -141,4 +112,32 @@ see the next book added to XPPL:  {{ nextbook.title|truncate(40,True,'...')}} > {% endif %} + + +{% for row in bannot %} + {%for book in books%} + {%if book.file == row.uri%} +

    {{book.title}}


    + {% endif %} + {% endfor %} + +

    {{row.title}}


    + +

    Extracts:

    +
    + "{{ row.extract }}"

    + +

    Annotations:

    +{%if 'https://www.youtube.com'in row.text %} + {{row.text}}
    +
    + {%elif '.jpg' in row.text%} + +
    + {%else%} +
    {{row.text}}

    +
    + {% endif %} + {%endfor%} + {% endblock %} diff --git a/app/templates/show_stack_detail.html b/app/templates/show_stack_detail.html index f55d6a2..75b317f 100644 --- a/app/templates/show_stack_detail.html +++ b/app/templates/show_stack_detail.html @@ -20,6 +20,7 @@
    +
    {% endfor %}

    diff --git a/app/views.py b/app/views.py index 5cbc8bd..5fcdb17 100755 --- a/app/views.py +++ b/app/views.py @@ -15,12 +15,9 @@ from sqlalchemy.sql import except_ from app.forms import UploadForm, EditForm, SearchForm, ChatForm, StackForm, AddtoStackForm, EditStackForm from app.models import Book, BookSchema, Author, AuthorSchema, Stack, StackSchema, UserIns, Chat, ChatSchema, Instance, Potential from app.cover import get_cover -<<<<<<< HEAD -from app.getannot import get_annotations +from app.getannot import get_annotations, get_annot_results, get_annot_book from urllib.parse import quote as urlquote -======= from app.extractText import extract_text ->>>>>>> master from os import environ from flask_socketio import SocketIO, emit from weasyprint import HTML @@ -141,6 +138,9 @@ def show_books_grid(): books = db.session.query(Book).all() # or you could have used User.query.all() return render_template('show_books_grid.html', books=books) + + + @app.route('/books/') def show_book_by_id(id): book = Book.query.get(id) @@ -168,6 +168,16 @@ def show_book_by_id(id): return render_template('show_book_detail.html', book=book, previousbook = previousbook, nextbook = nextbook, all_instances=all_instances) + +@app.route('/books//annotations', methods=['POST', 'GET']) +def book_annot(): + books = db.session.query(Book).all() + name=book.file + annot = get_annotations() + res = get_annot_book(annot,name) + return redirect(url_for('show_book_detail'), name=name, annot=annot, res=res, books=books) + + @app.route('/books//delete', methods=['POST', 'GET']) def remove_book_by_id(id): book_to_edit = Book.query.filter_by(id=id).first() @@ -474,18 +484,10 @@ def remove_from_stack(bookid, stackid): ## search view = ['1'] + @app.route('/books', methods= ['POST','GET']) def show_books(): -<<<<<<< HEAD -<<<<<<< HEAD - autocomplete.load() #Train markov model once, for autocomplete in search - books = db.session.query(Book).all() -======= - books = db.session.query(Book).order_by(Book.title) ->>>>>>> stack_stuff -======= books = db.session.query(Book).order_by(Book.title) ->>>>>>> master search = SearchForm(request.form) view.append('1') viewby = '1' @@ -535,13 +537,6 @@ def search_results(searchtype, query, viewby): if searchtype== 'Stack': results=db.session.query(Book).join(Book.stacks).filter(Stack.stack_name.contains(query)).order_by(Book.title) - -<<<<<<< HEAD - # if searchtype== 'Annotation': - # results=Book.query.filter(Book.category.contains(query)).all() - - if not results: -======= if searchtype== 'All': # results=Book.query.whoosh_search(query) results=Book.query.filter(Book.title.contains(query)) @@ -553,7 +548,6 @@ def search_results(searchtype, query, viewby): if results.count() == 0: books = Book.query.filter(Book.file.like('potential.pdf')) ->>>>>>> stack_stuff upload_form = UploadForm(title= query, author='') return render_template('red_link.html', form=upload_form, title=query, books=books) @@ -596,72 +590,17 @@ def search_results(searchtype, query, viewby): if viewby == '2': return render_template('results_grid.html', form=search, books=results, books_all=books_all, searchtype=search.select.data, query=query, count = count, whole = whole, percentage = percentage) -<<<<<<< HEAD -<<<<<<< HEAD -## Search - autocomplete -autocomplete_suggestions = [] -autocomplete.load() #Train markov model once, for autocomplete in search - -@app.route('/autocomplete_suggestions', methods=['GET', 'POST']) -def test1(): - if request.method == 'POST': - query = request.form['search'] - query_tokenized = query.lower().split() - print(query_tokenized) - word_1 = query_tokenized[-2] - word_2 = query_tokenized[-1] - #print(word_1) - autocomplete_output = autocomplete.predict(word_1 , word_2) - autocomplete_suggestions.clear() - for suggestion, score in autocomplete_output: - autocomplete_suggestions.append(suggestion) - - session['autocomplete_suggestions'] = str(autocomplete_suggestions) - - print(session['autocomplete_suggestions']) - - return Response(json.dumps(session['autocomplete_suggestions']), mimetype='application/json') - -## STACKS! -======= -======= ->>>>>>> master +@app.route('/search_annot', methods=['POST', 'GET']) +def search_annot(): + books = db.session.query(Book).all() + if request.method=='POST': + return redirect (url_for('annotations')) else: - return render_template('results.html', form=search, books=results, books_all=books_all, searchtype=search.select.data, query=query, count = count, whole = whole, percentage = percentage) - - -# ## Search - autocomplete -# autocomplete_suggestions = [] - -# @app.route('/autocomplete_suggestions', methods=['GET', 'POST']) -# def test1(): -# if request.method == 'POST': -# autocomplete.load() -# query = request.form['search'] -# query_tokenized = query.lower().split() -# print(query_tokenized) -# word_1 = query_tokenized[-2] -# word_2 = query_tokenized[-1] -# #print(word_1) -# autocomplete_output = autocomplete.predict(word_1 , word_2) -# autocomplete_suggestions.clear() -# for suggestion, score in autocomplete_output: -# autocomplete_suggestions.append(suggestion) -# -# session['autocomplete_suggestions'] = str(autocomplete_suggestions) -# -# print(session['autocomplete_suggestions']) -# -# return Response(json.dumps(session['autocomplete_suggestions']), mimetype='application/json') - -<<<<<<< HEAD -# print(autocomplete_suggestions) - -# return Response(json.dumps(autocomplete_suggestions), mimetype='application/json') ->>>>>>> stack_stuff -======= -## STACKS! ->>>>>>> master + name=str(request.args.get('query')) + annot = get_annotations() + res = get_annot_results(annot,name) + return render_template('results_annot.html', name=name, annot=annot, res=res, books=books) + @app.route('/add_to_stack/', methods=['GET', 'POST']) def add_to_stack(id): @@ -812,10 +751,12 @@ def send_text_file(file_name): @app.route('/annotations') def annotations(): """Render annotations page.""" + books = db.session.query(Book).all() + # books = db.session.query(Book).order_by(Book.title) + # id = book.id annot = get_annotations() print(annot) - dump = json.dumps(annot, indent=2) - return render_template('annotations.html', annot=annot, dump=dump) + return render_template('annotations.html', annot=annot, books=books) # PDF from annotations @app.route('/annotations.pdf') @@ -825,6 +766,12 @@ def annotations_pdf(): html = render_template(('annotations.html'), annot=annot) return render_pdf(HTML(string=html)) +@app.route('/mybook.pdf') +def mybook_pdf(): + # Make a PDF straight from HTML in a string. + html = redirect(url_for('search_annot')) + return render_pdf(HTML(string=html)) + @app.after_request def add_header(response): diff --git a/run.py b/run.py index 4f85843..61f7a27 100755 --- a/run.py +++ b/run.py @@ -1,13 +1,3 @@ #! /usr/bin/env python from app import app, socketio -<<<<<<< HEAD -<<<<<<< HEAD -# socketio.run(app) -app.run(debug=True,host="0.0.0.0",port=8080) -======= -socketio.run(app, port=8080) -======= socketio.run(app,host="0.0.0.0", port=8080) ->>>>>>> master -#app.run(debug=True,host="0.0.0.0",port=8080) ->>>>>>> stack_stuff