From cd3adb4177efea1071b2f8830b665ff8c6cf6de0 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Sat, 24 Aug 2024 18:26:51 +0200 Subject: [PATCH 1/4] Retire sco_header/footer. 100% templates. --- app/scodoc/gen_tables.py | 2 +- app/scodoc/html_sco_header.py | 215 +------------------- app/scodoc/sco_bulletins_signature.py | 1 - app/scodoc/sco_edit_formation.py | 84 ++++---- app/scodoc/sco_edit_matiere.py | 69 ++++--- app/scodoc/sco_etape_apogee_view.py | 47 +++-- app/scodoc/sco_evaluation_edit.py | 40 ++-- app/scodoc/sco_evaluation_recap.py | 5 +- app/scodoc/sco_export_results.py | 20 +- app/scodoc/sco_formsemestre_custommenu.py | 5 +- app/scodoc/sco_formsemestre_edit.py | 1 - app/scodoc/sco_formsemestre_exterieurs.py | 41 ++-- app/scodoc/sco_formsemestre_inscriptions.py | 24 +-- app/scodoc/sco_formsemestre_validation.py | 94 +++++---- app/scodoc/sco_groups.py | 47 ++--- app/scodoc/sco_groups_edit.py | 30 ++- app/scodoc/sco_import_etuds.py | 28 +-- app/scodoc/sco_lycee.py | 63 +++--- app/scodoc/sco_permissions_check.py | 68 +++---- app/scodoc/sco_users.py | 1 - app/templates/formsemestre/etuds_lycees.j2 | 32 +++ app/templates/scolar/affect_groups.j2 | 6 +- 22 files changed, 374 insertions(+), 549 deletions(-) create mode 100644 app/templates/formsemestre/etuds_lycees.j2 diff --git a/app/scodoc/gen_tables.py b/app/scodoc/gen_tables.py index e9368f071..b5ce3e6de 100644 --- a/app/scodoc/gen_tables.py +++ b/app/scodoc/gen_tables.py @@ -760,7 +760,7 @@ class GenTable: return js else: log(f"make_page: format={fmt}") - raise ValueError("_make_page: invalid format") + raise ValueError("make_page: invalid format") # ----- diff --git a/app/scodoc/html_sco_header.py b/app/scodoc/html_sco_header.py index 572c535b4..de0dd2d01 100644 --- a/app/scodoc/html_sco_header.py +++ b/app/scodoc/html_sco_header.py @@ -25,222 +25,9 @@ # ############################################################################## -"""HTML Header/Footer for ScoDoc pages""" - -from flask import g, render_template, url_for -from flask_login import current_user - -import app.scodoc.sco_utils as scu -from app import scodoc_flash_status_messages -from app.scodoc import html_sidebar -import sco_version +"""Legacy constants (TODO: remove)""" # Some constants: BOOTSTRAP_JS = ["libjs/bootstrap/js/bootstrap.min.js", "libjs/purl.js"] BOOTSTRAP_CSS = ["libjs/bootstrap/css/bootstrap.min.css"] - - -def standard_html_header(): - """Standard HTML header for pages outside depts""" - # not used in ZScolar, see sco_header - return f""" - -ScoDoc: accueil - - - - - - - -{scu.CUSTOM_HTML_HEADER_CNX}""" - - -def standard_html_footer(): - """Le pied de page HTML de la page d'accueil.""" - return f""" -

Problèmes et suggestions sur le logiciel: {scu.SCO_USERS_LIST}

-

ScoDoc est un logiciel libre développé par Emmanuel Viennet.

-""" - - -_HTML_BEGIN = f""" - - - - - - - - - -%(page_title)s - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -""" - - -def scodoc_top_html_header(page_title="ScoDoc: bienvenue"): - """HTML header for top level pages""" - H = [ - _HTML_BEGIN % {"page_title": page_title, "encoding": scu.SCO_ENCODING}, - """""", - scu.CUSTOM_HTML_HEADER_CNX, - ] - return "\n".join(H) - - -# Header: -def sco_header( - # optional args - page_title="", # page title - no_sidebar=False, # hide sidebar - cssstyles=(), # additionals CSS sheets - javascripts=(), # additionals JS filenames to load - scripts=(), # script to put in page header - init_google_maps=False, # Google maps - titrebandeau="", # titre dans bandeau superieur - etudid=None, - formsemestre_id=None, -): - """Main HTML page header for ScoDoc - Utilisé dans les anciennes pages. Les nouvelles pages utilisent le template Jinja. - """ - from app.scodoc.sco_formsemestre_status import formsemestre_page_title - - if etudid is not None: - g.current_etudid = etudid - scodoc_flash_status_messages() - - params = { - "page_title": page_title or sco_version.SCONAME, - "no_sidebar": no_sidebar, - "ScoURL": url_for("scolar.index_html", scodoc_dept=g.scodoc_dept), - "encoding": scu.SCO_ENCODING, - "titrebandeau_mkup": "" + titrebandeau + "", - "authuser": current_user.user_name, - } - if no_sidebar: - params["margin_left"] = "1em" - else: - params["margin_left"] = "140px" - - H = [_HTML_BEGIN % params] - - if init_google_maps: - # It may be necessary to add an API key: - H.append('') - - # Feuilles de style additionnelles: - for cssstyle in cssstyles: - H.append( - f"""\n""" - ) - - H.append( - f""" -""" - ) - - if init_google_maps: # utilisé uniquement pour carte lycées - H.append( - f'' - ) - - # JS additionels - for js in javascripts: - H.append(f"""\n""") - - H.append( - f""" -""" - ) - # Scripts de la page: - if scripts: - H.append("""""") - - # Fin head, Body et bandeau haut: - H.append( - f""" - - -{scu.CUSTOM_HTML_HEADER} -{'' if no_sidebar else html_sidebar.sidebar(etudid)} - - -
-""" - ) - # En attendant le replacement complet de cette fonction, - # inclusion ici des messages flask - H.append(render_template("flashed_messages.j2")) - # - # Barre menu semestre: - H.append(formsemestre_page_title(formsemestre_id)) - - # div pour affichage messages temporaires - H.append('
') - # - H.append('
') - return "".join(H) - - -def sco_footer(): - """Main HTMl pages footer""" - return ( - """
""" - + scu.CUSTOM_HTML_FOOTER - + """""" - ) diff --git a/app/scodoc/sco_bulletins_signature.py b/app/scodoc/sco_bulletins_signature.py index 0b30f8d24..e862a1699 100644 --- a/app/scodoc/sco_bulletins_signature.py +++ b/app/scodoc/sco_bulletins_signature.py @@ -69,7 +69,6 @@ et sur page "réglages bulletin" (avec formsemestre_id) # raise ValueError("invalid value for 'side' parameter") # signatureloc = get_bul_sig_img() # H = [ -# self.sco_header(page_title="Changement de signature"), # """

