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,
)
return tab.make_page(fmt=fmt, javascripts=["js/etud_info.js"])
return tab.make_page(fmt=fmt)
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_logos import find_logo
JAVASCRIPTS = html_sco_header.BOOTSTRAP_JS + []
CSSSTYLES = html_sco_header.BOOTSTRAP_CSS
JAVASCRIPTS = html_sco_header.BOOTSTRAP_JS
# class ItemForm(FlaskForm):
# """Unused Generic class to document common behavior for classes

View File

@ -271,10 +271,10 @@ class ScolarNews(db.Model):
return ""
dept_news_url = url_for("scolar.dept_news", scodoc_dept=g.scodoc_dept)
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
}">Dernières opérations</a>
</div><ul class="newslist">"""
</div><ul class="newslist" desktop="true">"""
]
for news in news_list:
@ -289,11 +289,18 @@ class ScolarNews(db.Model):
</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
H.append(
f"""<div>
f"""<div desktop="true">
Pour en savoir plus sur ScoDoc voir
<a class="stdlink" href="{scu.SCO_ANNONCES_WEBSITE}">scodoc.org</a>
</div>

View File

@ -57,7 +57,6 @@ from reportlab.lib.units import cm
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_excel
from app.scodoc import sco_pdf

View File

@ -134,7 +134,7 @@ def scodoc_top_html_header(page_title="ScoDoc: bienvenue"):
def sco_header(
# optional args
page_title="", # page title
no_side_bar=False, # hide sidebar
no_sidebar=False, # hide sidebar
cssstyles=(), # additionals CSS sheets
javascripts=(), # additionals JS filenames to load
scripts=(), # script to put in page header
@ -154,13 +154,13 @@ def sco_header(
params = {
"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),
"encoding": scu.SCO_ENCODING,
"titrebandeau_mkup": "<td>" + titrebandeau + "</td>",
"authuser": current_user.user_name,
}
if no_side_bar:
if no_sidebar:
params["margin_left"] = "1em"
else:
params["margin_left"] = "140px"
@ -217,7 +217,7 @@ def sco_header(
<!-- Legacy ScoDoc header -->
<body>
{scu.CUSTOM_HTML_HEADER}
{'' if no_side_bar else html_sidebar.sidebar(etudid)}
{'' if no_sidebar else html_sidebar.sidebar(etudid)}
<div id="gtrcontent">
"""
)
@ -242,18 +242,3 @@ def sco_footer():
+ scu.CUSTOM_HTML_FOOTER
+ """</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_archives
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 import html_sco_header
from app.scodoc import sco_etud
class EtudsArchiver(sco_archives.BaseArchiver):
@ -142,9 +140,6 @@ def etud_upload_file_form(etudid):
etud = Identite.get_etud(etudid)
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>
<p>Le fichier ne doit pas dépasser {
@ -171,8 +166,12 @@ def etud_upload_file_form(etudid):
cancelbutton="Annuler",
)
if tf[0] == 0:
return "\n".join(H) + tf[1] + html_sco_header.sco_footer()
elif tf[0] == -1:
return render_template(
"sco_page.j2",
title=f"Chargement d'un document associé à {etud.nomprenom}",
content="\n".join(H) + tf[1],
)
if tf[0] == -1:
return flask.redirect(etud.url_fiche())
data = tf[2]["datafile"].read()
descr = tf[2]["description"]
@ -263,9 +262,6 @@ def etudarchive_generate_excel_sample(group_id=None):
def etudarchive_import_files_form(group_id):
"""Formulaire pour importation fichiers d'un groupe"""
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>
<p>Les fichiers associés (dossiers d'admission, certificats, ...), de
types quelconques (pdf, doc, images) sont accessibles aux utilisateurs via
@ -292,7 +288,6 @@ def etudarchive_import_files_form(group_id):
"""
% group_id,
]
F = html_sco_header.sco_footer()
tf = TrivialFormulator(
request.base_url,
scu.get_request_args(),
@ -313,7 +308,11 @@ def etudarchive_import_files_form(group_id):
)
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:
group = sco_groups.get_group(group_id)
if tf[0] == -1:

View File

@ -27,7 +27,7 @@
import json
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.but import jury_but_pv
@ -127,7 +127,7 @@ def do_formsemestre_archive(
[
html_sco_header.sco_header(
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>',
"""<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 = [
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
les documents résultant de ce semestre: PV de jury, lettres individuelles,
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,
)
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:
msg = "Opération annulée"
else:
@ -371,7 +376,7 @@ def formsemestre_list_archives(formsemestre_id):
}
archives_descr.append(a)
H = [html_sco_header.html_sem_header("Archive des PV et résultats ")]
H = []
if not archives_descr:
H.append("<p>aucune archive enregistrée</p>")
else:
@ -399,7 +404,9 @@ def formsemestre_list_archives(formsemestre_id):
H.append("</ul></li>")
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):

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}"
return tab.make_page(
title="""<h2 class="formsemestre">Débouchés étudiants </h2>""",
javascripts=["js/etud_info.js"],
fmt=fmt,
with_html_headers=True,
)

View File

@ -25,9 +25,7 @@
#
##############################################################################
"""Ajout/Modification/Suppression UE
"""
"""Ajout/Modification/Suppression UE"""
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é)"
)
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}
</h2>
""",
@ -1069,8 +1053,22 @@ du programme" (menu "Semestre") si vous avez un semestre en cours);
warn, _ = sco_formsemestre_validation.check_formation_ues(formation)
H.append(warn)
H.append(html_sco_header.sco_footer())
return "".join(H)
return render_template(
"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):
@ -1130,7 +1128,9 @@ def _ue_table_ues(
scodoc_dept=g.scodoc_dept,
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']}"
data-placeholder="{scu.APO_MISSING_CODE_STR}">{
ue["code_apogee"] or ""

View File

@ -597,7 +597,6 @@ def _view_etuds_page(
return f"""
{html_sco_header.sco_header(
page_title=title,
javascripts=["js/etud_info.js"],
)}
<h2>{title}</h2>
@ -750,7 +749,6 @@ def view_apo_csv(etape_apo="", semset_id="", fmt="html"):
H = [
html_sco_header.sco_header(
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>
<p>Pour l'ensemble <a class="stdlink" href="{

View File

@ -27,7 +27,7 @@
"""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 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_evaluation_db
from app.scodoc import sco_groups
from app.views import ScoData
def evaluation_check_absences(evaluation: Evaluation):
@ -109,8 +110,10 @@ def evaluation_check_absences(evaluation: Evaluation):
def evaluation_check_absences_html(
evaluation: Evaluation, with_header=True, show_ok=True
):
"""Affiche état vérification absences d'une évaluation"""
) -> str:
"""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
abs_non_signalee, # note ABS alors que pas signalé abs
@ -121,10 +124,6 @@ def evaluation_check_absences_html(
if with_header:
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),
"""<p class="help">Vérification de la cohérence entre les notes saisies
et les absences signalées.</p>""",
@ -208,19 +207,19 @@ def evaluation_check_absences_html(
etudlist(abs_but_exc)
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)
def formsemestre_check_absences_html(formsemestre_id):
"""Affiche etat verification absences pour toutes les evaluations du semestre !"""
formsemestre: FormSemestre = FormSemestre.query.filter_by(
dept_id=g.scodoc_dept_id, id=formsemestre_id
).first_or_404()
def formsemestre_check_absences_html(formsemestre_id: int):
"""Affiche état vérification absences pour toutes les évaluations du semestre."""
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
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
et les absences signalées.
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(html_sco_header.sco_footer())
return "\n".join(H)
return render_template(
"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.
"""
import time
from flask import g, url_for
from flask import g, render_template, url_for
from app import db
from app.models import Evaluation, FormSemestre
@ -23,7 +23,7 @@ import app.scodoc.sco_utils as scu
def evaluations_recap(formsemestre_id: int) -> str:
"""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)
column_ids = titles.keys()
filename = scu.sanitize_filename(
@ -32,11 +32,14 @@ def evaluations_recap(formsemestre_id: int) -> str:
if not rows:
return '<div class="evaluations_recap"><div class="message">aucune évaluation</div></div>'
H = [
html_sco_header.sco_header(
page_title="Évaluations du semestre",
javascripts=["js/evaluations_recap.js"],
),
f"""<div class="evaluations_recap"><table class="evaluations_recap compact {
f"""<h2>Évaluations du semestre</h2>
<div>
<a class="stdlink" href="{url_for(
'notes.formsemestre_check_absences_html',
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'
}"
data-filename="{filename}">""",
@ -56,13 +59,19 @@ def evaluations_recap(formsemestre_id: int) -> str:
H.append(
"""</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(
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]:

View File

@ -31,9 +31,7 @@ import collections
import datetime
import operator
from flask import url_for
from flask import g
from flask import request
from flask import g, render_template, request, url_for
from flask_login import current_user
from app import db
@ -45,8 +43,6 @@ from app.models import Evaluation, FormSemestre, ModuleImpl, Module
import app.scodoc.sco_utils as scu
from app.scodoc.sco_utils import ModuleType
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_formsemestre_inscriptions
from app.scodoc import sco_groups
@ -470,7 +466,7 @@ class CalendrierEval(sco_gen_cal.Calendrier):
# View
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)
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
@ -481,13 +477,12 @@ def formsemestre_evaluations_cal(formsemestre_id):
cal = CalendrierEval(year, evaluations, nt)
cal_html = cal.get_html()
return f"""
{
html_sco_header.html_sem_header(
"Evaluations du semestre",
cssstyles=["css/calabs.css"],
)
}
return render_template(
"sco_page.j2",
cssstyles=["css/calabs.css"],
title="Évaluations du semestre",
content=f"""
<h2>Évaluations du semestre</h2>
<div class="cal_evaluations">
{ cal_html }
</div>
@ -513,8 +508,8 @@ def formsemestre_evaluations_cal(formsemestre_id):
)
}" class="stdlink">voir les délais de correction</a>
</p>
{ html_sco_header.sco_footer() }
"""
""",
)
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
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
responsable: User = db.session.get(User, modimpl.responsable_id)
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]
# 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:
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
@ -285,8 +287,7 @@ def scodoc_table_results(
H = [
html_sco_header.sco_header(
page_title="Export résultats",
javascripts=html_sco_header.BOOTSTRAP_JS
+ ["js/etud_info.js", "js/export_results.js"],
javascripts=html_sco_header.BOOTSTRAP_JS + ["js/export_results.js"],
cssstyles=html_sco_header.BOOTSTRAP_CSS,
),
# XXX

View File

@ -28,7 +28,7 @@
"""Recherche d'étudiants
"""
import flask
from flask import url_for, g, request
from flask import url_for, g, render_template, request
from flask_login import current_user
import sqlalchemy as sa
@ -177,13 +177,7 @@ def search_etud_in_dept(expnom=""):
url_args["etudid"] = etuds[0].id
return flask.redirect(url_for(endpoint, **url_args))
H = [
html_sco_header.sco_header(
page_title="Recherche d'un étudiant",
no_side_bar=False,
javascripts=["js/etud_info.js"],
)
]
H = []
if len(etuds) == 0 and len(etuds) <= 1:
H.append("""<h2>chercher un étudiant:</h2>""")
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
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]:
@ -313,7 +309,7 @@ def search_etud_by_name(term: str) -> list:
# ---------- Recherche sur plusieurs département
def search_etud_in_accessible_depts(
def search_etuds_in_accessible_depts(
expnom=None,
) -> tuple[list[list[Identite]], list[str]]:
"""
@ -334,14 +330,14 @@ def search_etud_in_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.
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 = [
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>
""",
]
@ -366,7 +362,7 @@ def table_etud_in_accessible_depts(expnom=None):
rows=rows,
html_sortable=True,
html_class="table_leftalign",
# table_id="etud_in_accessible_depts",
table_id="etuds_in_accessible_depts",
)
H.append('<div class="table_etud_in_dept">')
@ -386,8 +382,10 @@ def table_etud_in_accessible_depts(expnom=None):
</div>
"""
)
return (
html_sco_header.scodoc_top_html_header(page_title="Choix d'un étudiant")
+ "\n".join(H)
+ html_sco_header.standard_html_footer()
return render_template(
"base.j2",
title="Choix d'un étudiant",
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
"""
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 app.models.config import ScoDocSiteConfig, PersonalizedLink
@ -37,9 +37,6 @@ import app.scodoc.sco_utils as scu
import app.scodoc.notesdb as ndb
from app.scodoc.TrivialFormulator import TrivialFormulator
from app.scodoc import html_sco_header
from app.scodoc import htmlutils
from app.scodoc import sco_formsemestre
from app.scodoc import sco_edt_cal
_custommenuEditor = ndb.EditableTable(
"notes_formsemestre_custommenu",
@ -106,14 +103,13 @@ def formsemestre_custommenu_html(formsemestre_id):
def formsemestre_custommenu_edit(formsemestre_id):
"""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(
"notes.formsemestre_status",
scodoc_dept=g.scodoc_dept,
formsemestre_id=formsemestre_id,
)
H = [
html_sco_header.html_sem_header("Modification du menu du semestre "),
"""<div class="help">
<p>Ce menu, spécifique à chaque semestre, peut être utilisé pour
placer des liens vers vos applications préférées.
@ -164,7 +160,14 @@ def formsemestre_custommenu_edit(formsemestre_id):
name="tf",
)
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:
return flask.redirect(dest_url)
else:

View File

@ -28,8 +28,7 @@
"""Form choix modules / responsables et creation formsemestre
"""
import flask
from flask import url_for, flash, redirect
from flask import g, request
from flask import flash, g, request, redirect, render_template, url_for
from flask_login import current_user
import sqlalchemy as sa
@ -97,18 +96,10 @@ def formsemestre_createwithmodules():
return "\n".join(H) + html_sco_header.sco_footer()
def formsemestre_editwithmodules(formsemestre_id):
def formsemestre_editwithmodules(formsemestre_id: int):
"""Page modification semestre"""
formsemestre: FormSemestre = FormSemestre.query.filter_by(
id=formsemestre_id, dept_id=g.scodoc_dept_id
).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"],
)
]
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
H = []
if not formsemestre.etat:
H.append(
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):
@ -1162,12 +1159,9 @@ def formsemestre_clone(formsemestre_id):
}
H = [
html_sco_header.html_sem_header(
"Copie du semestre",
javascripts=["libjs/AutoSuggest.js"],
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>""",
"""<p class="help">Cette opération duplique un semestre:
on reprend les mêmes modules et responsables.
Aucun étudiant n'est inscrit.</p>""",
]
descr = [
@ -1244,7 +1238,13 @@ def formsemestre_clone(formsemestre_id):
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>'
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
return flask.redirect(
url_for(
@ -1388,8 +1388,8 @@ def formsemestre_delete(formsemestre_id: int) -> str | flask.Response:
"""Delete a formsemestre (affiche avertissements)"""
formsemestre: FormSemestre = FormSemestre.get_formsemestre(formsemestre_id)
H = [
html_sco_header.html_sem_header("Suppression du semestre"),
"""<div class="ue_warning"><span>Attention !</span>
"""<h2>Suppression du semestre</h2>
<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,
<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 !).
@ -1442,8 +1442,9 @@ Ceci n'est possible que si :
)
else:
H.append(tf[1])
return "\n".join(H) + html_sco_header.sco_footer()
return render_template(
"sco_page.j2", title="Suppression du semestre", content="\n".join(H)
)
if tf[0] == -1: # cancel
return flask.redirect(
@ -1743,7 +1744,6 @@ def formsemestre_edit_uecoefs(formsemestre_id, err_ue_id=None):
if not ok:
return err
footer = html_sco_header.sco_footer()
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.
</p>
@ -1766,7 +1766,6 @@ def formsemestre_edit_uecoefs(formsemestre_id, err_ue_id=None):
</p>
"""
H = [
html_sco_header.html_sem_header("Coefficients des UE du semestre"),
help_msg,
]
#
@ -1809,7 +1808,11 @@ def formsemestre_edit_uecoefs(formsemestre_id, err_ue_id=None):
initvalues=initvalues,
)
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:
return redirect(
url_for(
@ -1846,11 +1849,13 @@ def formsemestre_edit_uecoefs(formsemestre_id, err_ue_id=None):
)
if not ok:
return (
"\n".join(H)
render_template(
"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)
+ tf[1]
+ footer
+ tf[1],
)
# apply modifications
@ -1873,20 +1878,25 @@ def formsemestre_edit_uecoefs(formsemestre_id, err_ue_id=None):
for ue in ue_deleted:
message.append(f"<li>{ue.acronyme}</li>")
message.append("</ul>")
sco_cache.invalidate_formsemestre(
formsemestre_id=formsemestre_id
) # > modif coef UE cap (modifs notes de _certains_ etudiants)
else:
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")}
{" ".join(message)}
<p><a class="stdlink" href="{url_for("notes.formsemestre_status",
return render_template(
"sco_page.j2",
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)
}">Revenir au tableau de bord</a>
</p>
{footer}
"""
""",
)
def _get_sem_ues_modimpls(

View File

@ -31,7 +31,7 @@ import collections
import time
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.comp import res_sem
@ -428,12 +428,7 @@ def formsemestre_inscription_with_modules(
etud = Identite.get_etud(etudid)
if etud.dept_id != formsemestre.dept_id:
raise ScoValueError("l'étudiant n'est pas dans ce département")
H = [
html_sco_header.html_sem_header(
f"Inscription de {etud.nomprenom} dans ce semestre",
)
]
footer = html_sco_header.sco_footer()
H = []
# Check 1: déjà inscrit ici ?
inscr = FormSemestreInscription.query.filter_by(
etudid=etud.id, formsemestre_id=formsemestre.id
@ -456,7 +451,12 @@ def formsemestre_inscription_with_modules(
</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 ?
# Informe et propose dé-inscriptions
others = est_inscrit_ailleurs(etudid, formsemestre_id)
@ -494,7 +494,12 @@ def formsemestre_inscription_with_modules(
</p>"""
# 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:
# OK, inscription
@ -527,7 +532,12 @@ def formsemestre_inscription_with_modules(
</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):
@ -855,12 +865,7 @@ def formsemestre_inscrits_ailleurs(formsemestre_id):
"""Page listant les étudiants inscrits dans un autre semestre
dont les dates recouvrent le semestre indiqué.
"""
H = [
html_sco_header.html_sem_header(
"Inscriptions multiples parmi les étudiants du semestre ",
javascripts=["js/etud_info.js"],
)
]
H = []
insd = list_inscrits_ailleurs(formsemestre_id)
# liste ordonnée par nom
etudlist = [Identite.get_etud(etudid) for etudid, sems in insd.items() if sems]
@ -912,4 +917,9 @@ def formsemestre_inscrits_ailleurs(formsemestre_id):
)
else:
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,
html_caption=title,
html_class="table_leftalign formsemestre_description",
html_title=html_sco_header.html_sem_header(
"Description du semestre", with_page_header=False
),
html_title="<h2>Description du semestre</h2>",
origin=f"Généré par {sco_version.SCONAME} le {scu.timedate_human_repr()}",
page_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 "
H = [
html_sco_header.html_sem_header(
page_title, with_page_header=False, with_h2=False
),
f"""<table>
<tr><td class="fichetitre2">Formation: </td><td>
<a href="{url_for('notes.ue_table',

View File

@ -30,8 +30,7 @@
import time
import flask
from flask import url_for, flash, g, request
from flask.templating import render_template
from flask import flash, g, render_template, request, url_for
import sqlalchemy as sa
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):
"Formulaire saisie automatisee des decisions d'un semestre"
H = [
html_sco_header.html_sem_header("Saisie automatique des décisions du semestre"),
f"""
def formsemestre_validation_auto(formsemestre_id: int):
"Formulaire saisie automatisée des décisions d'un semestre"
return render_template(
"sco_page.j2",
title="Saisie automatique des décisions",
content=f"""
<h2>Saisie automatique des décisions du semestre</h2>
<ul>
<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>
@ -978,9 +979,7 @@ def formsemestre_validation_auto(formsemestre_id):
<p><em>Le calcul prend quelques minutes, soyez patients !</em></p>
</form>
""",
html_sco_header.sco_footer(),
]
return "\n".join(H)
)
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
JAVASCRIPTS = html_sco_header.BOOTSTRAP_JS + [
"js/etud_info.js",
"js/groups_view.js",
"js/multi-select.js",
]
CSSSTYLES = html_sco_header.BOOTSTRAP_CSS + [
"libjs/bootstrap/css/bootstrap.min.css",
]
CSSSTYLES = html_sco_header.BOOTSTRAP_CSS
# view:
@ -615,8 +612,8 @@ def groups_table(
etud_info["_nom_disp_order"] = etud_sort_key(etud_info)
etud_info["_prenom_target"] = fiche_url
etud_info["_nom_disp_td_attrs"] = (
'id="%s" class="etudinfo"' % (etud_info["etudid"])
etud_info["_nom_disp_td_attrs"] = 'id="%s" class="etudinfo"' % (
etud_info["etudid"]
)
etud_info["bourse_str"] = "oui" if etud_info["boursier"] else "non"
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.sco_utils as scu
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.scodoc.gen_tables import GenTable
from app.scodoc import html_sco_header
@ -315,7 +313,6 @@ def formsemestre_inscr_passage(
H = [
html_sco_header.sco_header(
page_title="Passage des étudiants",
javascripts=["js/etud_info.js"],
)
]
footer = html_sco_header.sco_footer()
@ -487,10 +484,9 @@ def _build_page(
else:
ignore_jury_checked = ""
H = [
html_sco_header.html_sem_header(
"Passages dans le semestre", with_page_header=False
),
f"""<form name="f" method="post" action="{request.base_url}">
f"""
<h2 class="formsemestre">Passages dans le semestre</h2>
<form name="f" method="post" action="{request.base_url}">
<input type="hidden" name="formsemestre_id" value="{formsemestre.id}"/>
@ -589,7 +585,7 @@ def formsemestre_inscr_passage_help(formsemestre: FormSemestre):
def etuds_select_boxes(
auth_etuds_by_cat,
inscrits_ailleurs={},
inscrits_ailleurs: dict = None,
sel_inscrits=True,
show_empty_boxes=False,
export_cat_xls=None,
@ -602,6 +598,7 @@ def etuds_select_boxes(
sel_inscrits=
export_cat_xls =
"""
inscrits_ailleurs = inscrits_ailleurs or {}
if 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():
infos = auth_etuds_by_cat[src_cat]["infos"]
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.sort(key=itemgetter("nom"))
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" """
% infos
)
if help: # bubble
H.append('title="%s"' % help)
if help_txt: # bubble
H.append('title="%s"' % help_txt)
H.append(
""">%(title)s</a></div>
<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(
page_title=tab.page_title,
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>"""
% (len(etuds), len(semdepts)),
@ -219,8 +219,7 @@ def formsemestre_etuds_lycees(
page_title=tab.page_title,
init_google_maps=True,
cssstyles=sco_groups_view.CSSSTYLES,
javascripts=sco_groups_view.JAVASCRIPTS
+ ["js/etud_info.js", "js/map_lycees.js"],
javascripts=sco_groups_view.JAVASCRIPTS + ["js/map_lycees.js"],
),
"""<h2 class="formsemestre">Lycées d'origine des étudiants</h2>""",
"\n".join(F),

View File

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

View File

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

View File

@ -112,7 +112,7 @@ get_base_preferences(formsemestre_id)
"""
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.models import Departement
@ -2243,14 +2243,8 @@ class BasePreferences:
def edit(self):
"""HTML dialog: edit global preferences"""
from app.scodoc import html_sco_header
self.load()
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"""<p><a href="{url_for("scodoc.configure_logos", scodoc_dept=g.scodoc_dept)
# }">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)
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:
return flask.redirect(dest_url) # cancel
#
@ -2384,18 +2383,11 @@ class SemPreferences:
# The dialog
def edit(self, 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:
raise ScoValueError(
"sem_preferences.edit doit etre appele sur un semestre !"
) # a bug !
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="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:
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:
flash("Annulé")
return flask.redirect(dest_url)

View File

@ -35,8 +35,7 @@ from reportlab.platypus import Paragraph
from reportlab.lib import styles
import flask
from flask import flash, redirect, url_for
from flask import g, request
from flask import flash, g, redirect, render_template, request, url_for
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)
if not dpv:
if fmt == "html":
return (
html_sco_header.sco_header()
+ "<h2>Aucune information disponible !</h2>"
+ footer
return render_template(
"sco_page.j2",
title="PV Jury",
content="<h2>Aucune information disponible !</h2>",
)
else:
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)
H = [
html_sco_header.html_sem_header(
"Décisions du jury pour le semestre",
javascripts=["js/etud_info.js"],
),
"""<p>(dernière modif le %s)</p>""" % dpv["date"],
f"""
<h2 class="formsemestre">Décisions du jury pour le semestre</h2>
<p>(dernière modif le {dpv["date"]})</p>
""",
]
H.append(
@ -333,7 +329,9 @@ def formsemestre_pvjury(formsemestre_id, fmt="html", publish=True):
"""
)
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:
# PV pour ce seul étudiant:
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]
else:
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]
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.
<span class="fontred">Il est recommandé d'archiver les versions définitives:
<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"
(accessible à l'administrateur du département).</em>
</p>""",
html_sco_header.sco_footer(),
]
descr = descrform_pvjury(formsemestre)
if etudid:
@ -409,7 +398,20 @@ def formsemestre_pvjury_pdf(formsemestre_id, group_ids: list[int] = None, etudid
html_foot_markup=menu_choix_groupe,
)
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:
return flask.redirect(
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"
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id)
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]
H = [
html_sco_header.html_sem_header(
"Édition des lettres individuelles",
javascripts=sco_groups_view.JAVASCRIPTS,
cssstyles=sco_groups_view.CSSSTYLES,
),
f"""<p class="help">Utiliser cette page pour éditer des versions provisoires des PV.
f"""
<h2 class="formsemestre">Édition des lettres individuelles</h2>
<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
href="{url_for(
"notes.formsemestre_archive",
@ -568,7 +567,6 @@ def formsemestre_lettres_individuelles(formsemestre_id, group_ids=[]):
>voir cette page</a></span></p>
""",
]
F = html_sco_header.sco_footer()
descr = descrform_lettres_individuelles()
menu_choix_groupe = (
"""<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,
)
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:
return flask.redirect(
url_for(

View File

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

View File

@ -1367,7 +1367,6 @@ def formsemestre_suivi_cursus(
H = [
html_sco_header.sco_header(
page_title=tab.page_title,
javascripts=["js/etud_info.js"],
),
"""<h2 class="formsemestre">Cursus suivis par les étudiants de ce semestre</h2>""",
"\n".join(F),
@ -1747,7 +1746,7 @@ def formsemestre_graph_cursus(
cssstyles=sco_groups_view.CSSSTYLES,
javascripts=sco_groups_view.JAVASCRIPTS,
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>""",
doc,

View File

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

View File

@ -54,14 +54,13 @@ Solution proposée (nov 2014):
"""
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 app.models.formsemestre import FormSemestre
from app import db, log
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 sco_edit_matiere
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)
H = [
html_sco_header.html_sem_header(
f"Ajout d'une UE externe pour {etud.nomprenom}",
javascripts=["js/sco_ue_external.js"],
),
"""<p class="help">Cette page permet d'indiquer que l'étudiant a suivi une UE
f"""
<h2 class="formsemestre">Ajout d'une UE externe pour {etud.nomprenom}</h2>
<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>
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
@ -252,7 +249,6 @@ def external_ue_create_form(formsemestre_id: int, etudid: int):
</p>
""",
]
html_footer = html_sco_header.sco_footer()
parcours = formsemestre.formation.get_cursus()
ue_types = [
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,
)
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:
return flask.redirect(bull_url)
else:
@ -358,12 +359,14 @@ def external_ue_create_form(formsemestre_id: int, etudid: int):
note, 20.0, etudid=etudid, absents=[], invalids=[]
)
if invalid:
return (
"\n".join(H)
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_error_message("valeur note invalide")
+ tf[1]
+ html_footer
+ tf[1],
)
if 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:
acronyme = tf[2]["acronyme"].strip()
if not acronyme:
return (
"\n".join(H)
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_error_message("spécifier acronyme d'UE")
+ tf[1]
+ html_footer
+ tf[1],
)
modimpl = external_ue_create(
formsemestre_id,

View File

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

View File

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

View File

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

View File

@ -10,9 +10,16 @@
{%- endblock metas %}
{%- 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 -->
<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">
{% for css in cssstyles %}
<link rel="stylesheet" href="{{scu.STATIC_DIR}}/{{css}}">
{% endfor %}
{%- endblock styles %}
{%- endblock head %}
</head>

View File

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

View File

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

View File

@ -3,10 +3,6 @@
{% block styles %}
{{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/scodoc97.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"/>
</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" %}
{% if sco.formsemestre %}
{% block formsemestre_header %}
{% include "formsemestre_header.j2" %}
{% endblock %}
{% endif %}
</div>
{% endif %}
<div id="sidebar">
{% include "sidebar.j2" %}
</div>
@ -73,6 +73,7 @@
<script src="{{scu.STATIC_DIR}}/libjs/menu.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/etud_info.js"></script>
<script src="{{scu.STATIC_DIR}}/DataTables/datatables.min.js"></script>
<script>
window.onload = function () {

View File

@ -45,8 +45,8 @@
{% if current_user.is_authenticated %}
<form action="{{url_for('scodoc.table_etud_in_accessible_depts')}}" method="POST">
<b>Chercher étudiant:</b>
<form action="{{url_for('scodoc.table_etuds_in_accessible_depts')}}">
<b>Chercher étudiant&nbsp;:</b>
<input type="text" name="expnom" width="12" spellcheck="false" value="">
<input type="submit" value="Chercher">
<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 -*- #}
{% extends "sco_page.j2" %}
{% if not is_edt_configured %}
<style>
span.calendarEdit {
display: none;
}
</style>
{% endif %}
{% block title %}
Partitions de {{ formsemestre.titre_annee() }}
{% endblock title %}
{% 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>
<h2></h2>
<main>
<div class="wait"></div>
@ -1024,3 +1041,4 @@ span.calendarEdit {
}
</script>
{% endblock %}

View File

@ -246,7 +246,6 @@ def list_billets():
H = [
html_sco_header.sco_header(
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>",
]

View File

@ -942,18 +942,12 @@ def edit_enseignants_form(moduleimpl_id):
"modif liste enseignants/moduleimpl"
modimpl = ModuleImpl.get_modimpl(moduleimpl_id)
modimpl.can_change_ens(raise_exc=True)
# --
header = html_sco_header.html_sem_header(
f"""Enseignants du <a href="{
#
page_title = f"Enseignants du module {modimpl.module.titre or modimpl.module.code}"
title = f"""Enseignants du <a href="{
url_for("notes.moduleimpl_status",
scodoc_dept=g.scodoc_dept, moduleimpl_id=modimpl.id)
}">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()
}">module {modimpl.module.titre or modimpl.module.code}</a>"""
# Liste des enseignants avec forme pour affichage / saisie avec suggestion
userlist = sco_users.get_user_list()
uid2display = {} # uid : forme pour affichage = "NOM Prenom (login)"(login)"
@ -1021,7 +1015,13 @@ def edit_enseignants_form(moduleimpl_id):
cancelbutton="Annuler",
)
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:
return flask.redirect(
url_for(
@ -1058,7 +1058,13 @@ def edit_enseignants_form(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"])
@ -1072,15 +1078,13 @@ def edit_moduleimpl_resp(moduleimpl_id: int):
modimpl: ModuleImpl = ModuleImpl.query.get_or_404(moduleimpl_id)
modimpl.can_change_responsable(current_user, raise_exc=True) # access control
H = [
html_sco_header.html_sem_header(
f"""Modification du responsable du <a class="stdlink" href="{
f"""<h2 class="formsemestre">Modification du responsable du
<a class="stdlink" href="{
url_for("notes.moduleimpl_status",
scodoc_dept=g.scodoc_dept, moduleimpl_id=moduleimpl_id)
}">module {modimpl.module.titre or ""}</a>""",
javascripts=["libjs/AutoSuggest.js"],
cssstyles=["css/autosuggest_inquisitor.css"],
)
}">module {modimpl.module.titre or ""}</a></h2>"""
]
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
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,
)
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:
return flask.redirect(
url_for(
@ -1198,21 +1208,13 @@ def view_module_abs(moduleimpl_id, fmt="html"):
}
)
H = [
html_sco_header.html_sem_header(
f"""Absences du <a href="{
url_for("notes.moduleimpl_status",
scodoc_dept=g.scodoc_dept, moduleimpl_id=moduleimpl_id
)}">module {modimpl.module.titre_str()}</a>""",
page_title=f"Absences du module {modimpl.module.titre_str()}",
)
]
content = f"""
<h2>Absences du <a href="{
url_for("notes.moduleimpl_status",
scodoc_dept=g.scodoc_dept, moduleimpl_id=moduleimpl_id
)}">module {modimpl.module.titre_str()}</a></h2>"""
if not rows and fmt == "html":
return (
"\n".join(H)
+ "<p>Aucune absence signalée</p>"
+ html_sco_header.sco_footer()
)
content += "<p>Aucune absence signalée</p>"
tab = GenTable(
titles={
@ -1236,7 +1238,14 @@ def view_module_abs(moduleimpl_id, fmt="html"):
if fmt != "html":
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"])
@ -1337,9 +1346,7 @@ def formsemestre_enseignants_list(formsemestre_id, fmt="html"):
html_class="table_leftalign formsemestre_enseignants_list",
html_with_td_classes=True,
filename=scu.make_filename(f"Enseignants-{formsemestre.titre_annee()}"),
html_title=html_sco_header.html_sem_header(
"Enseignants du semestre", with_page_header=False
),
html_title="""<h2 class="formsemestre">Enseignants du semestre</h2>""",
base_url=f"{request.base_url}?formsemestre_id={formsemestre_id}",
caption="""Tous les enseignants (responsables ou associés aux modules de
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)
H = [
f"""
{html_sco_header.html_sem_header(tit, with_h2=False)}
<h2 class="formsemestre">Module <tt>{evaluation.moduleimpl.module.code}</tt>
{evaluation.moduleimpl.module.titre_str()}</h2>
<h3>{tit}</h3>
@ -1682,7 +1688,7 @@ def evaluation_delete(evaluation_id):
</p>
</div>"""
)
return "\n".join(H) + html_sco_header.sco_footer()
return render_template("sco_page.j2", title=tit, content="\n".join(H))
if warning:
H.append("""</div>""")
@ -1695,7 +1701,7 @@ def evaluation_delete(evaluation_id):
cancelbutton="Annuler",
)
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:
return flask.redirect(
url_for(
@ -1706,14 +1712,15 @@ def evaluation_delete(evaluation_id):
)
else:
evaluation.delete()
return (
"\n".join(H)
return render_template(
"sco_page.j2",
title=tit,
content="\n".join(H)
+ f"""<p>OK, évaluation supprimée.</p>
<p><a class="stdlink" href="{
url_for("notes.moduleimpl_status", scodoc_dept=g.scodoc_dept,
moduleimpl_id=evaluation.moduleimpl_id)
}">Continuer</a></p>"""
+ html_sco_header.sco_footer()
}">Continuer</a></p>""",
)
@ -1762,19 +1769,17 @@ def evaluation_listenotes():
raise ScoValueError("evaluation_listenotes: id invalides !") from exc
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
)
if fmt == "html":
H = html_sco_header.sco_header(
page_title=page_title,
return render_template(
"sco_page.j2",
content=content,
title=page_title,
cssstyles=["css/verticalhisto.css"],
javascripts=["js/etud_info.js"],
)
F = html_sco_header.sco_footer()
return H + html_content + F
else:
return html_content
return content
sco_publish(

View File

@ -45,7 +45,6 @@ from flask import (
url_for,
)
from flask import request
import flask_login
from flask_login.utils import login_required, current_user
from PIL import Image as PILImage
@ -54,13 +53,9 @@ from werkzeug.exceptions import BadRequest, NotFound
from app import db, log
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.decorators import (
admin_required,
scodoc7func,
scodoc,
)
from app.decorators import admin_required
from app.forms.generic import SimpleConfirmationForm
from app.forms.main import config_logos, config_main
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/<scodoc_dept>/")
def index_dept(scodoc_dept):
@bp.route("/ScoDoc/<string:scodoc_dept>/")
def index_dept(scodoc_dept: str):
"Renvoie les url /ScoDoc/RT/ vers /ScoDoc/RT/Scolarite"
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
def table_etud_in_accessible_depts():
def table_etuds_in_accessible_depts():
"""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

View File

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

View File

@ -221,12 +221,7 @@ def create_user_form(user_name=None, edit=0, all_roles=True):
initvalues = {}
edit = int(edit)
all_roles = int(all_roles)
H = [
html_sco_header.sco_header(
javascripts=["js/user_form.js"],
)
]
F = html_sco_header.sco_footer()
H = []
the_user: User = None
if edit:
if not user_name:
@ -603,7 +598,11 @@ def create_user_form(user_name=None, edit=0, all_roles=True):
cancelbutton="Annuler",
)
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:
return flask.redirect(url_for("users.index_html", scodoc_dept=g.scodoc_dept))
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é"
if 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:
ok_modif, msg = sco_users.check_modif_user(
edit,
@ -660,8 +664,11 @@ def create_user_form(user_name=None, edit=0, all_roles=True):
)
if not ok_modif:
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:
try:
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():
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:
vals["date_expiration"] = None
except ValueError:
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 (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(
"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
# cf énumération Mode
# 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(
"""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"]):
msg = tf_error_message(
"""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:
if not can_choose_dept:
vals["dept"] = auth_dept
@ -1000,13 +1027,12 @@ def form_change_password(user_name=None):
# check access
if not can_handle_passwd(user):
return "\n".join(
[
html_sco_header.sco_header(),
"<p>Vous n'avez pas la permission de changer ce mot de passe</p>",
html_sco_header.sco_footer(),
]
return render_template(
"base.j2",
content="<p>Vous n'avez pas la permission de changer ce mot de passe</p>",
title="Accès refusé",
)
form = ChangePasswordForm(user_name=user.user_name, email=user.email)
destination = url_for(
"users.user_info_page",