|
|
import typing as t
|
|
|
import urllib.parse
|
|
|
from unidecode import unidecode # to remove accents in house and prince names in the urls
|
|
|
|
|
|
from flask import Blueprint, abort, render_template, request, send_from_directory
|
|
|
from pymongo import MongoClient
|
|
|
import folium
|
|
|
|
|
|
from .config import dbadmin, dbpassword, server_ip
|
|
|
from .helper import find_one_or_404
|
|
|
|
|
|
|
|
|
main = Blueprint("main", __name__, url_prefix="/")
|
|
|
|
|
|
# TODO : maybe put the mongodb connector in the flask app object
|
|
|
# ______________________________________________________________________________
|
|
|
# database connexion
|
|
|
username = urllib.parse.quote_plus(dbadmin)
|
|
|
password = urllib.parse.quote_plus(dbpassword)
|
|
|
dbclient = MongoClient(f'mongodb://{username}:{password}@{server_ip}:27017')
|
|
|
# database
|
|
|
actesdb = dbclient["actesdb"]
|
|
|
# collections
|
|
|
housecol = actesdb["house"]
|
|
|
# the acte collection is the most important collection
|
|
|
actecol = actesdb["acte"]
|
|
|
helpers = actesdb["helpers"]
|
|
|
#folium_map = actesdb["folium_map"]
|
|
|
|
|
|
# ______________________________________________________________________________
|
|
|
# storage extractor utilities
|
|
|
|
|
|
def extract_princes_in_houses():
|
|
|
"""Extracts all princes from a house
|
|
|
by queries in the storage, (not by using csv metadatas)
|
|
|
|
|
|
sample:
|
|
|
>>> extract_princes_in_houses['anjou']
|
|
|
[{'prince_name': "Louis Ier d'Anjou", 'prince_code': 'lo_i'}, {'prince_name': "Louis III d'Anjou", 'prince_code': 'lo_iii'}, {'prince_name': 'Isabelle de Lorraine', 'prince_code': 'isa_i'}, {'prince_name': "Louis II d'Anjou", 'prince_code': 'lo_ii'}, {'prince_name': 'Marie de Blois', 'prince_code': 'mar_i'}, {'prince_name': "René d'Anjou", 'prince_code': 're_i'}, {'prince_name': "Yollande d'Aragon", 'prince_code': 'yol_i'}]
|
|
|
"""
|
|
|
princes_in_houses = dict()
|
|
|
for house in housecol.find():
|
|
|
housename = house['name'].lower()
|
|
|
query = list(actecol.aggregate([{"$match": {"house": housename}}, {'$group': {'_id': {'prince_name': '$prince_name', 'prince_code': '$prince_code'}}}]))
|
|
|
princes_in_houses[housename] = [pr['_id'] for pr in query]
|
|
|
return princes_in_houses
|
|
|
|
|
|
|
|
|
def normalize_trigrams(trigram):
|
|
|
"""normalizes names, usefull for the uris routes
|
|
|
|
|
|
sample: Alençon -> Alencon
|
|
|
Orléans -> Orleans
|
|
|
"""
|
|
|
return {unidecode(value):key for key, value in trigram.items()}
|
|
|
|
|
|
# ______________________________________________________________________________
|
|
|
# in memory storage extracted meta informations on the database
|
|
|
# TODO: if it takes too much time at launch, put it in something like
|
|
|
# a `flask init` procedure
|
|
|
|
|
|
helpers_dicts = helpers.find_one()
|
|
|
house_trigram = helpers_dicts["house_trigram"]
|
|
|
prince_bigram = helpers_dicts["prince_bigram"]
|
|
|
|
|
|
princes_in_houses = extract_princes_in_houses()
|
|
|
# normalized_trigrams
|
|
|
house_trigram = normalize_trigrams(house_trigram)
|
|
|
prince_bigram = normalize_trigrams(prince_bigram)
|
|
|
|
|
|
def bigram_prince(prince):
|
|
|
"Translates Charles_i -> ch_i"
|
|
|
name, number = prince.split("_")
|
|
|
return prince_bigram[name] + "_" + number
|
|
|
|
|
|
# TODO: write tests in the datascience project `datascience/tests`
|
|
|
#print(bigram_prince("Agnes"))
|
|
|
#print(bigram_prince("Arthur"))
|
|
|
#print(bigram_prince("Bernard"))
|
|
|
#print(trigram_house("Anjou"))
|
|
|
#print(trigram_house("Orleans"))
|
|
|
|
|
|
def trigram_house(house):
|
|
|
return house_trigram[house]
|
|
|
|
|
|
|
|
|
def make_acteid_from_route(house=None, prince=None, date_and_item=None):
|
|
|
"/acte/Anjou/Isabelle_i/1441_08_05a -> anj_isa_i_1441_08_05a"
|
|
|
return "_".join([trigram_house(house), bigram_prince(prince), date_and_item])
|
|
|
|
|
|
# ______________________________________________________________________________
|
|
|
# routes
|
|
|
|
|
|
@main.route("/")
|
|
|
def home():
|
|
|
"""home route"""
|
|
|
return render_template("home.html")
|
|
|
|
|
|
|
|
|
@main.route("/about/")
|
|
|
def about():
|
|
|
"""about route"""
|
|
|
return render_template("about.html")
|
|
|
|
|
|
|
|
|
@main.route("/actes/")
|
|
|
def corpora_all():
|
|
|
"""copora all
|
|
|
|
|
|
lists houses
|
|
|
sample_house_names = ["Bourbon", "Berry", "Anjou", ...]
|
|
|
"""
|
|
|
houses = list(housecol.find())
|
|
|
return render_template("corpora_all.html", houses=houses)
|
|
|
|
|
|
|
|
|
@main.route("/actes/<house>") # dont put a slash at the end
|
|
|
def actes(house):
|
|
|
"""actes route
|
|
|
|
|
|
shows the princes in the selected house
|
|
|
|
|
|
:param: the house in the url is the house name
|
|
|
with a capital letter at the beginning
|
|
|
example: `house = "Berry"`
|
|
|
"""
|
|
|
# house in the store shall be in lower case, but let's force it, just in case
|
|
|
house = house.lower()
|
|
|
# the nosql query below is equivalent to this code, which is more readable but slower:
|
|
|
#princes = []
|
|
|
#for act in actecol.find({"house":house}):
|
|
|
# prince_name = act['prince_name'].capitalize()
|
|
|
# prince_code = act['prince_code'].capitalize()
|
|
|
# if (prince_name, prince_code) not in princes:
|
|
|
# princes.append((prince_name, prince_code))
|
|
|
|
|
|
|
|
|
# [('Louis II de Bourbon', 'lo_ii'), ('Anne Dauphine', 'ann_i'), ('Agnès de Bourgogne', 'agn_i'), ('Charles Ier de Bourbon', 'ch_i')]
|
|
|
princes = princes_in_houses[house]
|
|
|
# TODO : modify the jinja template and suppress this line
|
|
|
princes = [(prc['prince_name'], prc['prince_code']) for prc in princes]
|
|
|
# [('Agnès de Bourgogne', 'agn_i'), ('Anne Dauphine', 'ann_i'), ('Charles Ier de Bourbon', 'ch_i'), ('Louis II de Bourbon', 'lo_ii')
|
|
|
return render_template("corpus.html", house=house.capitalize(), princes=princes)
|
|
|
|
|
|
|
|
|
@main.route("/actes/<house>/<prince>") # don't put a slash at the end
|
|
|
def prince_corpus(house=None, prince=None):
|
|
|
"""copora prince, **timeline view**"""
|
|
|
house = house.lower()
|
|
|
# prince bigram -> prince_code
|
|
|
# sample uri: /actes/Anjou/lo_i -> Louis_i -> Louis Ier d'Anjou
|
|
|
prc_big, prc_num = prince.split("_")
|
|
|
prince_code = prince_bigram[prc_big] + "_" + prc_num
|
|
|
# for item in prince_acte:
|
|
|
# print("\n\n", item)
|
|
|
#info = [(t.date_time, t.date, t.filename, t.analysis, t.prod_place_acte,
|
|
|
# t.diplo_type_acte, t.state_doc)
|
|
|
# ['1418-12-20', '1418, 20 décembre', 'anj_yo_i_1418_12_20a', "Donation à Antoine de la Salle d'une maison à Arles", "Château d'Anger", 'Lettres patentes', 'Copie']
|
|
|
# ['1421-06-28', '1421, 28 juin', 'anj_yo_i_1421_06_28a', "Confirmation par Yolande, duchesse d'Anjou, du douaire assigné à sa belle-fille, Isabelle de Lorraine", 'NS', 'Lettres patentes', 'Original']
|
|
|
# ['1442-02-24', '1442 (n. st.), 24 février', 'anj_yo_i_1442_02_24a', 'Pierre Throvan, secrétaire de la reine, nommé trésorier général de Provence et de Languedoc du 16 juillet au 31 octobre 1441, puis pendant trois ans à partir du 1er novembre 1441', 'Château de Saumur', 'Lettres patentes', 'Copie']
|
|
|
return render_template("prince_corpus.html", houseS=house, duke_name=prince_name,
|
|
|
lst_id=prince_acte)
|
|
|
|
|
|
|
|
|
@main.route("/acte/<house>/<prince>/<dateitem>") # don't put a slash at the end
|
|
|
def acte(house=None, prince=None, dateitem=None):
|
|
|
"""specific prince's acte view
|
|
|
|
|
|
:params: - house
|
|
|
- prince
|
|
|
- date + item (sample: 1441_08_05a)
|
|
|
:url location sample: /acte/Anjou/Isabelle_i/1441_08_05a
|
|
|
|
|
|
url transcription samples:
|
|
|
/acte/Anjou/Isabelle_i/1441_08_05a -> anj_isa_i_1441_08_05a
|
|
|
/acte/Bourbon/Anne_i/1388_09_15a -> brb_ann_i_1388_09_15a
|
|
|
"""
|
|
|
filestem = make_acteid_from_route(house, prince, dateitem)
|
|
|
result = actecol.find_one({'_id': filestem})
|
|
|
return render_template("acte.html", house=house, prince=prince,
|
|
|
#infos=None, place=None, doc=None, arch=None,
|
|
|
#diplo=diplo_t[0].replace("_", " "), state=state[0],
|
|
|
output_doc=result.get('xmlcontent'), name_prince=result.get("prince_name"),
|
|
|
folium=result.get("folium"),
|
|
|
transcribers=result.get('transcribers'))
|
|
|
|
|
|
@main.route("/geoloc")
|
|
|
def geoloc():
|
|
|
"global folium/leaflet map"
|
|
|
m = folium.Map(location=[46.603354, 1.888334], zoom_start=6)
|
|
|
for result in actecol.find():
|
|
|
place = result['place']
|
|
|
if place.get('latitude') is not None:
|
|
|
folium.Marker(
|
|
|
location=[place['latitude'], place['longitude']],
|
|
|
popup=place['name'],
|
|
|
icon=folium.Icon(color='lightgray', icon="circle", prefix='fa')
|
|
|
#icon=folium.Icon(color='lightgray', icon='home', prefix='fa')
|
|
|
).add_to(m)
|
|
|
geolocalisation = m._repr_html_()
|
|
|
return render_template("map.html", geolocalisation=geolocalisation)
|
|
|
#geolocalisation = folium_map.find_one()
|
|
|
#geolocalisation = geolocalisation['globalmap']
|
|
|
#return render_template("map.html", geolocalisation=geolocalisation)
|
|
|
|
|
|
@main.route("/contact")
|
|
|
def contact() -> t.Text:
|
|
|
"""Displays the Contact page"""
|
|
|
return render_template("contact.html", title="Contact")
|
|
|
|
|
|
|
|
|
@main.route("/termsofservice")
|
|
|
def terms() -> t.Text:
|
|
|
"""Displaysthe T&C page."""
|
|
|
return render_template("terms.html", title="Mentions légales")
|
|
|
|
|
|
|
|
|
@main.route("/privacy")
|
|
|
def privacy() -> t.Text:
|
|
|
"""Displays the privacy policy page."""
|
|
|
return render_template("privacy.html", title="Politique de confidentialité")
|