Changement de la signature bulletin de %(sidetxt)s

# """ # % (sidetxt,), diff --git a/app/scodoc/sco_edit_formation.py b/app/scodoc/sco_edit_formation.py index 8e52c0656..6eb276035 100644 --- a/app/scodoc/sco_edit_formation.py +++ b/app/scodoc/sco_edit_formation.py @@ -43,7 +43,6 @@ import app.scodoc.sco_utils as scu from app.scodoc.TrivialFormulator import TrivialFormulator, tf_error_message from app.scodoc.sco_exceptions import ScoValueError, ScoNonEmptyFormationObject -from app.scodoc import html_sco_header from app.scodoc import sco_cache from app.scodoc import codes_cursus from app.scodoc import sco_edit_ue @@ -146,7 +145,6 @@ def formation_edit(formation_id=None, create=False): """Edit or create a formation""" if create: H = [ - html_sco_header.sco_header(page_title="Création d'une formation"), """

Création d'une formation

Une "formation" décrit une filière, comme un DUT ou une Licence. La formation se subdivise en unités pédagogiques (UE, matières, modules). Elle peut se diviser en plusieurs semestres (ou sessions), qui seront mis en place séparément. @@ -168,7 +166,6 @@ def formation_edit(formation_id=None, create=False): is_locked = formation.has_locked_sems(formation_id) submitlabel = "Modifier les valeurs" H = [ - html_sco_header.sco_header(page_title="Modification d'une formation"), f"""

Modification de la formation {formation.acronyme} version {formation.version}

""", @@ -251,52 +248,57 @@ def formation_edit(formation_id=None, create=False): submitlabel=submitlabel, ) if tf[0] == 0: - return "\n".join(H) + tf[1] + html_sco_header.sco_footer() - elif tf[0] == -1: + return render_template( + "sco_page_dept.j2", + title="Modification d'une formation", + content="\n".join(H) + tf[1], + ) + if tf[0] == -1: return flask.redirect(url_for("notes.index_html", scodoc_dept=g.scodoc_dept)) + + # check unicity : constraint UNIQUE(acronyme,titre,version) + if create: + version = 1 else: - # check unicity : constraint UNIQUE(acronyme,titre,version) - if create: - version = 1 - else: - version = initvalues["version"] - args = { - "acronyme": tf[2]["acronyme"], - "titre": tf[2]["titre"], - "version": version, - "dept_id": g.scodoc_dept_id, - } - other_formations: list[Formation] = Formation.query.filter_by(**args).all() - if other_formations and ( - (len(other_formations) > 1) or other_formations[0].id != formation_id - ): - return ( + version = initvalues["version"] + args = { + "acronyme": tf[2]["acronyme"], + "titre": tf[2]["titre"], + "version": version, + "dept_id": g.scodoc_dept_id, + } + other_formations: list[Formation] = Formation.query.filter_by(**args).all() + if other_formations and ( + (len(other_formations) > 1) or other_formations[0].id != formation_id + ): + return render_template( + "sco_page_dept.j2", + title="Modification d'une formation", + content=( "\n".join(H) + tf_error_message( f"""Valeurs incorrectes: il existe déjà une formation avec même titre, - acronyme et version. - """ + url_for('notes.ue_table', + scodoc_dept=g.scodoc_dept, formation_id=other_formations[0].id) + }">une formation avec même titre, + acronyme et version. + """ ) + tf[1] - + html_sco_header.sco_footer() - ) - # - if create: - formation = do_formation_create(tf[2]) - else: - if do_formation_edit(tf[2]): - flash( - f"""Modification de la formation { - formation.titre} ({formation.acronyme}) version {formation.version}""" - ) - return flask.redirect( - url_for( - "notes.ue_table", scodoc_dept=g.scodoc_dept, formation_id=formation.id - ) + ), ) + # + if create: + formation = do_formation_create(tf[2]) + else: + if do_formation_edit(tf[2]): + flash( + f"""Modification de la formation { + formation.titre} ({formation.acronyme}) version {formation.version}""" + ) + return flask.redirect( + url_for("notes.ue_table", scodoc_dept=g.scodoc_dept, formation_id=formation.id) + ) def do_formation_create(args: dict) -> Formation: diff --git a/app/scodoc/sco_edit_matiere.py b/app/scodoc/sco_edit_matiere.py index 1a212a7ad..9bba3d05c 100644 --- a/app/scodoc/sco_edit_matiere.py +++ b/app/scodoc/sco_edit_matiere.py @@ -29,7 +29,7 @@ (portage from DTML) """ import flask -from flask import g, url_for, request +from flask import g, render_template, request, url_for from app import db, log from app.models import Formation, Matiere, UniteEns, ScolarNews @@ -43,7 +43,6 @@ from app.scodoc.sco_exceptions import ( ScoLockedFormError, ScoNonEmptyFormationObject, ) -from app.scodoc import html_sco_header _matiereEditor = ndb.EditableTable( "notes_matieres", @@ -63,7 +62,6 @@ def matiere_list(*args, **kw): def do_matiere_edit(*args, **kw): "edit a matiere" from app.scodoc import sco_edit_ue - from app.scodoc import sco_edit_formation cnx = ndb.GetDBConnexion() # check @@ -79,7 +77,6 @@ def do_matiere_edit(*args, **kw): def do_matiere_create(args): "create a matiere" from app.scodoc import sco_edit_ue - from app.models import ScolarNews cnx = ndb.GetDBConnexion() # check @@ -103,7 +100,6 @@ def matiere_create(ue_id=None): ue: UniteEns = UniteEns.query.get_or_404(ue_id) default_numero = max([mat.numero for mat in ue.matieres] or [9]) + 1 H = [ - html_sco_header.sco_header(page_title="Création d'une matière"), f"""

