diff --git a/.gitignore b/.gitignore index b63eec6..b35c035 100644 --- a/.gitignore +++ b/.gitignore @@ -379,4 +379,8 @@ TSWLatexianTemp* # addenda app/actes_princiers.db app/static/xml/Bourbon/old-5-Charles-Ier/ +CONTRIBUTING.md +INSTALL.md +LICENSE.md +actes_princiers.sqlite diff --git a/app/__init__.py b/app/__init__.py index e69de29..b30cfbc 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -0,0 +1,21 @@ +import typing as t + +import werkzeug +from flask import render_template + +from .app import app +from .cmd import db_cli +from .routes import main + +app.register_blueprint(main) +app.cli.add_command(db_cli) + + +@app.errorhandler(404) +def page_not_found(e: werkzeug.exceptions.HTTPException) -> t.Tuple[t.Text, int]: + return render_template("404.html", title="Page non trouvée"), 404 + + +@app.errorhandler(500) +def internal_server_error(e: werkzeug.exceptions.HTTPException) -> t.Tuple[t.Text, int]: + return render_template("500.html", title="Erreur interne du serveur"), 500 diff --git a/app/app.py b/app/app.py index 26a228f..c81ca5c 100644 --- a/app/app.py +++ b/app/app.py @@ -1,19 +1,15 @@ -#!/usr/bin/python -# -*- coding: UTF-8 -*- - import os - from flask import Flask from playhouse.sqlite_ext import SqliteExtDatabase - from .debugger import initialize_flask_server_debugger_if_needed APPPATH = os.path.dirname(os.path.abspath(__file__)) templates = os.path.join(APPPATH, "templates") statics = os.path.join(APPPATH, "static") + app = Flask( "Application", template_folder=templates, @@ -21,11 +17,8 @@ app = Flask( ) # DB configuration -app.config["DATABASE"] = os.path.join(APPPATH, ".", "actes_princiers.db") +app.config["DATABASE"] = os.path.join(APPPATH, "..", "actes_princiers.sqlite") db = SqliteExtDatabase(app.config["DATABASE"], pragmas=[("journal_mode", "wal")]) # Enables debugging in VS Code if DEBUG env var is set _debugging = initialize_flask_server_debugger_if_needed() - -# Import de la route principale depuis le fichier routes.py -from .routes import home diff --git a/app/cmd/__init__.py b/app/cmd/__init__.py index e69de29..9f5f418 100644 --- a/app/cmd/__init__.py +++ b/app/cmd/__init__.py @@ -0,0 +1,3 @@ +from .db import db_cli + +__all__ = ["db_cli"] diff --git a/app/cmd/db.py b/app/cmd/db.py new file mode 100644 index 0000000..1e8f8e4 --- /dev/null +++ b/app/cmd/db.py @@ -0,0 +1,223 @@ +import csv +import os +import re +import typing as t + +from bs4 import BeautifulSoup +from flask.cli import AppGroup +from lxml import etree +from tqdm import tqdm + +from app.app import APPPATH, db +from app.data_actes import diplomatic_type, institution, state +from app.modeles import Institution, State, Production_place, Diplo_type, Document, Acte, Individual, Duke, Produced_by + +# from app.data import institution +# from app.data import state +# from app.data import diplomatic_type + + +db_cli = AppGroup("db") + + +def _nonempty(s: str) -> t.Optional[str]: + """Returns content only if non-empty; otherwise returns None""" + if s: + return s + else: + return None + + +def _capitalize_first(s: t.Optional[str]) -> t.Optional[str]: + return (s[0].upper() + s[1:]) if s else None + + +def make_soup(file): + """open a xml file and return a BeautifulSoup object""" + with open(file, 'r', encoding="utf-8") as opening: + xml = BeautifulSoup(opening, 'xml') + return xml + + +def _create_institution(data_lst: list)-> None: + """create institution table""" + for data in tqdm(data_lst, desc="Populating Institution..."): + Institution.create(**data) + +def _create_state(data_lst: list)-> None: + """create state table""" + for data in tqdm(data_lst, desc="Populating State..."): + State.create(**data) + +def _create_diplo_type(data_lst: list)-> None: + """create diplo type table""" + for data in tqdm(data_lst, desc="Populating Diplo_type..."): + Diplo_type.create(**data) + +def _create_produc_place(xml_file: str, folder: str)-> None: + """create production place table""" + places_xtract = [] + production_places = [] + for acte in os.listdir(folder): + soup = make_soup(os.path.join(folder, acte)) + for place in soup.find('placeName', {'type': 'production_place'}): + places_xtract.append(place) + production_places = [{"placename": xtraction} for xtraction in set(places_xtract)] + for data in tqdm(production_places, desc="Populating Place..."): + Production_place.create(**data) + +def _create_doc(xml_file: str, folder: str)-> None: + """create doc table""" + details_doc = [] + infos_doc = [] + # 1/ get repository (doc archives) + doc collection in a list + for acte in os.listdir(folder): + soup = make_soup(os.path.join(folder, acte)) + inst_doc = soup.repository.text + nb_doc_1 = soup.msIdentifier.find_all("idno", {"n": "1"})[0].text + details_doc.append(inst_doc + " == " + nb_doc_1) + # 2/ make a query on table Inst to get inst id + # then pretiffy data for the table Doc + for doc in set(details_doc): + doc_archives = re.sub('(.+) == .+', '\\1', doc) + doc_cote = re.sub('.+ == (.+)', '\\1', doc) + inst_query = [t.id_institution for t in Institution.select().where( + Institution.full_label == doc_archives)] + infos_doc.append({ + "inst_doc": inst_query[0], + "collection_doc": doc_cote, + }) + # 3/ create the table + for data in tqdm(infos_doc, desc="Populating Document..."): + Document.create(**data) + +def _create_acte(xml_file: str, folder: str)-> None: + actes = [] + for acte in os.listdir(folder): + soup = make_soup(os.path.join(folder, acte)) + numb = soup.TEI["xml:id"] + date_time = soup.msItem.docDate["when"] + date = soup.msItem.docDate.text + analyse = soup.abstract.p.text + ref = soup.msIdentifier.find_all("idno", {"n": "2"}) + if len(ref) > 0: + ref_acte = ref[0].text + else: + ref_acte = "NS" + prod_place = soup.find_all("placeName", {"type": "production_place"})[0].text + doc = soup.msIdentifier.find_all("idno", {"n": "1"})[0] + type_diplo = soup.body.div["subtype"] + diplo_state = soup.body.div["type"] + place_query = [t.id_place for t in Production_place.select().where( + Production_place.placename == prod_place)] + doc_query = [t.id_document for t in Document.select().where( + Document.collection_doc == doc.text)] + diplo_query = [t.id_diplo_type for t in Diplo_type.select().where( + Diplo_type.diplo_label == type_diplo)] + state_query = [t.id_state for t in State.select().where( + State.state_label == diplo_state)] + actes.append({ + "numb_acte": numb, + "date_time": date_time, + "date": date, + "prod_place_acte": place_query[0], + "analysis": analyse, + "doc_acte": doc_query[0], + "ref_acte": ref_acte, + "state_doc": state_query[0], + "diplo_type_acte": diplo_query[0] + }) + for data in tqdm(actes, desc="Populating Actes..."): + Acte.create(**data) + + +def __find_indiv(xml_soup, role: str, indiv_lst: list)-> None: + princes = xml_soup.sourceDesc.find_all("listPerson", {"type": role}) + for prince in princes: + dukes = prince.find_all("person") + for duke in dukes: + indiv_lst.append(duke.text.replace("\n", "")) +""" +def _create_individual(xml_file: str, folder: str)-> None: + indiv_prince = [] + indiv_secret = [] + for acte in os.listdir(folder): + soup = make_soup(os.path.join(folder, acte)) + __find_indiv(soup, "prince", indiv_prince) + __find_indiv(soup, "signatory", indiv_secret) + print(set(indiv_secret)) + print(set(indiv_prince)) +""" + +def __indiv_infos(indiv_type): + with open(os.path.join(APPPATH, "static", "csv", "actors.csv"), 'r', encoding="utf-8") as opening: + actors_csv = csv.reader(opening, delimiter=";") + next(actors_csv, None) + lst_of_indiv = [row for row in actors_csv if row[1] == indiv_type] + return lst_of_indiv + +def _create_indiv(): + actors = [*__indiv_infos("secret"), *__indiv_infos("prince")] + individuals = [{"name_indiv": actor[0], "role_indiv": actor[1]} + for actor in actors] + for data in tqdm(individuals, desc="Populating Individual..."): + Individual.create(**data) + +def _create_duke(): + dukes = [] + for info in __indiv_infos("prince"): + indiv_query = [t.id_indiv for t in Individual.select().where( + Individual.name_indiv == info[0])] + dukes.append({"house": info[2], "indiv_duke": indiv_query[0], + "birth": info[3], "reign": info[4], "death": info[4]}) + for data in tqdm(dukes, desc="Populating Duke..."): + Duke.create(**data) + +def _create_produced_by(xml_file: str, folder: str): + princes_actes = [] + for acte in os.listdir(folder): + acte_q = [t.id_acte for t in Acte.select().where( + Acte.numb_acte == acte.replace(".xml", ""))] + # print(acte, "==", acte_q[0]) + soup = make_soup(os.path.join(folder, acte)) + princes = soup.sourceDesc.find_all("listPerson", {"type": "prince"}) + for prince in princes: + dukes = prince.find_all("person") + for duke in dukes: + prince = duke.text.replace("\n", "") + prince_q = [t.id_indiv for t in Individual.select().where( + Individual.name_indiv == duke.text.replace("\n", ""))] + duke_q = [t.id_duke for t in Duke.select().where( + Duke.indiv_duke == prince_q[0])] + # print(prince, "==", prince_q[0], "==", duke_q[0]) + princes_actes.append({"produced_by_acte": acte_q[0], + "produced_by_prince": duke_q[0]}) + for data in tqdm(princes_actes, desc="Populating Produced_by..."): + Produced_by.create(**data) + + +@db_cli.command() +def init() -> None: + """Initialization of the database""" + xml = os.path.join(APPPATH, "static", "xml", + "Bourbon", "Brb_5_Charles_Ier"), ".xml" + xml_folder = os.path.join(APPPATH, "static", "xml", + "Bourbon", "Brb_5_Charles_Ier") + + print("Dropping existing DB...") + db.drop_tables([Institution, State, Production_place, + Diplo_type, Document, Acte, Individual, Duke, + Produced_by]) + print("Re-creating schema...") + db.create_tables([Institution, State, Production_place, + Diplo_type, Document, Acte, Individual, Duke, + Produced_by]) + _create_institution(institution) + _create_state(state) + _create_diplo_type(diplomatic_type) + _create_produc_place(xml, xml_folder) + _create_doc(xml, xml_folder) + _create_acte(xml, xml_folder) + _create_indiv() + _create_duke() + _create_produced_by(xml, xml_folder) diff --git a/app/data_actes/__init__.py b/app/data_actes/__init__.py new file mode 100644 index 0000000..82c03bc --- /dev/null +++ b/app/data_actes/__init__.py @@ -0,0 +1,5 @@ +from .diplo_type_data import diplomatic_type +from .institution_data import institution +from .state_data import state + +__all__ = ["diplomatic_type", "institution", "state"] diff --git a/app/data/diplo_type_data.py b/app/data_actes/diplo_type_data.py similarity index 100% rename from app/data/diplo_type_data.py rename to app/data_actes/diplo_type_data.py diff --git a/app/data/house_data.py b/app/data_actes/house_data.py similarity index 100% rename from app/data/house_data.py rename to app/data_actes/house_data.py diff --git a/app/data/institution_data.py b/app/data_actes/institution_data.py similarity index 100% rename from app/data/institution_data.py rename to app/data_actes/institution_data.py diff --git a/app/data/princes_data.py b/app/data_actes/princes_data.py similarity index 100% rename from app/data/princes_data.py rename to app/data_actes/princes_data.py diff --git a/app/data/state_data.py b/app/data_actes/state_data.py similarity index 100% rename from app/data/state_data.py rename to app/data_actes/state_data.py diff --git a/app/db_maker.py b/app/db_maker.py deleted file mode 100644 index 046a1a2..0000000 --- a/app/db_maker.py +++ /dev/null @@ -1,217 +0,0 @@ -#!/usr/bin/python -# -*- coding: UTF-8 -*- - -""" -Authors : Jean-Damien Généro -Affiliation : French National Center for Scientific Research (CNRS) -Assigned at the Centre de recherches historiques (CRH, UMR 8558) -Date : 2022-10-11 -Update : 2022-10-13 -""" - -import csv -import os -import re -from bs4 import BeautifulSoup -from peewee import * -from tqdm import tqdm - -from modeles.princes_db_tables import db, Institution, State, Production_place, Diplo_type, Document, Acte, Individual, Duke, Produced_by - -from data.institution_data import institution -from data.state_data import state -from data.diplo_type_data import diplomatic_type - - -def make_soup(file): - """open a xml file and return a BeautifulSoup object""" - with open(file, 'r', encoding="utf-8") as opening: - xml = BeautifulSoup(opening, 'xml') - return xml - - -def _create_institution(data_lst: list)-> None: - """create institution table""" - for data in tqdm(data_lst, desc="Populating Institution..."): - Institution.create(**data) - -def _create_state(data_lst: list)-> None: - """create state table""" - for data in tqdm(data_lst, desc="Populating State..."): - State.create(**data) - -def _create_diplo_type(data_lst: list)-> None: - """create diplo type table""" - for data in tqdm(data_lst, desc="Populating Diplo_type..."): - Diplo_type.create(**data) - -def _create_produc_place(xml_file: str, folder: str)-> None: - """create production place table""" - places_xtract = [] - production_places = [] - for acte in os.listdir(folder): - soup = make_soup(os.path.join(folder, acte)) - for place in soup.find('placeName', {'type': 'production_place'}): - places_xtract.append(place) - production_places = [{"placename": xtraction} for xtraction in set(places_xtract)] - for data in tqdm(production_places, desc="Populating Place..."): - Production_place.create(**data) - -def _create_doc(xml_file: str, folder: str)-> None: - """create doc table""" - details_doc = [] - infos_doc = [] - # 1/ get repository (doc archives) + doc collection in a list - for acte in os.listdir(folder): - soup = make_soup(os.path.join(folder, acte)) - inst_doc = soup.repository.text - nb_doc_1 = soup.msIdentifier.find_all("idno", {"n": "1"})[0].text - details_doc.append(inst_doc + " == " + nb_doc_1) - # 2/ make a query on table Inst to get inst id - # then pretiffy data for the table Doc - for doc in set(details_doc): - doc_archives = re.sub('(.+) == .+', '\\1', doc) - doc_cote = re.sub('.+ == (.+)', '\\1', doc) - inst_query = [t.id_institution for t in Institution.select().where( - Institution.full_label == doc_archives)] - infos_doc.append({ - "inst_doc": inst_query[0], - "collection_doc": doc_cote, - }) - # 3/ create the table - for data in tqdm(infos_doc, desc="Populating Document..."): - Document.create(**data) - -def _create_acte(xml_file: str, folder: str)-> None: - actes = [] - for acte in os.listdir(folder): - soup = make_soup(os.path.join(folder, acte)) - numb = soup.TEI["xml:id"] - date_time = soup.msItem.docDate["when"] - date = soup.msItem.docDate.text - analyse = soup.abstract.p.text - ref = soup.msIdentifier.find_all("idno", {"n": "2"}) - if len(ref) > 0: - ref_acte = ref[0].text - else: - ref_acte = "NS" - prod_place = soup.find_all("placeName", {"type": "production_place"})[0].text - doc = soup.msIdentifier.find_all("idno", {"n": "1"})[0] - type_diplo = soup.body.div["subtype"] - diplo_state = soup.body.div["type"] - place_query = [t.id_place for t in Production_place.select().where( - Production_place.placename == prod_place)] - doc_query = [t.id_document for t in Document.select().where( - Document.collection_doc == doc.text)] - diplo_query = [t.id_diplo_type for t in Diplo_type.select().where( - Diplo_type.diplo_label == type_diplo)] - state_query = [t.id_state for t in State.select().where( - State.state_label == diplo_state)] - actes.append({ - "numb_acte": numb, - "date_time": date_time, - "date": date, - "prod_place_acte": place_query[0], - "analysis": analyse, - "doc_acte": doc_query[0], - "ref_acte": ref_acte, - "state_doc": state_query[0], - "diplo_type_acte": diplo_query[0] - }) - for data in tqdm(actes, desc="Populating Actes..."): - Acte.create(**data) - - -def __find_indiv(xml_soup, role: str, indiv_lst: list)-> None: - princes = xml_soup.sourceDesc.find_all("listPerson", {"type": role}) - for prince in princes: - dukes = prince.find_all("person") - for duke in dukes: - indiv_lst.append(duke.text.replace("\n", "")) -""" -def _create_individual(xml_file: str, folder: str)-> None: - indiv_prince = [] - indiv_secret = [] - for acte in os.listdir(folder): - soup = make_soup(os.path.join(folder, acte)) - __find_indiv(soup, "prince", indiv_prince) - __find_indiv(soup, "signatory", indiv_secret) - print(set(indiv_secret)) - print(set(indiv_prince)) -""" - -def __indiv_infos(indiv_type): - with open("./static/csv/actors.csv", 'r', encoding="utf-8") as opening: - actors_csv = csv.reader(opening, delimiter=";") - next(actors_csv, None) - lst_of_indiv = [row for row in actors_csv if row[1] == indiv_type] - return lst_of_indiv - -def _create_indiv(): - actors = [*__indiv_infos("secret"), *__indiv_infos("prince")] - individuals = [{"name_indiv": actor[0], "role_indiv": actor[1]} - for actor in actors] - for data in tqdm(individuals, desc="Populating Individual..."): - Individual.create(**data) - -def _create_duke(): - dukes = [] - for info in __indiv_infos("prince"): - indiv_query = [t.id_indiv for t in Individual.select().where( - Individual.name_indiv == info[0])] - dukes.append({"house": info[2], "indiv_duke": indiv_query[0], - "birth": info[3], "reign": info[4], "death": info[4]}) - for data in tqdm(dukes, desc="Populating Duke..."): - Duke.create(**data) - -def _create_produced_by(xml_file: str, folder: str): - princes_actes = [] - for acte in os.listdir(folder): - acte_q = [t.id_acte for t in Acte.select().where( - Acte.numb_acte == acte.replace(".xml", ""))] - # print(acte, "==", acte_q[0]) - soup = make_soup(os.path.join(folder, acte)) - princes = soup.sourceDesc.find_all("listPerson", {"type": "prince"}) - for prince in princes: - dukes = prince.find_all("person") - for duke in dukes: - prince = duke.text.replace("\n", "") - prince_q = [t.id_indiv for t in Individual.select().where( - Individual.name_indiv == duke.text.replace("\n", ""))] - duke_q = [t.id_duke for t in Duke.select().where( - Duke.indiv_duke == prince_q[0])] - # print(prince, "==", prince_q[0], "==", duke_q[0]) - princes_actes.append({"produced_by_acte": acte_q[0], - "produced_by_prince": duke_q[0]}) - for data in tqdm(princes_actes, desc="Populating Produced_by..."): - Produced_by.create(**data) - - - -def init(): - """initializing db""" - db.connect() - print("Dropping existing DB...") - db.drop_tables([Institution, State, Production_place, - Diplo_type, Document, Acte, Individual, Duke, - Produced_by]) - print("Re-creating schema...") - db.create_tables([Institution, State, Production_place, - Diplo_type, Document, Acte, Individual, Duke, - Produced_by]) - _create_institution(institution) - _create_state(state) - _create_diplo_type(diplomatic_type) - _create_produc_place(xml, xml_folder) - _create_doc(xml, xml_folder) - _create_acte(xml, xml_folder) - _create_indiv() - _create_duke() - _create_produced_by(xml, xml_folder) - -xml = "../bourbon-latex/charles-actes-latex.xml" -xml_folder = "./static/xml/Bourbon/Brb_5_Charles_Ier" - -init() -# _create_individual(xml, xml_folder) -# _create_produced_by(xml, xml_folder) diff --git a/app/modeles/__init__.py b/app/modeles/__init__.py index e69de29..81bbefa 100644 --- a/app/modeles/__init__.py +++ b/app/modeles/__init__.py @@ -0,0 +1,3 @@ +from .data import Institution, State, Production_place, Diplo_type, Document, Acte, Individual, Duke, Produced_by + +__all__ = ["Institution", "State", "Production_place", "Diplo_type", "Document", "Acte", "Individual", "Duke", "Produced_by"] diff --git a/app/modeles/data.py b/app/modeles/data.py new file mode 100644 index 0000000..1cdb365 --- /dev/null +++ b/app/modeles/data.py @@ -0,0 +1,126 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- + +""" +Authors : Jean-Damien Généro +Affiliation : French National Center for Scientific Research (CNRS) +Assigned at the Centre de recherches historiques (CRH, UMR 8558) +Date : 2022-10-11 +Update : +""" + + +import re +import typing as t + +import peewee +from flask import url_for +from playhouse.sqlite_ext import FTS5Model, RowIDField, SearchField + +from app.app import db + + +class BaseModel(peewee.Model): + class Meta: + database = db + + +# db = SqliteDatabase('actes_princiers.db') +# from app.app import db + +class Institution(BaseModel): + id_institution = peewee.AutoField() + full_label = peewee.TextField() + inst_label = peewee.TextField() + art_inst = peewee.TextField() + inst_place = peewee.TextField() + inst_rank = peewee.TextField() + inst_type = peewee.TextField() + + class Meta: + database = db + db_table = 'Institution' + + +class State(BaseModel): + id_state = peewee.AutoField() + state_label = peewee.TextField() + + class Meta: + database = db + db_table = 'State' + + +class Production_place(BaseModel): + id_place = peewee.AutoField() + placename = peewee.TextField() + + class Meta: + database = db + db_table = 'Production_place' + + +class Diplo_type(BaseModel): + id_diplo_type = peewee.AutoField() + diplo_label = peewee.TextField() + + class Meta: + database = db + db_table = 'Diplo_type' + + +class Document(BaseModel): + id_document = peewee.AutoField() + inst_doc = peewee.ForeignKeyField(Institution, backref='documents') + collection_doc = peewee.TextField() + + class Meta: + database = db + db_table = 'Document' + + +class Acte(BaseModel): + id_acte = peewee.AutoField() + numb_acte = peewee.TextField() + date_time = peewee.TextField() # YYYY-MM-DD + date = peewee.TextField() # verbose + prod_place_acte = peewee.ForeignKeyField(Production_place, backref='actes') + analysis = peewee.TextField() + doc_acte = peewee.ForeignKeyField(Document, backref='actes') + ref_acte = peewee.TextField() # cote + state_doc = peewee.ForeignKeyField(State, backref='actes') + diplo_type_acte = peewee.ForeignKeyField(Diplo_type, backref='actes') + + class Meta: + database = db + db_table = 'Acte' + +class Individual(BaseModel): + id_indiv = peewee.AutoField() + name_indiv = peewee.TextField() + role_indiv = peewee.TextField() + + class Meta: + database = db + db_table = 'Individual' + +class Duke(BaseModel): + id_duke = peewee.AutoField() + house = peewee.TextField() + indiv_duke = peewee.ForeignKeyField(Individual, backref='dukes') + birth = peewee.TextField() + reign = peewee.TextField() + death = peewee.TextField() + + class Meta: + database = db + db_table = 'Duke' + +class Produced_by(BaseModel): + id_produced_by = peewee.AutoField() + produced_by_acte = peewee.ForeignKeyField(Acte, backref='produced_bys') + produced_by_prince = peewee.ForeignKeyField(Duke, backref='produced_bys') + + class Meta: + database = db + db_table = 'Produced_by' diff --git a/app/modeles/princes_db_tables.py b/app/modeles/princes_db_tables.py deleted file mode 100644 index 1fa5cd4..0000000 --- a/app/modeles/princes_db_tables.py +++ /dev/null @@ -1,114 +0,0 @@ -#!/usr/bin/python -# -*- coding: UTF-8 -*- - -""" -Authors : Jean-Damien Généro -Affiliation : French National Center for Scientific Research (CNRS) -Assigned at the Centre de recherches historiques (CRH, UMR 8558) -Date : 2022-10-11 -Update : -""" - - -from peewee import * - - -db = SqliteDatabase('actes_princiers.db') -# from app.app import db - -class Institution(Model): - id_institution = IntegerField(primary_key=True) - full_label = TextField() - inst_label = TextField() - art_inst = TextField() - inst_place = TextField() - inst_rank = TextField() - inst_type = TextField() - - class Meta: - database = db - db_table = 'Institution' - - -class State(Model): - id_state = IntegerField(primary_key=True) - state_label = TextField() - - class Meta: - database = db - db_table = 'State' - - -class Production_place(Model): - id_place = IntegerField(primary_key=True) - placename = TextField() - - class Meta: - database = db - db_table = 'Production_place' - - -class Diplo_type(Model): - id_diplo_type = IntegerField(primary_key=True) - diplo_label = TextField() - - class Meta: - database = db - db_table = 'Diplo_type' - - -class Document(Model): - id_document = IntegerField(primary_key=True) - inst_doc = ForeignKeyField(Institution, backref='documents') - collection_doc = TextField() - - class Meta: - database = db - db_table = 'Document' - - -class Acte(Model): - id_acte = IntegerField(primary_key=True) - numb_acte = TextField() - date_time = TextField() # YYYY-MM-DD - date = TextField() # verbose - prod_place_acte = ForeignKeyField(Production_place, backref='actes') - analysis = TextField() - doc_acte = ForeignKeyField(Document, backref='actes') - ref_acte = TextField() # cote - state_doc = ForeignKeyField(State, backref='actes') - diplo_type_acte = ForeignKeyField(Diplo_type, backref='actes') - - class Meta: - database = db - db_table = 'Acte' - -class Individual(Model): - id_indiv = IntegerField(primary_key=True) - name_indiv = TextField() - role_indiv = TextField() - - class Meta: - database = db - db_table = 'Individual' - -class Duke(Model): - id_duke = IntegerField(primary_key=True) - house = TextField() - indiv_duke = ForeignKeyField(Individual, backref='dukes') - birth = TextField() - reign = TextField() - death = TextField() - - class Meta: - database = db - db_table = 'Duke' - -class Produced_by(Model): - id_produced_by = IntegerField(primary_key=True) - produced_by_acte = ForeignKeyField(Acte, backref='produced_bys') - produced_by_prince = ForeignKeyField(Duke, backref='produced_bys') - - class Meta: - database = db - db_table = 'Produced_by' diff --git a/app/routes.py b/app/routes.py index bba3532..bdbe2d9 100644 --- a/app/routes.py +++ b/app/routes.py @@ -1,42 +1,58 @@ -#!/usr/bin/python -# -*- coding: UTF-8 -*- +import os +import re +import typing as t +import peewee +from flask import Blueprint, abort, render_template, request, send_from_directory +from playhouse.flask_utils import PaginatedQuery -""" - author : Jean-Damien Généro - date : 2022-10-01 - update : -""" +from .app import APPPATH +from .modeles import Institution, State, Production_place, Diplo_type, Document, Acte, Individual, Duke, Produced_by +RESULT_PAR_PAGES = 5 -# import des librairie -from flask import Flask, render_template, request -from .app import app +main = Blueprint("main", __name__, url_prefix="/") -@app.route("/") +@main.route("/") def home(): - """home route""" - return render_template("home.html") + """home route""" + return render_template("home.html") -@app.route("/about/") +@main.route("/about/") def about(): """home route""" return render_template("about.html") -@app.route("/actes/") +@main.route("/actes/") def corpora_all(): """copora all route""" return render_template("corpora_all.html") -@app.route("/actes/") # dont put a slash at the end +@main.route("/actes/") # dont put a slash at the end def actes(house): """actes route""" return render_template("corpus.html", house=house) -@app.route("/actes//") # dont put a slash at the end +@main.route("/actes//") # dont put a slash at the end def prince_corpus(house=None, prince=None): """copora prince route""" return render_template("prince_corpus.html", house=house, prince=prince) +@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é") diff --git a/app/static/js/jquery-3.6.0.min.js b/app/static/js/jquery-3.6.0.min.js new file mode 100644 index 0000000..c4c6022 --- /dev/null +++ b/app/static/js/jquery-3.6.0.min.js @@ -0,0 +1,2 @@ +/*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.0",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var _t,zt=[],Ut=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=zt.pop()||S.expando+"_"+wt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Ut.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ut.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Ut,"$1"+r):!1!==e.jsonp&&(e.url+=(Tt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,zt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((_t=E.implementation.createHTMLDocument("").body).innerHTML="
",2===_t.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=Fe(y.pixelPosition,function(e,t){if(t)return t=We(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0Impossible de trouver cette page.

