WIP fusion master/no-bs

This commit is contained in:
Emmanuel Viennet 2024-08-25 02:13:13 +02:00
commit 65e2ead1b4
29 changed files with 401 additions and 576 deletions

View File

@ -425,22 +425,15 @@ class TF(object):
hiddenitemtemplate = "%(elem)s" hiddenitemtemplate = "%(elem)s"
separatortemplate = '<tr%(item_dom_attr)s><td colspan="2">%(label)s</td></tr>' separatortemplate = '<tr%(item_dom_attr)s><td colspan="2">%(label)s</td></tr>'
# ---- build form # ---- build form
buttons_markup = "" buttons_markup = """<div class="form-group">"""
if self.submitbutton: if self.submitbutton:
buttons_markup += ( buttons_markup += f"""<input class="btn btn-default" type="submit" name="{
'<input type="submit" name="%s_submit" id="%s_submit" value="%s" %s/>' self.formid}_submit" id="{self.formid}_submit" value="{self.submitlabel
% ( }" {' '.join(self.submitbuttonattributes)}/>"""
self.formid,
self.formid,
self.submitlabel,
" ".join(self.submitbuttonattributes),
)
)
if self.cancelbutton: if self.cancelbutton:
buttons_markup += ( buttons_markup += f""" <input class="btn btn-default" type="submit" name="cancel" id="{
' <input type="submit" name="%s_cancel" id="%s_cancel" value="%s">' self.formid}_cancel" value="{self.cancelbutton}">"""
% (self.formid, self.formid, self.cancelbutton) buttons_markup += "</div>"
)
R = [] R = []
suggest_js = [] suggest_js = []
@ -803,8 +796,10 @@ var {field}_as = new bsn.AutoSuggest('{field}', {field}_opts);
} }
// Selections etendues avec shift (use jquery.field) // Selections etendues avec shift (use jquery.field)
$('input[name="tf-checked:list"]').createCheckboxRange(); window.onload = function() {
</script>""" $('input[name="tf-checked:list"]').createCheckboxRange();
}
</script>"""
) )
R.append("</form>") R.append("</form>")
return R return R

View File

@ -760,7 +760,7 @@ class GenTable:
return js return js
else: else:
log(f"make_page: format={fmt}") log(f"make_page: format={fmt}")
raise ValueError("_make_page: invalid format") raise ValueError("make_page: invalid format")
# ----- # -----

View File

@ -25,217 +25,4 @@
# #
############################################################################## ##############################################################################
"""HTML Header/Footer for ScoDoc pages""" """Legacy constants (TODO: remove)"""
from flask import g, render_template, url_for
from flask_login import current_user
import app.scodoc.sco_utils as scu
from app import scodoc_flash_status_messages
from app.scodoc import html_sidebar
import sco_version
def standard_html_header():
"""Standard HTML header for pages outside depts"""
# not used in ZScolar, see sco_header
return f"""<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html><head>
<title>ScoDoc: accueil</title>
<META http-equiv="Content-Type" content="text/html; charset={scu.SCO_ENCODING}">
<META http-equiv="Content-Style-Type" content="text/css">
<META name="LANG" content="fr">
<META name="DESCRIPTION" content="ScoDoc: gestion scolarite">
<link href="{scu.STATIC_DIR}/css/scodoc.css" rel="stylesheet" type="text/css"/>
</head><body>{scu.CUSTOM_HTML_HEADER_CNX}"""
def standard_html_footer():
"""Le pied de page HTML de la page d'accueil."""
return f"""<p class="footer">
Problème de connexion (identifiant, mot de passe): <em>contacter votre responsable ou chef de département</em>.</p>
<p>Probl&egrave;mes et suggestions sur le logiciel: <a href="mailto:{scu.SCO_USERS_LIST}">{scu.SCO_USERS_LIST}</a></p>
<p><em>ScoDoc est un logiciel libre développé par Emmanuel Viennet.</em></p>
</body></html>"""
_HTML_BEGIN = f"""<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Content-Type" content="text/html; charset=%(encoding)s" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta name="LANG" content="fr" />
<meta name="DESCRIPTION" content="ScoDoc" />
<title>%(page_title)s</title>
<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 href="{scu.STATIC_DIR}/css/scodoc.css" rel="stylesheet" type="text/css" />
<link href="{scu.STATIC_DIR}/css/menu.css" rel="stylesheet" type="text/css" />
<link rel="stylesheet" type="text/css" href="{scu.STATIC_DIR}/DataTables/datatables.min.css" />
<link href="{scu.STATIC_DIR}/css/gt_table.css" rel="stylesheet" type="text/css" />
<script src="{scu.STATIC_DIR}/libjs/menu.js"></script>
<script src="{scu.STATIC_DIR}/libjs/bubble.js"></script>
<script src="{scu.STATIC_DIR}/jQuery/jquery.js"></script>
<script src="{scu.STATIC_DIR}/jQuery/jquery-migrate-3.5.2.min.js"></script>
<script src="{scu.STATIC_DIR}/libjs/jquery.field.min.js"></script>
<script src="{scu.STATIC_DIR}/libjs/jquery-ui-1.10.4.custom/js/jquery-ui-1.10.4.custom.min.js"></script>
<script src="{scu.STATIC_DIR}/DataTables/datatables.min.js"></script>
<script src="{scu.STATIC_DIR}/libjs/qtip/jquery.qtip-3.0.3.min.js"></script>
<link type="text/css" rel="stylesheet" href="{scu.STATIC_DIR}/libjs/qtip/jquery.qtip-3.0.3.min.css" />
<link type="text/css" rel="stylesheet" href="{scu.STATIC_DIR}/libjs/timepicker-1.3.5/jquery.timepicker.min.css" />
<script src="{scu.STATIC_DIR}/libjs/timepicker-1.3.5/jquery.timepicker.min.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}/libjs/qtip/jquery.qtip-3.0.3.min.js"></script>
<link type="text/css" rel="stylesheet" href="{scu.STATIC_DIR}/libjs/qtip/jquery.qtip-3.0.3.min.css" />
<script>
document.addEventListener('DOMContentLoaded', function() {{
if (document.getElementById('gtrcontent')) {{
enableTooltips("gtrcontent");
}}
if (document.getElementById('sidebar')) {{
enableTooltips("sidebar");
}}
}});
</script>
"""
def scodoc_top_html_header(page_title="ScoDoc: bienvenue"):
"""HTML header for top level pages"""
H = [
_HTML_BEGIN % {"page_title": page_title, "encoding": scu.SCO_ENCODING},
"""</head><body id="gtrcontent">""",
scu.CUSTOM_HTML_HEADER_CNX,
]
return "\n".join(H)
# Header:
def sco_header(
# optional args
page_title="", # page title
no_sidebar=False, # hide sidebar
cssstyles=(), # additionals CSS sheets
javascripts=(), # additionals JS filenames to load
scripts=(), # script to put in page header
init_google_maps=False, # Google maps
titrebandeau="", # titre dans bandeau superieur
etudid=None,
formsemestre_id=None,
):
"""Main HTML page header for ScoDoc
Utilisé dans les anciennes pages. Les nouvelles pages utilisent le template Jinja.
"""
from app.scodoc.sco_formsemestre_status import formsemestre_page_title
if etudid is not None:
g.current_etudid = etudid
scodoc_flash_status_messages()
params = {
"page_title": page_title or sco_version.SCONAME,
"no_sidebar": no_sidebar,
"ScoURL": url_for("scolar.index_html", scodoc_dept=g.scodoc_dept),
"encoding": scu.SCO_ENCODING,
"titrebandeau_mkup": "<td>" + titrebandeau + "</td>",
"authuser": current_user.user_name,
}
if no_sidebar:
params["margin_left"] = "1em"
else:
params["margin_left"] = "140px"
H = [_HTML_BEGIN % params]
if init_google_maps:
# It may be necessary to add an API key:
H.append('<script src="https://maps.google.com/maps/api/js"></script>')
# Feuilles de style additionnelles:
for cssstyle in cssstyles:
H.append(
f"""<link type="text/css" rel="stylesheet" href="{scu.STATIC_DIR}/{cssstyle}" />\n"""
)
H.append(
f"""
<script>
const SCO_URL="{url_for("scolar.index_html", scodoc_dept=g.scodoc_dept)}";
const SCO_TIMEZONE="{scu.TIME_ZONE}";
</script>"""
)
if init_google_maps: # utilisé uniquement pour carte lycées
H.append(
f'<script src="{scu.STATIC_DIR}/libjs/jquery.ui.map.full.min.js"></script>'
)
# JS additionels
for js in javascripts:
H.append(f"""<script src="{scu.STATIC_DIR}/{js}"></script>\n""")
H.append(
f"""<style>
#gtrcontent {{
margin-left: {params["margin_left"]};
height: 100%%;
margin-bottom: 16px;
}}
</style>
"""
)
# Scripts de la page:
if scripts:
H.append("""<script>""")
for script in scripts:
H.append(script)
H.append("""</script>""")
# Fin head, Body et bandeau haut:
H.append(
f"""</head>
<!-- Legacy ScoDoc header -->
<body>
{scu.CUSTOM_HTML_HEADER}
{'' if no_sidebar else html_sidebar.sidebar(etudid)}
<div id="mobileNav" mobile="true" style="display:none;"></div>
<div id="gtrcontent">
"""
)
# En attendant le replacement complet de cette fonction,
# inclusion ici des messages flask
H.append(render_template("flashed_messages.j2"))
#
# Barre menu semestre:
H.append(formsemestre_page_title(formsemestre_id))
# div pour affichage messages temporaires
H.append('<div id="sco_msg" class="head_message"></div>')
#
H.append('<div class="sco-app-content">')
return "".join(H)
def sco_footer():
"""Main HTMl pages footer"""
return (
"""</div></div><!-- /gtrcontent -->"""
+ scu.CUSTOM_HTML_FOOTER
+ """</body></html>"""
)

View File

