User:Angeliki/X-LIB/Annotations
Annotations structure intervening XPPL
Recipes
Hypothes.is set-up
Augmented pdf (links, audio, video, images)
Ideas
- Annotate the PDF file
- Annotate the URL of XPPL
- Develop tool for embedded PDF with sound/ other media
Steps
Attempt 1:
Steps to host the software hypothes.is in the same machine with XPPL so there is more control over the annotation data and the access of users
Installing hypothes.is in my machine: https://h.readthedocs.io/en/latest/developing/install/
Database with the annotations locally- able to interact with the database of the books?
Comments:
- Concept/Idea
- I have to accept the users signing in my 'local' hypothesis. How to connect with real users? Using a general user, that could be stayed logged in. One user for each instance?
- Embed PDF: just embed the h in the url of the pdf Viewer PDF. Configure the sidebar: icon, fonts, hyperlinks.. /home/angeliki/Documents/PZI-ITL/client/src (4)
- There will be a separate h interface for people to sign up Using one user they will sign up with one password/ The interface to follow the interface and structure of XPPL. Edit the scripts of hypothesis/ Develop the feature for services in the sidebar
- Interactive hyperlinks, media in the json structure of the api https://www.newtonsoft.com/json/help/html/SelectToken.htm
- embed PDF with hypothesis in stack(1)
- Get annotations from api of the different user instances what API, what data
- Download PDFs with annotations. generate a new pdf/ reportlab/weasyprint/ stamp pdf. tash script/ the position of annotations in the page. https://pythonhosted.org/Flask-WeasyPrint/.
- Search through annotations (ask Tash) https://www.newtonsoft.com/json/help/html/SelectToken.htm(2)
- BIG ISSUE: the localhost should change to public ip address (Michael)/ or use the IP of the pi. crossbrowser (5)
- SET UP H. IN PI (6)
- Make a bash with all the commands needed to run client, h, XPPL/ Organise the installation
- ~/Documents/PZI-ITL/h$ sudo docker-compose up
- ~/Documents/PZI-ITL/h$ source .venv/bin/activate
- ~/Documents/PZI-ITL/client$ export SIDEBAR_APP_URL=http://localhost:5000/app.html
- ~/Documents/PZI-ITL/client$ gulp watch
- ~/Documents/PZI-ITL/h$ export CLIENT_OAUTH_ID=b0dedcdc-675b-11e8-8450-0f70f73a2d89
- ~/Documents/PZI-ITL/h$ export CLIENT_URL=http://localhost:3001/hypothesis
- ~/Documents/PZI-ITL/h$ make dev
- ~/Apps/rqlite-v4.3.0-linux-amd64$ ./rqlited ~/node.1
- ~/Documents/PZI-ITL/xpub-lib$ bash ./init_db.sh
- ~/Documents/PZI-ITL/xpub-lib$ python3 run.py
- List of licenses and softwares
Installing to pi
fixing errors:
https://github.com/Medium/phantomjs/issues/654
https://github.com/sass/node-sass/issues/1609
https://github.com/aeberhardo/phantomjs-linux-armv6l/blob/master/README.md
Node.js- Phantomjs impossible to install
Useful links:
hypothesis client: http://h.readthedocs.io/projects/client/en/latest/developers/developing/#running-the-client-from-h
http://localhost:5000/docs/help
http://localhost:5000/admin
https://github.com/hypothesis/frontend-toolkit
Attempt 2: Plan:
- embed h
PROBLEM1: file path for the PDF viewer
PROBLEM2: add the viewer with the annotations of pdfs embedded to the stack page
annotate each link of the PDF. (Using that link in my scripts: http://localhost:8000/uploads/title.pdf) embedding the tool. Hosting hypothesis to each PDF online https://github.com/hypothesis/pdf.js-hypothes.is. Solutions: to change the path of the files in viewer.html, to interact with app.route uploads at the views.py, to add the viewer.html to the templates? Template that will link all this information (the viewer there, the other things somewhere else and what they do together). embedding Hypothesis in Websites and Platforms
- export annotations
I want to create a 'block'/html page of exported annotations from the PDFs. So I add the HTML page of the exported material.
But also to link every PDF with its own annotations? Interact with the API
back end: API, python scripts, fetch the data in a file (CSV file/JSON of the annotations)
front end: html, css, javascript. put them online. Static first and then dynamic(Javascript of the JSON files)
Connecting Hypothes.is to XPPL
Working with the API
from flask import request
import requests
import json
def get_annotations():
KEY = "6879-n8AksBoSB7kYoQ3eEwzpEr3nFQEmSp3XN-0PcKL_Sik"
#a dictionary containing necessary http headers
headers = {
"Host": "hypothes.is",
"Accept": "application/json",
"Authorization": "Bearer %s" % KEY
}
base_url = "https://hypothes.is/api/search?user=xpub@hypothes.is"
search_url = "".join([base_url])
r = requests.get(search_url, headers=headers)
#data is a python dictionary
data = json.loads(r.text)
server = request.host
for row in data['rows']:
row['uri']= row['uri'].replace('http://' + server+'/uploads/','')
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'], 'url':item['uri']}
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'], 'url':item['uri']}
res.append(data)
return res
def get_annot_book(annot,name):
res=[]
server = request.host
for item in annot['rows']:
if 'selector' in item['target'][0]:
if len(item['target'][0]['selector'])>2:
string=item['uri']
if name==string.replace('http://' + server+'/uploads/',''):
data={'text': item['text'],'extract':item['target'][0]['selector'][2]['exact'],'title':item['document']['title'], 'url':item['uri']}
res.append(data)
else:
string=item['uri']
if name==string.replace('http://' + server+'/uploads/',''):
data={'text': item['text'],'extract':item['target'][0]['selector'][1]['exact'],'title':item['document']['title'], 'url':item['uri']}
res.append(data)
return res
# annotations
@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
server = request.host
rstr=('http://' + server+'/uploads/','')
annot = get_annotations()
print(annot)
return render_template('annotations.html', annot=annot, books=books, light=light)
# PDF from annotations
@app.route('/annotations.pdf')
def annotations_pdf():
annot = get_annotations()
# Make a PDF straight from HTML in a string.
html = render_template(('annotations.html'), annot=annot, light=light)
return render_pdf(HTML(string=html))
@app.route('/books/<int:id>')
def show_book_by_id(id):
book = Book.query.get(id)
all_instances = db.session.query(Instance).all()
previousbook = Book.query.filter_by(id=id - 1).first()
nextbook = Book.query.filter_by(id=id + 1).first()
allbooks = db.session.query(Book).all()
edge = len(allbooks)
if id == 1:
previousbook = None
if id == edge:
nextbook = None
name= book.file
annot = get_annotations()
res = get_annot_book(annot,name)
@app.route('/search_annot', methods=['POST', 'GET'])
def search_annot():
books = db.session.query(Book).all()
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)
html pages annotations.html:
{% extends 'base.html' %}
{% block main %}
<h1 class="header">Annotations of XPPL</h1>
<a href="{{ url_for('annotations_pdf') }}" style="color:#ff3300;">Get as PDF</a> <a href="/search_annot" style="color:#ff3300;"> Search</a><br><br><br><br><br><br><br><br>
{% for row in annot.rows %}
{% if 'selector' in row.target[0] %}
{%for book in books%}
{%if book.file == row.uri%}
<p align="right" style="font-family:archivo narrow;font-size:10px;">Book</p>
<a href="books/{{book.id}}"><p align="right" style="font-family:archivo narrow;font-size:18px;">{{book.title}}</p></a><br>
{% endif %}
{% endfor %}
{% if row.target[0].selector|length > 2%}
<p style="font-family:archivo narrow;font-size:10px;">Extract</p>
<div style="font-family:archivo narrow;font-size:18px;"><i>"{{row.target[0].selector[2].exact}}"</i></div><br>
<p style="font-family:archivo narrow;font-size:10px;color:#ff3300;">Annotation</p>
{%if 'https://www.youtube.com' in row.text %}
<a style="font-family:archivo narrow;font-size:18px;color:#ff3300;" href="{{row.text}}">{{row.text}}</a><br>
{%elif '.jpg' in row.text%}
<img src="{{row.text}}" alt="{{row.document.title}}" width="400">
{%elif '.mp3' in row.text %}
<a style="font-family:archivo narrow;font-size:18px;color:#ff3300;" href="{{row.text}}">{{row.text}}</a><br>
{%else%}
<div style="font-family:archivo narrow;font-size:18px;color:#ff3300;">{{row.text}}</div><br>
{% endif %}
<hr>
{%else%}
<p style="font-family:archivo narrow;font-size:10px;">Extract</p>
<div style="font-family:archivo narrow;font-size:18px;">
<i>"{{row.target[0].selector[1].exact}}"</i></div><br>
<p style="font-family:archivo narrow;font-size:10px;color:#ff3300;">Annotation</p>
{%if 'https://www.youtube.com'in row.text %}
<a style="font-family:archivo narrow;font-size:18px;color:#ff3300;" href="{{row.text}}">{{row.text}}</a><br>
{%elif '.jpg' in row.text%}
<img src="{{row.text}}" alt="{{row.document.title}}" width="400">
{%elif '.mp3' in row.text %}
<a style="font-family:archivo narrow;font-size:18px;color:#ff3300;" href="{{row.text}}">{{row.text}}</a><br>
{%else%}
<div style="font-family:archivo narrow;font-size:18px;color:#ff3300;">{{row.text}}</div><br>
{% endif %}
<hr>
{% endif %}
{%else%}
<p style="font-family:archivo narrow;font-size:18px;color:#ff3300;">{{row.text}}</p><br>
<hr><br>
{% endif %}
{% endfor %}
<!-- dump of the API json annotations -->
<!-- dump:
<pre>
{{dump}}
</pre> -->
{% endblock %}
results_annot.html
{% extends 'base.html' %}
{% block main %}
<br><br><br>
<form style="float:left;" action="/search_annot" method="GET">
<div style="float:left;" class="search">
<input type="text" name="query" value="">
</div>
<input style="background-color: grey; color:white; font-family: archivo narrow; font-size: 18px; border: none;padding: 8px 24px;" type="submit" value="browse annotations"></input>
</form>
<br><br><br>
<a href="annotations" style="color:#ff3300;"> All annotations</a><br><br>
<h1 class="header">Annotations/ Extracts with: <i>{{name}}</i></h1>
{% for row in res %}
{%for book in books%}
{%if book.file == row.url|replace('http://localhost:8080/uploads/','')%}
<p align="right" style="font-family:archivo narrow;font-size:10px;">Book</p>
<a href="books/{{book.id}}"><p align="right" style="font-family:archivo narrow;font-size:18px;">{{book.title}}</p></a><br>
{% endif %}
{% endfor %}
<p style="font-family:archivo narrow;font-size:10px;">Extract</p>
<div style="font-family:archivo narrow;font-family:archivo narrow;font-size:18px;">
<i>"{{ row.extract }}"</i></div><br>
<p style="font-family:archivo narrow;font-size:10px;color:#ff3300;">Annotation</p>
{%if 'https://www.youtube.com'in row.text %}
<a style="font-family:archivo narrow;font-size:18px;color:#ff3300;" href="{{row.text}}">{{row.text}}</a><br>
<hr>
{%elif '.jpg' in row.text%}
<img src="{{row.text}}" alt="" width="400">
<hr>
{%else%}
<div style="font-family:archivo narrow;font-size:18px;color:#ff3300;">{{row.text}}</div><br>
<hr>
{% endif %}
{% endfor %}
{% endblock %}
Questions
Questions arisen during my process of dealing with the XPPL project:
- Frictions: bridging together two different realities (an already made application and an interface of a library/ an already made community and a team/fine arts-xpub)
- Two different communities/public spheres
- The 'otherness' in the process (an alien tool intervene, trying to adjust it)
The structure of hypothes.is tool is based on the contribution of individual users. How an external tool can be part of xppl, by following its conceptual context?
Legal object (annotations and extracts of the PDFs)/ illegal object (PDF downloaded with annotations)
The collective identity (ref. gregor)