forked from ScoDoc/ScoDoc
Adaptation multi-select groupes
This commit is contained in:
parent
65e2ead1b4
commit
6c044dd4dd
@ -40,6 +40,7 @@ def TrivialFormulator(
|
||||
submitbuttonattributes=None,
|
||||
top_buttons=False, # place buttons at top of form
|
||||
bottom_buttons=True, # buttons after form
|
||||
html_head_markup="",
|
||||
html_foot_markup="",
|
||||
readonly=False,
|
||||
is_submitted=False,
|
||||
@ -116,6 +117,7 @@ def TrivialFormulator(
|
||||
submitbuttonattributes=submitbuttonattributes or [],
|
||||
top_buttons=top_buttons,
|
||||
bottom_buttons=bottom_buttons,
|
||||
html_head_markup=html_head_markup,
|
||||
html_foot_markup=html_foot_markup,
|
||||
readonly=readonly,
|
||||
is_submitted=is_submitted,
|
||||
@ -152,6 +154,7 @@ class TF(object):
|
||||
submitbuttonattributes=None,
|
||||
top_buttons=False, # place buttons at top of form
|
||||
bottom_buttons=True, # buttons after form
|
||||
html_head_markup="", # html snippet put at the beginning, just before the table
|
||||
html_foot_markup="", # html snippet put at the end, just after the table
|
||||
readonly=False,
|
||||
is_submitted=False,
|
||||
@ -178,6 +181,7 @@ class TF(object):
|
||||
self.submitbuttonattributes = submitbuttonattributes or []
|
||||
self.top_buttons = top_buttons
|
||||
self.bottom_buttons = bottom_buttons
|
||||
self.html_head_markup = html_head_markup
|
||||
self.html_foot_markup = html_foot_markup
|
||||
self.title = title
|
||||
self.after_table = after_table
|
||||
@ -469,6 +473,7 @@ class TF(object):
|
||||
if self.top_buttons:
|
||||
R.append(buttons_markup + "<p></p>")
|
||||
R.append(self.before_table.format(title=self.title))
|
||||
R.append(self.html_head_markup)
|
||||
R.append('<table class="tf">')
|
||||
for field, descr in self.formdescription:
|
||||
if descr.get("readonly", False):
|
||||
|
@ -289,7 +289,7 @@ enregistrés et non modifiables, on peut les retrouver ultérieurement.
|
||||
]
|
||||
menu_choix_groupe = (
|
||||
"""<div class="group_ids_sel_menu">Groupes d'étudiants à lister: """
|
||||
+ sco_groups_view.menu_groups_choice(groups_infos)
|
||||
+ sco_groups_view.menu_groups_choice(groups_infos, submit_on_change=True)
|
||||
+ """(pour les PV et lettres)</div>"""
|
||||
)
|
||||
|
||||
|
@ -732,7 +732,9 @@ def evaluation_describe(evaluation_id="", edit_in_place=True, link_saisie=True)
|
||||
H.append(
|
||||
f"""
|
||||
<a style="margin-left: 12px;" class="stdlink" href="{url_for(
|
||||
"notes.saisie_notes", scodoc_dept=g.scodoc_dept, evaluation_id=evaluation_id)
|
||||
"notes.form_saisie_notes",
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
evaluation_id=evaluation_id)
|
||||
}">saisie des notes</a>
|
||||
"""
|
||||
)
|
||||
|
@ -72,7 +72,7 @@ def moduleimpl_evaluation_menu(evaluation: Evaluation, nbnotes: int = 0) -> str:
|
||||
menu_eval = [
|
||||
{
|
||||
"title": "Saisir les notes",
|
||||
"endpoint": "notes.saisie_notes",
|
||||
"endpoint": "notes.form_saisie_notes",
|
||||
"args": {
|
||||
"evaluation_id": evaluation_id,
|
||||
},
|
||||
@ -745,7 +745,7 @@ def _ligne_evaluation(
|
||||
)
|
||||
if can_edit_notes:
|
||||
H.append(
|
||||
f"""<a class="smallbutton" href="{url_for('notes.saisie_notes',
|
||||
f"""<a class="smallbutton" href="{url_for('notes.form_saisie_notes',
|
||||
scodoc_dept=g.scodoc_dept, evaluation_id=evaluation.id)
|
||||
}">{scu.icontag("notes_img", alt="saisie notes", title="Saisie des notes")}</a>"""
|
||||
)
|
||||
@ -824,7 +824,7 @@ def _ligne_evaluation(
|
||||
)
|
||||
else:
|
||||
H.append(
|
||||
f"""<a class="redlink" href="{url_for('notes.saisie_notes',
|
||||
f"""<a class="redlink" href="{url_for('notes.form_saisie_notes',
|
||||
scodoc_dept=g.scodoc_dept, evaluation_id=evaluation.id)
|
||||
}">saisir notes</a>
|
||||
"""
|
||||
@ -880,7 +880,7 @@ def _ligne_evaluation(
|
||||
H.append("""[<font color="red">""")
|
||||
if can_edit_notes:
|
||||
H.append(
|
||||
f"""<a class="redlink" href="{url_for('notes.saisie_notes',
|
||||
f"""<a class="redlink" href="{url_for('notes.form_saisie_notes',
|
||||
scodoc_dept=g.scodoc_dept, evaluation_id=evaluation.id,
|
||||
**{'group_ids:list': gr_moyenne["group_id"]})
|
||||
}">incomplet : terminer saisie</a></font>]"""
|
||||
@ -891,9 +891,9 @@ def _ligne_evaluation(
|
||||
H.append("""<span class="redboldtext"> """)
|
||||
if can_edit_notes:
|
||||
H.append(
|
||||
f"""<a class="redlink" href="{url_for('notes.saisie_notes',
|
||||
f"""<a class="redlink" href="{url_for('notes.form_saisie_notes',
|
||||
scodoc_dept=g.scodoc_dept, evaluation_id=evaluation.id,
|
||||
**{'group_ids:list': gr_moyenne["group_id"]})
|
||||
**{'group_ids': gr_moyenne["group_id"]})
|
||||
}">"""
|
||||
)
|
||||
H.append("pas de notes")
|
||||
|
@ -50,6 +50,7 @@ from app.scodoc import sco_pdf
|
||||
from app.scodoc import sco_preferences
|
||||
from app.scodoc import sco_pv_pdf
|
||||
from app.scodoc import sco_pv_lettres_inviduelles
|
||||
from app.scodoc.sco_exceptions import ScoValueError
|
||||
from app.scodoc.gen_tables import GenTable
|
||||
from app.scodoc.codes_cursus import NO_SEMESTRE_ID
|
||||
from app.scodoc.sco_pdf import PDFLOCK
|
||||
@ -336,12 +337,20 @@ def formsemestre_pvjury(formsemestre_id, fmt="html", publish=True):
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
def formsemestre_pvjury_pdf(formsemestre_id, group_ids: list[int] = None, etudid=None):
|
||||
"""Generation PV jury en PDF: saisie des paramètres
|
||||
Si etudid, PV pour un seul etudiant. Sinon, tout les inscrits au groupe indiqué.
|
||||
def formsemestre_pvjury_pdf(formsemestre_id, etudid=None):
|
||||
"""Génération PV jury en PDF: saisie des paramètres
|
||||
Si etudid, PV pour un seul etudiant.
|
||||
Sinon, tout les inscrits au(x) groupe(s) indiqué(s).
|
||||
"""
|
||||
group_ids = group_ids or []
|
||||
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
||||
if request.method == "POST":
|
||||
group_ids = request.form.getlist("group_ids")
|
||||
else:
|
||||
group_ids = request.args.getlist("group_ids")
|
||||
try:
|
||||
group_ids = [int(gid) for gid in group_ids]
|
||||
except ValueError as exc:
|
||||
raise ScoValueError("group_ids invalide") from exc
|
||||
formsemestre: FormSemestre = FormSemestre.get_formsemestre(formsemestre_id)
|
||||
# Mise à jour des groupes d'étapes:
|
||||
sco_groups.create_etapes_partition(formsemestre_id)
|
||||
groups_infos = None
|
||||
@ -361,7 +370,8 @@ def formsemestre_pvjury_pdf(formsemestre_id, group_ids: list[int] = None, etudid
|
||||
etudids = [m["etudid"] for m in groups_infos.members]
|
||||
|
||||
H = [
|
||||
f"""<div class="help">Utiliser cette page pour éditer des versions provisoires des PV.
|
||||
f"""<div class="help space-after-24">
|
||||
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(
|
||||
'notes.formsemestre_archive',
|
||||
@ -381,7 +391,7 @@ def formsemestre_pvjury_pdf(formsemestre_id, group_ids: list[int] = None, etudid
|
||||
if groups_infos:
|
||||
menu_choix_groupe = (
|
||||
"""<div class="group_ids_sel_menu">Groupes d'étudiants à lister sur le PV: """
|
||||
+ sco_groups_view.menu_groups_choice(groups_infos)
|
||||
+ sco_groups_view.menu_groups_choice(groups_infos, submit_on_change=True)
|
||||
+ """</div>"""
|
||||
)
|
||||
else:
|
||||
@ -394,24 +404,28 @@ def formsemestre_pvjury_pdf(formsemestre_id, group_ids: list[int] = None, etudid
|
||||
submitlabel="Générer document",
|
||||
name="tf",
|
||||
formid="group_selector",
|
||||
html_foot_markup=menu_choix_groupe,
|
||||
html_head_markup=menu_choix_groupe,
|
||||
)
|
||||
if tf[0] == 0:
|
||||
info_etud = (
|
||||
f"""de <a class="discretelink" href="{
|
||||
url_for("scolar.fiche_etud", scodoc_dept=g.scodoc_dept, etudid=etudid)
|
||||
}">{etud.nomprenom}</a>"""
|
||||
if etud
|
||||
else ""
|
||||
)
|
||||
return render_template(
|
||||
"sco_page.j2",
|
||||
title=f"Édition du PV de jury {('de ' + etud.nom_prenom()) if etud else ''}",
|
||||
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>"""
|
||||
{info_etud}</h2>"""
|
||||
+ "\n".join(H)
|
||||
+ "\n"
|
||||
+ tf[1]
|
||||
+ "\n".join(F),
|
||||
javascripts=sco_groups_view.JAVASCRIPTS,
|
||||
cssstyles=sco_groups_view.CSSSTYLES,
|
||||
javascripts=["js/groups_view.js"],
|
||||
)
|
||||
elif tf[0] == -1:
|
||||
if tf[0] == -1:
|
||||
return flask.redirect(
|
||||
url_for(
|
||||
"notes.formsemestre_pvjury",
|
||||
@ -419,34 +433,34 @@ def formsemestre_pvjury_pdf(formsemestre_id, group_ids: list[int] = None, etudid
|
||||
formsemestre_id=formsemestre_id,
|
||||
)
|
||||
)
|
||||
|
||||
# submit
|
||||
tf[2]["show_title"] = bool(tf[2]["show_title"])
|
||||
tf[2]["anonymous"] = bool(tf[2]["anonymous"])
|
||||
try:
|
||||
PDFLOCK.acquire()
|
||||
pdfdoc = sco_pv_pdf.pvjury_pdf(
|
||||
formsemestre,
|
||||
etudids,
|
||||
numero_arrete=tf[2]["numero_arrete"],
|
||||
code_vdi=tf[2]["code_vdi"],
|
||||
date_commission=tf[2]["date_commission"],
|
||||
date_jury=tf[2]["date_jury"],
|
||||
show_title=tf[2]["show_title"],
|
||||
pv_title_session=tf[2]["pv_title_session"],
|
||||
pv_title=tf[2]["pv_title"],
|
||||
with_paragraph_nom=tf[2]["with_paragraph_nom"],
|
||||
anonymous=tf[2]["anonymous"],
|
||||
)
|
||||
finally:
|
||||
PDFLOCK.release()
|
||||
date_iso = time.strftime("%Y-%m-%d")
|
||||
if groups_infos:
|
||||
groups_filename = "-" + groups_infos.groups_filename
|
||||
else:
|
||||
# submit
|
||||
tf[2]["show_title"] = bool(tf[2]["show_title"])
|
||||
tf[2]["anonymous"] = bool(tf[2]["anonymous"])
|
||||
try:
|
||||
PDFLOCK.acquire()
|
||||
pdfdoc = sco_pv_pdf.pvjury_pdf(
|
||||
formsemestre,
|
||||
etudids,
|
||||
numero_arrete=tf[2]["numero_arrete"],
|
||||
code_vdi=tf[2]["code_vdi"],
|
||||
date_commission=tf[2]["date_commission"],
|
||||
date_jury=tf[2]["date_jury"],
|
||||
show_title=tf[2]["show_title"],
|
||||
pv_title_session=tf[2]["pv_title_session"],
|
||||
pv_title=tf[2]["pv_title"],
|
||||
with_paragraph_nom=tf[2]["with_paragraph_nom"],
|
||||
anonymous=tf[2]["anonymous"],
|
||||
)
|
||||
finally:
|
||||
PDFLOCK.release()
|
||||
date_iso = time.strftime("%Y-%m-%d")
|
||||
if groups_infos:
|
||||
groups_filename = "-" + groups_infos.groups_filename
|
||||
else:
|
||||
groups_filename = ""
|
||||
filename = f"""PV-{formsemestre.titre_num()}{groups_filename}-{date_iso}.pdf"""
|
||||
return scu.sendPDFFile(pdfdoc, filename)
|
||||
groups_filename = ""
|
||||
filename = f"""PV-{formsemestre.titre_num()}{groups_filename}-{date_iso}.pdf"""
|
||||
return scu.sendPDFFile(pdfdoc, filename)
|
||||
|
||||
|
||||
def descrform_pvjury(formsemestre: FormSemestre):
|
||||
@ -542,9 +556,17 @@ def descrform_pvjury(formsemestre: FormSemestre):
|
||||
]
|
||||
|
||||
|
||||
def formsemestre_lettres_individuelles(formsemestre_id, group_ids=()):
|
||||
def formsemestre_lettres_individuelles(formsemestre_id):
|
||||
"Lettres avis jury en PDF"
|
||||
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
||||
if request.method == "POST":
|
||||
group_ids = request.form.getlist("group_ids")
|
||||
else:
|
||||
group_ids = request.args.getlist("group_ids")
|
||||
try:
|
||||
group_ids = [int(gid) for gid in group_ids]
|
||||
except ValueError as exc:
|
||||
raise ScoValueError("group_ids invalide") from exc
|
||||
if not group_ids:
|
||||
# tous les inscrits du semestre
|
||||
group_ids = [sco_groups.get_default_group(formsemestre_id)]
|
||||
@ -556,20 +578,22 @@ def formsemestre_lettres_individuelles(formsemestre_id, group_ids=()):
|
||||
H = [
|
||||
f"""
|
||||
<h2 class="formsemestre">Édition des lettres individuelles</h2>
|
||||
<p class="help">Utiliser cette page pour éditer des versions provisoires des PV.
|
||||
<div class="help space-after-24">
|
||||
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",
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
formsemestre_id=formsemestre_id,
|
||||
)}"
|
||||
>voir cette page</a></span></p>
|
||||
>voir cette page</a></span>
|
||||
</div>
|
||||
""",
|
||||
]
|
||||
descr = descrform_lettres_individuelles()
|
||||
menu_choix_groupe = (
|
||||
"""<div class="group_ids_sel_menu">Groupes d'étudiants à lister: """
|
||||
+ sco_groups_view.menu_groups_choice(groups_infos)
|
||||
+ sco_groups_view.menu_groups_choice(groups_infos, submit_on_change=True)
|
||||
+ """</div>"""
|
||||
)
|
||||
|
||||
@ -581,15 +605,14 @@ def formsemestre_lettres_individuelles(formsemestre_id, group_ids=()):
|
||||
submitlabel="Générer document",
|
||||
name="tf",
|
||||
formid="group_selector",
|
||||
html_foot_markup=menu_choix_groupe,
|
||||
html_head_markup=menu_choix_groupe,
|
||||
)
|
||||
if tf[0] == 0:
|
||||
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,
|
||||
javascripts=["js/groups_view.js"],
|
||||
)
|
||||
elif tf[0] == -1:
|
||||
return flask.redirect(
|
||||
|
@ -296,6 +296,14 @@ def formsemestre_report_counts(
|
||||
sinon liste prédéfinie (voir ci-dessous)
|
||||
"""
|
||||
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
|
||||
if request.method == "POST":
|
||||
group_ids = request.form.getlist("group_ids")
|
||||
else:
|
||||
group_ids = request.args.getlist("group_ids")
|
||||
try:
|
||||
group_ids = [int(gid) for gid in group_ids]
|
||||
except ValueError as exc:
|
||||
raise ScoValueError("group_ids invalide") from exc
|
||||
groups_infos = sco_groups_view.DisplayedGroupsInfos(
|
||||
group_ids,
|
||||
formsemestre_id=formsemestre.id,
|
||||
@ -420,8 +428,7 @@ def formsemestre_report_counts(
|
||||
]
|
||||
return render_template(
|
||||
"sco_page.j2",
|
||||
cssstyles=sco_groups_view.CSSSTYLES,
|
||||
javascripts=sco_groups_view.JAVASCRIPTS,
|
||||
javascripts=["js/groups_view.js"],
|
||||
title=title,
|
||||
content="\n".join(H),
|
||||
)
|
||||
@ -740,7 +747,6 @@ def table_suivi_cohorte(
|
||||
def formsemestre_suivi_cohorte(
|
||||
formsemestre_id,
|
||||
fmt="html",
|
||||
group_ids: list[int] = None, # si indiqué, ne prend que ces groupes
|
||||
percent=1,
|
||||
bac="",
|
||||
bacspecialite="",
|
||||
@ -759,6 +765,14 @@ def formsemestre_suivi_cohorte(
|
||||
raise ScoValueError("formsemestre_suivi_cohorte: argument invalide") from exc
|
||||
|
||||
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
|
||||
if request.method == "POST":
|
||||
group_ids = request.form.getlist("group_ids")
|
||||
else:
|
||||
group_ids = request.args.getlist("group_ids")
|
||||
try:
|
||||
group_ids = [int(gid) for gid in group_ids]
|
||||
except ValueError as exc:
|
||||
raise ScoValueError("group_ids invalide") from exc
|
||||
groups_infos = sco_groups_view.DisplayedGroupsInfos(
|
||||
group_ids,
|
||||
formsemestre_id=formsemestre.id,
|
||||
@ -850,8 +864,7 @@ def formsemestre_suivi_cohorte(
|
||||
]
|
||||
return render_template(
|
||||
"sco_page.j2",
|
||||
cssstyles=sco_groups_view.CSSSTYLES,
|
||||
javascripts=sco_groups_view.JAVASCRIPTS,
|
||||
javascripts=["js/groups_view.js"],
|
||||
title=tab.page_title,
|
||||
content="\n".join(H),
|
||||
)
|
||||
@ -1629,7 +1642,6 @@ def graph_cursus(
|
||||
|
||||
def formsemestre_graph_cursus(
|
||||
formsemestre_id,
|
||||
group_ids: list[int] = None, # si indiqué, ne prend que ces groupes
|
||||
fmt="html",
|
||||
only_primo=False,
|
||||
bac="", # selection sur type de bac
|
||||
@ -1644,6 +1656,15 @@ def formsemestre_graph_cursus(
|
||||
annee_bac = str(annee_bac or "")
|
||||
annee_admission = str(annee_admission or "")
|
||||
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
|
||||
if request.method == "POST":
|
||||
group_ids = request.form.getlist("group_ids")
|
||||
else:
|
||||
group_ids = request.args.getlist("group_ids")
|
||||
try:
|
||||
group_ids = [int(gid) for gid in group_ids]
|
||||
except ValueError as exc:
|
||||
raise ScoValueError("group_ids invalide") from exc
|
||||
|
||||
groups_infos = sco_groups_view.DisplayedGroupsInfos(
|
||||
group_ids,
|
||||
formsemestre_id=formsemestre.id,
|
||||
@ -1781,8 +1802,7 @@ def formsemestre_graph_cursus(
|
||||
]
|
||||
return render_template(
|
||||
"sco_page.j2",
|
||||
cssstyles=sco_groups_view.CSSSTYLES,
|
||||
javascripts=sco_groups_view.JAVASCRIPTS,
|
||||
javascripts=["js/groups_view.js"],
|
||||
page_title=f"Graphe cursus de {sem['titreannee']}",
|
||||
no_sidebar=True,
|
||||
content="\n".join(H),
|
||||
|
@ -68,7 +68,9 @@ from app.views import ScoData
|
||||
FONT_NAME = "Arial"
|
||||
|
||||
|
||||
def excel_feuille_saisie(evaluation: "Evaluation", rows: list[dict]) -> AnyStr:
|
||||
def excel_feuille_saisie(
|
||||
evaluation: "Evaluation", rows: list[dict], groups_titles: str = ""
|
||||
) -> AnyStr:
|
||||
"""Génère feuille excel pour saisie des notes dans l'evaluation
|
||||
- evaluation
|
||||
- rows: liste de dict
|
||||
@ -77,7 +79,9 @@ def excel_feuille_saisie(evaluation: "Evaluation", rows: list[dict]) -> AnyStr:
|
||||
"""
|
||||
ws = ScoExcelSheet("Saisie notes")
|
||||
styles = _build_styles()
|
||||
nb_lines_titles = _insert_top_title(ws, styles, evaluation=evaluation)
|
||||
nb_lines_titles = _insert_top_title(
|
||||
ws, styles, evaluation=evaluation, groups_titles=groups_titles
|
||||
)
|
||||
|
||||
_insert_line_titles(
|
||||
ws,
|
||||
@ -263,6 +267,7 @@ def _insert_top_title(
|
||||
evaluation: Evaluation | None = None,
|
||||
formsemestre: FormSemestre | None = None,
|
||||
description="",
|
||||
groups_titles: str = "",
|
||||
) -> int:
|
||||
"""Insère les lignes de titre de la feuille (suivies d'une ligne blanche).
|
||||
Si evaluation, indique son titre.
|
||||
@ -298,7 +303,7 @@ def _insert_top_title(
|
||||
evaluation.moduleimpl.formsemestre.titre_annee()
|
||||
if evaluation
|
||||
else (formsemestre.titre_annee() if formsemestre else "")
|
||||
)
|
||||
) + ((" - " + groups_titles) if groups_titles else "")
|
||||
ws.append_single_cell_row(
|
||||
scu.unescape_html(titre_annee), styles["titres"], prefix=[""]
|
||||
)
|
||||
@ -372,15 +377,16 @@ def _insert_bottom_help(ws, styles: dict):
|
||||
)
|
||||
|
||||
|
||||
def feuille_saisie_notes(
|
||||
evaluation_id, group_ids: list[int] = None
|
||||
): # TODO ré-écrire et passer dans notes.py
|
||||
def feuille_saisie_notes(evaluation_id: int): # TODO ré-écrire et passer dans notes.py
|
||||
"""Vue: document Excel pour saisie notes dans l'évaluation et les groupes indiqués"""
|
||||
evaluation = Evaluation.get_evaluation(evaluation_id)
|
||||
group_ids = group_ids or []
|
||||
group_ids = request.args.getlist("group_ids") or []
|
||||
try:
|
||||
group_ids = [int(gid) for gid in group_ids]
|
||||
except ValueError as exc:
|
||||
raise ScoValueError("group_ids invalide") from exc
|
||||
modimpl = evaluation.moduleimpl
|
||||
formsemestre = modimpl.formsemestre
|
||||
|
||||
if evaluation.date_debut:
|
||||
indication_date = evaluation.date_debut.date().isoformat()
|
||||
else:
|
||||
@ -430,7 +436,9 @@ def feuille_saisie_notes(
|
||||
|
||||
eval_name = f"{evaluation.moduleimpl.module.code}-{indication_date}"
|
||||
filename = f"notes_{eval_name}_{gr_title_filename}"
|
||||
xls = excel_feuille_saisie(evaluation, rows=rows)
|
||||
xls = excel_feuille_saisie(
|
||||
evaluation, rows=rows, groups_titles=groups_infos.groups_titles
|
||||
)
|
||||
return scu.send_file(xls, filename, scu.XLSX_SUFFIX, mime=scu.XLSX_MIMETYPE)
|
||||
|
||||
|
||||
@ -962,9 +970,14 @@ def _get_sheet_evaluations(
|
||||
raise ValueError("_get_sheet_evaluations")
|
||||
|
||||
|
||||
def saisie_notes_tableur(evaluation_id: int, group_ids=()):
|
||||
def saisie_notes_tableur(evaluation_id: int):
|
||||
"""Saisie des notes via un fichier Excel"""
|
||||
evaluation = Evaluation.query.get_or_404(evaluation_id)
|
||||
group_ids = request.args.getlist("group_ids")
|
||||
try:
|
||||
group_ids = [int(gid) for gid in group_ids]
|
||||
except ValueError as exc:
|
||||
raise ScoValueError("group_ids invalide") from exc
|
||||
evaluation = Evaluation.get_evaluation(evaluation_id)
|
||||
moduleimpl_id = evaluation.moduleimpl.id
|
||||
formsemestre_id = evaluation.moduleimpl.formsemestre_id
|
||||
if not evaluation.moduleimpl.can_edit_notes(current_user):
|
||||
@ -1004,18 +1017,20 @@ def saisie_notes_tableur(evaluation_id: int, group_ids=()):
|
||||
|
||||
# Menu choix groupe:
|
||||
H.append("""<div id="group-tabs"><table><tr><td>""")
|
||||
H.append(sco_groups_view.form_groups_choice(groups_infos))
|
||||
H.append(sco_groups_view.form_groups_choice(groups_infos, submit_on_change=True))
|
||||
H.append("</td></tr></table></div>")
|
||||
|
||||
H.append(
|
||||
f"""<div class="saisienote_etape1">
|
||||
<span class="titredivsaisienote">Étape 1 : </span>
|
||||
<ul>
|
||||
<li><a class="stdlink" href="feuille_saisie_notes?evaluation_id={evaluation_id}&{
|
||||
<li><a class="stdlink" href="{
|
||||
url_for('notes.feuille_saisie_notes',
|
||||
scodoc_dept=g.scodoc_dept, evaluation_id=evaluation_id)}&{
|
||||
groups_infos.groups_query_args}"
|
||||
id="lnk_feuille_saisie">obtenir le fichier tableur à remplir</a>
|
||||
</li>
|
||||
<li>ou <a class="stdlink" href="{url_for("notes.saisie_notes",
|
||||
<li>ou <a class="stdlink" href="{url_for("notes.form_saisie_notes",
|
||||
scodoc_dept=g.scodoc_dept, evaluation_id=evaluation_id)
|
||||
}">aller au formulaire de saisie</a></li>
|
||||
</ul>
|
||||
@ -1085,7 +1100,7 @@ def saisie_notes_tableur(evaluation_id: int, group_ids=()):
|
||||
scodoc_dept=g.scodoc_dept, evaluation_id=evaluation.id)
|
||||
}">Charger un autre fichier de notes</a>
|
||||
|
||||
<a class="stdlink" href="{url_for("notes.saisie_notes",
|
||||
<a class="stdlink" href="{url_for("notes.form_saisie_notes",
|
||||
scodoc_dept=g.scodoc_dept, evaluation_id=evaluation.id)
|
||||
}">Formulaire de saisie des notes</a>
|
||||
</div>"""
|
||||
@ -1113,7 +1128,9 @@ def saisie_notes_tableur(evaluation_id: int, group_ids=()):
|
||||
<div>
|
||||
<ul>
|
||||
<li>
|
||||
<form action="do_evaluation_set_missing" method="POST">
|
||||
<form action="{
|
||||
url_for("notes.do_evaluation_set_missing", scodoc_dept=g.scodoc_dept)
|
||||
}" method="POST">
|
||||
Mettre toutes les notes manquantes à <input type="text" size="5" name="value"/>
|
||||
<input type="submit" value="OK"/>
|
||||
<input type="hidden" name="evaluation_id" value="{evaluation_id}"/>
|
||||
@ -1129,7 +1146,7 @@ def saisie_notes_tableur(evaluation_id: int, group_ids=()):
|
||||
scodoc_dept=g.scodoc_dept, moduleimpl_id=moduleimpl_id)
|
||||
}">Revenir au module</a>
|
||||
</li>
|
||||
<li><a class="stdlink" href="{url_for("notes.saisie_notes",
|
||||
<li><a class="stdlink" href="{url_for("notes.form_saisie_notes",
|
||||
scodoc_dept=g.scodoc_dept, evaluation_id=evaluation.id)
|
||||
}">Revenir au formulaire de saisie</a>
|
||||
</li>
|
||||
@ -1176,8 +1193,7 @@ def saisie_notes_tableur(evaluation_id: int, group_ids=()):
|
||||
"sco_page.j2",
|
||||
content="\n".join(H),
|
||||
page_title=page_title,
|
||||
javascripts=sco_groups_view.JAVASCRIPTS,
|
||||
cssstyles=sco_groups_view.CSSSTYLES,
|
||||
javascripts=["js/groups_view.js"],
|
||||
)
|
||||
|
||||
|
||||
|
@ -54,7 +54,6 @@ from app.scodoc.sco_exceptions import (
|
||||
AccessDenied,
|
||||
NoteProcessError,
|
||||
ScoException,
|
||||
ScoInvalidParamError,
|
||||
ScoValueError,
|
||||
)
|
||||
from app.scodoc import htmlutils
|
||||
@ -71,6 +70,7 @@ from app.scodoc.TrivialFormulator import TF
|
||||
import app.scodoc.sco_utils as scu
|
||||
from app.scodoc.sco_utils import json_error
|
||||
from app.scodoc.sco_utils import ModuleType
|
||||
from app.views import ScoData
|
||||
|
||||
|
||||
def convert_note_from_string(
|
||||
@ -212,7 +212,7 @@ def do_evaluation_set_missing(
|
||||
evaluation_id, value, dialog_confirmed=False, group_ids_str: str = ""
|
||||
):
|
||||
"""Initialisation des notes manquantes"""
|
||||
evaluation = Evaluation.query.get_or_404(evaluation_id)
|
||||
evaluation = Evaluation.get_evaluation(evaluation_id)
|
||||
modimpl = evaluation.moduleimpl
|
||||
# Check access
|
||||
# (admin, respformation, and responsable_id)
|
||||
@ -222,8 +222,12 @@ def do_evaluation_set_missing(
|
||||
notes_db = sco_evaluation_db.do_evaluation_get_all_notes(evaluation_id)
|
||||
if not group_ids_str:
|
||||
groups = None
|
||||
groups_infos = None
|
||||
else:
|
||||
group_ids = [int(x) for x in str(group_ids_str).split(",")]
|
||||
groups_infos = sco_groups_view.DisplayedGroupsInfos(
|
||||
group_ids, formsemestre_id=modimpl.formsemestre.id
|
||||
)
|
||||
groups = sco_groups.listgroups(group_ids)
|
||||
|
||||
etudid_etats = sco_groups.do_evaluation_listeetuds_groups(
|
||||
@ -240,7 +244,9 @@ def do_evaluation_set_missing(
|
||||
# Convert and check values
|
||||
valid_notes, invalids, _, _, _ = check_notes(notes, evaluation)
|
||||
dest_url = url_for(
|
||||
"notes.saisie_notes", scodoc_dept=g.scodoc_dept, evaluation_id=evaluation_id
|
||||
"notes.form_saisie_notes",
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
evaluation_id=evaluation_id,
|
||||
)
|
||||
diag = ""
|
||||
if len(invalids) > 0:
|
||||
@ -260,12 +266,17 @@ def do_evaluation_set_missing(
|
||||
plural = len(valid_notes) > 1
|
||||
return scu.confirm_dialog(
|
||||
f"""<h2>Mettre toutes les notes manquantes de l'évaluation
|
||||
à la valeur {value} ?</h2>
|
||||
à la valeur <span class="fontred">{value} / {evaluation.note_max:g}</span> ?</h2>
|
||||
<p>Seuls les étudiants pour lesquels aucune note (ni valeur, ni ABS, ni EXC)
|
||||
n'a été rentrée seront affectés.</p>
|
||||
<p><b>{len(valid_notes)} étudiant{"s" if plural else ""} concerné{"s" if plural else ""}
|
||||
<div>
|
||||
<b>Groupes: {groups_infos.groups_titles if groups_infos else "tous"},
|
||||
dont
|
||||
<span class="fontred">
|
||||
{len(valid_notes)} étudiant{"s" if plural else ""} concerné{"s" if plural else ""}
|
||||
</span>
|
||||
par ce changement de note.</b>
|
||||
</p>
|
||||
</div>
|
||||
""",
|
||||
dest_url="",
|
||||
cancel_url=dest_url,
|
||||
@ -624,14 +635,8 @@ def _record_note(
|
||||
|
||||
|
||||
# Nouveau formulaire saisie notes (2016)
|
||||
def saisie_notes(evaluation_id: int, group_ids: list = None):
|
||||
def saisie_notes(evaluation: Evaluation, group_ids: list[int] | tuple[int] = ()):
|
||||
"""Formulaire saisie notes d'une évaluation pour un groupe"""
|
||||
if not isinstance(evaluation_id, int):
|
||||
raise ScoInvalidParamError()
|
||||
group_ids = [int(group_id) for group_id in (group_ids or [])]
|
||||
evaluation: Evaluation = db.session.get(Evaluation, evaluation_id)
|
||||
if evaluation is None:
|
||||
raise ScoValueError("évaluation inexistante")
|
||||
modimpl = evaluation.moduleimpl
|
||||
moduleimpl_status_url = url_for(
|
||||
"notes.moduleimpl_status",
|
||||
@ -660,7 +665,6 @@ def saisie_notes(evaluation_id: int, group_ids: list = None):
|
||||
select_all_when_unspecified=True,
|
||||
etat=None,
|
||||
)
|
||||
|
||||
page_title = (
|
||||
f'Saisie "{evaluation.description}"'
|
||||
if evaluation.description
|
||||
@ -669,12 +673,12 @@ def saisie_notes(evaluation_id: int, group_ids: list = None):
|
||||
# HTML page:
|
||||
H = [
|
||||
sco_evaluations.evaluation_describe(
|
||||
evaluation_id=evaluation_id, link_saisie=False
|
||||
evaluation_id=evaluation.id, link_saisie=False
|
||||
),
|
||||
'<div id="saisie_notes"><span class="eval_title">Saisie des notes</span>',
|
||||
]
|
||||
H.append("""<div id="group-tabs"><table><tr><td>""")
|
||||
H.append(sco_groups_view.form_groups_choice(groups_infos))
|
||||
H.append(sco_groups_view.form_groups_choice(groups_infos, submit_on_change=True))
|
||||
H.append('</td><td style="padding-left: 35px;">')
|
||||
H.append(
|
||||
htmlutils.make_menu(
|
||||
@ -755,7 +759,8 @@ def saisie_notes(evaluation_id: int, group_ids: list = None):
|
||||
"sco_page.j2",
|
||||
content="\n".join(H),
|
||||
title=page_title,
|
||||
javascripts=["js/saisie_notes.js"],
|
||||
javascripts=["js/groups_view.js", "js/saisie_notes.js"],
|
||||
sco=ScoData(formsemestre=modimpl.formsemestre),
|
||||
)
|
||||
|
||||
|
||||
@ -839,11 +844,15 @@ def _form_saisie_notes(
|
||||
"""
|
||||
formsemestre_id = modimpl.formsemestre_id
|
||||
formsemestre: FormSemestre = evaluation.moduleimpl.formsemestre
|
||||
groups = sco_groups.listgroups(groups_infos.group_ids)
|
||||
res: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
||||
etudids = [
|
||||
x[0]
|
||||
for x in sco_groups.do_evaluation_listeetuds_groups(
|
||||
evaluation.id, getallstudents=True, include_demdef=True
|
||||
evaluation.id,
|
||||
groups=groups,
|
||||
getallstudents=groups is None,
|
||||
include_demdef=True,
|
||||
)
|
||||
]
|
||||
if not etudids:
|
||||
@ -1001,7 +1010,9 @@ def _form_saisie_notes(
|
||||
H.append(
|
||||
f"""
|
||||
<div>
|
||||
<form id="do_evaluation_set_missing" action="do_evaluation_set_missing" method="POST">
|
||||
<form id="do_evaluation_set_missing" action="{
|
||||
url_for("notes.do_evaluation_set_missing", scodoc_dept=g.scodoc_dept)
|
||||
}" method="POST">
|
||||
Mettre les notes manquantes à
|
||||
<input type="text" size="5" name="value"/>
|
||||
<input type="submit" value="OK"/>
|
||||
|
@ -12,7 +12,6 @@ from docx.shared import Mm
|
||||
from docx.enum.text import WD_ALIGN_PARAGRAPH
|
||||
from docx.enum.table import WD_ALIGN_VERTICAL
|
||||
|
||||
from app.scodoc import sco_etud
|
||||
from app.scodoc import sco_photos
|
||||
import app.scodoc.sco_utils as scu
|
||||
import sco_version
|
||||
@ -31,9 +30,9 @@ def trombino_doc(groups_infos):
|
||||
)
|
||||
section = document.sections[0]
|
||||
footer = section.footer
|
||||
footer.paragraphs[
|
||||
0
|
||||
].text = f"Généré par {sco_version.SCONAME} le {scu.timedate_human_repr()}"
|
||||
footer.paragraphs[0].text = (
|
||||
f"Généré par {sco_version.SCONAME} le {scu.timedate_human_repr()}"
|
||||
)
|
||||
|
||||
nb_images = len(groups_infos.members)
|
||||
table = document.add_table(rows=2 * (nb_images // N_PER_ROW + 1), cols=N_PER_ROW)
|
||||
|
@ -1543,15 +1543,18 @@ def confirm_dialog(
|
||||
H = [
|
||||
f"""<form {action} method="POST">
|
||||
{message}
|
||||
|
||||
<div class="form-group space-before-24">
|
||||
""",
|
||||
]
|
||||
if OK or not cancel_url:
|
||||
H.append(f'<input type="submit" value="{OK}"/>')
|
||||
H.append(f'<input class="btn btn-default" type="submit" value="{OK}"/>')
|
||||
if cancel_url:
|
||||
H.append(
|
||||
f"""<input type ="button" value="{cancel_label}"
|
||||
onClick="document.location='{cancel_url}';"/>"""
|
||||
f"""<input class="btn btn-default" type="submit" name="cancel" type ="button" value="{cancel_label}"
|
||||
onClick="event.preventDefault(); document.location='{cancel_url}';"/>"""
|
||||
)
|
||||
H.append("</div>")
|
||||
for param in parameters.keys():
|
||||
if parameters[param] is None:
|
||||
parameters[param] = ""
|
||||
|
@ -66,6 +66,10 @@ div.sco-app-content {
|
||||
margin-top: 24px !important;
|
||||
}
|
||||
|
||||
.space-after-24 {
|
||||
margin-bottom: 24px !important;
|
||||
}
|
||||
|
||||
div.scobox.maxwidth {
|
||||
max-width: none;
|
||||
}
|
||||
|
@ -441,8 +441,13 @@ textarea {
|
||||
transition: border-color 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.form-group input[type="submit"] {
|
||||
max-width: var(--sco-content-max-width);
|
||||
/* Media query for desktop devices
|
||||
évite que les boutons submit ne deviennent trop larges
|
||||
*/
|
||||
@media (min-width: 769px) {
|
||||
.form-group input[type="submit"] {
|
||||
width: 192px;
|
||||
}
|
||||
}
|
||||
|
||||
.form-group input:focus,
|
||||
|
@ -1836,7 +1836,6 @@ sco_publish(
|
||||
sco_saisie_excel.feuille_saisie_notes,
|
||||
Permission.EnsView,
|
||||
)
|
||||
sco_publish("/saisie_notes", sco_saisie_notes.saisie_notes, Permission.EnsView)
|
||||
sco_publish(
|
||||
"/do_evaluation_set_missing",
|
||||
sco_saisie_notes.do_evaluation_set_missing,
|
||||
@ -1851,6 +1850,20 @@ sco_publish(
|
||||
)
|
||||
|
||||
|
||||
@bp.route("/form_saisie_notes/<int:evaluation_id>")
|
||||
@scodoc
|
||||
@permission_required(Permission.EnsView) # + controle contextuel
|
||||
def form_saisie_notes(evaluation_id: int):
|
||||
"Formulaire de saisie des notes d'une évaluation"
|
||||
evaluation = Evaluation.get_evaluation(evaluation_id)
|
||||
group_ids = request.args.getlist("group_ids")
|
||||
try:
|
||||
group_ids = [int(gid) for gid in group_ids]
|
||||
except ValueError as exc:
|
||||
raise ScoValueError("group_ids invalide") from exc
|
||||
return sco_saisie_notes.saisie_notes(evaluation, group_ids)
|
||||
|
||||
|
||||
@bp.route("/formsemestre_import_notes/<int:formsemestre_id>", methods=["GET", "POST"])
|
||||
@scodoc
|
||||
@permission_required(Permission.ScoView) # controle contextuel
|
||||
@ -2117,7 +2130,9 @@ def _formsemestre_bulletins_choice(
|
||||
explanation=explanation,
|
||||
choose_mail=choose_mail,
|
||||
formsemestre=formsemestre,
|
||||
menu_groups_choice=sco_groups_view.menu_groups_choice(groups_infos),
|
||||
menu_groups_choice=sco_groups_view.menu_groups_choice(
|
||||
groups_infos, submit_on_change=True
|
||||
),
|
||||
sco=ScoData(formsemestre=formsemestre),
|
||||
sco_groups_view=sco_groups_view,
|
||||
title=title,
|
||||
|
Loading…
Reference in New Issue
Block a user