+ +{% endblock %} \ No newline at end of file diff --git a/app/templates/500.html b/app/templates/500.html new file mode 100644 index 0000000..98b3c9a --- /dev/null +++ b/app/templates/500.html @@ -0,0 +1,6 @@ +{% extends "container.html" %} +{% block corps %} + +

Une erreur interne s'est produite.

+ +{% endblock %} \ No newline at end of file diff --git a/app/templates/contact.html b/app/templates/contact.html new file mode 100644 index 0000000..6bbe2b1 --- /dev/null +++ b/app/templates/contact.html @@ -0,0 +1,10 @@ +{% extends "container.html" %} +{% block corps %} + +

Le travail sur le site et le corpus est toujours en cours. Pour toute remarque, suggestion ou demande d'informations complémentaires, vous pouvez contacter l'équipe scientifique et technique à cette adresse :

+ +

gestion.sourcesetdonnees [at] ehess.fr

+ +

En contactant l'équipe du site Ouvriers des deux mondes, vous consentez au traitement des données que vous transmeterez dans votre mail. La Règlementation générale sur la protection des données (RGPD) vous permet d'exercer vos droits d'accès, de rectification, de modification ou de suppression de vos données personnelles par simple demande à dpo [at] ehess [.] fr. Pour plus d'information, consultez les mentions légales.

+ +{% endblock %} \ No newline at end of file diff --git a/app/templates/container.html b/app/templates/container.html index 6033243..571e9bd 100644 --- a/app/templates/container.html +++ b/app/templates/container.html @@ -15,7 +15,7 @@