Création d'une matière dans l'UE {ue.titre or ''} ({ue.acronyme})

Les matières sont des groupes de modules dans une UE d'une formation donnée. Les matières servent surtout pour la @@ -151,21 +147,25 @@ associé. ) if tf[0] == 0: - return "\n".join(H) + tf[1] + html_sco_header.sco_footer() - elif tf[0] == -1: + return render_template( + "sco_page.j2", title="Création d'une matière", content="\n".join(H) + tf[1] + ) + if tf[0] == -1: return flask.redirect(dest_url) - else: - # check unicity - mats = matiere_list(args={"ue_id": ue_id, "titre": tf[2]["titre"]}) - if mats: - return ( + # check unicity + mats = matiere_list(args={"ue_id": ue_id, "titre": tf[2]["titre"]}) + if mats: + return render_template( + "sco_page.j2", + title="Création d'une matière", + content=( "\n".join(H) + tf_error_message("Titre de matière déjà existant dans cette UE") + tf[1] - + html_sco_header.sco_footer() - ) - _ = do_matiere_create(tf[2]) - return flask.redirect(dest_url) + ), + ) + _ = do_matiere_create(tf[2]) + return flask.redirect(dest_url) def can_delete_matiere(matiere: Matiere) -> tuple[bool, str]: @@ -230,7 +230,6 @@ def matiere_delete(matiere_id=None): mat = matiere_list(args={"matiere_id": matiere_id})[0] UE = sco_edit_ue.ue_list(args={"ue_id": mat["ue_id"]})[0] H = [ - html_sco_header.sco_header(page_title="Suppression d'une matière"), "

Suppression de la matière %(titre)s" % mat, " dans l'UE (%(acronyme)s))

" % UE, ] @@ -248,13 +247,17 @@ def matiere_delete(matiere_id=None): cancelbutton="Annuler", ) if tf[0] == 0: - return "\n".join(H) + tf[1] + html_sco_header.sco_footer() - elif tf[0] == -1: - return flask.redirect(dest_url) - else: - do_matiere_delete(matiere_id) + return render_template( + "sco_page.j2", + title="Suppression d'une matière", + content="\n".join(H) + tf[1], + ) + if tf[0] == -1: return flask.redirect(dest_url) + do_matiere_delete(matiere_id) + return flask.redirect(dest_url) + def matiere_edit(matiere_id=None): """Edit matiere""" @@ -273,11 +276,10 @@ def matiere_edit(matiere_id=None): ue_names = ["%(acronyme)s (%(titre)s)" % u for u in ues] ue_ids = [u["ue_id"] for u in ues] H = [ - html_sco_header.sco_header(page_title="Modification d'une matière"), """