@ -307,8 +307,6 @@ enregistrés et non modifiables, on peut les retrouver ultérieurement.
return render_template( return render_template(
"sco_page.j2", "sco_page.j2",
title="Archiver les PV et résultats", 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>" content="<h2>Archiver les PV et résultats du semestre</h2>"
+ "\n".join(H) + "\n".join(H)
+ "\n" + "\n"

View File

@ -69,7 +69,6 @@ et sur page "réglages bulletin" (avec formsemestre_id)
# raise ValueError("invalid value for 'side' parameter") # raise ValueError("invalid value for 'side' parameter")
# signatureloc = get_bul_sig_img() # signatureloc = get_bul_sig_img()
# H = [ # H = [
# self.sco_header(page_title="Changement de signature"),
# """<h2>Changement de la signature bulletin de %(sidetxt)s</h2> # """<h2>Changement de la signature bulletin de %(sidetxt)s</h2>
# """ # """
# % (sidetxt,), # % (sidetxt,),

View File

@ -43,7 +43,6 @@ import app.scodoc.sco_utils as scu
from app.scodoc.TrivialFormulator import TrivialFormulator, tf_error_message from app.scodoc.TrivialFormulator import TrivialFormulator, tf_error_message
from app.scodoc.sco_exceptions import ScoValueError, ScoNonEmptyFormationObject from app.scodoc.sco_exceptions import ScoValueError, ScoNonEmptyFormationObject
from app.scodoc import html_sco_header
from app.scodoc import sco_cache from app.scodoc import sco_cache
from app.scodoc import codes_cursus from app.scodoc import codes_cursus
from app.scodoc import sco_edit_ue from app.scodoc import sco_edit_ue
@ -146,7 +145,6 @@ def formation_edit(formation_id=None, create=False):
"""Edit or create a formation""" """Edit or create a formation"""
if create: if create:
H = [ H = [
html_sco_header.sco_header(page_title="Création d'une formation"),
"""<h2>Création d'une formation</h2> """<h2>Création d'une formation</h2>
<p class="help">Une "formation" décrit une filière, comme un DUT ou une Licence. La formation se subdivise en unités pédagogiques (UE, matières, modules). Elle peut se diviser en plusieurs semestres (ou sessions), qui seront mis en place séparément. <p class="help">Une "formation" décrit une filière, comme un DUT ou une Licence. La formation se subdivise en unités pédagogiques (UE, matières, modules). Elle peut se diviser en plusieurs semestres (ou sessions), qui seront mis en place séparément.
@ -168,7 +166,6 @@ def formation_edit(formation_id=None, create=False):
is_locked = formation.has_locked_sems(formation_id) is_locked = formation.has_locked_sems(formation_id)
submitlabel = "Modifier les valeurs" submitlabel = "Modifier les valeurs"
H = [ H = [
html_sco_header.sco_header(page_title="Modification d'une formation"),
f"""<h2>Modification de la formation {formation.acronyme} f"""<h2>Modification de la formation {formation.acronyme}
version {formation.version} version {formation.version}
</h2>""", </h2>""",
@ -251,52 +248,57 @@ def formation_edit(formation_id=None, create=False):
submitlabel=submitlabel, submitlabel=submitlabel,
) )
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_dept.j2",
title="Modification d'une formation",
content="\n".join(H) + tf[1],
)
if tf[0] == -1:
return flask.redirect(url_for("notes.index_html", scodoc_dept=g.scodoc_dept)) return flask.redirect(url_for("notes.index_html", scodoc_dept=g.scodoc_dept))
# check unicity : constraint UNIQUE(acronyme,titre,version)
if create:
version = 1
else: else:
# check unicity : constraint UNIQUE(acronyme,titre,version) version = initvalues["version"]
if create: args = {
version = 1 "acronyme": tf[2]["acronyme"],
else: "titre": tf[2]["titre"],
version = initvalues["version"] "version": version,
args = { "dept_id": g.scodoc_dept_id,
"acronyme": tf[2]["acronyme"], }
"titre": tf[2]["titre"], other_formations: list[Formation] = Formation.query.filter_by(**args).all()
"version": version, if other_formations and (
"dept_id": g.scodoc_dept_id, (len(other_formations) > 1) or other_formations[0].id != formation_id
} ):
other_formations: list[Formation] = Formation.query.filter_by(**args).all() return render_template(
if other_formations and ( "sco_page_dept.j2",
(len(other_formations) > 1) or other_formations[0].id != formation_id title="Modification d'une formation",
): content=(
return (
"\n".join(H) "\n".join(H)
+ tf_error_message( + tf_error_message(
f"""Valeurs incorrectes: il existe déjà <a href="{ f"""Valeurs incorrectes: il existe déjà <a href="{
url_for('notes.ue_table', url_for('notes.ue_table',
scodoc_dept=g.scodoc_dept, formation_id=other_formations[0].id) scodoc_dept=g.scodoc_dept, formation_id=other_formations[0].id)
}">une formation</a> avec même titre, }">une formation</a> avec même titre,
acronyme et version. acronyme et version.
""" """
) )
+ tf[1] + tf[1]
+ html_sco_header.sco_footer() ),
)
#
if create:
formation = do_formation_create(tf[2])
else:
if do_formation_edit(tf[2]):
flash(
f"""Modification de la formation {
formation.titre} ({formation.acronyme}) version {formation.version}"""
)
return flask.redirect(
url_for(
"notes.ue_table", scodoc_dept=g.scodoc_dept, formation_id=formation.id
)
) )
#
if create:
formation = do_formation_create(tf[2])
else:
if do_formation_edit(tf[2]):
flash(
f"""Modification de la formation {
formation.titre} ({formation.acronyme}) version {formation.version}"""
)
return flask.redirect(
url_for("notes.ue_table", scodoc_dept=g.scodoc_dept, formation_id=formation.id)
)
def do_formation_create(args: dict) -> Formation: def do_formation_create(args: dict) -> Formation:

View File

@ -29,7 +29,7 @@
(portage from DTML) (portage from DTML)
""" """
import flask import flask
from flask import g, url_for, request from flask import g, render_template, request, url_for
from app import db, log from app import db, log
from app.models import Formation, Matiere, UniteEns, ScolarNews from app.models import Formation, Matiere, UniteEns, ScolarNews
@ -43,7 +43,6 @@ from app.scodoc.sco_exceptions import (
ScoLockedFormError, ScoLockedFormError,
ScoNonEmptyFormationObject, ScoNonEmptyFormationObject,
) )
from app.scodoc import html_sco_header
_matiereEditor = ndb.EditableTable( _matiereEditor = ndb.EditableTable(
"notes_matieres", "notes_matieres",
@ -63,7 +62,6 @@ def matiere_list(*args, **kw):
def do_matiere_edit(*args, **kw): def do_matiere_edit(*args, **kw):
"edit a matiere" "edit a matiere"
from app.scodoc import sco_edit_ue from app.scodoc import sco_edit_ue
from app.scodoc import sco_edit_formation
cnx = ndb.GetDBConnexion() cnx = ndb.GetDBConnexion()
# check # check
@ -79,7 +77,6 @@ def do_matiere_edit(*args, **kw):
def do_matiere_create(args): def do_matiere_create(args):
"create a matiere" "create a matiere"
from app.scodoc import sco_edit_ue from app.scodoc import sco_edit_ue
from app.models import ScolarNews
cnx = ndb.GetDBConnexion() cnx = ndb.GetDBConnexion()
# check # check
@ -103,7 +100,6 @@ def matiere_create(ue_id=None):
ue: UniteEns = UniteEns.query.get_or_404(ue_id) ue: UniteEns = UniteEns.query.get_or_404(ue_id)
default_numero = max([mat.numero for mat in ue.matieres] or [9]) + 1 default_numero = max([mat.numero for mat in ue.matieres] or [9]) + 1
H = [ H = [
html_sco_header.sco_header(page_title="Création d'une matière"),
f"""<h2>Création d'une matière dans l'UE {ue.titre or ''} ({ue.acronyme})</h2> f"""<h2>Création d'une matière dans l'UE {ue.titre or ''} ({ue.acronyme})</h2>
<p class="help">Les matières sont des groupes de modules dans une UE <p class="help">Les matières sont des groupes de modules dans une UE
d'une formation donnée. Les matières servent surtout pour la d'une formation donnée. Les matières servent surtout pour la
@ -151,21 +147,25 @@ associé.
) )
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="Création d'une matière", content="\n".join(H) + tf[1]
)
if tf[0] == -1:
return flask.redirect(dest_url) return flask.redirect(dest_url)
else: # check unicity
# check unicity mats = matiere_list(args={"ue_id": ue_id, "titre": tf[2]["titre"]})
mats = matiere_list(args={"ue_id": ue_id, "titre": tf[2]["titre"]}) if mats:
if mats: return render_template(
return ( "sco_page.j2",
title="Création d'une matière",
content=(
"\n".join(H) "\n".join(H)
+ tf_error_message("Titre de matière déjà existant dans cette UE") + tf_error_message("Titre de matière déjà existant dans cette UE")
+ tf[1] + tf[1]
+ html_sco_header.sco_footer() ),
) )
_ = do_matiere_create(tf[2]) _ = do_matiere_create(tf[2])
return flask.redirect(dest_url) return flask.redirect(dest_url)
def can_delete_matiere(matiere: Matiere) -> tuple[bool, str]: def can_delete_matiere(matiere: Matiere) -> tuple[bool, str]:
@ -230,7 +230,6 @@ def matiere_delete(matiere_id=None):
mat = matiere_list(args={"matiere_id": matiere_id})[0] mat = matiere_list(args={"matiere_id": matiere_id})[0]
UE = sco_edit_ue.ue_list(args={"ue_id": mat["ue_id"]})[0] UE = sco_edit_ue.ue_list(args={"ue_id": mat["ue_id"]})[0]
H = [ H = [
html_sco_header.sco_header(page_title="Suppression d'une matière"),
"<h2>Suppression de la matière %(titre)s" % mat, "<h2>Suppression de la matière %(titre)s" % mat,
" dans l'UE (%(acronyme)s))</h2>" % UE, " dans l'UE (%(acronyme)s))</h2>" % UE,
] ]
@ -248,13 +247,17 @@ def matiere_delete(matiere_id=None):
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",
return flask.redirect(dest_url) title="Suppression d'une matière",
else: content="\n".join(H) + tf[1],
do_matiere_delete(matiere_id) )
if tf[0] == -1:
return flask.redirect(dest_url) return flask.redirect(dest_url)
do_matiere_delete(matiere_id)
return flask.redirect(dest_url)
def matiere_edit(matiere_id=None): def matiere_edit(matiere_id=None):
"""Edit matiere""" """Edit matiere"""
@ -273,11 +276,10 @@ def matiere_edit(matiere_id=None):
ue_names = ["%(acronyme)s (%(titre)s)" % u for u in ues] ue_names = ["%(acronyme)s (%(titre)s)" % u for u in ues]
ue_ids = [u["ue_id"] for u in ues] ue_ids = [u["ue_id"] for u in ues]
H = [ H = [
html_sco_header.sco_header(page_title="Modification d'une matière"),
"""<h2>Modification de la matière %(titre)s""" % F, """<h2>Modification de la matière %(titre)s""" % F,
f"""(formation ({formation.acronyme}, version {formation.version})</h2>""", f"""(formation ({formation.acronyme}, version {formation.version})</h2>""",
] ]
help = """<p class="help">Les matières sont des groupes de modules dans une UE help_msg = """<p class="help">Les matières sont des groupes de modules dans une UE
d'une formation donnée. Les matières servent surtout pour la d'une formation donnée. Les matières servent surtout pour la
présentation (bulletins, etc) mais <em>n'ont pas de rôle dans le calcul présentation (bulletins, etc) mais <em>n'ont pas de rôle dans le calcul
des notes.</em> des notes.</em>
@ -325,18 +327,25 @@ associé.
formation_id=str(ue["formation_id"]), formation_id=str(ue["formation_id"]),
) )
if tf[0] == 0: if tf[0] == 0:
return "\n".join(H) + tf[1] + help + html_sco_header.sco_footer() return render_template(
"sco_page.j2",
title="Modification d'une matière",
content="\n".join(H) + tf[1] + help_msg,
)
elif tf[0] == -1: elif tf[0] == -1:
return flask.redirect(dest_url) return flask.redirect(dest_url)
else: else:
# check unicity # check unicity
mats = matiere_list(args={"ue_id": tf[2]["ue_id"], "titre": tf[2]["titre"]}) mats = matiere_list(args={"ue_id": tf[2]["ue_id"], "titre": tf[2]["titre"]})
if len(mats) > 1 or (len(mats) == 1 and mats[0]["matiere_id"] != matiere_id): if len(mats) > 1 or (len(mats) == 1 and mats[0]["matiere_id"] != matiere_id):
return ( return render_template(
"\n".join(H) "sco_page.j2",
+ tf_error_message("Titre de matière déjà existant dans cette UE") title="Modification d'une matière",
+ tf[1] content=(
+ html_sco_header.sco_footer() "\n".join(H)
+ tf_error_message("Titre de matière déjà existant dans cette UE")
+ tf[1]
),
) )
# changement d'UE ? # changement d'UE ?

