Compare commits

..

4 Commits

46 changed files with 549 additions and 506 deletions

View File

@ -105,7 +105,7 @@ def pvjury_page_but(formsemestre_id: int, fmt="html"):
}, },
xls_style_base=xls_style_base, xls_style_base=xls_style_base,
) )
return tab.make_page(fmt=fmt, javascripts=["js/etud_info.js"]) return tab.make_page(fmt=fmt)
def pvjury_table_but( def pvjury_table_but(

View File

@ -46,10 +46,8 @@ from app.scodoc.sco_config_actions import LogoInsert
from app.scodoc.sco_exceptions import ScoValueError from app.scodoc.sco_exceptions import ScoValueError
from app.scodoc.sco_logos import find_logo from app.scodoc.sco_logos import find_logo
JAVASCRIPTS = html_sco_header.BOOTSTRAP_JS + []
CSSSTYLES = html_sco_header.BOOTSTRAP_CSS CSSSTYLES = html_sco_header.BOOTSTRAP_CSS
JAVASCRIPTS = html_sco_header.BOOTSTRAP_JS
# class ItemForm(FlaskForm): # class ItemForm(FlaskForm):
# """Unused Generic class to document common behavior for classes # """Unused Generic class to document common behavior for classes

View File

@ -271,10 +271,10 @@ class ScolarNews(db.Model):
return "" return ""
dept_news_url = url_for("scolar.dept_news", scodoc_dept=g.scodoc_dept) dept_news_url = url_for("scolar.dept_news", scodoc_dept=g.scodoc_dept)
H = [ H = [
f"""<div class="scobox news"><div class="scobox-title"><a href="{ f"""<div class="scobox news"><div class="scobox-title" desktop="true"><a href="{
dept_news_url dept_news_url
}">Dernières opérations</a> }">Dernières opérations</a>
</div><ul class="newslist">""" </div><ul class="newslist" desktop="true">"""
] ]
for news in news_list: for news in news_list:
@ -289,11 +289,18 @@ class ScolarNews(db.Model):
</li>""" </li>"""
) )
H.append("</ul></div>") H.append(
"""</ul>
<ul class="newslist" mobile="true" style="margin-bottom: 0px;">
<li><a href="{dept_news_url}" class="stdlink">Dernières opérations</a></li>
</ul>
</div>
"""
)
# Informations générales # Informations générales
H.append( H.append(
f"""<div> f"""<div desktop="true">
Pour en savoir plus sur ScoDoc voir Pour en savoir plus sur ScoDoc voir
<a class="stdlink" href="{scu.SCO_ANNONCES_WEBSITE}">scodoc.org</a> <a class="stdlink" href="{scu.SCO_ANNONCES_WEBSITE}">scodoc.org</a>
</div> </div>

View File

@ -57,7 +57,6 @@ from reportlab.lib.units import cm
from flask import render_template from flask import render_template
from app.scodoc import html_sco_header
from app.scodoc import sco_utils as scu from app.scodoc import sco_utils as scu
from app.scodoc import sco_excel from app.scodoc import sco_excel
from app.scodoc import sco_pdf from app.scodoc import sco_pdf

View File

@ -134,7 +134,7 @@ def scodoc_top_html_header(page_title="ScoDoc: bienvenue"):
def sco_header( def sco_header(
# optional args # optional args
page_title="", # page title page_title="", # page title
no_side_bar=False, # hide sidebar no_sidebar=False, # hide sidebar
cssstyles=(), # additionals CSS sheets cssstyles=(), # additionals CSS sheets
javascripts=(), # additionals JS filenames to load javascripts=(), # additionals JS filenames to load
scripts=(), # script to put in page header scripts=(), # script to put in page header
@ -154,13 +154,13 @@ def sco_header(
params = { params = {
"page_title": page_title or sco_version.SCONAME, "page_title": page_title or sco_version.SCONAME,
"no_side_bar": no_side_bar, "no_sidebar": no_sidebar,
"ScoURL": url_for("scolar.index_html", scodoc_dept=g.scodoc_dept), "ScoURL": url_for("scolar.index_html", scodoc_dept=g.scodoc_dept),
"encoding": scu.SCO_ENCODING, "encoding": scu.SCO_ENCODING,
"titrebandeau_mkup": "<td>" + titrebandeau + "</td>", "titrebandeau_mkup": "<td>" + titrebandeau + "</td>",
"authuser": current_user.user_name, "authuser": current_user.user_name,
} }
if no_side_bar: if no_sidebar:
params["margin_left"] = "1em" params["margin_left"] = "1em"
else: else:
params["margin_left"] = "140px" params["margin_left"] = "140px"
@ -217,7 +217,7 @@ def sco_header(
<!-- Legacy ScoDoc header --> <!-- Legacy ScoDoc header -->
<body> <body>
{scu.CUSTOM_HTML_HEADER} {scu.CUSTOM_HTML_HEADER}
{'' if no_side_bar else html_sidebar.sidebar(etudid)} {'' if no_sidebar else html_sidebar.sidebar(etudid)}
<div id="gtrcontent"> <div id="gtrcontent">
""" """
) )
@ -242,18 +242,3 @@ def sco_footer():
+ scu.CUSTOM_HTML_FOOTER + scu.CUSTOM_HTML_FOOTER
+ """</body></html>""" + """</body></html>"""
) )
def html_sem_header(
title, with_page_header=True, with_h2=True, page_title=None, **args
):
"Titre d'une page semestre avec lien vers tableau de bord"
# sem now unused and thus optional...
if with_page_header:
h = sco_header(page_title="%s" % (page_title or title), **args)
else:
h = ""
if with_h2:
return h + f"""<h2 class="formsemestre">{title}</h2>"""
else:
return h

View File

@ -41,10 +41,8 @@ from app.scodoc import sco_groups
from app.scodoc import sco_trombino from app.scodoc import sco_trombino
from app.scodoc import sco_archives from app.scodoc import sco_archives
from app.scodoc.sco_permissions import Permission from app.scodoc.sco_permissions import Permission
from app.scodoc.sco_exceptions import AccessDenied, ScoValueError from app.scodoc.sco_exceptions import AccessDenied
from app.scodoc.TrivialFormulator import TrivialFormulator from app.scodoc.TrivialFormulator import TrivialFormulator
from app.scodoc import html_sco_header
from app.scodoc import sco_etud
class EtudsArchiver(sco_archives.BaseArchiver): class EtudsArchiver(sco_archives.BaseArchiver):
@ -142,9 +140,6 @@ def etud_upload_file_form(etudid):
etud = Identite.get_etud(etudid) etud = Identite.get_etud(etudid)
H = [ H = [
html_sco_header.sco_header(
page_title=f"Chargement d'un document associé à {etud.nomprenom}",
),
f"""<h2>Chargement d'un document associé à {etud.nomprenom}</h2> f"""<h2>Chargement d'un document associé à {etud.nomprenom}</h2>
<p>Le fichier ne doit pas dépasser { <p>Le fichier ne doit pas dépasser {
@ -171,8 +166,12 @@ def etud_upload_file_form(etudid):
cancelbutton="Annuler", cancelbutton="Annuler",
) )
if tf[0] == 0: if tf[0] == 0:
return "\n".join(H) + tf[1] + html_sco_header.sco_footer() return render_template(
elif tf[0] == -1: "sco_page.j2",
title=f"Chargement d'un document associé à {etud.nomprenom}",
content="\n".join(H) + tf[1],
)
if tf[0] == -1:
return flask.redirect(etud.url_fiche()) return flask.redirect(etud.url_fiche())
data = tf[2]["datafile"].read() data = tf[2]["datafile"].read()
descr = tf[2]["description"] descr = tf[2]["description"]
@ -263,9 +262,6 @@ def etudarchive_generate_excel_sample(group_id=None):
def etudarchive_import_files_form(group_id): def etudarchive_import_files_form(group_id):
"""Formulaire pour importation fichiers d'un groupe""" """Formulaire pour importation fichiers d'un groupe"""
H = [ H = [
html_sco_header.sco_header(
page_title="Import de fichiers associés aux étudiants"
),
"""<h2 class="formsemestre">Téléchargement de fichier associés aux étudiants</h2> """<h2 class="formsemestre">Téléchargement de fichier associés aux étudiants</h2>
<p>Les fichiers associés (dossiers d'admission, certificats, ...), de <p>Les fichiers associés (dossiers d'admission, certificats, ...), de
types quelconques (pdf, doc, images) sont accessibles aux utilisateurs via types quelconques (pdf, doc, images) sont accessibles aux utilisateurs via
@ -292,7 +288,6 @@ def etudarchive_import_files_form(group_id):
""" """
% group_id, % group_id,
] ]
F = html_sco_header.sco_footer()
tf = TrivialFormulator( tf = TrivialFormulator(
request.base_url, request.base_url,
scu.get_request_args(), scu.get_request_args(),
@ -313,7 +308,11 @@ def etudarchive_import_files_form(group_id):
) )
if tf[0] == 0: if tf[0] == 0:
return "\n".join(H) + tf[1] + "</li></ol>" + F return render_template(
"sco_page.j2",
title="Import de fichiers associés aux étudiants",
content="\n".join(H) + tf[1] + "</li></ol>",
)
# retrouve le semestre à partir du groupe: # retrouve le semestre à partir du groupe:
group = sco_groups.get_group(group_id) group = sco_groups.get_group(group_id)
if tf[0] == -1: if tf[0] == -1:

View File

@ -27,7 +27,7 @@
import json import json
import flask import flask
from flask import flash, g, request, url_for from flask import flash, g, render_template, request, url_for
from app import ScoDocJSONEncoder from app import ScoDocJSONEncoder
from app.but import jury_but_pv from app.but import jury_but_pv
@ -127,7 +127,7 @@ def do_formsemestre_archive(
[ [
html_sco_header.sco_header( html_sco_header.sco_header(
page_title=f"Moyennes archivées le {date}", page_title=f"Moyennes archivées le {date}",
no_side_bar=True, no_sidebar=True,
), ),
f'<h2 class="fontorange">Valeurs archivées le {date}</h2>', f'<h2 class="fontorange">Valeurs archivées le {date}</h2>',
"""<style type="text/css">table.notes_recapcomplet tr { color: rgb(185,70,0); } """<style type="text/css">table.notes_recapcomplet tr { color: rgb(185,70,0); }
@ -238,11 +238,6 @@ def formsemestre_archive(formsemestre_id, group_ids: list[int] = None):
) )
H = [ H = [
html_sco_header.html_sem_header(
"Archiver les PV et résultats du semestre",
javascripts=sco_groups_view.JAVASCRIPTS,
cssstyles=sco_groups_view.CSSSTYLES,
),
"""<p class="help">Cette page permet de générer et d'archiver tous """<p class="help">Cette page permet de générer et d'archiver tous
les documents résultant de ce semestre: PV de jury, lettres individuelles, les documents résultant de ce semestre: PV de jury, lettres individuelles,
tableaux récapitulatifs.</p><p class="help">Les documents archivés sont tableaux récapitulatifs.</p><p class="help">Les documents archivés sont
@ -311,7 +306,17 @@ enregistrés et non modifiables, on peut les retrouver ultérieurement.
html_foot_markup=menu_choix_groupe, html_foot_markup=menu_choix_groupe,
) )
if tf[0] == 0: if tf[0] == 0:
return "\n".join(H) + "\n" + tf[1] + "\n".join(F) return render_template(
"sco_page.j2",
title="Archiver les PV et résultats",
javascripts=sco_groups_view.JAVASCRIPTS,
cssstyles=sco_groups_view.CSSSTYLES,
content="<h2>Archiver les PV et résultats du semestre</h2>"
+ "\n".join(H)
+ "\n"
+ tf[1]
+ "\n".join(F),
)
elif tf[0] == -1: elif tf[0] == -1:
msg = "Opération annulée" msg = "Opération annulée"
else: else:
@ -371,7 +376,7 @@ def formsemestre_list_archives(formsemestre_id):
} }
archives_descr.append(a) archives_descr.append(a)
H = [html_sco_header.html_sem_header("Archive des PV et résultats ")] H = []
if not archives_descr: if not archives_descr:
H.append("<p>aucune archive enregistrée</p>") H.append("<p>aucune archive enregistrée</p>")
else: else:
@ -399,7 +404,9 @@ def formsemestre_list_archives(formsemestre_id):
H.append("</ul></li>") H.append("</ul></li>")
H.append("</ul>") H.append("</ul>")
return "\n".join(H) + html_sco_header.sco_footer() return render_template(
"sco_page.j2", title="Archive des PV et résultats", content="\n".join(H)
)
def formsemestre_get_archived_file(formsemestre_id, archive_name, filename): def formsemestre_get_archived_file(formsemestre_id, archive_name, filename):

View File

@ -76,7 +76,6 @@ def report_debouche_date(start_year=None, fmt="html"):
tab.base_url = f"{request.base_url}?start_year={start_year}" tab.base_url = f"{request.base_url}?start_year={start_year}"
return tab.make_page( return tab.make_page(
title="""<h2 class="formsemestre">Débouchés étudiants </h2>""", title="""<h2 class="formsemestre">Débouchés étudiants </h2>""",
javascripts=["js/etud_info.js"],
fmt=fmt, fmt=fmt,
with_html_headers=True, with_html_headers=True,
) )

View File

@ -25,9 +25,7 @@
# #
############################################################################## ##############################################################################
"""Ajout/Modification/Suppression UE """Ajout/Modification/Suppression UE"""
"""
import re import re
@ -765,20 +763,6 @@ def ue_table(formation_id=None, semestre_idx=1, msg=""): # was ue_list
"delete_small_dis_img", title="Suppression impossible (module utilisé)" "delete_small_dis_img", title="Suppression impossible (module utilisé)"
) )
H = [ H = [
html_sco_header.sco_header(
cssstyles=html_sco_header.BOOTSTRAP_CSS
+ ["libjs/jQuery-tagEditor/jquery.tag-editor.css", "css/ue_table.css"],
javascripts=html_sco_header.BOOTSTRAP_JS
+ [
"libjs/jinplace-1.2.1.min.js",
"js/ue_list.js",
"js/edit_ue.js",
"libjs/jQuery-tagEditor/jquery.tag-editor.min.js",
"libjs/jQuery-tagEditor/jquery.caret.min.js",
"js/module_tag_editor.js",
],
page_title=f"Formation {formation.acronyme} v{formation.version}",
),
f"""<h2>{formation.html()} {lockicon} f"""<h2>{formation.html()} {lockicon}
</h2> </h2>
""", """,
@ -1069,8 +1053,22 @@ du programme" (menu "Semestre") si vous avez un semestre en cours);
warn, _ = sco_formsemestre_validation.check_formation_ues(formation) warn, _ = sco_formsemestre_validation.check_formation_ues(formation)
H.append(warn) H.append(warn)
H.append(html_sco_header.sco_footer()) return render_template(
return "".join(H) "sco_page_dept.j2",
content="".join(H),
page_title=f"Formation {formation.acronyme} v{formation.version}",
cssstyles=html_sco_header.BOOTSTRAP_CSS
+ ["libjs/jQuery-tagEditor/jquery.tag-editor.css", "css/ue_table.css"],
javascripts=html_sco_header.BOOTSTRAP_JS
+ [
"libjs/jinplace-1.2.1.min.js",
"js/ue_list.js",
"js/edit_ue.js",
"libjs/jQuery-tagEditor/jquery.tag-editor.min.js",
"libjs/jQuery-tagEditor/jquery.caret.min.js",
"js/module_tag_editor.js",
],
)
def _html_select_semestre_idx(formation_id, semestre_ids, semestre_idx): def _html_select_semestre_idx(formation_id, semestre_ids, semestre_idx):
@ -1130,7 +1128,9 @@ def _ue_table_ues(
scodoc_dept=g.scodoc_dept, scodoc_dept=g.scodoc_dept,
ue_id=ue["ue_id"], ue_id=ue["ue_id"],
) )
ue["code_apogee_str"] = f""", Apo: <span ue[
"code_apogee_str"
] = f""", Apo: <span
class="{klass}" data-url="{edit_url}" id="{ue['ue_id']}" class="{klass}" data-url="{edit_url}" id="{ue['ue_id']}"
data-placeholder="{scu.APO_MISSING_CODE_STR}">{ data-placeholder="{scu.APO_MISSING_CODE_STR}">{
ue["code_apogee"] or "" ue["code_apogee"] or ""

View File

@ -597,7 +597,6 @@ def _view_etuds_page(
return f""" return f"""
{html_sco_header.sco_header( {html_sco_header.sco_header(
page_title=title, page_title=title,
javascripts=["js/etud_info.js"],
)} )}
<h2>{title}</h2> <h2>{title}</h2>
@ -750,7 +749,6 @@ def view_apo_csv(etape_apo="", semset_id="", fmt="html"):
H = [ H = [
html_sco_header.sco_header( html_sco_header.sco_header(
page_title=f"""Maquette Apogée enregistrée pour {etape_apo}""", page_title=f"""Maquette Apogée enregistrée pour {etape_apo}""",
javascripts=["js/etud_info.js"],
), ),
f"""<h2>Étudiants dans la maquette Apogée {etape_apo}</h2> f"""<h2>Étudiants dans la maquette Apogée {etape_apo}</h2>
<p>Pour l'ensemble <a class="stdlink" href="{ <p>Pour l'ensemble <a class="stdlink" href="{

View File

@ -27,7 +27,7 @@
"""Vérification des absences à une évaluation """Vérification des absences à une évaluation
""" """
from flask import url_for, g from flask import g, render_template, url_for
from flask_sqlalchemy.query import Query from flask_sqlalchemy.query import Query
from app import db from app import db
@ -37,6 +37,7 @@ from app.scodoc import html_sco_header
from app.scodoc import sco_evaluations from app.scodoc import sco_evaluations
from app.scodoc import sco_evaluation_db from app.scodoc import sco_evaluation_db
from app.scodoc import sco_groups from app.scodoc import sco_groups
from app.views import ScoData
def evaluation_check_absences(evaluation: Evaluation): def evaluation_check_absences(evaluation: Evaluation):
@ -109,8 +110,10 @@ def evaluation_check_absences(evaluation: Evaluation):
def evaluation_check_absences_html( def evaluation_check_absences_html(
evaluation: Evaluation, with_header=True, show_ok=True evaluation: Evaluation, with_header=True, show_ok=True
): ) -> str:
"""Affiche état vérification absences d'une évaluation""" """Affiche état vérification absences d'une évaluation.
Si with_header, génère page complète, sinon fragment html.
"""
( (
note_but_abs, # une note alors qu'il était signalé abs note_but_abs, # une note alors qu'il était signalé abs
abs_non_signalee, # note ABS alors que pas signalé abs abs_non_signalee, # note ABS alors que pas signalé abs
@ -121,10 +124,6 @@ def evaluation_check_absences_html(
if with_header: if with_header:
H = [ H = [
html_sco_header.html_sem_header(
"Vérification absences à l'évaluation",
formsemestre_id=evaluation.moduleimpl.formsemestre_id,
),
sco_evaluations.evaluation_describe(evaluation_id=evaluation.id), sco_evaluations.evaluation_describe(evaluation_id=evaluation.id),
"""<p class="help">Vérification de la cohérence entre les notes saisies """<p class="help">Vérification de la cohérence entre les notes saisies
et les absences signalées.</p>""", et les absences signalées.</p>""",
@ -208,19 +207,19 @@ def evaluation_check_absences_html(
etudlist(abs_but_exc) etudlist(abs_but_exc)
if with_header: if with_header:
H.append(html_sco_header.sco_footer()) return render_template(
"sco_page.j2",
title="Vérification absences à l'évaluation",
content="<h2>Vérification absences à l'évaluation</h2>" + "\n".join(H),
sco=ScoData(formsemestre=evaluation.moduleimpl.formsemestre),
)
return "\n".join(H) return "\n".join(H)
def formsemestre_check_absences_html(formsemestre_id): def formsemestre_check_absences_html(formsemestre_id: int):
"""Affiche etat verification absences pour toutes les evaluations du semestre !""" """Affiche état vérification absences pour toutes les évaluations du semestre."""
formsemestre: FormSemestre = FormSemestre.query.filter_by( formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
dept_id=g.scodoc_dept_id, id=formsemestre_id
).first_or_404()
H = [ H = [
html_sco_header.html_sem_header(
"Vérification absences aux évaluations de ce semestre",
),
"""<p class="help">Vérification de la cohérence entre les notes saisies """<p class="help">Vérification de la cohérence entre les notes saisies
et les absences signalées. et les absences signalées.
Sont listés tous les modules avec des évaluations.<br>Aucune action n'est effectuée: Sont listés tous les modules avec des évaluations.<br>Aucune action n'est effectuée:
@ -248,5 +247,9 @@ def formsemestre_check_absences_html(formsemestre_id):
) )
H.append("</div>") H.append("</div>")
H.append(html_sco_header.sco_footer()) return render_template(
return "\n".join(H) "sco_page.j2",
content="<h2>Vérification absences aux évaluations de ce semestre</h2>"
+ "\n".join(H),
title="Vérification absences aux évaluations de ce semestre",
)

View File

@ -10,7 +10,7 @@ avec leur état.
Sur une idée de Pascal Bouron, de Lyon. Sur une idée de Pascal Bouron, de Lyon.
""" """
import time import time
from flask import g, url_for from flask import g, render_template, url_for
from app import db from app import db
from app.models import Evaluation, FormSemestre from app.models import Evaluation, FormSemestre
@ -23,7 +23,7 @@ import app.scodoc.sco_utils as scu
def evaluations_recap(formsemestre_id: int) -> str: def evaluations_recap(formsemestre_id: int) -> str:
"""Page récap. de toutes les évaluations d'un semestre""" """Page récap. de toutes les évaluations d'un semestre"""
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id) formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
rows, titles = evaluations_recap_table(formsemestre) rows, titles = evaluations_recap_table(formsemestre)
column_ids = titles.keys() column_ids = titles.keys()
filename = scu.sanitize_filename( filename = scu.sanitize_filename(
@ -32,11 +32,14 @@ def evaluations_recap(formsemestre_id: int) -> str:
if not rows: if not rows:
return '<div class="evaluations_recap"><div class="message">aucune évaluation</div></div>' return '<div class="evaluations_recap"><div class="message">aucune évaluation</div></div>'
H = [ H = [
html_sco_header.sco_header( f"""<h2>Évaluations du semestre</h2>
page_title="Évaluations du semestre", <div>
javascripts=["js/evaluations_recap.js"], <a class="stdlink" href="{url_for(
), 'notes.formsemestre_check_absences_html',
f"""<div class="evaluations_recap"><table class="evaluations_recap compact { scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre.id,
)}">Vérifier les absences aux évaluations</a>
</div>
<div class="evaluations_recap"><table class="evaluations_recap compact {
'apc' if formsemestre.formation.is_apc() else 'classic' 'apc' if formsemestre.formation.is_apc() else 'classic'
}" }"
data-filename="{filename}">""", data-filename="{filename}">""",
@ -56,13 +59,19 @@ def evaluations_recap(formsemestre_id: int) -> str:
H.append( H.append(
"""</tbody></table></div> """</tbody></table></div>
<div class="help">Les étudiants démissionnaires ou défaillants ne sont pas pris en compte dans cette table.</div> <div class="help">Les étudiants démissionnaires ou défaillants ne sont
pas pris en compte dans cette table.</div>
""" """
) )
H.append( H.append(
html_sco_header.sco_footer(), html_sco_header.sco_footer(),
) )
return "".join(H) return render_template(
"sco_page.j2",
title="Évaluations du semestre",
javascripts=["js/evaluations_recap.js"],
content="".join(H),
)
def evaluations_recap_table(formsemestre: FormSemestre) -> list[dict]: def evaluations_recap_table(formsemestre: FormSemestre) -> list[dict]:

View File

@ -31,9 +31,7 @@ import collections
import datetime import datetime
import operator import operator
from flask import url_for from flask import g, render_template, request, url_for
from flask import g
from flask import request
from flask_login import current_user from flask_login import current_user
from app import db from app import db
@ -45,8 +43,6 @@ from app.models import Evaluation, FormSemestre, ModuleImpl, Module
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
from app.scodoc.sco_utils import ModuleType from app.scodoc.sco_utils import ModuleType
from app.scodoc.gen_tables import GenTable from app.scodoc.gen_tables import GenTable
from app.scodoc import html_sco_header
from app.scodoc import sco_cal
from app.scodoc import sco_evaluation_db from app.scodoc import sco_evaluation_db
from app.scodoc import sco_formsemestre_inscriptions from app.scodoc import sco_formsemestre_inscriptions
from app.scodoc import sco_groups from app.scodoc import sco_groups
@ -470,7 +466,7 @@ class CalendrierEval(sco_gen_cal.Calendrier):
# View # View
def formsemestre_evaluations_cal(formsemestre_id): def formsemestre_evaluations_cal(formsemestre_id):
"""Page avec calendrier de toutes les evaluations de ce semestre""" """Page avec calendrier de toutes les évaluations de ce semestre"""
formsemestre = FormSemestre.get_formsemestre(formsemestre_id) formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre) nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
@ -481,13 +477,12 @@ def formsemestre_evaluations_cal(formsemestre_id):
cal = CalendrierEval(year, evaluations, nt) cal = CalendrierEval(year, evaluations, nt)
cal_html = cal.get_html() cal_html = cal.get_html()
return f""" return render_template(
{ "sco_page.j2",
html_sco_header.html_sem_header( cssstyles=["css/calabs.css"],
"Evaluations du semestre", title="Évaluations du semestre",
cssstyles=["css/calabs.css"], content=f"""
) <h2>Évaluations du semestre</h2>
}
<div class="cal_evaluations"> <div class="cal_evaluations">
{ cal_html } { cal_html }
</div> </div>
@ -513,8 +508,8 @@ def formsemestre_evaluations_cal(formsemestre_id):
) )
}" class="stdlink">voir les délais de correction</a> }" class="stdlink">voir les délais de correction</a>
</p> </p>
{ html_sco_header.sco_footer() } """,
""" )
def evaluation_date_first_completion(evaluation_id) -> datetime.datetime: def evaluation_date_first_completion(evaluation_id) -> datetime.datetime:
@ -651,7 +646,7 @@ def evaluation_describe(evaluation_id="", edit_in_place=True, link_saisie=True)
"""HTML description of evaluation, for page headers """HTML description of evaluation, for page headers
edit_in_place: allow in-place editing when permitted (not implemented) edit_in_place: allow in-place editing when permitted (not implemented)
""" """
evaluation: Evaluation = Evaluation.query.get_or_404(evaluation_id) evaluation = Evaluation.get_evaluation(evaluation_id)
modimpl = evaluation.moduleimpl modimpl = evaluation.moduleimpl
responsable: User = db.session.get(User, modimpl.responsable_id) responsable: User = db.session.get(User, modimpl.responsable_id)
resp_nomprenom = responsable.get_prenomnom() resp_nomprenom = responsable.get_prenomnom()

View File

@ -73,7 +73,9 @@ def _build_results_table(start_date=None, end_date=None, types_parcours=[]):
formsemestre_ids_parcours = [sem["formsemestre_id"] for sem in semlist_parcours] formsemestre_ids_parcours = [sem["formsemestre_id"] for sem in semlist_parcours]
# Ensemble des étudiants # Ensemble des étudiants
etuds_infos = {} # etudid : { formsemestre_id d'inscription le plus recent dans les dates considérées, etud } etuds_infos = (
{}
) # etudid : { formsemestre_id d'inscription le plus recent dans les dates considérées, etud }
for formsemestre_id in formsemestre_ids_parcours: for formsemestre_id in formsemestre_ids_parcours:
formsemestre = FormSemestre.get_formsemestre(formsemestre_id) formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre) nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
@ -285,8 +287,7 @@ def scodoc_table_results(
H = [ H = [
html_sco_header.sco_header( html_sco_header.sco_header(
page_title="Export résultats", page_title="Export résultats",
javascripts=html_sco_header.BOOTSTRAP_JS javascripts=html_sco_header.BOOTSTRAP_JS + ["js/export_results.js"],
+ ["js/etud_info.js", "js/export_results.js"],
cssstyles=html_sco_header.BOOTSTRAP_CSS, cssstyles=html_sco_header.BOOTSTRAP_CSS,
), ),
# XXX # XXX

View File

@ -28,7 +28,7 @@
"""Recherche d'étudiants """Recherche d'étudiants
""" """
import flask import flask
from flask import url_for, g, request from flask import url_for, g, render_template, request
from flask_login import current_user from flask_login import current_user
import sqlalchemy as sa import sqlalchemy as sa
@ -177,13 +177,7 @@ def search_etud_in_dept(expnom=""):
url_args["etudid"] = etuds[0].id url_args["etudid"] = etuds[0].id
return flask.redirect(url_for(endpoint, **url_args)) return flask.redirect(url_for(endpoint, **url_args))
H = [ H = []
html_sco_header.sco_header(
page_title="Recherche d'un étudiant",
no_side_bar=False,
javascripts=["js/etud_info.js"],
)
]
if len(etuds) == 0 and len(etuds) <= 1: if len(etuds) == 0 and len(etuds) <= 1:
H.append("""<h2>chercher un étudiant:</h2>""") H.append("""<h2>chercher un étudiant:</h2>""")
else: else:
@ -266,7 +260,9 @@ def search_etud_in_dept(expnom=""):
"""<p class="help">La recherche porte sur tout ou partie du NOM ou du NIP """<p class="help">La recherche porte sur tout ou partie du NOM ou du NIP
de l'étudiant. Saisir au moins deux caractères.</p>""" de l'étudiant. Saisir au moins deux caractères.</p>"""
) )
return "\n".join(H) + html_sco_header.sco_footer() return render_template(
"sco_page_dept.j2", title="Recherche d'un étudiant", content="\n".join(H)
)
def search_etuds_infos(expnom=None, code_nip=None) -> list[dict]: def search_etuds_infos(expnom=None, code_nip=None) -> list[dict]:
@ -313,7 +309,7 @@ def search_etud_by_name(term: str) -> list:
# ---------- Recherche sur plusieurs département # ---------- Recherche sur plusieurs département
def search_etud_in_accessible_depts( def search_etuds_in_accessible_depts(
expnom=None, expnom=None,
) -> tuple[list[list[Identite]], list[str]]: ) -> tuple[list[list[Identite]], list[str]]:
""" """
@ -334,14 +330,14 @@ def search_etud_in_accessible_depts(
return result, accessible_depts return result, accessible_depts
def table_etud_in_accessible_depts(expnom=None): def table_etuds_in_accessible_depts(expnom=None):
""" """
Page avec table étudiants trouvés, dans tous les departements. Page avec table étudiants trouvés, dans tous les departements.
Attention: nous sommes ici au niveau de ScoDoc, pas dans un département Attention: nous sommes ici au niveau de ScoDoc, pas dans un département
""" """
result, accessible_depts = search_etud_in_accessible_depts(expnom=expnom) result, accessible_depts = search_etuds_in_accessible_depts(expnom=expnom)
H = [ H = [
f"""<div class="table_etud_in_accessible_depts"> f"""<div class="table_etuds_in_accessible_depts">
<h3>Recherche multi-département de "<tt>{expnom}</tt>"</h3> <h3>Recherche multi-département de "<tt>{expnom}</tt>"</h3>
""", """,
] ]
@ -366,7 +362,7 @@ def table_etud_in_accessible_depts(expnom=None):
rows=rows, rows=rows,
html_sortable=True, html_sortable=True,
html_class="table_leftalign", html_class="table_leftalign",
# table_id="etud_in_accessible_depts", table_id="etuds_in_accessible_depts",
) )
H.append('<div class="table_etud_in_dept">') H.append('<div class="table_etud_in_dept">')
@ -386,8 +382,10 @@ def table_etud_in_accessible_depts(expnom=None):
</div> </div>
""" """
) )
return ( return render_template(
html_sco_header.scodoc_top_html_header(page_title="Choix d'un étudiant") "base.j2",
+ "\n".join(H) title="Choix d'un étudiant",
+ html_sco_header.standard_html_footer() content="\n".join(H),
javascripts=["DataTables/datatables.min.js"],
cssstyles=["DataTables/datatables.min.css"],
) )

View File

@ -28,7 +28,7 @@
"""Menu "custom" (défini par l'utilisateur) dans les semestres """Menu "custom" (défini par l'utilisateur) dans les semestres
""" """
import flask import flask
from flask import g, url_for, request from flask import g, url_for, render_template, request
from flask_login import current_user from flask_login import current_user
from app.models.config import ScoDocSiteConfig, PersonalizedLink from app.models.config import ScoDocSiteConfig, PersonalizedLink
@ -37,9 +37,6 @@ import app.scodoc.sco_utils as scu
import app.scodoc.notesdb as ndb import app.scodoc.notesdb as ndb
from app.scodoc.TrivialFormulator import TrivialFormulator from app.scodoc.TrivialFormulator import TrivialFormulator
from app.scodoc import html_sco_header from app.scodoc import html_sco_header
from app.scodoc import htmlutils
from app.scodoc import sco_formsemestre
from app.scodoc import sco_edt_cal
_custommenuEditor = ndb.EditableTable( _custommenuEditor = ndb.EditableTable(
"notes_formsemestre_custommenu", "notes_formsemestre_custommenu",
@ -106,14 +103,13 @@ def formsemestre_custommenu_html(formsemestre_id):
def formsemestre_custommenu_edit(formsemestre_id): def formsemestre_custommenu_edit(formsemestre_id):
"""Dialog to edit the custom menu""" """Dialog to edit the custom menu"""
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id) formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
dest_url = url_for( dest_url = url_for(
"notes.formsemestre_status", "notes.formsemestre_status",
scodoc_dept=g.scodoc_dept, scodoc_dept=g.scodoc_dept,
formsemestre_id=formsemestre_id, formsemestre_id=formsemestre_id,
) )
H = [ H = [
html_sco_header.html_sem_header("Modification du menu du semestre "),
"""<div class="help"> """<div class="help">
<p>Ce menu, spécifique à chaque semestre, peut être utilisé pour <p>Ce menu, spécifique à chaque semestre, peut être utilisé pour
placer des liens vers vos applications préférées. placer des liens vers vos applications préférées.
@ -164,7 +160,14 @@ def formsemestre_custommenu_edit(formsemestre_id):
name="tf", name="tf",
) )
if tf[0] == 0: if tf[0] == 0:
return "\n".join(H) + "\n" + tf[1] + html_sco_header.sco_footer() return render_template(
"sco_page.j2",
title="Modification du menu du semestre",
content="<h2>Modification du menu du semestre</h2>"
+ "\n".join(H)
+ "\n"
+ tf[1],
)
elif tf[0] == -1: elif tf[0] == -1:
return flask.redirect(dest_url) return flask.redirect(dest_url)
else: else:

View File

@ -28,8 +28,7 @@
"""Form choix modules / responsables et creation formsemestre """Form choix modules / responsables et creation formsemestre
""" """
import flask import flask
from flask import url_for, flash, redirect from flask import flash, g, request, redirect, render_template, url_for
from flask import g, request
from flask_login import current_user from flask_login import current_user
import sqlalchemy as sa import sqlalchemy as sa
@ -97,18 +96,10 @@ def formsemestre_createwithmodules():
return "\n".join(H) + html_sco_header.sco_footer() return "\n".join(H) + html_sco_header.sco_footer()
def formsemestre_editwithmodules(formsemestre_id): def formsemestre_editwithmodules(formsemestre_id: int):
"""Page modification semestre""" """Page modification semestre"""
formsemestre: FormSemestre = FormSemestre.query.filter_by( formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
id=formsemestre_id, dept_id=g.scodoc_dept_id H = []
).first_or_404()
H = [
html_sco_header.html_sem_header(
"Modification du semestre",
javascripts=["libjs/AutoSuggest.js", "js/formsemestre_edit.js"],
cssstyles=["css/autosuggest_inquisitor.css"],
)
]
if not formsemestre.etat: if not formsemestre.etat:
H.append( H.append(
f"""<p>{scu.icontag( f"""<p>{scu.icontag(
@ -136,7 +127,13 @@ def formsemestre_editwithmodules(formsemestre_id):
""" """
) )
return "\n".join(H) + html_sco_header.sco_footer() return render_template(
"sco_page.j2",
javascripts=["libjs/AutoSuggest.js", "js/formsemestre_edit.js"],
cssstyles=["css/autosuggest_inquisitor.css"],
title="Modification du semestre",
content="<h2>Modification du semestre</h2>" + "\n".join(H),
)
def can_edit_sem(formsemestre_id: int = None, sem=None): def can_edit_sem(formsemestre_id: int = None, sem=None):
@ -1162,12 +1159,9 @@ def formsemestre_clone(formsemestre_id):
} }
H = [ H = [
html_sco_header.html_sem_header( """<p class="help">Cette opération duplique un semestre:
"Copie du semestre", on reprend les mêmes modules et responsables.
javascripts=["libjs/AutoSuggest.js"], Aucun étudiant n'est inscrit.</p>""",
cssstyles=["css/autosuggest_inquisitor.css"],
),
"""<p class="help">Cette opération duplique un semestre: on reprend les mêmes modules et responsables. Aucun étudiant n'est inscrit.</p>""",
] ]
descr = [ descr = [
@ -1244,7 +1238,13 @@ def formsemestre_clone(formsemestre_id):
if ndb.DateDMYtoISO(tf[2]["date_debut"]) > ndb.DateDMYtoISO(tf[2]["date_fin"]): if ndb.DateDMYtoISO(tf[2]["date_debut"]) > ndb.DateDMYtoISO(tf[2]["date_fin"]):
msg = '<ul class="tf-msg"><li class="tf-msg">Dates de début et fin incompatibles !</li></ul>' msg = '<ul class="tf-msg"><li class="tf-msg">Dates de début et fin incompatibles !</li></ul>'
if tf[0] == 0 or msg: if tf[0] == 0 or msg:
return "".join(H) + msg + tf[1] + html_sco_header.sco_footer() return render_template(
"sco_page.j2",
javascripts=["libjs/AutoSuggest.js"],
cssstyles=["css/autosuggest_inquisitor.css"],
title="Copie du semestre",
content="".join(H) + msg + tf[1],
)
elif tf[0] == -1: # cancel elif tf[0] == -1: # cancel
return flask.redirect( return flask.redirect(
url_for( url_for(
@ -1388,8 +1388,8 @@ def formsemestre_delete(formsemestre_id: int) -> str | flask.Response:
"""Delete a formsemestre (affiche avertissements)""" """Delete a formsemestre (affiche avertissements)"""
formsemestre: FormSemestre = FormSemestre.get_formsemestre(formsemestre_id) formsemestre: FormSemestre = FormSemestre.get_formsemestre(formsemestre_id)
H = [ H = [
html_sco_header.html_sem_header("Suppression du semestre"), """<h2>Suppression du semestre</h2>
"""<div class="ue_warning"><span>Attention !</span> <div class="ue_warning"><span>Attention !</span>
<p class="help">A n'utiliser qu'en cas d'erreur lors de la saisie d'une formation. Normalement, <p class="help">A n'utiliser qu'en cas d'erreur lors de la saisie d'une formation. Normalement,
<b>un semestre ne doit jamais être supprimé</b> <b>un semestre ne doit jamais être supprimé</b>
(on perd la mémoire des notes et de tous les événements liés à ce semestre !). (on perd la mémoire des notes et de tous les événements liés à ce semestre !).
@ -1442,8 +1442,9 @@ Ceci n'est possible que si :
) )
else: else:
H.append(tf[1]) H.append(tf[1])
return render_template(
return "\n".join(H) + html_sco_header.sco_footer() "sco_page.j2", title="Suppression du semestre", content="\n".join(H)
)
if tf[0] == -1: # cancel if tf[0] == -1: # cancel
return flask.redirect( return flask.redirect(
@ -1743,7 +1744,6 @@ def formsemestre_edit_uecoefs(formsemestre_id, err_ue_id=None):
if not ok: if not ok:
return err return err
footer = html_sco_header.sco_footer()
help_msg = """<p class="help"> help_msg = """<p class="help">
Seuls les modules ont un coefficient. Cependant, il est nécessaire d'affecter un coefficient aux UE capitalisée pour pouvoir les prendre en compte dans la moyenne générale. Seuls les modules ont un coefficient. Cependant, il est nécessaire d'affecter un coefficient aux UE capitalisée pour pouvoir les prendre en compte dans la moyenne générale.
</p> </p>
@ -1766,7 +1766,6 @@ def formsemestre_edit_uecoefs(formsemestre_id, err_ue_id=None):
</p> </p>
""" """
H = [ H = [
html_sco_header.html_sem_header("Coefficients des UE du semestre"),
help_msg, help_msg,
] ]
# #
@ -1809,7 +1808,11 @@ def formsemestre_edit_uecoefs(formsemestre_id, err_ue_id=None):
initvalues=initvalues, initvalues=initvalues,
) )
if tf[0] == 0: if tf[0] == 0:
return "\n".join(H) + tf[1] + footer return render_template(
"sco_page.j2",
title="Coefficients des UE du semestre",
content="<h2>Coefficients des UE du semestre</h2>" + "\n".join(H) + tf[1],
)
elif tf[0] == -1: elif tf[0] == -1:
return redirect( return redirect(
url_for( url_for(
@ -1846,11 +1849,13 @@ def formsemestre_edit_uecoefs(formsemestre_id, err_ue_id=None):
) )
if not ok: if not ok:
return ( render_template(
"\n".join(H) "sco_page.j2",
title="Coefficients des UE du semestre",
content="<h2>Coefficients des UE du semestre</h2>"
+ "\n".join(H)
+ "<p><ul><li>%s</li></ul></p>" % "</li><li>".join(msg) + "<p><ul><li>%s</li></ul></p>" % "</li><li>".join(msg)
+ tf[1] + tf[1],
+ footer
) )
# apply modifications # apply modifications
@ -1873,20 +1878,25 @@ def formsemestre_edit_uecoefs(formsemestre_id, err_ue_id=None):
for ue in ue_deleted: for ue in ue_deleted:
message.append(f"<li>{ue.acronyme}</li>") message.append(f"<li>{ue.acronyme}</li>")
message.append("</ul>") message.append("</ul>")
sco_cache.invalidate_formsemestre(
formsemestre_id=formsemestre_id
) # > modif coef UE cap (modifs notes de _certains_ etudiants)
else: else:
message = ["""<h3>Aucune modification</h3>"""] message = ["""<h3>Aucune modification</h3>"""]
sco_cache.invalidate_formsemestre(
formsemestre_id=formsemestre_id
) # > modif coef UE cap (modifs notes de _certains_ etudiants)
return f"""{html_sco_header.html_sem_header("Coefficients des UE du semestre")} return render_template(
{" ".join(message)} "sco_page.j2",
<p><a class="stdlink" href="{url_for("notes.formsemestre_status", title="Coefficients des UE du semestre",
content=f"""
<h2>Coefficients des UE du semestre</h2>
{" ".join(message)}
<p><a class="stdlink" href="{url_for(
"notes.formsemestre_status",
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id) scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id)
}">Revenir au tableau de bord</a> }">Revenir au tableau de bord</a>
</p> </p>
{footer} """,
""" )
def _get_sem_ues_modimpls( def _get_sem_ues_modimpls(

View File

@ -31,7 +31,7 @@ import collections
import time import time
import flask import flask
from flask import flash, url_for, g, request from flask import flash, url_for, g, render_template, request
from app import db from app import db
from app.comp import res_sem from app.comp import res_sem
@ -428,12 +428,7 @@ def formsemestre_inscription_with_modules(
etud = Identite.get_etud(etudid) etud = Identite.get_etud(etudid)
if etud.dept_id != formsemestre.dept_id: if etud.dept_id != formsemestre.dept_id:
raise ScoValueError("l'étudiant n'est pas dans ce département") raise ScoValueError("l'étudiant n'est pas dans ce département")
H = [ H = []
html_sco_header.html_sem_header(
f"Inscription de {etud.nomprenom} dans ce semestre",
)
]
footer = html_sco_header.sco_footer()
# Check 1: déjà inscrit ici ? # Check 1: déjà inscrit ici ?
inscr = FormSemestreInscription.query.filter_by( inscr = FormSemestreInscription.query.filter_by(
etudid=etud.id, formsemestre_id=formsemestre.id etudid=etud.id, formsemestre_id=formsemestre.id
@ -456,7 +451,12 @@ def formsemestre_inscription_with_modules(
</ul> </ul>
""" """
) )
return "\n".join(H) + footer return render_template(
"sco_page.j2",
title=f"Inscription de {etud.nomprenom} dans ce semestre",
content=f"<h2>Inscription de {etud.nomprenom} dans ce semestre</h2>"
+ "\n".join(H),
)
# Check 2: déjà inscrit dans un semestre recouvrant les même dates ? # Check 2: déjà inscrit dans un semestre recouvrant les même dates ?
# Informe et propose dé-inscriptions # Informe et propose dé-inscriptions
others = est_inscrit_ailleurs(etudid, formsemestre_id) others = est_inscrit_ailleurs(etudid, formsemestre_id)
@ -494,7 +494,12 @@ def formsemestre_inscription_with_modules(
</p>""" </p>"""
# was sco_groups.make_query_groups(group_ids) # was sco_groups.make_query_groups(group_ids)
) )
return "\n".join(H) + footer return render_template(
"sco_page.j2",
title=f"Inscription de {etud.nomprenom} dans ce semestre",
content=f"<h2>Inscription de {etud.nomprenom} dans ce semestre</h2>"
+ "\n".join(H),
)
# #
if group_ids is not None: if group_ids is not None:
# OK, inscription # OK, inscription
@ -527,7 +532,12 @@ def formsemestre_inscription_with_modules(
</form> </form>
""" """
) )
return "\n".join(H) + footer return render_template(
"sco_page.j2",
title=f"Inscription de {etud.nomprenom} dans ce semestre",
content=f"<h2>Inscription de {etud.nomprenom} dans ce semestre</h2>"
+ "\n".join(H),
)
def formsemestre_inscription_option(etudid, formsemestre_id): def formsemestre_inscription_option(etudid, formsemestre_id):
@ -855,12 +865,7 @@ def formsemestre_inscrits_ailleurs(formsemestre_id):
"""Page listant les étudiants inscrits dans un autre semestre """Page listant les étudiants inscrits dans un autre semestre
dont les dates recouvrent le semestre indiqué. dont les dates recouvrent le semestre indiqué.
""" """
H = [ H = []
html_sco_header.html_sem_header(
"Inscriptions multiples parmi les étudiants du semestre ",
javascripts=["js/etud_info.js"],
)
]
insd = list_inscrits_ailleurs(formsemestre_id) insd = list_inscrits_ailleurs(formsemestre_id)
# liste ordonnée par nom # liste ordonnée par nom
etudlist = [Identite.get_etud(etudid) for etudid, sems in insd.items() if sems] etudlist = [Identite.get_etud(etudid) for etudid, sems in insd.items() if sems]
@ -912,4 +917,9 @@ def formsemestre_inscrits_ailleurs(formsemestre_id):
) )
else: else:
H.append("""<p>Aucun étudiant en inscription multiple (c'est normal) !</p>""") H.append("""<p>Aucun étudiant en inscription multiple (c'est normal) !</p>""")
return "\n".join(H) + html_sco_header.sco_footer() return render_template(
"sco_page.j2",
title="Inscriptions multiples parmi les étudiants du semestre",
content="<h2>Inscriptions multiples parmi les étudiants du semestre</h2>"
+ "\n".join(H),
)

View File

@ -741,9 +741,7 @@ def formsemestre_description_table(
columns_ids=columns_ids, columns_ids=columns_ids,
html_caption=title, html_caption=title,
html_class="table_leftalign formsemestre_description", html_class="table_leftalign formsemestre_description",
html_title=html_sco_header.html_sem_header( html_title="<h2>Description du semestre</h2>",
"Description du semestre", with_page_header=False
),
origin=f"Généré par {sco_version.SCONAME} le {scu.timedate_human_repr()}", origin=f"Généré par {sco_version.SCONAME} le {scu.timedate_human_repr()}",
page_title=title, page_title=title,
pdf_title=title, pdf_title=title,
@ -977,9 +975,6 @@ def formsemestre_status_head(formsemestre_id: int = None, page_title: str = None
page_title = page_title or "Modules de " page_title = page_title or "Modules de "
H = [ H = [
html_sco_header.html_sem_header(
page_title, with_page_header=False, with_h2=False
),
f"""<table> f"""<table>
<tr><td class="fichetitre2">Formation: </td><td> <tr><td class="fichetitre2">Formation: </td><td>
<a href="{url_for('notes.ue_table', <a href="{url_for('notes.ue_table',

View File

@ -30,8 +30,7 @@
import time import time
import flask import flask
from flask import url_for, flash, g, request from flask import flash, g, render_template, request, url_for
from flask.templating import render_template
import sqlalchemy as sa import sqlalchemy as sa
from app.models import Identite, Evaluation from app.models import Identite, Evaluation
@ -957,11 +956,13 @@ def form_decision_manuelle(Se, formsemestre_id, etudid, desturl="", sortcol=None
# ----------- # -----------
def formsemestre_validation_auto(formsemestre_id): def formsemestre_validation_auto(formsemestre_id: int):
"Formulaire saisie automatisee des decisions d'un semestre" "Formulaire saisie automatisée des décisions d'un semestre"
H = [ return render_template(
html_sco_header.html_sem_header("Saisie automatique des décisions du semestre"), "sco_page.j2",
f""" title="Saisie automatique des décisions",
content=f"""
<h2>Saisie automatique des décisions du semestre</h2>
<ul> <ul>
<li>Seuls les étudiants qui obtiennent le semestre seront affectés (code ADM, moyenne générale et <li>Seuls les étudiants qui obtiennent le semestre seront affectés (code ADM, moyenne générale et
toutes les barres, semestre précédent validé);</li> toutes les barres, semestre précédent validé);</li>
@ -978,9 +979,7 @@ def formsemestre_validation_auto(formsemestre_id):
<p><em>Le calcul prend quelques minutes, soyez patients !</em></p> <p><em>Le calcul prend quelques minutes, soyez patients !</em></p>
</form> </form>
""", """,
html_sco_header.sco_footer(), )
]
return "\n".join(H)
def do_formsemestre_validation_auto(formsemestre_id): def do_formsemestre_validation_auto(formsemestre_id):

View File

@ -57,14 +57,11 @@ from app.scodoc.sco_exceptions import ScoValueError, ScoPermissionDenied
from app.scodoc.sco_permissions import Permission from app.scodoc.sco_permissions import Permission
JAVASCRIPTS = html_sco_header.BOOTSTRAP_JS + [ JAVASCRIPTS = html_sco_header.BOOTSTRAP_JS + [
"js/etud_info.js",
"js/groups_view.js", "js/groups_view.js",
"js/multi-select.js", "js/multi-select.js",
] ]
CSSSTYLES = html_sco_header.BOOTSTRAP_CSS + [ CSSSTYLES = html_sco_header.BOOTSTRAP_CSS
"libjs/bootstrap/css/bootstrap.min.css",
]
# view: # view:
@ -615,8 +612,8 @@ def groups_table(
etud_info["_nom_disp_order"] = etud_sort_key(etud_info) etud_info["_nom_disp_order"] = etud_sort_key(etud_info)
etud_info["_prenom_target"] = fiche_url etud_info["_prenom_target"] = fiche_url
etud_info["_nom_disp_td_attrs"] = ( etud_info["_nom_disp_td_attrs"] = 'id="%s" class="etudinfo"' % (
'id="%s" class="etudinfo"' % (etud_info["etudid"]) etud_info["etudid"]
) )
etud_info["bourse_str"] = "oui" if etud_info["boursier"] else "non" etud_info["bourse_str"] = "oui" if etud_info["boursier"] else "non"
if etud_info["etat"] == "D": if etud_info["etat"] == "D":

View File

@ -36,8 +36,6 @@ from flask import url_for, g, request
import app.scodoc.notesdb as ndb import app.scodoc.notesdb as ndb
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
from app import db, log from app import db, log
from app.comp import res_sem
from app.comp.res_compat import NotesTableCompat
from app.models import Formation, FormSemestre, GroupDescr, Identite from app.models import Formation, FormSemestre, GroupDescr, Identite
from app.scodoc.gen_tables import GenTable from app.scodoc.gen_tables import GenTable
from app.scodoc import html_sco_header from app.scodoc import html_sco_header
@ -315,7 +313,6 @@ def formsemestre_inscr_passage(
H = [ H = [
html_sco_header.sco_header( html_sco_header.sco_header(
page_title="Passage des étudiants", page_title="Passage des étudiants",
javascripts=["js/etud_info.js"],
) )
] ]
footer = html_sco_header.sco_footer() footer = html_sco_header.sco_footer()
@ -487,10 +484,9 @@ def _build_page(
else: else:
ignore_jury_checked = "" ignore_jury_checked = ""
H = [ H = [
html_sco_header.html_sem_header( f"""
"Passages dans le semestre", with_page_header=False <h2 class="formsemestre">Passages dans le semestre</h2>
), <form name="f" method="post" action="{request.base_url}">
f"""<form name="f" method="post" action="{request.base_url}">
<input type="hidden" name="formsemestre_id" value="{formsemestre.id}"/> <input type="hidden" name="formsemestre_id" value="{formsemestre.id}"/>
@ -589,7 +585,7 @@ def formsemestre_inscr_passage_help(formsemestre: FormSemestre):
def etuds_select_boxes( def etuds_select_boxes(
auth_etuds_by_cat, auth_etuds_by_cat,
inscrits_ailleurs={}, inscrits_ailleurs: dict = None,
sel_inscrits=True, sel_inscrits=True,
show_empty_boxes=False, show_empty_boxes=False,
export_cat_xls=None, export_cat_xls=None,
@ -602,6 +598,7 @@ def etuds_select_boxes(
sel_inscrits= sel_inscrits=
export_cat_xls = export_cat_xls =
""" """
inscrits_ailleurs = inscrits_ailleurs or {}
if export_cat_xls: if export_cat_xls:
return etuds_select_box_xls(auth_etuds_by_cat[export_cat_xls]) return etuds_select_box_xls(auth_etuds_by_cat[export_cat_xls])
@ -633,7 +630,7 @@ def etuds_select_boxes(
for src_cat in auth_etuds_by_cat.keys(): for src_cat in auth_etuds_by_cat.keys():
infos = auth_etuds_by_cat[src_cat]["infos"] infos = auth_etuds_by_cat[src_cat]["infos"]
infos["comment"] = infos.get("comment", "") # commentaire dans sous-titre boite infos["comment"] = infos.get("comment", "") # commentaire dans sous-titre boite
help = infos.get("help", "") help_txt = infos.get("help", "")
etuds = auth_etuds_by_cat[src_cat]["etuds"] etuds = auth_etuds_by_cat[src_cat]["etuds"]
etuds.sort(key=itemgetter("nom")) etuds.sort(key=itemgetter("nom"))
with_checkbox = (not read_only) and auth_etuds_by_cat[src_cat]["infos"].get( with_checkbox = (not read_only) and auth_etuds_by_cat[src_cat]["infos"].get(
@ -650,8 +647,8 @@ def etuds_select_boxes(
<div class="pas_sembox_title"><a href="%(title_target)s" """ <div class="pas_sembox_title"><a href="%(title_target)s" """
% infos % infos
) )
if help: # bubble if help_txt: # bubble
H.append('title="%s"' % help) H.append('title="%s"' % help_txt)
H.append( H.append(
""">%(title)s</a></div> """>%(title)s</a></div>
<div class="pas_sembox_subtitle">(%(nbetuds)d étudiants%(comment)s)""" <div class="pas_sembox_subtitle">(%(nbetuds)d étudiants%(comment)s)"""

View File

@ -98,7 +98,7 @@ def scodoc_table_etuds_lycees(fmt="html"):
html_sco_header.sco_header( html_sco_header.sco_header(
page_title=tab.page_title, page_title=tab.page_title,
init_google_maps=True, init_google_maps=True,
javascripts=["js/etud_info.js", "js/map_lycees.js"], javascripts=["js/map_lycees.js"],
), ),
"""<h2 class="formsemestre">Lycées d'origine des %d étudiants (%d semestres)</h2>""" """<h2 class="formsemestre">Lycées d'origine des %d étudiants (%d semestres)</h2>"""
% (len(etuds), len(semdepts)), % (len(etuds), len(semdepts)),
@ -219,8 +219,7 @@ def formsemestre_etuds_lycees(
page_title=tab.page_title, page_title=tab.page_title,
init_google_maps=True, init_google_maps=True,
cssstyles=sco_groups_view.CSSSTYLES, cssstyles=sco_groups_view.CSSSTYLES,
javascripts=sco_groups_view.JAVASCRIPTS javascripts=sco_groups_view.JAVASCRIPTS + ["js/map_lycees.js"],
+ ["js/etud_info.js", "js/map_lycees.js"],
), ),
"""<h2 class="formsemestre">Lycées d'origine des étudiants</h2>""", """<h2 class="formsemestre">Lycées d'origine des étudiants</h2>""",
"\n".join(F), "\n".join(F),

View File

@ -31,7 +31,7 @@ import collections
from operator import attrgetter from operator import attrgetter
import flask import flask
from flask import url_for, g, request from flask import url_for, g, render_template, request
from flask_login import current_user from flask_login import current_user
from app import db, log from app import db, log
@ -46,7 +46,6 @@ from app.models import (
UniteEns, UniteEns,
Scolog, Scolog,
) )
from app.scodoc import html_sco_header
from app.scodoc import htmlutils from app.scodoc import htmlutils
from app.scodoc import sco_cache from app.scodoc import sco_cache
from app.scodoc import codes_cursus from app.scodoc import codes_cursus
@ -82,13 +81,8 @@ def moduleimpl_inscriptions_edit(
# -- check permission (and lock) # -- check permission (and lock)
if not modimpl.can_change_inscriptions(): if not modimpl.can_change_inscriptions():
return # can_change_inscriptions raises exception return # can_change_inscriptions raises exception
header = html_sco_header.sco_header(
page_title="Inscription au module",
javascripts=["js/etud_info.js"],
)
footer = html_sco_header.sco_footer()
H = [ H = [
header,
f"""<h2>Inscriptions au module <a class="stdlink" href="{ f"""<h2>Inscriptions au module <a class="stdlink" href="{
url_for("notes.moduleimpl_status", scodoc_dept=g.scodoc_dept, url_for("notes.moduleimpl_status", scodoc_dept=g.scodoc_dept,
moduleimpl_id=moduleimpl_id) moduleimpl_id=moduleimpl_id)
@ -216,8 +210,9 @@ def moduleimpl_inscriptions_edit(
) )
) )
# #
H.append(footer) return render_template(
return "\n".join(H) "sco_page.j2", title="Inscriptions au module", content="\n".join(H)
)
def _make_menu(partitions: list[dict], title="", check="true") -> str: def _make_menu(partitions: list[dict], title="", check="true") -> str:
@ -301,14 +296,12 @@ def moduleimpl_inscriptions_stats(formsemestre_id):
# Page HTML: # Page HTML:
H = [ H = [
html_sco_header.html_sem_header( f"""
"Inscriptions aux modules et UE du semestre", <h2 class="formsemestre">Inscriptions aux modules et UE du semestre</h2>
javascripts=["js/etud_info.js", "js/moduleimpl_inscriptions_stats.js"], <h3>Inscrits au semestre: {len(inscrits)} étudiants</h3>
) """
] ]
H.append(f"<h3>Inscrits au semestre: {len(inscrits)} étudiants</h3>")
if options: if options:
H.append("<h3>Modules auxquels tous les étudiants ne sont pas inscrits:</h3>") H.append("<h3>Modules auxquels tous les étudiants ne sont pas inscrits:</h3>")
H.append( H.append(
@ -495,8 +488,12 @@ def moduleimpl_inscriptions_stats(formsemestre_id):
""" """
) )
H.append(html_sco_header.sco_footer()) return render_template(
return "\n".join(H) "sco_page.j2",
title="Inscriptions aux modules et UE du semestre",
javascripts=["js/moduleimpl_inscriptions_stats.js"],
content="\n".join(H),
)
def _list_but_ue_inscriptions(res: NotesTableCompat, read_only: bool = True) -> str: def _list_but_ue_inscriptions(res: NotesTableCompat, read_only: bool = True) -> str:

View File

@ -47,7 +47,6 @@ from app.models import (
) )
from app.scodoc import ( from app.scodoc import (
codes_cursus, codes_cursus,
html_sco_header,
htmlutils, htmlutils,
sco_archives_etud, sco_archives_etud,
sco_bac, sco_bac,
@ -628,8 +627,10 @@ def fiche_etud(etudid=None):
</div> </div>
""" """
) )
header = html_sco_header.sco_header( return render_template(
page_title=f"Fiche étudiant {etud.nomprenom}", "sco_page.j2",
content=tmpl % info,
title=f"Fiche étudiant {etud.nomprenom}",
cssstyles=[ cssstyles=[
"libjs/jQuery-tagEditor/jquery.tag-editor.css", "libjs/jQuery-tagEditor/jquery.tag-editor.css",
"css/jury_but.css", "css/jury_but.css",
@ -644,7 +645,6 @@ def fiche_etud(etudid=None):
"js/etud_debouche.js", "js/etud_debouche.js",
], ],
) )
return header + tmpl % info + html_sco_header.sco_footer()
def _format_adresse(adresse: Adresse | None) -> dict: def _format_adresse(adresse: Adresse | None) -> dict:
@ -874,10 +874,6 @@ def etud_info_html(etudid, with_photo="1", debug=False):
H += "</div>" H += "</div>"
if debug: if debug:
return ( return render_template("sco_page.j2", title="debug", content=H)
html_sco_header.standard_html_header()
+ H return H
+ html_sco_header.standard_html_footer()
)
else:
return H

View File

@ -233,7 +233,6 @@ def formsemestre_poursuite_report(formsemestre_id, fmt="html"):
tab.base_url = "%s?formsemestre_id=%s" % (request.base_url, formsemestre_id) tab.base_url = "%s?formsemestre_id=%s" % (request.base_url, formsemestre_id)
return tab.make_page( return tab.make_page(
title="""<h2 class="formsemestre">Poursuite d'études</h2>""", title="""<h2 class="formsemestre">Poursuite d'études</h2>""",
javascripts=["js/etud_info.js"],
fmt=fmt, fmt=fmt,
with_html_headers=True, with_html_headers=True,
) )

View File

@ -112,7 +112,7 @@ get_base_preferences(formsemestre_id)
""" """
import flask import flask
from flask import current_app, flash, g, request, url_for from flask import current_app, flash, g, render_template, request, url_for
from app import db, log from app import db, log
from app.models import Departement from app.models import Departement
@ -2243,14 +2243,8 @@ class BasePreferences:
def edit(self): def edit(self):
"""HTML dialog: edit global preferences""" """HTML dialog: edit global preferences"""
from app.scodoc import html_sco_header
self.load() self.load()
H = [ H = [
html_sco_header.sco_header(
page_title=f"Préférences {g.scodoc_dept}",
javascripts=["js/detail_summary_persistence.js"],
),
f"<h2>Préférences globales pour le département {g.scodoc_dept}</h2>", f"<h2>Préférences globales pour le département {g.scodoc_dept}</h2>",
# f"""<p><a href="{url_for("scodoc.configure_logos", scodoc_dept=g.scodoc_dept) # f"""<p><a href="{url_for("scodoc.configure_logos", scodoc_dept=g.scodoc_dept)
# }">modification des logos du département (pour documents pdf)</a></p>""" # }">modification des logos du département (pour documents pdf)</a></p>"""
@ -2277,7 +2271,12 @@ class BasePreferences:
) )
dest_url = url_for("scolar.index_html", scodoc_dept=g.scodoc_dept) dest_url = url_for("scolar.index_html", scodoc_dept=g.scodoc_dept)
if tf[0] == 0: if tf[0] == 0:
return "\n".join(H) + tf[1] + html_sco_header.sco_footer() return render_template(
"sco_page_dept.j2",
content="\n".join(H) + tf[1],
title=f"Préférences {g.scodoc_dept}",
javascripts=["js/detail_summary_persistence.js"],
)
if tf[0] == -1: if tf[0] == -1:
return flask.redirect(dest_url) # cancel return flask.redirect(dest_url) # cancel
# #
@ -2384,18 +2383,11 @@ class SemPreferences:
# The dialog # The dialog
def edit(self, categories=[]): def edit(self, categories=[]):
"""Dialog to edit semestre preferences in given categories""" """Dialog to edit semestre preferences in given categories"""
from app.scodoc import html_sco_header
from app.scodoc import sco_formsemestre
if not self.formsemestre_id: if not self.formsemestre_id:
raise ScoValueError( raise ScoValueError(
"sem_preferences.edit doit etre appele sur un semestre !" "sem_preferences.edit doit etre appele sur un semestre !"
) # a bug ! ) # a bug !
H = [ H = [
html_sco_header.html_sem_header(
"Préférences du semestre",
javascripts=["js/detail_summary_persistence.js"],
),
""" """
<p class="help">Les paramètres définis ici ne s'appliqueront qu'à ce semestre.</p> <p class="help">Les paramètres définis ici ne s'appliqueront qu'à ce semestre.</p>
<p class="msg">Attention: cliquez sur "Enregistrer les modifications" en bas de page pour appliquer vos changements !</p> <p class="msg">Attention: cliquez sur "Enregistrer les modifications" en bas de page pour appliquer vos changements !</p>
@ -2456,7 +2448,12 @@ function set_global_pref(el, pref_name) {
) )
if tf[0] == 0: if tf[0] == 0:
return "\n".join(H) + tf[1] + html_sco_header.sco_footer() return render_template(
"sco_page.j2",
content="\n".join(H) + tf[1],
title="Préférences du semestre",
javascripts=["js/detail_summary_persistence.js"],
)
elif tf[0] == -1: elif tf[0] == -1:
flash("Annulé") flash("Annulé")
return flask.redirect(dest_url) return flask.redirect(dest_url)

View File

@ -35,8 +35,7 @@ from reportlab.platypus import Paragraph
from reportlab.lib import styles from reportlab.lib import styles
import flask import flask
from flask import flash, redirect, url_for from flask import flash, g, redirect, render_template, request, url_for
from flask import g, request
from app.models import FormSemestre, Identite from app.models import FormSemestre, Identite
@ -223,15 +222,13 @@ def formsemestre_pvjury(formsemestre_id, fmt="html", publish=True):
) )
) )
footer = html_sco_header.sco_footer()
dpv = sco_pv_dict.dict_pvjury(formsemestre_id, with_prev=True) dpv = sco_pv_dict.dict_pvjury(formsemestre_id, with_prev=True)
if not dpv: if not dpv:
if fmt == "html": if fmt == "html":
return ( return render_template(
html_sco_header.sco_header() "sco_page.j2",
+ "<h2>Aucune information disponible !</h2>" title="PV Jury",
+ footer content="<h2>Aucune information disponible !</h2>",
) )
else: else:
return None return None
@ -262,11 +259,10 @@ def formsemestre_pvjury(formsemestre_id, fmt="html", publish=True):
) )
tab.base_url = "%s?formsemestre_id=%s" % (request.base_url, formsemestre_id) tab.base_url = "%s?formsemestre_id=%s" % (request.base_url, formsemestre_id)
H = [ H = [
html_sco_header.html_sem_header( f"""
"Décisions du jury pour le semestre", <h2 class="formsemestre">Décisions du jury pour le semestre</h2>
javascripts=["js/etud_info.js"], <p>(dernière modif le {dpv["date"]})</p>
), """,
"""<p>(dernière modif le %s)</p>""" % dpv["date"],
] ]
H.append( H.append(
@ -333,7 +329,9 @@ def formsemestre_pvjury(formsemestre_id, fmt="html", publish=True):
""" """
) )
H.append("</div>") # /codes H.append("</div>") # /codes
return "\n".join(H) + footer return render_template(
"sco_page.j2", title="Décisions du jury pour le semestre", content="\n".join(H)
)
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
@ -351,9 +349,6 @@ def formsemestre_pvjury_pdf(formsemestre_id, group_ids: list[int] = None, etudid
if etudid: if etudid:
# PV pour ce seul étudiant: # PV pour ce seul étudiant:
etud = Identite.get_etud(etudid) etud = Identite.get_etud(etudid)
etuddescr = f"""<a class="discretelink" href="{
url_for("scolar.fiche_etud", scodoc_dept=g.scodoc_dept, etudid=etudid)
}">{etud.nomprenom}</a>"""
etudids = [etudid] etudids = [etudid]
else: else:
etuddescr = "" etuddescr = ""
@ -367,11 +362,6 @@ def formsemestre_pvjury_pdf(formsemestre_id, group_ids: list[int] = None, etudid
etudids = [m["etudid"] for m in groups_infos.members] etudids = [m["etudid"] for m in groups_infos.members]
H = [ H = [
html_sco_header.html_sem_header(
f"Édition du PV de jury {etuddescr}",
javascripts=sco_groups_view.JAVASCRIPTS,
cssstyles=sco_groups_view.CSSSTYLES,
),
f"""<div class="help">Utiliser cette page pour éditer des versions provisoires des PV. f"""<div class="help">Utiliser cette page pour éditer des versions provisoires des PV.
<span class="fontred">Il est recommandé d'archiver les versions définitives: <span class="fontred">Il est recommandé d'archiver les versions définitives:
<a class="stdlink" href="{url_for( <a class="stdlink" href="{url_for(
@ -384,7 +374,6 @@ def formsemestre_pvjury_pdf(formsemestre_id, group_ids: list[int] = None, etudid
"""<p><em>Voir aussi si besoin les réglages sur la page "Paramétrage" """<p><em>Voir aussi si besoin les réglages sur la page "Paramétrage"
(accessible à l'administrateur du département).</em> (accessible à l'administrateur du département).</em>
</p>""", </p>""",
html_sco_header.sco_footer(),
] ]
descr = descrform_pvjury(formsemestre) descr = descrform_pvjury(formsemestre)
if etudid: if etudid:
@ -409,7 +398,20 @@ def formsemestre_pvjury_pdf(formsemestre_id, group_ids: list[int] = None, etudid
html_foot_markup=menu_choix_groupe, html_foot_markup=menu_choix_groupe,
) )
if tf[0] == 0: if tf[0] == 0:
return "\n".join(H) + "\n" + tf[1] + "\n".join(F) return render_template(
"sco_page.j2",
title=f"Édition du PV de jury de {etud.nom_prenom()}",
content=f"""<h2 class="formsemestre">Édition du PV de jury
de <a class="discretelink" href="{
url_for("scolar.fiche_etud", scodoc_dept=g.scodoc_dept, etudid=etudid)
}">{etud.nomprenom}</a></h2>"""
+ "\n".join(H)
+ "\n"
+ tf[1]
+ "\n".join(F),
javascripts=sco_groups_view.JAVASCRIPTS,
cssstyles=sco_groups_view.CSSSTYLES,
)
elif tf[0] == -1: elif tf[0] == -1:
return flask.redirect( return flask.redirect(
url_for( url_for(
@ -541,7 +543,7 @@ def descrform_pvjury(formsemestre: FormSemestre):
] ]
def formsemestre_lettres_individuelles(formsemestre_id, group_ids=[]): def formsemestre_lettres_individuelles(formsemestre_id, group_ids=()):
"Lettres avis jury en PDF" "Lettres avis jury en PDF"
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id) formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id)
if not group_ids: if not group_ids:
@ -553,12 +555,9 @@ def formsemestre_lettres_individuelles(formsemestre_id, group_ids=[]):
etudids = [m["etudid"] for m in groups_infos.members] etudids = [m["etudid"] for m in groups_infos.members]
H = [ H = [
html_sco_header.html_sem_header( f"""
"Édition des lettres individuelles", <h2 class="formsemestre">Édition des lettres individuelles</h2>
javascripts=sco_groups_view.JAVASCRIPTS, <p class="help">Utiliser cette page pour éditer des versions provisoires des PV.
cssstyles=sco_groups_view.CSSSTYLES,
),
f"""<p class="help">Utiliser cette page pour éditer des versions provisoires des PV.
<span class="fontred">Il est recommandé d'archiver les versions définitives: <a <span class="fontred">Il est recommandé d'archiver les versions définitives: <a
href="{url_for( href="{url_for(
"notes.formsemestre_archive", "notes.formsemestre_archive",
@ -568,7 +567,6 @@ def formsemestre_lettres_individuelles(formsemestre_id, group_ids=[]):
>voir cette page</a></span></p> >voir cette page</a></span></p>
""", """,
] ]
F = html_sco_header.sco_footer()
descr = descrform_lettres_individuelles() descr = descrform_lettres_individuelles()
menu_choix_groupe = ( menu_choix_groupe = (
"""<div class="group_ids_sel_menu">Groupes d'étudiants à lister: """ """<div class="group_ids_sel_menu">Groupes d'étudiants à lister: """
@ -587,7 +585,13 @@ def formsemestre_lettres_individuelles(formsemestre_id, group_ids=[]):
html_foot_markup=menu_choix_groupe, html_foot_markup=menu_choix_groupe,
) )
if tf[0] == 0: if tf[0] == 0:
return "\n".join(H) + "\n" + tf[1] + F return render_template(
"sco_page.j2",
title="Édition des lettres individuelles",
content="\n".join(H) + "\n" + tf[1],
javascripts=sco_groups_view.JAVASCRIPTS,
cssstyles=sco_groups_view.CSSSTYLES,
)
elif tf[0] == -1: elif tf[0] == -1:
return flask.redirect( return flask.redirect(
url_for( url_for(

View File

@ -122,8 +122,8 @@ def formsemestre_recapcomplet(
html_sco_header.sco_header( html_sco_header.sco_header(
page_title=f"{formsemestre.sem_modalite()}: " page_title=f"{formsemestre.sem_modalite()}: "
+ ("jury" if mode_jury else "moyennes"), + ("jury" if mode_jury else "moyennes"),
no_side_bar=True, no_sidebar=True,
javascripts=["js/etud_info.js", "js/table_recap.js"], javascripts=["js/table_recap.js"],
), ),
sco_formsemestre_status.formsemestre_status_head( sco_formsemestre_status.formsemestre_status_head(
formsemestre_id=formsemestre_id formsemestre_id=formsemestre_id

View File

@ -1367,7 +1367,6 @@ def formsemestre_suivi_cursus(
H = [ H = [
html_sco_header.sco_header( html_sco_header.sco_header(
page_title=tab.page_title, page_title=tab.page_title,
javascripts=["js/etud_info.js"],
), ),
"""<h2 class="formsemestre">Cursus suivis par les étudiants de ce semestre</h2>""", """<h2 class="formsemestre">Cursus suivis par les étudiants de ce semestre</h2>""",
"\n".join(F), "\n".join(F),
@ -1747,7 +1746,7 @@ def formsemestre_graph_cursus(
cssstyles=sco_groups_view.CSSSTYLES, cssstyles=sco_groups_view.CSSSTYLES,
javascripts=sco_groups_view.JAVASCRIPTS, javascripts=sco_groups_view.JAVASCRIPTS,
page_title="Graphe cursus de %(titreannee)s" % sem, page_title="Graphe cursus de %(titreannee)s" % sem,
no_side_bar=True, no_sidebar=True,
), ),
"""<h2 class="formsemestre">Cursus des étudiants de ce semestre</h2>""", """<h2 class="formsemestre">Cursus des étudiants de ce semestre</h2>""",
doc, doc,

View File

@ -168,12 +168,7 @@ def formsemestre_synchro_etuds(
suffix=scu.XLSX_SUFFIX, suffix=scu.XLSX_SUFFIX,
) )
H = [ H = [html_sco_header.sco_header(page_title="Synchronisation étudiants")]
html_sco_header.sco_header(
page_title="Synchronisation étudiants",
javascripts=["js/etud_info.js"],
)
]
if not submitted: if not submitted:
H += _build_page( H += _build_page(
sem, sem,

View File

@ -54,14 +54,13 @@ Solution proposée (nov 2014):
""" """
import flask import flask
from flask import flash, g, request, url_for from flask import flash, g, request, render_template, url_for
from flask_login import current_user from flask_login import current_user
from app.models.formsemestre import FormSemestre from app.models.formsemestre import FormSemestre
from app import db, log from app import db, log
from app.models import Evaluation, Identite, ModuleImpl, UniteEns from app.models import Evaluation, Identite, ModuleImpl, UniteEns
from app.scodoc import html_sco_header
from app.scodoc import codes_cursus from app.scodoc import codes_cursus
from app.scodoc import sco_edit_matiere from app.scodoc import sco_edit_matiere
from app.scodoc import sco_edit_module from app.scodoc import sco_edit_module
@ -240,11 +239,9 @@ def external_ue_create_form(formsemestre_id: int, etudid: int):
existing_external_ue = get_existing_external_ue(formation_id) existing_external_ue = get_existing_external_ue(formation_id)
H = [ H = [
html_sco_header.html_sem_header( f"""
f"Ajout d'une UE externe pour {etud.nomprenom}", <h2 class="formsemestre">Ajout d'une UE externe pour {etud.nomprenom}</h2>
javascripts=["js/sco_ue_external.js"], <p class="help">Cette page permet d'indiquer que l'étudiant a suivi une UE
),
"""<p class="help">Cette page permet d'indiquer que l'étudiant a suivi une UE
dans un autre établissement et qu'elle doit être intégrée dans le semestre courant.<br> dans un autre établissement et qu'elle doit être intégrée dans le semestre courant.<br>
La note (/20) obtenue par l'étudiant doit toujours être spécifiée.</br> La note (/20) obtenue par l'étudiant doit toujours être spécifiée.</br>
On peut choisir une UE externe existante (dans le menu), ou bien en créer une, qui sera On peut choisir une UE externe existante (dans le menu), ou bien en créer une, qui sera
@ -252,7 +249,6 @@ def external_ue_create_form(formsemestre_id: int, etudid: int):
</p> </p>
""", """,
] ]
html_footer = html_sco_header.sco_footer()
parcours = formsemestre.formation.get_cursus() parcours = formsemestre.formation.get_cursus()
ue_types = [ ue_types = [
typ for typ in parcours.ALLOWED_UE_TYPES if typ != codes_cursus.UE_SPORT typ for typ in parcours.ALLOWED_UE_TYPES if typ != codes_cursus.UE_SPORT
@ -349,7 +345,12 @@ def external_ue_create_form(formsemestre_id: int, etudid: int):
etudid=etudid, etudid=etudid,
) )
if tf[0] == 0: if tf[0] == 0:
return "\n".join(H) + "\n" + tf[1] + html_footer return render_template(
"sco_page.j2",
title=f"Ajout d'une UE externe pour {etud.nomprenom}",
javascripts=["js/sco_ue_external.js"],
content="\n".join(H) + "\n" + tf[1],
)
elif tf[0] == -1: elif tf[0] == -1:
return flask.redirect(bull_url) return flask.redirect(bull_url)
else: else:
@ -358,12 +359,14 @@ def external_ue_create_form(formsemestre_id: int, etudid: int):
note, 20.0, etudid=etudid, absents=[], invalids=[] note, 20.0, etudid=etudid, absents=[], invalids=[]
) )
if invalid: if invalid:
return ( return render_template(
"\n".join(H) "sco_page.j2",
title=f"Ajout d'une UE externe pour {etud.nomprenom}",
javascripts=["js/sco_ue_external.js"],
content="\n".join(H)
+ "\n" + "\n"
+ tf_error_message("valeur note invalide") + tf_error_message("valeur note invalide")
+ tf[1] + tf[1],
+ html_footer
) )
if tf[2]["existing_ue"]: if tf[2]["existing_ue"]:
ue_id = int(tf[2]["existing_ue"]) ue_id = int(tf[2]["existing_ue"])
@ -371,12 +374,14 @@ def external_ue_create_form(formsemestre_id: int, etudid: int):
else: else:
acronyme = tf[2]["acronyme"].strip() acronyme = tf[2]["acronyme"].strip()
if not acronyme: if not acronyme:
return ( return render_template(
"\n".join(H) "sco_page.j2",
title=f"Ajout d'une UE externe pour {etud.nomprenom}",
javascripts=["js/sco_ue_external.js"],
content="\n".join(H)
+ "\n" + "\n"
+ tf_error_message("spécifier acronyme d'UE") + tf_error_message("spécifier acronyme d'UE")
+ tf[1] + tf[1],
+ html_footer
) )
modimpl = external_ue_create( modimpl = external_ue_create(
formsemestre_id, formsemestre_id,

View File

@ -31,7 +31,7 @@
# Anciennement ZScoUsers.py, fonctions de gestion des données réécrites avec flask/SQLAlchemy # Anciennement ZScoUsers.py, fonctions de gestion des données réécrites avec flask/SQLAlchemy
import re import re
from flask import url_for, g, request from flask import url_for, g, render_template, request
from flask_login import current_user from flask_login import current_user
@ -54,7 +54,7 @@ def index_html(
all_depts = int(all_depts) all_depts = int(all_depts)
with_inactives = int(with_inactives) with_inactives = int(with_inactives)
H = [html_sco_header.html_sem_header("Gestion des utilisateurs")] H = ["<h2>Gestion des utilisateurs</h2>"]
if current_user.has_permission(Permission.UsersAdmin, g.scodoc_dept): if current_user.has_permission(Permission.UsersAdmin, g.scodoc_dept):
H.append( H.append(
@ -112,6 +112,7 @@ def index_html(
raise ScoValueError("nom de rôle invalide") raise ScoValueError("nom de rôle invalide")
else: else:
having_role = None having_role = None
content = list_users( content = list_users(
g.scodoc_dept, g.scodoc_dept,
all_depts=all_depts, all_depts=all_depts,
@ -122,10 +123,12 @@ def index_html(
) )
if fmt != "html": if fmt != "html":
return content return content
H.append(content) H.append(content)
F = html_sco_header.sco_footer() return render_template(
return "\n".join(H) + F "sco_page.j2", content="\n".join(H), title="Gestion des utilisateurs"
)
def list_users( def list_users(

View File

@ -483,7 +483,7 @@ span.dept_cache {
color: rgb(194, 5, 5); color: rgb(194, 5, 5);
} }
div.table_etud_in_accessible_depts { div.table_etuds_in_accessible_depts {
margin-left: 3em; margin-left: 3em;
margin-bottom: 2em; margin-bottom: 2em;
} }
@ -686,11 +686,6 @@ div.scobox.news {
background-color: rgb(255, 235, 170); background-color: rgb(255, 235, 170);
} }
div.news a,
div.news a.stdlink {
color: black;
text-decoration: none;
}
div.news a:hover { div.news a:hover {
color: rgb(153, 51, 51); color: rgb(153, 51, 51);

View File

@ -21,9 +21,10 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
flex-grow: 1; flex-grow: 1;
font-family: Arial, Helvetica, sans-serif;
justify-content: left; justify-content: left;
white-space: nowrap; white-space: nowrap;
padding: 0 10px; padding: 0 0px;
/* Optional: Padding for some space around the text */ /* Optional: Padding for some space around the text */
} }

View File

@ -10,9 +10,16 @@
{%- endblock metas %} {%- endblock metas %}
{%- block styles %} {%- block styles %}
<link type="text/css" rel="stylesheet"
href="{{scu.STATIC_DIR}}/libjs/jquery-ui-1.10.4.custom/css/smoothness/jquery-ui-1.10.4.custom.min.css" />
<link type="text/css" rel="stylesheet"
href="{{scu.STATIC_DIR}}/libjs/timepicker-1.3.5/jquery.timepicker.min.css" />
<!-- Bootstrap --> <!-- Bootstrap -->
<link href="{{scu.STATIC_DIR}}/libjs/bootstrap/css/bootstrap.css" rel="stylesheet"> <link href="{{scu.STATIC_DIR}}/libjs/bootstrap/css/bootstrap.css" rel="stylesheet">
<link type="text/css" rel="stylesheet" href="{{scu.STATIC_DIR}}/libjs/bootstrap-multiselect-1.1.2/bootstrap-multiselect.min.css"> <link type="text/css" rel="stylesheet" href="{{scu.STATIC_DIR}}/libjs/bootstrap-multiselect-1.1.2/bootstrap-multiselect.min.css">
{% for css in cssstyles %}
<link rel="stylesheet" href="{{scu.STATIC_DIR}}/{{css}}">
{% endfor %}
{%- endblock styles %} {%- endblock styles %}
{%- endblock head %} {%- endblock head %}
</head> </head>

View File

@ -57,18 +57,17 @@
</ul> </ul>
</div> </div>
</div> </div>
</nav> </nav>
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<div class="container flashes">
{% include "flashed_messages.j2" %} {% include "flashed_messages.j2" %}
</div>
{# application content needs to be provided in the app_content block #} {# application content needs to be provided in the app_content block #}
<div class="container"> <div class="container">
{% block app_content %}{% endblock %} {% block app_content %}{{ content | safe }}{% endblock %}
</div> </div>
<script> <script>

View File

@ -1,10 +1,9 @@
{# Styles du menu #} {# Styles du menu #}
<style> <style>
/** /**
* Menu Formsemestre * Menu Formsemestre
* *
* @author Matthias HARTMANN (Iziram) * @author Matthias HARTMANN (Iziram)
* @license MIT
* Approche Mobile-first * Approche Mobile-first
*/ */
@ -33,7 +32,7 @@
border-top: var(--sco-formsemestre-color-accent) solid 3px; border-top: var(--sco-formsemestre-color-accent) solid 3px;
padding: 0 1rem; padding: 0 1rem;
border-radius: 4px; border-radius: 4px;
margin: 0 4px; margin: 0 0px;
} }
.sco-formsemestre-menu-container { .sco-formsemestre-menu-container {
@ -119,7 +118,7 @@
.sco-formsemestre-menu-menu>.dropdown>summary { .sco-formsemestre-menu-menu>.dropdown>summary {
text-transform: uppercase; text-transform: uppercase;
font-weight: bold; font-weight: bold;
font-size: 14px !important; font-size: 12px !important;
} }
.sco-formsemestre-menu-link { .sco-formsemestre-menu-link {
@ -179,6 +178,7 @@
} }
.sco-formsemestre-menu .dropdown { .sco-formsemestre-menu .dropdown {
padding-right: 16px;
position: relative; position: relative;
} }
@ -460,7 +460,7 @@
<button class="sco-formsemestre-menu-toggle" aria-label="Toggle menu"> <button class="sco-formsemestre-menu-toggle" aria-label="Toggle menu">
<span class="sco-formsemestre-menu-toggle-icon"></span> <span class="sco-formsemestre-menu-toggle-icon"></span>
</button> </button>
{# Menu #} {# Menu #}
<ul class="sco-formsemestre-menu-menu"> <ul class="sco-formsemestre-menu-menu">
{% for category, items in menu.items() %} {% for category, items in menu.items() %}

View File

@ -3,10 +3,6 @@
{% block styles %} {% block styles %}
{{super()}} {{super()}}
<link type="text/css" rel="stylesheet"
href="{{scu.STATIC_DIR}}/libjs/jquery-ui-1.10.4.custom/css/smoothness/jquery-ui-1.10.4.custom.min.css" />
<link type="text/css" rel="stylesheet"
href="{{scu.STATIC_DIR}}/libjs/timepicker-1.3.5/jquery.timepicker.min.css" />
<link rel="stylesheet" href="{{scu.STATIC_DIR}}/css/scodoc.css"> <link rel="stylesheet" href="{{scu.STATIC_DIR}}/css/scodoc.css">
<link rel="stylesheet" href="{{scu.STATIC_DIR}}/css/scodoc97.css"> <link rel="stylesheet" href="{{scu.STATIC_DIR}}/css/scodoc97.css">
<link href="{{scu.STATIC_DIR}}/css/menu.css" rel="stylesheet" type="text/css" /> <link href="{{scu.STATIC_DIR}}/css/menu.css" rel="stylesheet" type="text/css" />
@ -43,14 +39,18 @@
<img id="toggle-sidebar-img" src="{{scu.STATIC_DIR}}/icons/back.svg" width="12px" alt="toggle sidebar"/> <img id="toggle-sidebar-img" src="{{scu.STATIC_DIR}}/icons/back.svg" width="12px" alt="toggle sidebar"/>
</div> </div>
</div> </div>
<div class="formsemestre-page-header"> {% if sco.formsemestre %}
<div class="formsemestre-page-header">
{% include "flashed_messages.j2" %}
{% if sco.formsemestre %}
{% block formsemestre_header %}
{% include "formsemestre_header.j2" %}
{% endblock %}
{% endif %}
</div>
{% else %}
{% include "flashed_messages.j2" %} {% include "flashed_messages.j2" %}
{% if sco.formsemestre %} {% endif %}
{% block formsemestre_header %}
{% include "formsemestre_header.j2" %}
{% endblock %}
{% endif %}
</div>
<div id="sidebar"> <div id="sidebar">
{% include "sidebar.j2" %} {% include "sidebar.j2" %}
</div> </div>
@ -73,6 +73,7 @@
<script src="{{scu.STATIC_DIR}}/libjs/menu.js"></script> <script src="{{scu.STATIC_DIR}}/libjs/menu.js"></script>
<script src="{{scu.STATIC_DIR}}/libjs/bubble.js"></script> <script src="{{scu.STATIC_DIR}}/libjs/bubble.js"></script>
<script src="{{scu.STATIC_DIR}}/js/scodoc.js"></script> <script src="{{scu.STATIC_DIR}}/js/scodoc.js"></script>
<script src="{{scu.STATIC_DIR}}/js/etud_info.js"></script>
<script src="{{scu.STATIC_DIR}}/DataTables/datatables.min.js"></script> <script src="{{scu.STATIC_DIR}}/DataTables/datatables.min.js"></script>
<script> <script>
window.onload = function () { window.onload = function () {

View File

@ -45,8 +45,8 @@
{% if current_user.is_authenticated %} {% if current_user.is_authenticated %}
<form action="{{url_for('scodoc.table_etud_in_accessible_depts')}}" method="POST"> <form action="{{url_for('scodoc.table_etuds_in_accessible_depts')}}">
<b>Chercher étudiant:</b> <b>Chercher étudiant&nbsp;:</b>
<input type="text" name="expnom" width="12" spellcheck="false" value=""> <input type="text" name="expnom" width="12" spellcheck="false" value="">
<input type="submit" value="Chercher"> <input type="submit" value="Chercher">
<br />(entrer une partie du nom ou le code NIP, cherche dans tous les départements autorisés) <br />(entrer une partie du nom ou le code NIP, cherche dans tous les départements autorisés)

View File

@ -1,15 +1,32 @@
{# -*- mode: jinja-html -*- #} {# -*- mode: jinja-html -*- #}
{% extends "sco_page.j2" %}
{% if not is_edt_configured %} {% block title %}
<style> Partitions de {{ formsemestre.titre_annee() }}
span.calendarEdit { {% endblock title %}
display: none;
}
</style>
{% endif %}
{% block styles %}
{{ super() }}
<link rel="stylesheet" href="{{scu.STATIC_DIR}}/css/partition_editor.css">
{% if not is_edt_configured %}
<style>
span.calendarEdit {
display: none;
}
</style>
{% endif %}
{% endblock %}
{% block scripts %}
{{ super() }}
<script src="{{scu.STATIC_DIR}}/js/partition_editor.js"></script>
{% endblock %}
{% block app_content %}
<h1>{% if not read_only %}Édition des p{% else %}P{%endif%}artitions</h1> <h1>{% if not read_only %}Édition des p{% else %}P{%endif%}artitions</h1>
<h2></h2>
<main> <main>
<div class="wait"></div> <div class="wait"></div>
@ -1024,3 +1041,4 @@ span.calendarEdit {
} }
</script> </script>
{% endblock %}

View File

@ -246,7 +246,6 @@ def list_billets():
H = [ H = [
html_sco_header.sco_header( html_sco_header.sco_header(
page_title="Billet d'absence non traités", page_title="Billet d'absence non traités",
javascripts=["js/etud_info.js"],
), ),
f"<h2>Billets d'absence en attente de traitement ({table.get_nb_rows()})</h2>", f"<h2>Billets d'absence en attente de traitement ({table.get_nb_rows()})</h2>",
] ]

View File

@ -942,18 +942,12 @@ def edit_enseignants_form(moduleimpl_id):
"modif liste enseignants/moduleimpl" "modif liste enseignants/moduleimpl"
modimpl = ModuleImpl.get_modimpl(moduleimpl_id) modimpl = ModuleImpl.get_modimpl(moduleimpl_id)
modimpl.can_change_ens(raise_exc=True) modimpl.can_change_ens(raise_exc=True)
# -- #
header = html_sco_header.html_sem_header( page_title = f"Enseignants du module {modimpl.module.titre or modimpl.module.code}"
f"""Enseignants du <a href="{ title = f"""Enseignants du <a href="{
url_for("notes.moduleimpl_status", url_for("notes.moduleimpl_status",
scodoc_dept=g.scodoc_dept, moduleimpl_id=modimpl.id) scodoc_dept=g.scodoc_dept, moduleimpl_id=modimpl.id)
}">module {modimpl.module.titre or modimpl.module.code}</a>""", }">module {modimpl.module.titre or modimpl.module.code}</a>"""
page_title=f"Enseignants du module {modimpl.module.titre or modimpl.module.code}",
javascripts=["libjs/AutoSuggest.js"],
cssstyles=["css/autosuggest_inquisitor.css"],
)
footer = html_sco_header.sco_footer()
# Liste des enseignants avec forme pour affichage / saisie avec suggestion # Liste des enseignants avec forme pour affichage / saisie avec suggestion
userlist = sco_users.get_user_list() userlist = sco_users.get_user_list()
uid2display = {} # uid : forme pour affichage = "NOM Prenom (login)"(login)" uid2display = {} # uid : forme pour affichage = "NOM Prenom (login)"(login)"
@ -1021,7 +1015,13 @@ def edit_enseignants_form(moduleimpl_id):
cancelbutton="Annuler", cancelbutton="Annuler",
) )
if tf[0] == 0: if tf[0] == 0:
return header + "\n".join(H) + tf[1] + F + footer return render_template(
"sco_page.j2",
title=page_title,
content=title + "\n".join(H) + tf[1],
javascripts=["libjs/AutoSuggest.js"],
cssstyles=["css/autosuggest_inquisitor.css"],
)
elif tf[0] == -1: elif tf[0] == -1:
return flask.redirect( return flask.redirect(
url_for( url_for(
@ -1058,7 +1058,13 @@ def edit_enseignants_form(moduleimpl_id):
moduleimpl_id=moduleimpl_id, moduleimpl_id=moduleimpl_id,
) )
) )
return header + "\n".join(H) + tf[1] + F + footer return render_template(
"sco_page.j2",
title=page_title,
content=title + "\n".join(H) + tf[1],
javascripts=["libjs/AutoSuggest.js"],
cssstyles=["css/autosuggest_inquisitor.css"],
)
@bp.route("/edit_moduleimpl_resp", methods=["GET", "POST"]) @bp.route("/edit_moduleimpl_resp", methods=["GET", "POST"])
@ -1072,15 +1078,13 @@ def edit_moduleimpl_resp(moduleimpl_id: int):
modimpl: ModuleImpl = ModuleImpl.query.get_or_404(moduleimpl_id) modimpl: ModuleImpl = ModuleImpl.query.get_or_404(moduleimpl_id)
modimpl.can_change_responsable(current_user, raise_exc=True) # access control modimpl.can_change_responsable(current_user, raise_exc=True) # access control
H = [ H = [
html_sco_header.html_sem_header( f"""<h2 class="formsemestre">Modification du responsable du
f"""Modification du responsable du <a class="stdlink" href="{ <a class="stdlink" href="{
url_for("notes.moduleimpl_status", url_for("notes.moduleimpl_status",
scodoc_dept=g.scodoc_dept, moduleimpl_id=moduleimpl_id) scodoc_dept=g.scodoc_dept, moduleimpl_id=moduleimpl_id)
}">module {modimpl.module.titre or ""}</a>""", }">module {modimpl.module.titre or ""}</a></h2>"""
javascripts=["libjs/AutoSuggest.js"],
cssstyles=["css/autosuggest_inquisitor.css"],
)
] ]
help_str = """<p class="help">Taper le début du nom de l'enseignant.</p>""" help_str = """<p class="help">Taper le début du nom de l'enseignant.</p>"""
# Liste des enseignants avec forme pour affichage / saisie avec suggestion # Liste des enseignants avec forme pour affichage / saisie avec suggestion
userlist = [sco_users.user_info(user=u) for u in sco_users.get_user_list()] userlist = [sco_users.user_info(user=u) for u in sco_users.get_user_list()]
@ -1125,7 +1129,13 @@ def edit_moduleimpl_resp(moduleimpl_id: int):
initvalues=initvalues, initvalues=initvalues,
) )
if tf[0] == 0: if tf[0] == 0:
return "\n".join(H) + tf[1] + help_str + html_sco_header.sco_footer() return render_template(
"sco_page.j2",
content="\n".join(H) + tf[1] + help_str,
title="Modification responsable module",
javascripts=["libjs/AutoSuggest.js"],
cssstyles=["css/autosuggest_inquisitor.css"],
)
elif tf[0] == -1: elif tf[0] == -1:
return flask.redirect( return flask.redirect(
url_for( url_for(
@ -1198,21 +1208,13 @@ def view_module_abs(moduleimpl_id, fmt="html"):
} }
) )
H = [ content = f"""
html_sco_header.html_sem_header( <h2>Absences du <a href="{
f"""Absences du <a href="{ url_for("notes.moduleimpl_status",
url_for("notes.moduleimpl_status", scodoc_dept=g.scodoc_dept, moduleimpl_id=moduleimpl_id
scodoc_dept=g.scodoc_dept, moduleimpl_id=moduleimpl_id )}">module {modimpl.module.titre_str()}</a></h2>"""
)}">module {modimpl.module.titre_str()}</a>""",
page_title=f"Absences du module {modimpl.module.titre_str()}",
)
]
if not rows and fmt == "html": if not rows and fmt == "html":
return ( content += "<p>Aucune absence signalée</p>"
"\n".join(H)
+ "<p>Aucune absence signalée</p>"
+ html_sco_header.sco_footer()
)
tab = GenTable( tab = GenTable(
titles={ titles={
@ -1236,7 +1238,14 @@ def view_module_abs(moduleimpl_id, fmt="html"):
if fmt != "html": if fmt != "html":
return tab.make_page(fmt=fmt) return tab.make_page(fmt=fmt)
return "\n".join(H) + tab.html() + html_sco_header.sco_footer() if not tab.is_empty():
content += tab.html()
return render_template(
"sco_page.j2",
content=content,
title=f"Absences du module {modimpl.module.titre_str()}",
)
@bp.route("/delete_ue_expr/<int:formsemestre_id>/<int:ue_id>", methods=["GET", "POST"]) @bp.route("/delete_ue_expr/<int:formsemestre_id>/<int:ue_id>", methods=["GET", "POST"])
@ -1337,9 +1346,7 @@ def formsemestre_enseignants_list(formsemestre_id, fmt="html"):
html_class="table_leftalign formsemestre_enseignants_list", html_class="table_leftalign formsemestre_enseignants_list",
html_with_td_classes=True, html_with_td_classes=True,
filename=scu.make_filename(f"Enseignants-{formsemestre.titre_annee()}"), filename=scu.make_filename(f"Enseignants-{formsemestre.titre_annee()}"),
html_title=html_sco_header.html_sem_header( html_title="""<h2 class="formsemestre">Enseignants du semestre</h2>""",
"Enseignants du semestre", with_page_header=False
),
base_url=f"{request.base_url}?formsemestre_id={formsemestre_id}", base_url=f"{request.base_url}?formsemestre_id={formsemestre_id}",
caption="""Tous les enseignants (responsables ou associés aux modules de caption="""Tous les enseignants (responsables ou associés aux modules de
ce semestre) apparaissent. Le nombre de saisies d'absences est indicatif.""", ce semestre) apparaissent. Le nombre de saisies d'absences est indicatif.""",
@ -1646,7 +1653,6 @@ def evaluation_delete(evaluation_id):
etat = sco_evaluations.do_evaluation_etat(evaluation.id) etat = sco_evaluations.do_evaluation_etat(evaluation.id)
H = [ H = [
f""" f"""
{html_sco_header.html_sem_header(tit, with_h2=False)}
<h2 class="formsemestre">Module <tt>{evaluation.moduleimpl.module.code}</tt> <h2 class="formsemestre">Module <tt>{evaluation.moduleimpl.module.code}</tt>
{evaluation.moduleimpl.module.titre_str()}</h2> {evaluation.moduleimpl.module.titre_str()}</h2>
<h3>{tit}</h3> <h3>{tit}</h3>
@ -1682,7 +1688,7 @@ def evaluation_delete(evaluation_id):
</p> </p>
</div>""" </div>"""
) )
return "\n".join(H) + html_sco_header.sco_footer() return render_template("sco_page.j2", title=tit, content="\n".join(H))
if warning: if warning:
H.append("""</div>""") H.append("""</div>""")
@ -1695,7 +1701,7 @@ def evaluation_delete(evaluation_id):
cancelbutton="Annuler", cancelbutton="Annuler",
) )
if tf[0] == 0: if tf[0] == 0:
return "\n".join(H) + tf[1] + html_sco_header.sco_footer() return render_template("sco_page.j2", title=tit, content="\n".join(H) + tf[1])
elif tf[0] == -1: elif tf[0] == -1:
return flask.redirect( return flask.redirect(
url_for( url_for(
@ -1706,14 +1712,15 @@ def evaluation_delete(evaluation_id):
) )
else: else:
evaluation.delete() evaluation.delete()
return ( return render_template(
"\n".join(H) "sco_page.j2",
title=tit,
content="\n".join(H)
+ f"""<p>OK, évaluation supprimée.</p> + f"""<p>OK, évaluation supprimée.</p>
<p><a class="stdlink" href="{ <p><a class="stdlink" href="{
url_for("notes.moduleimpl_status", scodoc_dept=g.scodoc_dept, url_for("notes.moduleimpl_status", scodoc_dept=g.scodoc_dept,
moduleimpl_id=evaluation.moduleimpl_id) moduleimpl_id=evaluation.moduleimpl_id)
}">Continuer</a></p>""" }">Continuer</a></p>""",
+ html_sco_header.sco_footer()
) )
@ -1762,19 +1769,17 @@ def evaluation_listenotes():
raise ScoValueError("evaluation_listenotes: id invalides !") from exc raise ScoValueError("evaluation_listenotes: id invalides !") from exc
fmt = vals.get("fmt", "html") fmt = vals.get("fmt", "html")
html_content, page_title = sco_liste_notes.do_evaluation_listenotes( content, page_title = sco_liste_notes.do_evaluation_listenotes(
evaluation_id=evaluation_id, moduleimpl_id=moduleimpl_id, fmt=fmt evaluation_id=evaluation_id, moduleimpl_id=moduleimpl_id, fmt=fmt
) )
if fmt == "html": if fmt == "html":
H = html_sco_header.sco_header( return render_template(
page_title=page_title, "sco_page.j2",
content=content,
title=page_title,
cssstyles=["css/verticalhisto.css"], cssstyles=["css/verticalhisto.css"],
javascripts=["js/etud_info.js"],
) )
F = html_sco_header.sco_footer() return content
return H + html_content + F
else:
return html_content
sco_publish( sco_publish(

View File

@ -45,7 +45,6 @@ from flask import (
url_for, url_for,
) )
from flask import request from flask import request
import flask_login
from flask_login.utils import login_required, current_user from flask_login.utils import login_required, current_user
from PIL import Image as PILImage from PIL import Image as PILImage
@ -54,13 +53,9 @@ from werkzeug.exceptions import BadRequest, NotFound
from app import db, log from app import db, log
from app import entreprises from app import entreprises
from app.auth.models import User, Role from app.auth.models import Role
from app.auth.cas import set_cas_configuration from app.auth.cas import set_cas_configuration
from app.decorators import ( from app.decorators import admin_required
admin_required,
scodoc7func,
scodoc,
)
from app.forms.generic import SimpleConfirmationForm from app.forms.generic import SimpleConfirmationForm
from app.forms.main import config_logos, config_main from app.forms.main import config_logos, config_main
from app.forms.main.activate_entreprises import ActivateEntreprisesForm from app.forms.main.activate_entreprises import ActivateEntreprisesForm
@ -112,9 +107,9 @@ def index():
) )
# Renvoie les url /ScoDoc/RT/ vers /ScoDoc/RT/Scolarite @bp.route("/ScoDoc/<string:scodoc_dept>/")
@bp.route("/ScoDoc/<scodoc_dept>/") def index_dept(scodoc_dept: str):
def index_dept(scodoc_dept): "Renvoie les url /ScoDoc/RT/ vers /ScoDoc/RT/Scolarite"
return redirect(url_for("scolar.index_html", scodoc_dept=scodoc_dept)) return redirect(url_for("scolar.index_html", scodoc_dept=scodoc_dept))
@ -518,11 +513,14 @@ def activate_entreprises():
) )
@bp.route("/ScoDoc/table_etud_in_accessible_depts", methods=["POST"]) @bp.route("/ScoDoc/table_etuds_in_accessible_depts")
@login_required @login_required
def table_etud_in_accessible_depts(): def table_etuds_in_accessible_depts():
"""recherche étudiants sur plusieurs départements""" """recherche étudiants sur plusieurs départements"""
return sco_find_etud.table_etud_in_accessible_depts(expnom=request.form["expnom"]) expnom = request.args.get("expnom")
if not expnom:
raise ScoValueError("paramètre manquant: expnom")
return sco_find_etud.table_etuds_in_accessible_depts(expnom=expnom)
# Fonction d'API accessible sans aucun authentification # Fonction d'API accessible sans aucun authentification

View File

@ -944,27 +944,15 @@ def partition_editor(formsemestre_id: int, edit_partition=False):
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id) formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id)
edit_partition = bool(int(edit_partition)) if edit_partition else False edit_partition = bool(int(edit_partition)) if edit_partition else False
formsemestre.setup_parcours_groups() formsemestre.setup_parcours_groups()
H = [ return render_template(
html_sco_header.sco_header( "scolar/partition_editor.j2",
cssstyles=["css/partition_editor.css"], formsemestre=formsemestre,
javascripts=[ read_only=not formsemestre.can_change_groups(),
"js/partition_editor.js", edit_partition=edit_partition,
], is_edt_configured=sco_edt_cal.is_edt_configured(),
page_title=f"Partitions de {formsemestre.titre_annee()}", sco=ScoData(formsemestre=formsemestre),
), scu=scu,
"""<h2></h2>""", )
render_template(
"scolar/partition_editor.j2",
formsemestre=formsemestre,
read_only=not formsemestre.can_change_groups(),
edit_partition=edit_partition,
is_edt_configured=sco_edt_cal.is_edt_configured(),
scu=scu,
),
html_sco_header.sco_footer(),
]
return "\n".join(H)
@bp.route("/students_groups_auto_assignment", methods=["GET", "POST"]) @bp.route("/students_groups_auto_assignment", methods=["GET", "POST"])
@ -1973,14 +1961,15 @@ def check_group_apogee(group_id, etat=None, fix=False, fixmail=False):
etat = etat or None etat = etat or None
members, group, _, sem, _ = sco_groups.get_group_infos(group_id, etat=etat) members, group, _, sem, _ = sco_groups.get_group_infos(group_id, etat=etat)
formsemestre_id = group["formsemestre_id"] formsemestre_id = group["formsemestre_id"]
title = f"""Étudiants du {group["group_name"] or "semestre"}"""
cnx = ndb.GetDBConnexion() cnx = ndb.GetDBConnexion()
H = [ H = [
html_sco_header.html_sem_header( f"""<h2 class="formsemestre">{title}</h2>
"Étudiants du %s" % (group["group_name"] or "semestre") <table class="sortable" id="listegroupe">
), <tr>
'<table class="sortable" id="listegroupe">', <th>Nom</th><th>Nom usuel</th><th>Prénom</th><th>Mail</th>
"<tr><th>Nom</th><th>Nom usuel</th><th>Prénom</th><th>Mail</th><th>NIP (ScoDoc)</th><th>Apogée</th></tr>", <th>NIP (ScoDoc)</th><th>Apogée</th>
</tr>"""
] ]
nerrs = 0 # nombre d'anomalies détectées nerrs = 0 # nombre d'anomalies détectées
nfix = 0 # nb codes changes nfix = 0 # nb codes changes
@ -2102,8 +2091,7 @@ def check_group_apogee(group_id, etat=None, fix=False, fixmail=False):
formsemestre_id, formsemestre_id,
) )
) )
return render_template("sco_page.j2", title=title, content="\n".join(H))
return "\n".join(H) + html_sco_header.sco_footer()
@bp.route("/export_etudiants_courants") @bp.route("/export_etudiants_courants")
@ -2495,8 +2483,11 @@ def formsemestre_import_etud_admission(
diag += "</ul>" diag += "</ul>"
diag_by_sem[formsemestre.id] = diag diag_by_sem[formsemestre.id] = diag
return f""" return render_template(
{ html_sco_header.html_sem_header("Ré-import données admission") } "sco_page.j2",
title="Ré-import données admission",
content=f"""
<h2>-import données admission</h2>
<h3>Opération effectuée</h3> <h3>Opération effectuée</h3>
<p>Sur le(s) semestres(s):</p> <p>Sur le(s) semestres(s):</p>
<ul> <ul>
@ -2504,8 +2495,8 @@ def formsemestre_import_etud_admission(
{ '</li><li>'.join( [(s.html_link_status() + diag_by_sem[s.id]) for s in formsemestres ]) } { '</li><li>'.join( [(s.html_link_status() + diag_by_sem[s.id]) for s in formsemestres ]) }
</li> </li>
</ul> </ul>
{ html_sco_header.sco_footer() } """,
""" )
sco_publish( sco_publish(

View File

@ -221,12 +221,7 @@ def create_user_form(user_name=None, edit=0, all_roles=True):
initvalues = {} initvalues = {}
edit = int(edit) edit = int(edit)
all_roles = int(all_roles) all_roles = int(all_roles)
H = [ H = []
html_sco_header.sco_header(
javascripts=["js/user_form.js"],
)
]
F = html_sco_header.sco_footer()
the_user: User = None the_user: User = None
if edit: if edit:
if not user_name: if not user_name:
@ -603,7 +598,11 @@ def create_user_form(user_name=None, edit=0, all_roles=True):
cancelbutton="Annuler", cancelbutton="Annuler",
) )
if tf[0] == 0: if tf[0] == 0:
return "\n".join(H) + "\n" + tf[1] + F return render_template(
"base.j2",
content="\n".join(H) + "\n" + tf[1],
javascripts=["js/user_form.js"],
)
elif tf[0] == -1: elif tf[0] == -1:
return flask.redirect(url_for("users.index_html", scodoc_dept=g.scodoc_dept)) return flask.redirect(url_for("users.index_html", scodoc_dept=g.scodoc_dept))
else: else:
@ -645,7 +644,12 @@ def create_user_form(user_name=None, edit=0, all_roles=True):
err_msg = f"identifiant {user_name} déjà utilisé" err_msg = f"identifiant {user_name} déjà utilisé"
if err_msg: if err_msg:
H.append(tf_error_message(f"""Erreur: {err_msg}""")) H.append(tf_error_message(f"""Erreur: {err_msg}"""))
return "\n".join(H) + "\n" + tf[1] + F return render_template(
"base.j2",
content="\n".join(H) + "\n" + tf[1],
javascripts=["js/user_form.js"],
)
if not edit_only_roles: if not edit_only_roles:
ok_modif, msg = sco_users.check_modif_user( ok_modif, msg = sco_users.check_modif_user(
edit, edit,
@ -660,8 +664,11 @@ def create_user_form(user_name=None, edit=0, all_roles=True):
) )
if not ok_modif: if not ok_modif:
H.append(tf_error_message(msg)) H.append(tf_error_message(msg))
return "\n".join(H) + "\n" + tf[1] + F return render_template(
"base.j2",
content="\n".join(H) + "\n" + tf[1],
javascripts=["js/user_form.js"],
)
if "date_expiration" in vals: if "date_expiration" in vals:
try: try:
if vals["date_expiration"]: if vals["date_expiration"]:
@ -670,12 +677,20 @@ def create_user_form(user_name=None, edit=0, all_roles=True):
) )
if vals["date_expiration"] < datetime.datetime.now(): if vals["date_expiration"] < datetime.datetime.now():
H.append(tf_error_message("date expiration passée")) H.append(tf_error_message("date expiration passée"))
return "\n".join(H) + "\n" + tf[1] + F return render_template(
"base.j2",
content="\n".join(H) + "\n" + tf[1],
javascripts=["js/user_form.js"],
)
else: else:
vals["date_expiration"] = None vals["date_expiration"] = None
except ValueError: except ValueError:
H.append(tf_error_message("date expiration invalide")) H.append(tf_error_message("date expiration invalide"))
return "\n".join(H) + "\n" + tf[1] + F return render_template(
"base.j2",
content="\n".join(H) + "\n" + tf[1],
javascripts=["js/user_form.js"],
)
if edit: # modif utilisateur (mais pas password ni user_name !) if edit: # modif utilisateur (mais pas password ni user_name !)
if (not can_choose_dept) and "dept" in vals: if (not can_choose_dept) and "dept" in vals:
@ -727,7 +742,11 @@ def create_user_form(user_name=None, edit=0, all_roles=True):
msg = tf_error_message( msg = tf_error_message(
"identifiant invalide (pas d'accents ni de caractères spéciaux)" "identifiant invalide (pas d'accents ni de caractères spéciaux)"
) )
return "\n".join(H) + msg + "\n" + tf[1] + F return render_template(
"base.j2",
content="\n".join(H) + msg + "\n" + tf[1],
javascripts=["js/user_form.js"],
)
# Traitement initial (mode) : 3 cas # Traitement initial (mode) : 3 cas
# cf énumération Mode # cf énumération Mode
# A: envoi de welcome + procedure de reset # A: envoi de welcome + procedure de reset
@ -754,12 +773,20 @@ def create_user_form(user_name=None, edit=0, all_roles=True):
msg = tf_error_message( msg = tf_error_message(
"""Les deux mots de passes ne correspondent pas !""" """Les deux mots de passes ne correspondent pas !"""
) )
return "\n".join(H) + msg + "\n" + tf[1] + F return render_template(
"base.j2",
content="\n".join(H) + msg + "\n" + tf[1],
javascripts=["js/user_form.js"],
)
if not is_valid_password(vals["password"]): if not is_valid_password(vals["password"]):
msg = tf_error_message( msg = tf_error_message(
"""Mot de passe trop simple, recommencez !""" """Mot de passe trop simple, recommencez !"""
) )
return "\n".join(H) + msg + "\n" + tf[1] + F return render_template(
"base.j2",
content="\n".join(H) + msg + "\n" + tf[1],
javascripts=["js/user_form.js"],
)
# Département: # Département:
if not can_choose_dept: if not can_choose_dept:
vals["dept"] = auth_dept vals["dept"] = auth_dept
@ -1000,13 +1027,12 @@ def form_change_password(user_name=None):
# check access # check access
if not can_handle_passwd(user): if not can_handle_passwd(user):
return "\n".join( return render_template(
[ "base.j2",
html_sco_header.sco_header(), content="<p>Vous n'avez pas la permission de changer ce mot de passe</p>",
"<p>Vous n'avez pas la permission de changer ce mot de passe</p>", title="Accès refusé",
html_sco_header.sco_footer(),
]
) )
form = ChangePasswordForm(user_name=user.user_name, email=user.email) form = ChangePasswordForm(user_name=user.user_name, email=user.email)
destination = url_for( destination = url_for(
"users.user_info_page", "users.user_info_page",