Modification de la matière %(titre)s""" % F, f"""(formation ({formation.acronyme}, version {formation.version})

""", ] - help = """

Les matières sont des groupes de modules dans une UE + help_msg = """

Les matières sont des groupes de modules dans une UE d'une formation donnée. Les matières servent surtout pour la présentation (bulletins, etc) mais n'ont pas de rôle dans le calcul des notes. @@ -325,18 +327,25 @@ associé. formation_id=str(ue["formation_id"]), ) if tf[0] == 0: - return "\n".join(H) + tf[1] + help + html_sco_header.sco_footer() + return render_template( + "sco_page.j2", + title="Modification d'une matière", + content="\n".join(H) + tf[1] + help_msg, + ) elif tf[0] == -1: return flask.redirect(dest_url) else: # check unicity mats = matiere_list(args={"ue_id": tf[2]["ue_id"], "titre": tf[2]["titre"]}) if len(mats) > 1 or (len(mats) == 1 and mats[0]["matiere_id"] != matiere_id): - return ( - "\n".join(H) - + tf_error_message("Titre de matière déjà existant dans cette UE") - + tf[1] - + html_sco_header.sco_footer() + return render_template( + "sco_page.j2", + title="Modification d'une matière", + content=( + "\n".join(H) + + tf_error_message("Titre de matière déjà existant dans cette UE") + + tf[1] + ), ) # changement d'UE ? diff --git a/app/scodoc/sco_etape_apogee_view.py b/app/scodoc/sco_etape_apogee_view.py index 1bf9cdf1b..1dda5aaab 100644 --- a/app/scodoc/sco_etape_apogee_view.py +++ b/app/scodoc/sco_etape_apogee_view.py @@ -32,12 +32,11 @@ import io from zipfile import ZipFile import flask -from flask import flash, g, request, Response, send_file, url_for +from flask import flash, g, render_template, request, Response, send_file, url_for import app.scodoc.sco_utils as scu from app import log from app.models import Formation -from app.scodoc import html_sco_header from app.scodoc import sco_apogee_csv, sco_apogee_reader from app.scodoc import sco_etape_apogee from app.scodoc import sco_formsemestre @@ -100,10 +99,6 @@ def apo_semset_maq_status( ok_for_export &= semset["jury_ok"] H = [ - html_sco_header.sco_header( - page_title="Export Apogée", - javascripts=["js/apo_semset_maq_status.js"], - ), """

Export des résultats vers Apogée

""" """
""", semset.html_descr(), @@ -438,8 +433,12 @@ def apo_semset_maq_status(
""" ) - H.append(html_sco_header.sco_footer()) - return "\n".join(H) + return render_template( + "sco_page_dept.j2", + title="Export Apogée", + javascripts=["js/apo_semset_maq_status.js"], + content="\n".join(H), + ) def table_apo_csv_list(semset): @@ -594,21 +593,21 @@ def _view_etuds_page( if fmt != "html": return tab.make_page(fmt=fmt) - return f""" - {html_sco_header.sco_header( - page_title=title, - )} + return render_template( + "sco_page_dept.j2", + title=title, + content=f"""

{title}

{tab.html()} -

Retour à la page d'export Apogée -

- {html_sco_header.sco_footer()} - """ + + """, + ) def view_apo_csv_store(semset_id="", csvfile=None, data: bytes = "", autodetect=False): @@ -747,9 +746,6 @@ def view_apo_csv(etape_apo="", semset_id="", fmt="html"): ) = sco_etape_apogee.apo_csv_semset_check(semset) H = [ - html_sco_header.sco_header( - page_title=f"""Maquette Apogée enregistrée pour {etape_apo}""", - ), f"""

Étudiants dans la maquette Apogée {etape_apo}

Pour l'ensemble Aucun étudiant

" + html_sco_header.sco_footer() + return render_template( + "sco_page_dept.j2", + title=f"""Maquette Apogée {etape_apo}""", + content="\n".join(H) + "

Aucun étudiant

", + ) # Ajout infos sur ScoDoc vs Apogee for e in etuds: @@ -830,10 +830,13 @@ def view_apo_csv(etape_apo="", semset_id="", fmt="html"): }">Retour
""", - html_sco_header.sco_footer(), ] - return "\n".join(H) + return render_template( + "sco_page_dept.j2", + title=f"""Maquette Apogée enregistrée pour {etape_apo}""", + content="\n".join(H), + ) # called from Web (GET) diff --git a/app/scodoc/sco_evaluation_edit.py b/app/scodoc/sco_evaluation_edit.py index 7a80d13d6..75eb56136 100644 --- a/app/scodoc/sco_evaluation_edit.py +++ b/app/scodoc/sco_evaluation_edit.py @@ -42,7 +42,6 @@ import app.scodoc.sco_utils as scu from app.scodoc.sco_utils import ModuleType from app.scodoc.sco_exceptions import ScoValueError from app.scodoc.TrivialFormulator import TrivialFormulator -from app.scodoc import html_sco_header from app.scodoc import sco_cache from app.scodoc import sco_evaluations from app.scodoc import sco_preferences @@ -74,16 +73,18 @@ def evaluation_create_form( min_note_max = scu.NOTES_PRECISION # le plus petit bareme possible # if not modimpl.can_edit_evaluation(current_user): - return f""" - {html_sco_header.sco_header()} + return render_template( + "sco_page.j2", + title="Opération non autorisée", + content=f"""

Opération non autorisée

Modification évaluation impossible pour {current_user.get_nomplogin()}

Revenir

- {html_sco_header.sco_footer()} - """ + """, + ) if not edit: # création nouvel if moduleimpl_id is None: @@ -361,20 +362,21 @@ def evaluation_create_form( """ ] if tf[0] == 0: - head = html_sco_header.sco_header(page_title=page_title) - return ( - head - + "\n".join(H) - + "\n" - + tf[1] - + render_template( - "scodoc/forms/evaluation_edit.j2", - ) - + render_template( - "scodoc/help/evaluations.j2", is_apc=is_apc, modimpl=modimpl - ) - + render_template("sco_timepicker.j2") - + html_sco_header.sco_footer() + return render_template( + "sco_page.j2", + title=page_title, + content=( + "\n".join(H) + + "\n" + + tf[1] + + render_template( + "scodoc/forms/evaluation_edit.j2", + ) + + render_template( + "scodoc/help/evaluations.j2", is_apc=is_apc, modimpl=modimpl + ) + + render_template("sco_timepicker.j2") + ), ) elif tf[0] == -1: return flask.redirect(dest_url) diff --git a/app/scodoc/sco_evaluation_recap.py b/app/scodoc/sco_evaluation_recap.py index e9edd6111..f79ddcdab 100644 --- a/app/scodoc/sco_evaluation_recap.py +++ b/app/scodoc/sco_evaluation_recap.py @@ -17,7 +17,6 @@ from app.models import Evaluation, FormSemestre from app.comp import res_sem from app.comp.res_compat import NotesTableCompat from app.comp.moy_mod import ModuleImplResults -from app.scodoc import html_sco_header import app.scodoc.sco_utils as scu @@ -63,9 +62,7 @@ def evaluations_recap(formsemestre_id: int) -> str: pas pris en compte dans cette table. """ ) - H.append( - html_sco_header.sco_footer(), - ) + return render_template( "sco_page.j2", title="Évaluations du semestre", diff --git a/app/scodoc/sco_export_results.py b/app/scodoc/sco_export_results.py index 252e7f169..c305f4340 100644 --- a/app/scodoc/sco_export_results.py +++ b/app/scodoc/sco_export_results.py @@ -27,7 +27,7 @@ """Export d'une table avec les résultats de tous les étudiants """ -from flask import url_for, g, request +from flask import url_for, g, render_template, request from app.comp import res_sem from app.comp.res_compat import NotesTableCompat @@ -42,12 +42,12 @@ from app.scodoc import codes_cursus from app.scodoc import sco_preferences from app.scodoc import sco_pv_dict from app.scodoc import sco_etud -import sco_version from app.scodoc.gen_tables import GenTable from app.scodoc.codes_cursus import NO_SEMESTRE_ID +import sco_version -def _build_results_table(start_date=None, end_date=None, types_parcours=[]): +def _build_results_table(start_date=None, end_date=None, types_parcours=()): """Construit une table avec les résultats de jury de TOUS les étudiants de TOUS les semestres ScoDoc de ce département entre les dates indiquées (c'est à dire commençant APRES ou à start_date et terminant avant ou à end_date) @@ -285,11 +285,6 @@ def scodoc_table_results( info_sems.append("") H = [ - html_sco_header.sco_header( - page_title="Export résultats", - javascripts=html_sco_header.BOOTSTRAP_JS + ["js/export_results.js"], - cssstyles=html_sco_header.BOOTSTRAP_CSS, - ), # XXX """