View File

@ -32,12 +32,11 @@ import io
from zipfile import ZipFile from zipfile import ZipFile
import flask import flask
from flask import flash, g, request, Response, send_file, url_for from flask import flash, g, render_template, request, Response, send_file, url_for
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
from app import log from app import log
from app.models import Formation from app.models import Formation
from app.scodoc import html_sco_header
from app.scodoc import sco_apogee_csv, sco_apogee_reader from app.scodoc import sco_apogee_csv, sco_apogee_reader
from app.scodoc import sco_etape_apogee from app.scodoc import sco_etape_apogee
from app.scodoc import sco_formsemestre from app.scodoc import sco_formsemestre
@ -100,10 +99,6 @@ def apo_semset_maq_status(
ok_for_export &= semset["jury_ok"] ok_for_export &= semset["jury_ok"]
H = [ H = [
html_sco_header.sco_header(
page_title="Export Apogée",
javascripts=["js/apo_semset_maq_status.js"],
),
"""<h2>Export des résultats vers Apogée</h2>""" """<h2>Export des résultats vers Apogée</h2>"""
"""<div class="semset_descr">""", """<div class="semset_descr">""",
semset.html_descr(), semset.html_descr(),
@ -438,8 +433,12 @@ def apo_semset_maq_status(
</div> </div>
""" """
) )
H.append(html_sco_header.sco_footer()) return render_template(
return "\n".join(H) "sco_page_dept.j2",
title="Export Apogée",
javascripts=["js/apo_semset_maq_status.js"],
content="\n".join(H),
)
def table_apo_csv_list(semset): def table_apo_csv_list(semset):
@ -594,21 +593,21 @@ def _view_etuds_page(
if fmt != "html": if fmt != "html":
return tab.make_page(fmt=fmt) return tab.make_page(fmt=fmt)
return f""" return render_template(
{html_sco_header.sco_header( "sco_page_dept.j2",
page_title=title, title=title,
)} content=f"""
<h2>{title}</h2> <h2>{title}</h2>
{tab.html()} {tab.html()}
<p><a href="{ <div class="space-before-24"><a class="stdlink" href="{
url_for("notes.apo_semset_maq_status", url_for("notes.apo_semset_maq_status",
scodoc_dept=g.scodoc_dept, semset_id=semset_id) scodoc_dept=g.scodoc_dept, semset_id=semset_id)
}">Retour à la page d'export Apogée</a> }">Retour à la page d'export Apogée</a>
</p> </div>
{html_sco_header.sco_footer()} """,
""" )
def view_apo_csv_store(semset_id="", csvfile=None, data: bytes = "", autodetect=False): def view_apo_csv_store(semset_id="", csvfile=None, data: bytes = "", autodetect=False):
@ -747,9 +746,6 @@ def view_apo_csv(etape_apo="", semset_id="", fmt="html"):
) = sco_etape_apogee.apo_csv_semset_check(semset) ) = sco_etape_apogee.apo_csv_semset_check(semset)
H = [ H = [
html_sco_header.sco_header(
page_title=f"""Maquette Apogée enregistrée pour {etape_apo}""",
),
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="{
url_for("notes.apo_semset_maq_status", url_for("notes.apo_semset_maq_status",
@ -768,7 +764,11 @@ def view_apo_csv(etape_apo="", semset_id="", fmt="html"):
# Liste des étudiants (sans les résultats pour le moment): TODO # Liste des étudiants (sans les résultats pour le moment): TODO
etuds = apo_data.etuds etuds = apo_data.etuds
if not etuds: if not etuds:
return "\n".join(H) + "<p>Aucun étudiant</p>" + html_sco_header.sco_footer() return render_template(
"sco_page_dept.j2",
title=f"""Maquette Apogée {etape_apo}""",
content="\n".join(H) + "<p>Aucun étudiant</p>",
)
# Ajout infos sur ScoDoc vs Apogee # Ajout infos sur ScoDoc vs Apogee
for e in etuds: for e in etuds:
@ -830,10 +830,13 @@ def view_apo_csv(etape_apo="", semset_id="", fmt="html"):
}">Retour</a> }">Retour</a>
</div> </div>
""", """,
html_sco_header.sco_footer(),
] ]
return "\n".join(H) return render_template(
"sco_page_dept.j2",
title=f"""Maquette Apogée enregistrée pour {etape_apo}""",
content="\n".join(H),
)
# called from Web (GET) # called from Web (GET)

View File

@ -42,7 +42,6 @@ import app.scodoc.sco_utils as scu
from app.scodoc.sco_utils import ModuleType from app.scodoc.sco_utils import ModuleType
from app.scodoc.sco_exceptions import ScoValueError from app.scodoc.sco_exceptions import ScoValueError
from app.scodoc.TrivialFormulator import TrivialFormulator from app.scodoc.TrivialFormulator import TrivialFormulator
from app.scodoc import html_sco_header
from app.scodoc import sco_cache from app.scodoc import sco_cache
from app.scodoc import sco_evaluations from app.scodoc import sco_evaluations
from app.scodoc import sco_preferences from app.scodoc import sco_preferences
@ -74,16 +73,18 @@ def evaluation_create_form(
min_note_max = scu.NOTES_PRECISION # le plus petit bareme possible min_note_max = scu.NOTES_PRECISION # le plus petit bareme possible
# #
if not modimpl.can_edit_evaluation(current_user): if not modimpl.can_edit_evaluation(current_user):
return f""" return render_template(
{html_sco_header.sco_header()} "sco_page.j2",
title="Opération non autorisée",
content=f"""
<h2>Opération non autorisée</h2> <h2>Opération non autorisée</h2>
<p>Modification évaluation impossible pour {current_user.get_nomplogin()}</p> <p>Modification évaluation impossible pour {current_user.get_nomplogin()}</p>
<p><a href="{url_for('notes.moduleimpl_status', <p><a href="{url_for('notes.moduleimpl_status',
scodoc_dept=g.scodoc_dept, moduleimpl_id=moduleimpl_id) scodoc_dept=g.scodoc_dept, moduleimpl_id=moduleimpl_id)
}" class="stdlink">Revenir</a> }" class="stdlink">Revenir</a>
</p> </p>
{html_sco_header.sco_footer()} """,
""" )
if not edit: if not edit:
# création nouvel # création nouvel
if moduleimpl_id is None: if moduleimpl_id is None:
@ -361,20 +362,21 @@ def evaluation_create_form(
""" """
] ]
if tf[0] == 0: if tf[0] == 0:
head = html_sco_header.sco_header(page_title=page_title) return render_template(
return ( "sco_page.j2",
head title=page_title,
+ "\n".join(H) content=(
+ "\n" "\n".join(H)
+ tf[1] + "\n"
+ render_template( + tf[1]
"scodoc/forms/evaluation_edit.j2", + render_template(
) "scodoc/forms/evaluation_edit.j2",
+ render_template( )
"scodoc/help/evaluations.j2", is_apc=is_apc, modimpl=modimpl + render_template(
) "scodoc/help/evaluations.j2", is_apc=is_apc, modimpl=modimpl
+ render_template("sco_timepicker.j2") )
+ html_sco_header.sco_footer() + render_template("sco_timepicker.j2")
),
) )
elif tf[0] == -1: elif tf[0] == -1:
return flask.redirect(dest_url) return flask.redirect(dest_url)