Table des résultats de tous les semestres

@@ -310,9 +305,14 @@ def scodoc_table_results( """, "\n".join(info_sems), """""", - html_sco_header.sco_footer(), ] - return "\n".join(H) + return render_template( + "sco_page_dept.j2", + title="Export résultats", + javascripts=html_sco_header.BOOTSTRAP_JS + ["js/export_results.js"], + cssstyles=html_sco_header.BOOTSTRAP_CSS, + content="\n".join(H), + ) # Formulaire pour saisie dates et sélection parcours diff --git a/app/scodoc/sco_formsemestre_custommenu.py b/app/scodoc/sco_formsemestre_custommenu.py index d719c42db..f6542bf8f 100644 --- a/app/scodoc/sco_formsemestre_custommenu.py +++ b/app/scodoc/sco_formsemestre_custommenu.py @@ -31,12 +31,11 @@ import flask from flask import g, url_for, render_template, request from flask_login import current_user -from app.models.config import ScoDocSiteConfig, PersonalizedLink +from app.models.config import ScoDocSiteConfig from app.models import FormSemestre import app.scodoc.sco_utils as scu import app.scodoc.notesdb as ndb from app.scodoc.TrivialFormulator import TrivialFormulator -from app.scodoc import html_sco_header _custommenuEditor = ndb.EditableTable( "notes_formsemestre_custommenu", @@ -107,7 +106,7 @@ def formsemestre_custommenu_edit(formsemestre_id): dest_url = url_for( "notes.formsemestre_status", scodoc_dept=g.scodoc_dept, - formsemestre_id=formsemestre_id, + formsemestre_id=formsemestre.id, ) H = [ """
diff --git a/app/scodoc/sco_formsemestre_edit.py b/app/scodoc/sco_formsemestre_edit.py index d0146ba19..2509739ce 100644 --- a/app/scodoc/sco_formsemestre_edit.py +++ b/app/scodoc/sco_formsemestre_edit.py @@ -1720,7 +1720,6 @@ def formsemestre_edit_options(formsemestre_id): """dialog to change formsemestre options (accessible par EditFormSemestre ou dir. etudes) """ - log("formsemestre_edit_options") ok, err = sco_permissions_check.check_access_diretud(formsemestre_id) if not ok: return err diff --git a/app/scodoc/sco_formsemestre_exterieurs.py b/app/scodoc/sco_formsemestre_exterieurs.py index b4c49c210..9b2c59748 100644 --- a/app/scodoc/sco_formsemestre_exterieurs.py +++ b/app/scodoc/sco_formsemestre_exterieurs.py @@ -34,7 +34,7 @@ Ces semestres n'auront qu'un seul inscrit ! import time import flask -from flask import url_for, g, request +from flask import flash, g, render_template, request, url_for from flask_login import current_user from app.comp import res_sem @@ -50,7 +50,6 @@ from app.models import ( import app.scodoc.sco_utils as scu from app import log from app.scodoc.TrivialFormulator import TrivialFormulator, tf_error_message -from app.scodoc import html_sco_header from app.scodoc import sco_formsemestre from app.scodoc import sco_formsemestre_inscriptions from app.scodoc import sco_formsemestre_validation @@ -86,7 +85,6 @@ def formsemestre_ext_create_form(etudid, formsemestre_id): """Formulaire création/inscription à un semestre extérieur""" etud = Identite.get_etud(etudid) H = [ - html_sco_header.sco_header(), f"""

Enregistrement d'une inscription antérieure dans un autre établissement

@@ -106,7 +104,6 @@ def formsemestre_ext_create_form(etudid, formsemestre_id): }" class="stdlink">Étudiant {etud.nomprenom} """, ] - F = html_sco_header.sco_footer() orig_sem = sco_formsemestre.get_formsemestre(formsemestre_id) # Ne propose que des semestres de semestre_id strictement inférieur # au semestre courant @@ -133,7 +130,7 @@ def formsemestre_ext_create_form(etudid, formsemestre_id): (indices entre {min_semestre_id} et {max_semestre_id}, semestre courant.)

""" ) - return "\n".join(H) + F + return render_template("sco_page.j2", content="\n".join(H)) # Formulaire semestre_ids_list = sorted(semestre_ids) semestre_ids_labels = [f"S{x}" for x in semestre_ids_list] @@ -205,7 +202,7 @@ def formsemestre_ext_create_form(etudid, formsemestre_id): la formation effectué dans un autre établissement.

""" ) - return "\n".join(H) + "\n" + tf[1] + F + return render_template("sco_page.j2", content="\n".join(H) + "\n" + tf[1]) elif tf[0] == -1: return flask.redirect( url_for( @@ -270,17 +267,35 @@ def formsemestre_ext_edit_ue_validations(formsemestre_id, etudid): ), ) if tf[0] == -1: - return "

annulation

" + flash("annulation") + return flask.redirect( + url_for( + "notes.formsemestre_bulletinetud", + scodoc_dept=g.scodoc_dept, + formsemestre_id=formsemestre_id, + etudid=etudid, + ) + ) else: H = _make_page(etud, formsemestre, tf) if tf[0] == 0: # premier affichage - return "\n".join(H) + return render_template( + "sco_page.j2", + title="Validation des UE d'un semestre extérieur", + javascripts=["js/formsemestre_ext_edit_ue_validations.js"], + content="\n".join(H), + ) else: # soumission # simule erreur ok, message = _check_values(formsemestre, ues, tf[2]) if not ok: H = _make_page(etud, formsemestre, tf, message=message) - return "\n".join(H) + return render_template( + "sco_page.j2", + title="Validation des UE d'un semestre extérieur", + javascripts=["js/formsemestre_ext_edit_ue_validations.js"], + content="\n".join(H), + ) else: # Submit _record_ue_validations_and_coefs(formsemestre, etud, ues, tf[2]) @@ -299,10 +314,6 @@ def _make_page(etud: Identite, formsemestre: FormSemestre, tf, message="") -> li nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre) moy_gen = nt.get_etud_moy_gen(etud.id) H = [ - html_sco_header.sco_header( - page_title="Validation des UE d'un semestre extérieur", - javascripts=["js/formsemestre_ext_edit_ue_validations.js"], - ), tf_error_message(message), f"""

{etud.nomprenom} est inscrit{etud.e} à ce semestre extérieur.

Voici ses UE enregistrées avec leur notes @@ -324,7 +335,6 @@ def _make_page(etud: Identite, formsemestre: FormSemestre, tf, message="") -> li )}">retour au bulletin de notes