View File

@ -17,7 +17,6 @@ from app.models import Evaluation, FormSemestre
from app.comp import res_sem from app.comp import res_sem
from app.comp.res_compat import NotesTableCompat from app.comp.res_compat import NotesTableCompat
from app.comp.moy_mod import ModuleImplResults from app.comp.moy_mod import ModuleImplResults
from app.scodoc import html_sco_header
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
@ -63,9 +62,7 @@ def evaluations_recap(formsemestre_id: int) -> str:
pas pris en compte dans cette table.</div> pas pris en compte dans cette table.</div>
""" """
) )
H.append(
html_sco_header.sco_footer(),
)
return render_template( return render_template(
"sco_page.j2", "sco_page.j2",
title="Évaluations du semestre", title="Évaluations du semestre",

View File

@ -25,9 +25,9 @@
# #
############################################################################## ##############################################################################
"""Export d'une table avec les résultats de tous les étudiants""" """Export d'une table avec les résultats de tous les étudiants
"""
from flask import url_for, g, request from flask import url_for, g, render_template, request
from app.comp import res_sem from app.comp import res_sem
from app.comp.res_compat import NotesTableCompat from app.comp.res_compat import NotesTableCompat
@ -42,12 +42,12 @@ from app.scodoc import codes_cursus
from app.scodoc import sco_preferences from app.scodoc import sco_preferences
from app.scodoc import sco_pv_dict from app.scodoc import sco_pv_dict
from app.scodoc import sco_etud from app.scodoc import sco_etud
import sco_version
from app.scodoc.gen_tables import GenTable from app.scodoc.gen_tables import GenTable
from app.scodoc.codes_cursus import NO_SEMESTRE_ID from app.scodoc.codes_cursus import NO_SEMESTRE_ID
import sco_version
def _build_results_table(start_date=None, end_date=None, types_parcours=[]): def _build_results_table(start_date=None, end_date=None, types_parcours=()):
"""Construit une table avec les résultats de jury de TOUS les étudiants """Construit une table avec les résultats de jury de TOUS les étudiants
de TOUS les semestres ScoDoc de ce département entre les dates indiquées de TOUS les semestres ScoDoc de ce département entre les dates indiquées
(c'est à dire commençant APRES ou à start_date et terminant avant ou à end_date) (c'est à dire commençant APRES ou à start_date et terminant avant ou à end_date)
@ -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)
@ -283,10 +285,6 @@ def scodoc_table_results(
info_sems.append("</ul>") info_sems.append("</ul>")
H = [ H = [
html_sco_header.sco_header(
page_title="Export résultats",
javascripts=["js/export_results.js"],
),
# XXX # XXX
""" """
<h2>Table des résultats de tous les semestres</h2> <h2>Table des résultats de tous les semestres</h2>
@ -307,9 +305,13 @@ def scodoc_table_results(
""", """,
"\n".join(info_sems), "\n".join(info_sems),
"""</div>""", """</div>""",
html_sco_header.sco_footer(),
] ]
return "\n".join(H) return render_template(
"sco_page_dept.j2",
title="Export résultats",
javascripts=["js/export_results.js"],
content="\n".join(H),
)
# Formulaire pour saisie dates et sélection parcours # Formulaire pour saisie dates et sélection parcours

View File

@ -31,12 +31,11 @@ import flask
from flask import g, url_for, render_template, 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
from app.models import FormSemestre from app.models import FormSemestre
import app.scodoc.sco_utils as scu 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
_custommenuEditor = ndb.EditableTable( _custommenuEditor = ndb.EditableTable(
"notes_formsemestre_custommenu", "notes_formsemestre_custommenu",
@ -107,7 +106,7 @@ def formsemestre_custommenu_edit(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 = [
"""<div class="help"> """<div class="help">

View File

@ -1720,7 +1720,6 @@ def formsemestre_edit_options(formsemestre_id):
"""dialog to change formsemestre options """dialog to change formsemestre options
(accessible par EditFormSemestre ou dir. etudes) (accessible par EditFormSemestre ou dir. etudes)
""" """
log("formsemestre_edit_options")
ok, err = sco_permissions_check.check_access_diretud(formsemestre_id) ok, err = sco_permissions_check.check_access_diretud(formsemestre_id)
if not ok: if not ok:
return err return err

View File

@ -34,7 +34,7 @@ Ces semestres n'auront qu'un seul inscrit !
import time import time
import flask import flask
from flask import url_for, g, request from flask import flash, g, render_template, request, url_for
from flask_login import current_user from flask_login import current_user
from app.comp import res_sem from app.comp import res_sem
@ -50,7 +50,6 @@ from app.models import (
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
from app import log from app import log
from app.scodoc.TrivialFormulator import TrivialFormulator, tf_error_message from app.scodoc.TrivialFormulator import TrivialFormulator, tf_error_message
from app.scodoc import html_sco_header
from app.scodoc import sco_formsemestre from app.scodoc import sco_formsemestre
from app.scodoc import sco_formsemestre_inscriptions from app.scodoc import sco_formsemestre_inscriptions
from app.scodoc import sco_formsemestre_validation from app.scodoc import sco_formsemestre_validation
@ -86,7 +85,6 @@ def formsemestre_ext_create_form(etudid, formsemestre_id):
"""Formulaire création/inscription à un semestre extérieur""" """Formulaire création/inscription à un semestre extérieur"""
etud = Identite.get_etud(etudid) etud = Identite.get_etud(etudid)
H = [ H = [
html_sco_header.sco_header(),
f"""<h2>Enregistrement d'une inscription antérieure dans un autre f"""<h2>Enregistrement d'une inscription antérieure dans un autre
établissement</h2> établissement</h2>
<p class="help"> <p class="help">
@ -106,7 +104,6 @@ def formsemestre_ext_create_form(etudid, formsemestre_id):
}" class="stdlink">Étudiant {etud.nomprenom}</a></h3> }" class="stdlink">Étudiant {etud.nomprenom}</a></h3>
""", """,
] ]
F = html_sco_header.sco_footer()
orig_sem = sco_formsemestre.get_formsemestre(formsemestre_id) orig_sem = sco_formsemestre.get_formsemestre(formsemestre_id)
# Ne propose que des semestres de semestre_id strictement inférieur # Ne propose que des semestres de semestre_id strictement inférieur
# au semestre courant # au semestre courant
@ -133,7 +130,7 @@ def formsemestre_ext_create_form(etudid, formsemestre_id):
(indices entre {min_semestre_id} et {max_semestre_id}, semestre courant.) (indices entre {min_semestre_id} et {max_semestre_id}, semestre courant.)
</p>""" </p>"""
) )
return "\n".join(H) + F return render_template("sco_page.j2", content="\n".join(H))
# Formulaire # Formulaire
semestre_ids_list = sorted(semestre_ids) semestre_ids_list = sorted(semestre_ids)
semestre_ids_labels = [f"S{x}" for x in semestre_ids_list] semestre_ids_labels = [f"S{x}" for x in semestre_ids_list]
@ -205,7 +202,7 @@ def formsemestre_ext_create_form(etudid, formsemestre_id):
la formation effectué dans un autre établissement. la formation effectué dans un autre établissement.
</p>""" </p>"""
) )
return "\n".join(H) + "\n" + tf[1] + F return render_template("sco_page.j2", content="\n".join(H) + "\n" + tf[1])
elif tf[0] == -1: elif tf[0] == -1:
return flask.redirect( return flask.redirect(
url_for( url_for(
@ -270,17 +267,35 @@ def formsemestre_ext_edit_ue_validations(formsemestre_id, etudid):
), ),
) )
if tf[0] == -1: if tf[0] == -1:
return "<h4>annulation</h4>" flash("annulation")
return flask.redirect(
url_for(
"notes.formsemestre_bulletinetud",
scodoc_dept=g.scodoc_dept,
formsemestre_id=formsemestre_id,
etudid=etudid,
)
)
else: else:
H = _make_page(etud, formsemestre, tf) H = _make_page(etud, formsemestre, tf)
if tf[0] == 0: # premier affichage if tf[0] == 0: # premier affichage
return "\n".join(H) return render_template(
"sco_page.j2",
title="Validation des UE d'un semestre extérieur",
javascripts=["js/formsemestre_ext_edit_ue_validations.js"],
content="\n".join(H),
)
else: # soumission else: # soumission
# simule erreur # simule erreur
ok, message = _check_values(formsemestre, ues, tf[2]) ok, message = _check_values(formsemestre, ues, tf[2])
if not ok: if not ok:
H = _make_page(etud, formsemestre, tf, message=message) H = _make_page(etud, formsemestre, tf, message=message)
return "\n".join(H) return render_template(
"sco_page.j2",
title="Validation des UE d'un semestre extérieur",
javascripts=["js/formsemestre_ext_edit_ue_validations.js"],
content="\n".join(H),
)
else: else:
# Submit # Submit
_record_ue_validations_and_coefs(formsemestre, etud, ues, tf[2]) _record_ue_validations_and_coefs(formsemestre, etud, ues, tf[2])
@ -299,10 +314,6 @@ def _make_page(etud: Identite, formsemestre: FormSemestre, tf, message="") -> li
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre) nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
moy_gen = nt.get_etud_moy_gen(etud.id) moy_gen = nt.get_etud_moy_gen(etud.id)
H = [ H = [
html_sco_header.sco_header(
page_title="Validation des UE d'un semestre extérieur",
javascripts=["js/formsemestre_ext_edit_ue_validations.js"],
),
tf_error_message(message), tf_error_message(message),
f"""<p><b>{etud.nomprenom}</b> est inscrit{etud.e} à ce semestre extérieur.</p> f"""<p><b>{etud.nomprenom}</b> est inscrit{etud.e} à ce semestre extérieur.</p>
<p>Voici ses UE enregistrées avec leur notes <p>Voici ses UE enregistrées avec leur notes
@ -324,7 +335,6 @@ def _make_page(etud: Identite, formsemestre: FormSemestre, tf, message="") -> li
)}">retour au bulletin de notes</a> )}">retour au bulletin de notes</a>
</div> </div>
""", """,
html_sco_header.sco_footer(),
] ]
return H return H
@ -522,7 +532,8 @@ def _record_ue_validations_and_coefs(
coef = None coef = None
now_dmy = time.strftime(scu.DATE_FMT) now_dmy = time.strftime(scu.DATE_FMT)
log( log(
f"_record_ue_validations_and_coefs: {formsemestre.id} etudid={etud.id} ue_id={ue.id} moy_ue={note} ue_coef={coef}" f"""_record_ue_validations_and_coefs: {
formsemestre.id} etudid={etud.id} ue_id={ue.id} moy_ue={note} ue_coef={coef}"""
) )
assert code is None or (note) # si code validant, il faut une note assert code is None or (note) # si code validant, il faut une note
sco_formsemestre_validation.do_formsemestre_validate_previous_ue( sco_formsemestre_validation.do_formsemestre_validate_previous_ue(

View File

@ -28,7 +28,6 @@
"""Opérations d'inscriptions aux semestres et modules """Opérations d'inscriptions aux semestres et modules
""" """
import collections import collections
import time
import flask import flask
from flask import flash, url_for, g, render_template, request from flask import flash, url_for, g, render_template, request
@ -52,7 +51,6 @@ from app.scodoc import sco_moduleimpl
from app.scodoc import sco_groups from app.scodoc import sco_groups
from app.scodoc import sco_etud from app.scodoc import sco_etud
from app.scodoc import sco_cache from app.scodoc import sco_cache
from app.scodoc import html_sco_header
# --- Gestion des inscriptions aux semestres # --- Gestion des inscriptions aux semestres
@ -250,7 +248,6 @@ def do_formsemestre_inscription_with_modules(
] ]
formsemestre = FormSemestre.get_formsemestre(formsemestre_id, dept_id=dept_id) formsemestre = FormSemestre.get_formsemestre(formsemestre_id, dept_id=dept_id)
# Inscription au semestre # Inscription au semestre
args = {"formsemestre_id": formsemestre_id, "etudid": etudid}
formsemestre.inscrit_etudiant(etud, etat=etat, etape=etape, method=method) formsemestre.inscrit_etudiant(etud, etat=etat, etape=etape, method=method)
log( log(
f"""do_formsemestre_inscription_with_modules: etudid={ f"""do_formsemestre_inscription_with_modules: etudid={
@ -307,7 +304,6 @@ def formsemestre_inscription_with_modules_form(etudid, only_ext=False):
id=etudid, dept_id=g.scodoc_dept_id id=etudid, dept_id=g.scodoc_dept_id
).first_or_404() ).first_or_404()
H = [ H = [
html_sco_header.sco_header(),
f"<h2>Inscription de {etud.nomprenom}", f"<h2>Inscription de {etud.nomprenom}",
] ]
if only_ext: if only_ext:
@ -319,8 +315,6 @@ def formsemestre_inscription_with_modules_form(etudid, only_ext=False):
</p> </p>
<h3>Choisir un semestre:</h3>""" <h3>Choisir un semestre:</h3>"""
) )
footer = html_sco_header.sco_footer()
# sems = sco_formsemestre.do_formsemestre_list(args={"etat": "1"})
formsemestres = ( formsemestres = (
FormSemestre.query.filter_by(etat=True, dept_id=g.scodoc_dept_id) FormSemestre.query.filter_by(etat=True, dept_id=g.scodoc_dept_id)
.join(Formation) .join(Formation)
@ -359,7 +353,9 @@ def formsemestre_inscription_with_modules_form(etudid, only_ext=False):
url_for("scolar.fiche_etud", scodoc_dept=g.scodoc_dept, etudid=etudid) url_for("scolar.fiche_etud", scodoc_dept=g.scodoc_dept, etudid=etudid)
}">retour à la fiche de {etud.nomprenom}</a>""" }">retour à la fiche de {etud.nomprenom}</a>"""
) )
return "\n".join(H) + footer return render_template(
"sco_page_dept.j2", title="Inscription", content="\n".join(H)
)
def formsemestre_inscription_with_modules( def formsemestre_inscription_with_modules(
@ -501,9 +497,7 @@ def formsemestre_inscription_option(etudid, formsemestre_id):
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)
footer = html_sco_header.sco_footer()
H = [ H = [
html_sco_header.sco_header(),
f"""<h2>Inscription de {etud.nomprenom} aux modules de {formsemestre.titre_mois()}</h2>""", f"""<h2>Inscription de {etud.nomprenom} aux modules de {formsemestre.titre_mois()}</h2>""",
] ]
@ -620,7 +614,7 @@ function chkbx_select(field_id, state) {
</p> </p>
""" """
) )
return "\n".join(H) + "\n" + tf[1] + footer return render_template("sco_page.j2", content="\n".join(H) + "\n" + tf[1])
if tf[0] == -1: if tf[0] == -1:
return flask.redirect( return flask.redirect(
url_for("scolar.fiche_etud", scodoc_dept=g.scodoc_dept, etudid=etudid) url_for("scolar.fiche_etud", scodoc_dept=g.scodoc_dept, etudid=etudid)
@ -663,7 +657,7 @@ function chkbx_select(field_id, state) {
}">retour à la fiche étudiant</a></p> }">retour à la fiche étudiant</a></p>
""" """
) )
return "\n".join(H) + footer return render_template("sco_page.j2", content="\n".join(H))
H.append("<h3>Confirmer les modifications:</h3>") H.append("<h3>Confirmer les modifications:</h3>")
if a_desinscrire: if a_desinscrire:
@ -711,7 +705,7 @@ function chkbx_select(field_id, state) {
</form> </form>
""" """
) )
return "\n".join(H) + footer return render_template("sco_page.j2", content="\n".join(H))
def do_moduleimpl_incription_options( def do_moduleimpl_incription_options(
@ -765,17 +759,15 @@ def do_moduleimpl_incription_options(
) )
H = [ H = [
html_sco_header.sco_header(),
f"""<h3>Modifications effectuées</h3> f"""<h3>Modifications effectuées</h3>
<p><a class="stdlink" href="{ <p><a class="stdlink" href="{
url_for("scolar.fiche_etud", scodoc_dept=g.scodoc_dept, etudid=etudid) url_for("scolar.fiche_etud", scodoc_dept=g.scodoc_dept, etudid=etudid)
}"> }">
Retour à la fiche étudiant</a> Retour à la fiche étudiant</a>
</p> </p>
""", """
html_sco_header.sco_footer(),
] ]
return "\n".join(H) return render_template("sco_page.j2", content="\n".join(H))
def est_inscrit_ailleurs(etudid, formsemestre_id): def est_inscrit_ailleurs(etudid, formsemestre_id):

View File

@ -51,11 +51,9 @@ from app.scodoc.sco_exceptions import ScoValueError
from app.scodoc.codes_cursus import * from app.scodoc.codes_cursus import *
from app.scodoc.TrivialFormulator import TrivialFormulator, tf_error_message from app.scodoc.TrivialFormulator import TrivialFormulator, tf_error_message
from app.scodoc import html_sco_header
from app.scodoc import sco_assiduites from app.scodoc import sco_assiduites
from app.scodoc import codes_cursus from app.scodoc import codes_cursus
from app.scodoc import sco_cache from app.scodoc import sco_cache
from app.scodoc import sco_etud
from app.scodoc import sco_formsemestre from app.scodoc import sco_formsemestre
from app.scodoc import sco_formsemestre_inscriptions from app.scodoc import sco_formsemestre_inscriptions
from app.scodoc import sco_cursus from app.scodoc import sco_cursus
@ -75,7 +73,7 @@ def formsemestre_validation_etud_form(
sortcol=None, sortcol=None,
read_only=True, read_only=True,
): ):
"""Formulaire de validation des décisions de jury""" """Formulaire de validation des décisions de jury (formations classiques)"""
formsemestre: FormSemestre = FormSemestre.query.filter_by( formsemestre: FormSemestre = FormSemestre.query.filter_by(
id=formsemestre_id, dept_id=g.scodoc_dept_id id=formsemestre_id, dept_id=g.scodoc_dept_id
).first_or_404() ).first_or_404()
@ -112,7 +110,6 @@ def formsemestre_validation_etud_form(
if read_only: if read_only:
check = True check = True
etud_d = sco_etud.get_etud_info(etudid=etudid, filled=True)[0]
Se = sco_cursus.get_situation_etud_cursus(etud, formsemestre_id) Se = sco_cursus.get_situation_etud_cursus(etud, formsemestre_id)
if not Se.sem["etat"]: if not Se.sem["etat"]:
raise ScoValueError("validation: semestre verrouille") raise ScoValueError("validation: semestre verrouille")
@ -125,13 +122,7 @@ def formsemestre_validation_etud_form(
selected_etudid=etudid, # va a la bonne ligne selected_etudid=etudid, # va a la bonne ligne
) )
H = [ H = []
html_sco_header.sco_header(
page_title=f"Parcours {etud.nomprenom}",
javascripts=["js/recap_parcours.js"],
)
]
# Navigation suivant/precedent # Navigation suivant/precedent
if etud_index_prev is not None: if etud_index_prev is not None:
etud_prev = Identite.get_etud(T[etud_index_prev][-1]) etud_prev = Identite.get_etud(T[etud_index_prev][-1])
@ -167,8 +158,6 @@ def formsemestre_validation_etud_form(
) )
footer.append("</span></div>") footer.append("</span></div>")
footer.append(html_sco_header.sco_footer())
H.append('<table style="width: 100%"><tr><td>') H.append('<table style="width: 100%"><tr><td>')
if not check: if not check:
H.append( H.append(
@ -206,7 +195,12 @@ def formsemestre_validation_etud_form(
</div> </div>
""" """
) )
return "\n".join(H + footer) return render_template(
"sco_page.j2",
javascripts=["js/recap_parcours.js"],
title=f"Parcours {etud.nomprenom}",
content="\n".join(H + footer),
)
H.append( H.append(
formsemestre_recap_parcours_table( formsemestre_recap_parcours_table(
@ -218,7 +212,12 @@ def formsemestre_validation_etud_form(
dest_url = url_tableau dest_url = url_tableau
H.append(f'<ul><li><a href="{dest_url}">Continuer</a></li></ul>') H.append(f'<ul><li><a href="{dest_url}">Continuer</a></li></ul>')
return "\n".join(H + footer) return render_template(
"sco_page.j2",
javascripts=["js/recap_parcours.js"],
title=f"Parcours {etud.nomprenom}",
content="\n".join(H + footer),
)
decision_jury = Se.nt.get_etud_decision_sem(etudid) decision_jury = Se.nt.get_etud_decision_sem(etudid)
@ -236,7 +235,12 @@ def formsemestre_validation_etud_form(
""" """
) )
) )
return "\n".join(H + footer) return render_template(
"sco_page.j2",
javascripts=["js/recap_parcours.js"],
title=f"Parcours {etud.nomprenom}",
content="\n".join(H + footer),
)
evaluations_a_debloquer = Evaluation.get_evaluations_blocked_for_etud( evaluations_a_debloquer = Evaluation.get_evaluations_blocked_for_etud(
formsemestre, etud formsemestre, etud
@ -256,7 +260,12 @@ def formsemestre_validation_etud_form(
""" """
) )
) )
return "\n".join(H + footer) return render_template(
"sco_page.j2",
javascripts=["js/recap_parcours.js"],
title=f"Parcours {etud.nomprenom}",
content="\n".join(H + footer),
)
# Infos si pas de semestre précédent # Infos si pas de semestre précédent
if not Se.prev_formsemestre: if not Se.prev_formsemestre:
@ -287,8 +296,12 @@ def formsemestre_validation_etud_form(
}" class="stdlink">Supprimer décision existante</a> }" class="stdlink">Supprimer décision existante</a>
""" """
) )
H.append(html_sco_header.sco_footer()) return render_template(
return "\n".join(H) "sco_page.j2",
javascripts=["js/recap_parcours.js"],
title=f"Parcours {etud.nomprenom}",
content="\n".join(H),
)
# Infos sur decisions déjà saisies # Infos sur decisions déjà saisies
if decision_jury: if decision_jury:
@ -329,8 +342,12 @@ def formsemestre_validation_etud_form(
H.append(f"""<input type="hidden" name="sortcol" value="{sortcol}"/>""") H.append(f"""<input type="hidden" name="sortcol" value="{sortcol}"/>""")
H.append("</form></div>") H.append("</form></div>")
H.append(html_sco_header.sco_footer()) return render_template(
return "\n".join(H) "sco_page.j2",
javascripts=["js/recap_parcours.js"],
title=f"Parcours {etud.nomprenom}",
content="\n".join(H),
)
# Explication sur barres actuelles # Explication sur barres actuelles
H.append('<p class="sfv_explication">L\'étudiant ') H.append('<p class="sfv_explication">L\'étudiant ')
@ -393,7 +410,12 @@ def formsemestre_validation_etud_form(
else: else:
H.append("sans semestres décalés</p>") H.append("sans semestres décalés</p>")
return "".join(H + footer) return render_template(
"sco_page.j2",
javascripts=["js/recap_parcours.js"],
title=f"Parcours {etud.nomprenom}",
content="\n".join(H + footer),
)
def formsemestre_validation_etud( def formsemestre_validation_etud(
@ -1062,7 +1084,7 @@ def do_formsemestre_validation_auto(formsemestre_id):
), ),
) )
H = [ H = [
f"""{html_sco_header.sco_header(page_title="Saisie automatique")} f"""
<h2>Saisie automatique des décisions du semestre {formsemestre.titre_annee()}</h2> <h2>Saisie automatique des décisions du semestre {formsemestre.titre_annee()}</h2>
<p>Opération effectuée.</p> <p>Opération effectuée.</p>
<p>{nb_valid} étudiants validés sur {len(etudids)}</p> <p>{nb_valid} étudiants validés sur {len(etudids)}</p>
@ -1088,8 +1110,10 @@ def do_formsemestre_validation_auto(formsemestre_id):
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id, mode_jury=1) scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id, mode_jury=1)
}">continuer</a>""" }">continuer</a>"""
) )
H.append(html_sco_header.sco_footer())
return "\n".join(H) return render_template(
"sco_page.j2", title="Saisie automatique", content="\n".join(H)
)
def formsemestre_validation_suppress_etud(formsemestre_id, etudid): def formsemestre_validation_suppress_etud(formsemestre_id, etudid):
@ -1218,14 +1242,14 @@ def formsemestre_validate_previous_ue(formsemestre: FormSemestre, etud: Identite
submitlabel="Enregistrer validation d'UE", submitlabel="Enregistrer validation d'UE",
) )
if tf[0] == 0: if tf[0] == 0:
return f""" return render_template(
{html_sco_header.sco_header( "sco_page_dept.j2",
page_title="Validation UE antérieure", title="Validation UE antérieure",
javascripts=["js/validate_previous_ue.js"], javascripts=["js/validate_previous_ue.js"],
cssstyles=["css/jury_delete_manual.css"], cssstyles=["css/jury_delete_manual.css"],
etudid=etud.id, etudid=etud.id,
formsemestre_id=formsemestre.id, formsemestre_id=formsemestre.id,
)} content=f"""
<h2 class="formsemestre">Gestion des validations d'UEs antérieures <h2 class="formsemestre">Gestion des validations d'UEs antérieures
de {etud.html_link_fiche()} de {etud.html_link_fiche()}
</h2> </h2>
@ -1265,8 +1289,8 @@ def formsemestre_validate_previous_ue(formsemestre: FormSemestre, etud: Identite
<!-- filled by ue_sharing_code --> <!-- filled by ue_sharing_code -->
</div> </div>
{check_formation_ues(formation)[0]} {check_formation_ues(formation)[0]}
{html_sco_header.sco_footer()} """,
""" )
dest_url = url_for( dest_url = url_for(
"notes.formsemestre_validate_previous_ue", "notes.formsemestre_validate_previous_ue",

View File

@ -34,8 +34,7 @@ from xml.etree import ElementTree
from xml.etree.ElementTree import Element from xml.etree.ElementTree import Element
import flask import flask
from flask import g, request from flask import g, make_response, render_template, request, url_for
from flask import url_for, make_response
from sqlalchemy.sql import text from sqlalchemy.sql import text
from app import cache, db, log from app import cache, db, log
@ -45,7 +44,6 @@ from app.models import FormSemestre, Identite, Scolog
from app.models import SHORT_STR_LEN from app.models import SHORT_STR_LEN
from app.models.groups import GroupDescr, Partition from app.models.groups import GroupDescr, Partition
import app.scodoc.notesdb as ndb import app.scodoc.notesdb as ndb
from app.scodoc import html_sco_header
from app.scodoc import sco_cache from app.scodoc import sco_cache
from app.scodoc import codes_cursus from app.scodoc import codes_cursus
from app.scodoc import sco_cursus from app.scodoc import sco_cursus
@ -56,7 +54,6 @@ from app.scodoc import sco_xml
from app.scodoc.sco_exceptions import ScoException, AccessDenied, ScoValueError from app.scodoc.sco_exceptions import ScoException, AccessDenied, ScoValueError
from app.scodoc.TrivialFormulator import TrivialFormulator from app.scodoc.TrivialFormulator import TrivialFormulator
partitionEditor = ndb.EditableTable( partitionEditor = ndb.EditableTable(
"partition", "partition",
"partition_id", "partition_id",
@ -930,16 +927,12 @@ def edit_partition_form(formsemestre_id=None):
raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !") raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !")
partitions = get_partitions_list(formsemestre_id) partitions = get_partitions_list(formsemestre_id)
arrow_up, arrow_down, arrow_none = get_arrow_icons_tags() arrow_up, arrow_down, _ = get_arrow_icons_tags()
suppricon = scu.icontag( suppricon = scu.icontag(
"delete_small_img", border="0", alt="supprimer", title="Supprimer" "delete_small_img", border="0", alt="supprimer", title="Supprimer"
) )
# #
H = [ H = [
html_sco_header.sco_header(
page_title="Partitions...",
javascripts=["js/edit_partition_form.js"],
),
# limite à SHORT_STR_LEN # limite à SHORT_STR_LEN
r"""<script type="text/javascript"> r"""<script type="text/javascript">
function checkname() { function checkname() {
@ -1057,7 +1050,8 @@ def edit_partition_form(formsemestre_id=None):
H.append( H.append(
f""" f"""
<div style="margin-top: 10px"><a class="stdlink" href="{ <div style="margin-top: 10px"><a class="stdlink" href="{
url_for("scolar.create_partition_parcours", scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id) url_for("scolar.create_partition_parcours",
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id)
}">Créer une partition avec un groupe par parcours (BUT)</a> }">Créer une partition avec un groupe par parcours (BUT)</a>
</div> </div>
""" """
@ -1082,14 +1076,19 @@ def edit_partition_form(formsemestre_id=None):
(ainsi, on peut afficher le classement en groupes de TD mais pas en (ainsi, on peut afficher le classement en groupes de TD mais pas en
groupe de TP, si ce sont deux partitions). groupe de TP, si ce sont deux partitions).
</li> </li>
<li>Décocher "Afficher ces groupes sur les tableaux et bulletins" pour ne pas que cette partition <li>Décocher "Afficher ces groupes sur les tableaux et bulletins"
apparaisse dans les noms de groupes pour ne pas que cette partition apparaisse dans les noms de groupes
</li> </li>
</ul> </ul>
</div> </div>
""" """
) )
return "\n".join(H) + html_sco_header.sco_footer() return render_template(
"sco_page.j2",
title="Partitions...",
javascripts=["js/edit_partition_form.js"],
content="\n".join(H),
)
def partition_set_attr(partition_id, attr, value): def partition_set_attr(partition_id, attr, value):
@ -1248,12 +1247,10 @@ def partition_rename(partition_id):
cancelbutton="Annuler", cancelbutton="Annuler",
) )
if tf[0] == 0: if tf[0] == 0:
return ( return render_template(
html_sco_header.sco_header() "sco_page.j2",
+ "\n".join(H) title="Renommer une partition",
+ "\n" content=("\n".join(H) + "\n" + tf[1]),
+ tf[1]
+ html_sco_header.sco_footer()
) )
elif tf[0] == -1: elif tf[0] == -1:
return flask.redirect( return flask.redirect(
@ -1308,6 +1305,8 @@ def groups_auto_repartition(partition: Partition):
"""Réparti les etudiants dans des groupes dans une partition, en respectant le niveau """Réparti les etudiants dans des groupes dans une partition, en respectant le niveau
et la mixité. et la mixité.
""" """
from app.views import ScoData
if not partition.groups_editable: if not partition.groups_editable:
raise AccessDenied("Partition non éditable") raise AccessDenied("Partition non éditable")
formsemestre = partition.formsemestre formsemestre = partition.formsemestre
@ -1334,9 +1333,6 @@ def groups_auto_repartition(partition: Partition):
] ]
H = [ H = [
html_sco_header.sco_header(
page_title="Répartition des groupes", formsemestre_id=formsemestre.id
),
f"""<h2>Répartition des groupes de {partition.partition_name}</h2> f"""<h2>Répartition des groupes de {partition.partition_name}</h2>
<p>Semestre {formsemestre.titre_annee()}</p> <p>Semestre {formsemestre.titre_annee()}</p>
<p class="help">Les groupes existants seront <b>effacés</b> et remplacés par <p class="help">Les groupes existants seront <b>effacés</b> et remplacés par
@ -1357,7 +1353,12 @@ def groups_auto_repartition(partition: Partition):
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="Répartition des groupes",
content="\n".join(H) + "\n" + tf[1],
sco=ScoData(formsemestre=formsemestre),
)
elif tf[0] == -1: elif tf[0] == -1:
return flask.redirect(dest_url) return flask.redirect(dest_url)
else: else:

View File

@ -32,14 +32,13 @@ from flask import flash, g, render_template, request, url_for
from app.models import FormSemestre, GroupDescr, Partition from app.models import FormSemestre, GroupDescr, Partition
from app.models import GROUPNAME_STR_LEN from app.models import GROUPNAME_STR_LEN
from app.scodoc import html_sco_header
from app.scodoc.sco_exceptions import AccessDenied from app.scodoc.sco_exceptions import AccessDenied
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
from app.scodoc.TrivialFormulator import TrivialFormulator from app.scodoc.TrivialFormulator import TrivialFormulator
def affect_groups(partition_id): def affect_groups(partition_id):
"""Formulaire affectation des etudiants aux groupes de la partition. """(ancien) formulaire affectation des etudiants aux groupes de la partition.
Permet aussi la creation et la suppression de groupes. Permet aussi la creation et la suppression de groupes.
""" """
# réécrit pour 9.0.47 avec un template # réécrit pour 9.0.47 avec un template
@ -50,12 +49,9 @@ def affect_groups(partition_id):
formsemestre.setup_parcours_groups() formsemestre.setup_parcours_groups()
return render_template( return render_template(
"scolar/affect_groups.j2", "scolar/affect_groups.j2",
sco_header=html_sco_header.sco_header( title="Affectation aux groupes",
page_title="Affectation aux groupes", javascripts=["js/groupmgr.js"],
javascripts=["js/groupmgr.js"], cssstyles=["css/groups.css"],
cssstyles=["css/groups.css"],
),
sco_footer=html_sco_header.sco_footer(),
partition=partition, partition=partition,
# Liste des partitions sans celle par defaut: # Liste des partitions sans celle par defaut:
partitions_list=partition.formsemestre.partitions.filter( partitions_list=partition.formsemestre.partitions.filter(
@ -86,9 +82,11 @@ def group_rename(group_id):
"size": 12, "size": 12,
"allow_null": False, "allow_null": False,
"validator": lambda val, _: len(val) < GROUPNAME_STR_LEN, "validator": lambda val, _: len(val) < GROUPNAME_STR_LEN,
"explanation": "doit être unique dans cette partition" "explanation": (
if group.partition.groups_editable "doit être unique dans cette partition"
else "groupes non modifiables dans cette partition", if group.partition.groups_editable
else "groupes non modifiables dans cette partition"
),
"enabled": group.partition.groups_editable, "enabled": group.partition.groups_editable,
}, },
), ),
@ -117,12 +115,10 @@ def group_rename(group_id):
edit_partition=1, edit_partition=1,
) )
if tf[0] == 0: if tf[0] == 0:
return ( return render_template(
html_sco_header.sco_header() "sco_page.j2",
+ "\n".join(H) title="Renommer un groupe",
+ "\n" content=("\n".join(H) + "\n" + tf[1]),
+ tf[1]
+ html_sco_header.sco_footer()
) )
elif tf[0] == -1: elif tf[0] == -1:
return flask.redirect(dest_url) return flask.redirect(dest_url)

View File

@ -33,7 +33,7 @@ import os
import re import re
import time import time
from flask import g, url_for from flask import g, render_template, url_for
from app import db, log from app import db, log
from app.models import Identite, GroupDescr, ScolarNews from app.models import Identite, GroupDescr, ScolarNews
@ -46,7 +46,6 @@ from app.scodoc.sco_exceptions import (
ScoException, ScoException,
ScoValueError, ScoValueError,
) )
from app.scodoc import html_sco_header
from app.scodoc import sco_cache from app.scodoc import sco_cache
from app.scodoc import sco_etud from app.scodoc import sco_etud
from app.scodoc import sco_groups from app.scodoc import sco_groups
@ -231,7 +230,7 @@ def students_import_excel(
check_homonyms=True, check_homonyms=True,
require_ine=False, require_ine=False,
return_html=True, return_html=True,
): ) -> str:
"import students from Excel file" "import students from Excel file"
diag = scolars_import_excel_file( diag = scolars_import_excel_file(
csvfile, csvfile,
@ -250,18 +249,20 @@ def students_import_excel(
if formsemestre_id if formsemestre_id
else url_for("notes.index_html", scodoc_dept=g.scodoc_dept) else url_for("notes.index_html", scodoc_dept=g.scodoc_dept)
) )
H = [html_sco_header.sco_header(page_title="Import etudiants")] H = ["<ul>"]
H.append("<ul>")
for d in diag: for d in diag:
H.append(f"<li>{d}</li>") H.append(f"<li>{d}</li>")
H.append( H.append(
f""" f"""
</ul>) </ul>)
<p>Import terminé !</p> <p>Import terminé !</p>
<p><a class="stdlink" href="{dest_url}">Continuer</a></p> <p><a class="stdlink" href="{dest_url}">Continuer</a></p>
""" """
) )
return "\n".join(H) + html_sco_header.sco_footer() return render_template(
"sco_page.j2", title="Import etudiants", content="\n".join(H)
)
return ""
def scolars_import_excel_file( def scolars_import_excel_file(
@ -518,8 +519,7 @@ def students_import_admission(
use_etudid=use_etudid, use_etudid=use_etudid,
) )
if return_html: if return_html:
H = [html_sco_header.sco_header(page_title="Import données admissions")] H = ["<p>Import terminé !</p>"]
H.append("<p>Import terminé !</p>")
H.append( H.append(
f"""<p><a class="stdlink" href="{ url_for( f"""<p><a class="stdlink" href="{ url_for(
"notes.formsemestre_status", "notes.formsemestre_status",
@ -536,7 +536,9 @@ def students_import_admission(
""" """
) )
return "\n".join(H) + html_sco_header.sco_footer() return render_template(
"sco_page.j2", title="Import données admissions", content="\n".join(H)
)
return "" return ""

View File

@ -28,14 +28,16 @@
"""Rapports sur lycées d'origine des étudiants d'un semestre. """Rapports sur lycées d'origine des étudiants d'un semestre.
- statistiques decisions - statistiques decisions
- suivi cohortes - suivi cohortes
TODO: remplacer Google Map par https://leafletjs.com/
""" """
from operator import itemgetter from operator import itemgetter
from flask import url_for, g, request from flask import url_for, g, render_template, request
import app import app
from app.scodoc import ( from app.scodoc import (
html_sco_header,
sco_formsemestre, sco_formsemestre,
sco_groups_view, sco_groups_view,
sco_preferences, sco_preferences,
@ -91,24 +93,16 @@ def scodoc_table_etuds_lycees(fmt="html"):
no_links=True, no_links=True,
) )
tab.base_url = request.base_url tab.base_url = request.base_url
t = tab.make_page(fmt=fmt, with_html_headers=False) table_html = tab.make_page(fmt=fmt, with_html_headers=False)
if fmt != "html": if fmt != "html":
return t return table_html
H = [ return render_template(
html_sco_header.sco_header( "formsemestre/etuds_lycees.j2",
page_title=tab.page_title, table_html=table_html,
init_google_maps=True, title=tab.page_title,
javascripts=["js/map_lycees.js"], title_h2=f"Lycées d'origine des {len(etuds)} étudiants ({len(semdepts)} semestres)",
), js_coords_lycees=js_coords_lycees(etuds_by_lycee),
"""<h2 class="formsemestre">Lycées d'origine des %d étudiants (%d semestres)</h2>""" )
% (len(etuds), len(semdepts)),
t,
"""<div id="lyc_map_canvas"></div>
""",
js_coords_lycees(etuds_by_lycee),
html_sco_header.sco_footer(),
]
return "\n".join(H)
def _table_etuds_lycees(etuds, group_lycees, title, preferences, no_links=False): def _table_etuds_lycees(etuds, group_lycees, title, preferences, no_links=False):
@ -206,30 +200,19 @@ def formsemestre_etuds_lycees(
tab.base_url += "&only_primo=1" tab.base_url += "&only_primo=1"
if no_grouping: if no_grouping:
tab.base_url += "&no_grouping=1" tab.base_url += "&no_grouping=1"
t = tab.make_page(fmt=fmt, with_html_headers=False) table_html = tab.make_page(fmt=fmt, with_html_headers=False)
if fmt != "html": if fmt != "html":
return t return table_html
F = [ return render_template(
sco_report.tsp_form_primo_group( "formsemestre/etuds_lycees.j2",
form_primo_group=sco_report.tsp_form_primo_group(
only_primo, no_grouping, formsemestre_id, fmt, groups_infos=groups_infos only_primo, no_grouping, formsemestre_id, fmt, groups_infos=groups_infos
)
]
H = [
html_sco_header.sco_header(
page_title=tab.page_title,
init_google_maps=True,
cssstyles=sco_groups_view.CSSSTYLES,
javascripts=sco_groups_view.JAVASCRIPTS + ["js/map_lycees.js"],
), ),
"""<h2 class="formsemestre">Lycées d'origine des étudiants</h2>""", table_html=table_html,
"\n".join(F), title=tab.page_title,
t, title_h2="Lycées d'origine des étudiants",
"""<div id="lyc_map_canvas"></div> js_coords_lycees=js_coords_lycees(etuds_by_lycee),
""", )
js_coords_lycees(etuds_by_lycee),
html_sco_header.sco_footer(),
]
return "\n".join(H)
def qjs(txt): # quote for JS def qjs(txt): # quote for JS

View File

@ -3,15 +3,12 @@
"""Functions checking permissions for some common operations """Functions checking permissions for some common operations
""" """
from flask import g from flask import g, render_template
from flask_login import current_user from flask_login import current_user
from app import db
from app.auth.models import User from app.auth.models import User
import app.scodoc.notesdb as ndb from app.models import EtudAnnotation, FormSemestre, Identite
from app.scodoc.sco_permissions import Permission from app.scodoc.sco_permissions import Permission
from app.scodoc import html_sco_header
from app.scodoc import sco_etud
from app.scodoc import sco_exceptions from app.scodoc import sco_exceptions
@ -20,12 +17,15 @@ def can_suppress_annotation(annotation_id):
Seuls l'auteur de l'annotation et le chef de dept peuvent supprimer Seuls l'auteur de l'annotation et le chef de dept peuvent supprimer
une annotation. une annotation.
""" """
cnx = ndb.GetDBConnexion() annotation = (
annos = sco_etud.etud_annotations_list(cnx, args={"id": annotation_id}) EtudAnnotation.query.filter_by(id=annotation_id)
if len(annos) != 1: .join(Identite)
.filter_by(dept_id=g.scodoc_dept_id)
.first_or_404()
)
if not annotation:
raise sco_exceptions.ScoValueError("annotation inexistante !") raise sco_exceptions.ScoValueError("annotation inexistante !")
anno = annos[0] return (current_user.user_name == annotation.author) or current_user.has_permission(
return (current_user.user_name == anno["author"]) or current_user.has_permission(
Permission.EtudAddAnnotations Permission.EtudAddAnnotations
) )
@ -35,49 +35,35 @@ def can_edit_suivi():
return current_user.has_permission(Permission.EtudChangeAdr) return current_user.has_permission(Permission.EtudChangeAdr)
def is_chef_or_diretud(sem): # remplacé par formsemestre.est_chef_or_diretud
"Vrai si utilisateur est admin, chef dept ou responsable du semestre"
if (
current_user.has_permission(Permission.EditFormSemestre)
or current_user.id in sem["responsables"]
):
return True
return False
def check_access_diretud( def check_access_diretud(
formsemestre_id, required_permission=Permission.EditFormSemestre formsemestre_id, required_permission=Permission.EditFormSemestre
): ):
"""Check if access granted: responsable or EditFormSemestre """Check if access granted: responsable or EditFormSemestre
Return True|False, HTML_error_page Return True|False, HTML_error_page
""" """
from app.scodoc import sco_formsemestre formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
if (not current_user.has_permission(required_permission)) and (
sem = sco_formsemestre.get_formsemestre(formsemestre_id) current_user.id not in (u.id for u in formsemestre.responsables)
header = html_sco_header.sco_header(page_title="Accès interdit")
footer = html_sco_header.sco_footer()
if (current_user.id not in sem["responsables"]) and not current_user.has_permission(
required_permission
): ):
return ( return (
False, False,
"\n".join( render_template(
[ "sco_page.j2",
header, title="Accès interdit",
"<h2>Opération non autorisée pour %s</h2>" % current_user, content=f"""<h2>Opération non autorisée pour {current_user}</h2>
"<p>Responsable de ce semestre : <b>%s</b></p>"
% ", ".join( <p>Responsable(s) de ce semestre : <b>{
', '.join(
[ [
db.session.get(User, i).get_prenomnom() u.get_prenomnom()
for i in sem["responsables"] for u in formsemestre.responsables
] ])
), }</b>
footer, </p>
] """,
), ),
) )
else: return True, ""
return True, ""
def can_handle_passwd(user: User, allow_admindepts=False) -> bool: def can_handle_passwd(user: User, allow_admindepts=False) -> bool:

View File

@ -928,7 +928,7 @@ def _get_sheet_evaluations(
i, r = _xls_search_sheet_code(rows, diag) i, r = _xls_search_sheet_code(rows, diag)
if isinstance(r, int): # mono-eval if isinstance(r, int): # mono-eval
sheet_eval_id = r sheet_eval_id = r
if sheet_eval_id != evaluation.id: if (evaluation is None) or (sheet_eval_id != evaluation.id):
diag.append( diag.append(
f"""Erreur: fichier invalide: le code d'évaluation de correspond pas ! ('{ f"""Erreur: fichier invalide: le code d'évaluation de correspond pas ! ('{
sheet_eval_id or ('non trouvé')}' != '{evaluation.id}')""" sheet_eval_id or ('non trouvé')}' != '{evaluation.id}')"""

View File

@ -755,8 +755,7 @@ def saisie_notes(evaluation_id: int, group_ids: list = None):
"sco_page.j2", "sco_page.j2",
content="\n".join(H), content="\n".join(H),
title=page_title, title=page_title,
javascripts=sco_groups_view.JAVASCRIPTS + ["js/saisie_notes.js"], javascripts=["js/saisie_notes.js"],
cssstyles=sco_groups_view.CSSSTYLES,
) )

View File

@ -39,7 +39,6 @@ from app import Departement
from app.auth.models import Permission, Role, User, UserRole from app.auth.models import Permission, Role, User, UserRole
from app.models import ScoDocSiteConfig, USERNAME_STR_LEN from app.models import ScoDocSiteConfig, USERNAME_STR_LEN
from app.scodoc import html_sco_header
from app.scodoc import sco_preferences from app.scodoc import sco_preferences
from app.scodoc.gen_tables import GenTable from app.scodoc.gen_tables import GenTable
from app import cache from app import cache

View File

@ -2476,6 +2476,10 @@ li.notes_formation_list {
padding-top: 10px; padding-top: 10px;
} }
.dt-scroll-body {
overflow: initial !important;
}
table.dataTable.formation_list_table.gt_table { table.dataTable.formation_list_table.gt_table {
border-collapse: collapse; border-collapse: collapse;
margin-right: 12px; margin-right: 12px;

View File

@ -441,6 +441,10 @@ textarea {
transition: border-color 0.2s ease-in-out; transition: border-color 0.2s ease-in-out;
} }
.form-group input[type="submit"] {
max-width: var(--sco-content-max-width);
}
.form-group input:focus, .form-group input:focus,
.form-control:focus { .form-control:focus {
outline: none; outline: none;

View File

@ -0,0 +1,32 @@
{% extends "sco_page.j2" %}
{% block styles %}
{{super()}}
<style>
</style>
{% endblock %}
{% block app_content %}
<h2 class="formsemestre">{{title_h2}}</h2>
<div class="help warning">
Page non fonctionnelle dans cette version (modif. API Google)
</div>
{{form_primo_group|safe}}
{{table_html|safe}}
<div id="lyc_map_canvas"></div>
{{js_coords_lycees|safe}}
{% endblock %}
{% block scripts %}
{{super()}}
<script src="{{scu.STATIC_DIR}}/libjs/jquery.ui.map.full.min.js"></script>
<script src="https://maps.google.com/maps/api/js"></script>
<script src="{{scu.STATIC_DIR}}/js/map_lycees.js"></script>
{% endblock %}

View File

@ -3,15 +3,13 @@
{% block styles %} {% block styles %}
{{super()}} {{super()}}
<link type="text/css" rel="stylesheet" href="{{scu.STATIC_DIR}}/libjs/qtip/jquery.qtip-3.0.3.min.css" />
<link rel="stylesheet" type="text/css" href="{{scu.STATIC_DIR}}/DataTables/datatables.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 rel="stylesheet" href="{{scu.STATIC_DIR}}/css/scodoc9_mobile.css"> <link rel="stylesheet" href="{{scu.STATIC_DIR}}/css/scodoc9_mobile.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" />
<link href="{{scu.STATIC_DIR}}/css/gt_table.css" rel="stylesheet" type="text/css" /> <link href="{{scu.STATIC_DIR}}/css/gt_table.css" rel="stylesheet" type="text/css" />
<link type="text/css" rel="stylesheet" href="{{scu.STATIC_DIR}}/libjs/qtip/jquery.qtip-3.0.3.min.css" />
{#
<link href="{{scu.STATIC_DIR}}/css/tooltip.css" rel="stylesheet" type="text/css" /> #}
<link rel="stylesheet" type="text/css" href="{{scu.STATIC_DIR}}/DataTables/datatables.min.css" />
{% endblock %} {% endblock %}
{% block title %} {% block title %}

View File

@ -1,5 +1,7 @@
{# -*- mode: jinja-html -*- #} {# -*- mode: jinja-html -*- #}
{{ sco_header|safe }} {% extends "sco_page.j2" %}
{% block app_content %}
<h2 class="formsemestre">Affectation aux groupes de {{ partition.partition_name }}</h2> <h2 class="formsemestre">Affectation aux groupes de {{ partition.partition_name }}</h2>
<p class="help"> <p class="help">
@ -54,4 +56,4 @@
</div> </div>
{{ sco_footer|safe }} {% endblock %}