""", - html_sco_header.sco_footer(), ] return H @@ -522,7 +532,8 @@ def _record_ue_validations_and_coefs( coef = None now_dmy = time.strftime(scu.DATE_FMT) log( - f"_record_ue_validations_and_coefs: {formsemestre.id} etudid={etud.id} ue_id={ue.id} moy_ue={note} ue_coef={coef}" + f"""_record_ue_validations_and_coefs: { + formsemestre.id} etudid={etud.id} ue_id={ue.id} moy_ue={note} ue_coef={coef}""" ) assert code is None or (note) # si code validant, il faut une note sco_formsemestre_validation.do_formsemestre_validate_previous_ue( diff --git a/app/scodoc/sco_formsemestre_inscriptions.py b/app/scodoc/sco_formsemestre_inscriptions.py index 823d1cc67..e8ce67ce1 100644 --- a/app/scodoc/sco_formsemestre_inscriptions.py +++ b/app/scodoc/sco_formsemestre_inscriptions.py @@ -28,7 +28,6 @@ """Opérations d'inscriptions aux semestres et modules """ import collections -import time import flask from flask import flash, url_for, g, render_template, request @@ -52,7 +51,6 @@ from app.scodoc import sco_moduleimpl from app.scodoc import sco_groups from app.scodoc import sco_etud from app.scodoc import sco_cache -from app.scodoc import html_sco_header # --- Gestion des inscriptions aux semestres @@ -250,7 +248,6 @@ def do_formsemestre_inscription_with_modules( ] formsemestre = FormSemestre.get_formsemestre(formsemestre_id, dept_id=dept_id) # Inscription au semestre - args = {"formsemestre_id": formsemestre_id, "etudid": etudid} formsemestre.inscrit_etudiant(etud, etat=etat, etape=etape, method=method) log( f"""do_formsemestre_inscription_with_modules: etudid={ @@ -307,7 +304,6 @@ def formsemestre_inscription_with_modules_form(etudid, only_ext=False): id=etudid, dept_id=g.scodoc_dept_id ).first_or_404() H = [ - html_sco_header.sco_header(), f"

Inscription de {etud.nomprenom}", ] if only_ext: @@ -319,8 +315,6 @@ def formsemestre_inscription_with_modules_form(etudid, only_ext=False):

Choisir un semestre:

""" ) - footer = html_sco_header.sco_footer() - # sems = sco_formsemestre.do_formsemestre_list(args={"etat": "1"}) formsemestres = ( FormSemestre.query.filter_by(etat=True, dept_id=g.scodoc_dept_id) .join(Formation) @@ -359,7 +353,9 @@ def formsemestre_inscription_with_modules_form(etudid, only_ext=False): url_for("scolar.fiche_etud", scodoc_dept=g.scodoc_dept, etudid=etudid) }">retour à la fiche de {etud.nomprenom}""" ) - return "\n".join(H) + footer + return render_template( + "sco_page_dept.j2", title="Inscription", content="\n".join(H) + ) def formsemestre_inscription_with_modules( @@ -501,9 +497,7 @@ def formsemestre_inscription_option(etudid, formsemestre_id): formsemestre = FormSemestre.get_formsemestre(formsemestre_id) nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre) - footer = html_sco_header.sco_footer() H = [ - html_sco_header.sco_header(), f"""

Inscription de {etud.nomprenom} aux modules de {formsemestre.titre_mois()}

""", ] @@ -620,7 +614,7 @@ function chkbx_select(field_id, state) {

""" ) - return "\n".join(H) + "\n" + tf[1] + footer + return render_template("sco_page.j2", content="\n".join(H) + "\n" + tf[1]) if tf[0] == -1: return flask.redirect( url_for("scolar.fiche_etud", scodoc_dept=g.scodoc_dept, etudid=etudid) @@ -663,7 +657,7 @@ function chkbx_select(field_id, state) { }">retour à la fiche étudiant

""" ) - return "\n".join(H) + footer + return render_template("sco_page.j2", content="\n".join(H)) H.append("

Confirmer les modifications:

") if a_desinscrire: @@ -711,7 +705,7 @@ function chkbx_select(field_id, state) { """ ) - return "\n".join(H) + footer + return render_template("sco_page.j2", content="\n".join(H)) def do_moduleimpl_incription_options( @@ -765,17 +759,15 @@ def do_moduleimpl_incription_options( ) H = [ - html_sco_header.sco_header(), f"""

Modifications effectuées

Retour à la fiche étudiant

- """, - html_sco_header.sco_footer(), + """ ] - return "\n".join(H) + return render_template("sco_page.j2", content="\n".join(H)) def est_inscrit_ailleurs(etudid, formsemestre_id): diff --git a/app/scodoc/sco_formsemestre_validation.py b/app/scodoc/sco_formsemestre_validation.py index f211a9da6..f82b54cde 100644 --- a/app/scodoc/sco_formsemestre_validation.py +++ b/app/scodoc/sco_formsemestre_validation.py @@ -51,11 +51,9 @@ from app.scodoc.sco_exceptions import ScoValueError from app.scodoc.codes_cursus import * from app.scodoc.TrivialFormulator import TrivialFormulator, tf_error_message -from app.scodoc import html_sco_header from app.scodoc import sco_assiduites from app.scodoc import codes_cursus from app.scodoc import sco_cache -from app.scodoc import sco_etud from app.scodoc import sco_formsemestre from app.scodoc import sco_formsemestre_inscriptions from app.scodoc import sco_cursus @@ -75,7 +73,7 @@ def formsemestre_validation_etud_form( sortcol=None, read_only=True, ): - """Formulaire de validation des décisions de jury""" + """Formulaire de validation des décisions de jury (formations classiques)""" formsemestre: FormSemestre = FormSemestre.query.filter_by( id=formsemestre_id, dept_id=g.scodoc_dept_id ).first_or_404() @@ -112,7 +110,6 @@ def formsemestre_validation_etud_form( if read_only: check = True - etud_d = sco_etud.get_etud_info(etudid=etudid, filled=True)[0] Se = sco_cursus.get_situation_etud_cursus(etud, formsemestre_id) if not Se.sem["etat"]: raise ScoValueError("validation: semestre verrouille") @@ -125,13 +122,7 @@ def formsemestre_validation_etud_form( selected_etudid=etudid, # va a la bonne ligne ) - H = [ - html_sco_header.sco_header( - page_title=f"Parcours {etud.nomprenom}", - javascripts=["js/recap_parcours.js"], - ) - ] - + H = [] # Navigation suivant/precedent if etud_index_prev is not None: etud_prev = Identite.get_etud(T[etud_index_prev][-1]) @@ -167,8 +158,6 @@ def formsemestre_validation_etud_form( ) footer.append("") - footer.append(html_sco_header.sco_footer()) - H.append('
') if not check: H.append( @@ -206,7 +195,12 @@ def formsemestre_validation_etud_form( """ ) - return "\n".join(H + footer) + return render_template( + "sco_page.j2", + javascripts=["js/recap_parcours.js"], + title=f"Parcours {etud.nomprenom}", + content="\n".join(H + footer), + ) H.append( formsemestre_recap_parcours_table( @@ -218,7 +212,12 @@ def formsemestre_validation_etud_form( dest_url = url_tableau H.append(f'') - return "\n".join(H + footer) + return render_template( + "sco_page.j2", + javascripts=["js/recap_parcours.js"], + title=f"Parcours {etud.nomprenom}", + content="\n".join(H + footer), + ) decision_jury = Se.nt.get_etud_decision_sem(etudid) @@ -236,7 +235,12 @@ def formsemestre_validation_etud_form( """ ) ) - return "\n".join(H + footer) + return render_template( + "sco_page.j2", + javascripts=["js/recap_parcours.js"], + title=f"Parcours {etud.nomprenom}", + content="\n".join(H + footer), + ) evaluations_a_debloquer = Evaluation.get_evaluations_blocked_for_etud( formsemestre, etud @@ -256,7 +260,12 @@ def formsemestre_validation_etud_form( """ ) ) - return "\n".join(H + footer) + return render_template( + "sco_page.j2", + javascripts=["js/recap_parcours.js"], + title=f"Parcours {etud.nomprenom}", + content="\n".join(H + footer), + ) # Infos si pas de semestre précédent if not Se.prev_formsemestre: @@ -287,8 +296,12 @@ def formsemestre_validation_etud_form( }" class="stdlink">Supprimer décision existante """ ) - H.append(html_sco_header.sco_footer()) - return "\n".join(H) + return render_template( + "sco_page.j2", + javascripts=["js/recap_parcours.js"], + title=f"Parcours {etud.nomprenom}", + content="\n".join(H), + ) # Infos sur decisions déjà saisies if decision_jury: @@ -329,8 +342,12 @@ def formsemestre_validation_etud_form( H.append(f"""""") H.append("") - H.append(html_sco_header.sco_footer()) - return "\n".join(H) + return render_template( + "sco_page.j2", + javascripts=["js/recap_parcours.js"], + title=f"Parcours {etud.nomprenom}", + content="\n".join(H), + ) # Explication sur barres actuelles H.append('

L\'étudiant ') @@ -393,7 +410,12 @@ def formsemestre_validation_etud_form( else: H.append("sans semestres décalés

") - return "".join(H + footer) + return render_template( + "sco_page.j2", + javascripts=["js/recap_parcours.js"], + title=f"Parcours {etud.nomprenom}", + content="\n".join(H + footer), + ) def formsemestre_validation_etud( @@ -1062,7 +1084,7 @@ def do_formsemestre_validation_auto(formsemestre_id): ), ) H = [ - f"""{html_sco_header.sco_header(page_title="Saisie automatique")} + f"""

Saisie automatique des décisions du semestre {formsemestre.titre_annee()}

Opération effectuée.

{nb_valid} étudiants validés sur {len(etudids)}

@@ -1088,8 +1110,10 @@ def do_formsemestre_validation_auto(formsemestre_id): scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id, mode_jury=1) }">continuer""" ) - H.append(html_sco_header.sco_footer()) - return "\n".join(H) + + return render_template( + "sco_page.j2", title="Saisie automatique", content="\n".join(H) + ) def formsemestre_validation_suppress_etud(formsemestre_id, etudid): @@ -1218,14 +1242,14 @@ def formsemestre_validate_previous_ue(formsemestre: FormSemestre, etud: Identite submitlabel="Enregistrer validation d'UE", ) if tf[0] == 0: - return f""" - {html_sco_header.sco_header( - page_title="Validation UE antérieure", - javascripts=["js/validate_previous_ue.js"], - cssstyles=["css/jury_delete_manual.css"], - etudid=etud.id, - formsemestre_id=formsemestre.id, - )} + return render_template( + "sco_page_dept.j2", + title="Validation UE antérieure", + javascripts=["js/validate_previous_ue.js"], + cssstyles=["css/jury_delete_manual.css"], + etudid=etud.id, + formsemestre_id=formsemestre.id, + content=f"""

Gestion des validations d'UEs antérieures de {etud.html_link_fiche()}

@@ -1265,8 +1289,8 @@ def formsemestre_validate_previous_ue(formsemestre: FormSemestre, etud: Identite {check_formation_ues(formation)[0]} - {html_sco_header.sco_footer()} - """ + """, + ) dest_url = url_for( "notes.formsemestre_validate_previous_ue", diff --git a/app/scodoc/sco_groups.py b/app/scodoc/sco_groups.py index 6faf1cea7..c585223d1 100644 --- a/app/scodoc/sco_groups.py +++ b/app/scodoc/sco_groups.py @@ -34,8 +34,7 @@ from xml.etree import ElementTree from xml.etree.ElementTree import Element import flask -from flask import g, request -from flask import url_for, make_response +from flask import g, make_response, render_template, request, url_for from sqlalchemy.sql import text from app import cache, db, log @@ -45,7 +44,6 @@ from app.models import FormSemestre, Identite, Scolog from app.models import SHORT_STR_LEN from app.models.groups import GroupDescr, Partition import app.scodoc.notesdb as ndb -from app.scodoc import html_sco_header from app.scodoc import sco_cache from app.scodoc import codes_cursus from app.scodoc import sco_cursus @@ -56,7 +54,6 @@ from app.scodoc import sco_xml from app.scodoc.sco_exceptions import ScoException, AccessDenied, ScoValueError from app.scodoc.TrivialFormulator import TrivialFormulator - partitionEditor = ndb.EditableTable( "partition", "partition_id", @@ -930,16 +927,12 @@ def edit_partition_form(formsemestre_id=None): raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !") partitions = get_partitions_list(formsemestre_id) - arrow_up, arrow_down, arrow_none = get_arrow_icons_tags() + arrow_up, arrow_down, _ = get_arrow_icons_tags() suppricon = scu.icontag( "delete_small_img", border="0", alt="supprimer", title="Supprimer" ) # H = [ - html_sco_header.sco_header( - page_title="Partitions...", - javascripts=["js/edit_partition_form.js"], - ), # limite à SHORT_STR_LEN r""" + + +{% endblock %} \ No newline at end of file diff --git a/app/templates/scolar/affect_groups.j2 b/app/templates/scolar/affect_groups.j2 index 51d7f599b..34920646c 100644 --- a/app/templates/scolar/affect_groups.j2 +++ b/app/templates/scolar/affect_groups.j2 @@ -1,5 +1,7 @@ {# -*- mode: jinja-html -*- #} -{{ sco_header|safe }} +{% extends "sco_page.j2" %} + +{% block app_content %}

Affectation aux groupes de {{ partition.partition_name }}

@@ -54,4 +56,4 @@ -{{ sco_footer|safe }} \ No newline at end of file +{% endblock %} From 50a01c8bd775577fc2e0275e6d3b13407ae7a6e4 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Sat, 24 Aug 2024 18:31:14 +0200 Subject: [PATCH 2/4] Tweak css datatables pour scroll horizontal --- app/static/css/scodoc.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/static/css/scodoc.css b/app/static/css/scodoc.css index e54fa801e..c2867025b 100644 --- a/app/static/css/scodoc.css +++ b/app/static/css/scodoc.css @@ -2476,6 +2476,10 @@ li.notes_formation_list { padding-top: 10px; } +.dt-scroll-body { + overflow: initial !important; +} + table.dataTable.formation_list_table.gt_table { border-collapse: collapse; margin-right: 12px; From 906ed1331b32b4cae93304f722f3f4955f5622a5 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Sat, 24 Aug 2024 18:50:41 +0200 Subject: [PATCH 3/4] Modifie ordre chargement css --- app/templates/sco_page.j2 | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/templates/sco_page.j2 b/app/templates/sco_page.j2 index 75abae694..553a39070 100644 --- a/app/templates/sco_page.j2 +++ b/app/templates/sco_page.j2 @@ -3,15 +3,13 @@ {% block styles %} {{super()}} + + - -{# - #} - {% endblock %} {% block title %} From 91af5704dcf7a3b085c716b7175ef5151eb834d4 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Sat, 24 Aug 2024 19:41:29 +0200 Subject: [PATCH 4/4] =?UTF-8?q?Fix:=20upload=20notes=20excel=20sans=20indi?= =?UTF-8?q?quer=20d'=C3=A9val.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/scodoc/sco_saisie_excel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/scodoc/sco_saisie_excel.py b/app/scodoc/sco_saisie_excel.py index 1f2383b82..6aa6a86f9 100644 --- a/app/scodoc/sco_saisie_excel.py +++ b/app/scodoc/sco_saisie_excel.py @@ -928,7 +928,7 @@ def _get_sheet_evaluations( i, r = _xls_search_sheet_code(rows, diag) if isinstance(r, int): # mono-eval sheet_eval_id = r - if sheet_eval_id != evaluation.id: + if (evaluation is None) or (sheet_eval_id != evaluation.id): diag.append( f"""Erreur: fichier invalide: le code d'évaluation de correspond pas ! ('{ sheet_eval_id or ('non trouvé')}' != '{evaluation.id}')"""