forked from ScoDoc/ScoDoc
Amélioration evaluation_listenotes
This commit is contained in:
parent
0c3216e432
commit
6c6d1103e6
@ -47,6 +47,7 @@ def TrivialFormulator(
|
||||
title="",
|
||||
after_table="",
|
||||
before_table="{title}",
|
||||
hidden_args: list[tuple] | None = None,
|
||||
):
|
||||
"""
|
||||
form_url : URL for this form
|
||||
@ -124,6 +125,7 @@ def TrivialFormulator(
|
||||
title=title,
|
||||
after_table=after_table,
|
||||
before_table=before_table,
|
||||
hidden_args=hidden_args,
|
||||
)
|
||||
form = t.getform()
|
||||
if t.canceled():
|
||||
@ -161,6 +163,7 @@ class TF(object):
|
||||
title="",
|
||||
after_table="",
|
||||
before_table="{title}",
|
||||
hidden_args: list[tuple] | None = None,
|
||||
):
|
||||
self.form_url = form_url
|
||||
self.values = values.copy()
|
||||
@ -186,6 +189,7 @@ class TF(object):
|
||||
self.title = title
|
||||
self.after_table = after_table
|
||||
self.before_table = before_table
|
||||
self.hidden_args = hidden_args or []
|
||||
self.readonly = readonly
|
||||
self.result = None
|
||||
self.is_submitted = is_submitted
|
||||
@ -470,6 +474,8 @@ class TF(object):
|
||||
}"/>"""
|
||||
)
|
||||
R.append(f"""<input type="hidden" name="{self.formid}_submitted" value="1"/>""")
|
||||
for k, v in self.hidden_args:
|
||||
R.append(f"""<input type="hidden" name="{k}" value="{v}"/>""")
|
||||
if self.top_buttons:
|
||||
R.append(buttons_markup + "<p></p>")
|
||||
R.append(self.before_table.format(title=self.title))
|
||||
|
@ -42,7 +42,6 @@ from flask_login import current_user
|
||||
from app import db, log
|
||||
from app.models import FormSemestre, Identite, ScolarEvent
|
||||
import app.scodoc.sco_utils as scu
|
||||
from app.scodoc import html_sco_header
|
||||
from app.scodoc import sco_assiduites as scass
|
||||
from app.scodoc import sco_excel
|
||||
from app.scodoc import sco_formsemestre
|
||||
@ -170,11 +169,10 @@ def form_groups_choice(
|
||||
with_deselect_butt=False,
|
||||
submit_on_change=False,
|
||||
default_deselect_others=True,
|
||||
args: dict | None = None,
|
||||
title="Groupes :",
|
||||
):
|
||||
"""form pour selection groupes
|
||||
group_ids est la liste des groupes actuellement sélectionnés
|
||||
et doit comporter au moins un élément, sauf si formsemestre_id est spécifié.
|
||||
(utilisé pour retrouver le semestre et proposer la liste des autres groupes)
|
||||
"""Formulaire complet pour choix de groupe.
|
||||
|
||||
Si submit_on_change, soumet (recharge la page) à chaque modif.
|
||||
Si default_deselect_others, désélectionne le groupe "Tous" quand on sélectionne un autre groupe.
|
||||
@ -182,7 +180,14 @@ def form_groups_choice(
|
||||
Ces deux options ajoutent des classes utilisées en JS pour la gestion du formulaire.
|
||||
"""
|
||||
default_group_id = sco_groups.get_default_group(groups_infos.formsemestre_id)
|
||||
|
||||
args = args or {}
|
||||
args_wdg = "\n".join(
|
||||
[
|
||||
f"""<input type="hidden" name="{k}" value="{v}"/>"""
|
||||
for k, v in args.items()
|
||||
if k not in ("formsemestre_id", "group_ids")
|
||||
]
|
||||
)
|
||||
H = [
|
||||
f"""
|
||||
<form id="group_selector" method="get">
|
||||
@ -190,7 +195,8 @@ def form_groups_choice(
|
||||
value="{groups_infos.formsemestre_id}"/>
|
||||
<input type="hidden" name="default_group_id" id="default_group_id"
|
||||
value="{default_group_id}"/>
|
||||
Groupes:
|
||||
{args_wdg}
|
||||
{title}
|
||||
{
|
||||
menu_groups_choice(
|
||||
groups_infos,
|
||||
@ -480,6 +486,7 @@ class DisplayedGroupsInfos:
|
||||
return "\n".join(H)
|
||||
|
||||
def get_formsemestre(self) -> FormSemestre:
|
||||
"le formsemestre"
|
||||
return (
|
||||
db.session.get(FormSemestre, self.formsemestre_id)
|
||||
if self.formsemestre_id
|
||||
|
@ -43,17 +43,21 @@ from app.models import FormSemestre, Module
|
||||
from app.models.etudiants import Identite
|
||||
from app.models.evaluations import Evaluation
|
||||
from app.models.moduleimpls import ModuleImpl
|
||||
from app.scodoc.TrivialFormulator import TrivialFormulator
|
||||
|
||||
from app.scodoc import (
|
||||
sco_evaluations,
|
||||
sco_evaluation_db,
|
||||
sco_groups,
|
||||
sco_groups_view,
|
||||
sco_preferences,
|
||||
sco_users,
|
||||
)
|
||||
from app.scodoc.sco_groups_view import DisplayedGroupsInfos
|
||||
from app.scodoc.sco_etud import etud_sort_key
|
||||
from app.scodoc import sco_evaluations
|
||||
from app.scodoc import sco_evaluation_db
|
||||
from app.scodoc import sco_groups
|
||||
from app.scodoc import sco_preferences
|
||||
from app.scodoc import sco_users
|
||||
import app.scodoc.sco_utils as scu
|
||||
from app.scodoc.sco_exceptions import ScoValueError
|
||||
from app.scodoc.gen_tables import GenTable
|
||||
from app.scodoc.htmlutils import histogram_notes
|
||||
from app.scodoc.TrivialFormulator import TrivialFormulator
|
||||
import app.scodoc.sco_utils as scu
|
||||
import sco_version
|
||||
|
||||
|
||||
@ -82,18 +86,23 @@ def do_evaluation_listenotes(
|
||||
return "<p>Aucune évaluation !</p>", "ScoDoc"
|
||||
evaluation = evaluations[0]
|
||||
modimpl = evaluation.moduleimpl # il y a au moins une evaluation
|
||||
# Argument groupes:
|
||||
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 = DisplayedGroupsInfos(
|
||||
group_ids,
|
||||
formsemestre_id=modimpl.formsemestre.id,
|
||||
select_all_when_unspecified=True,
|
||||
)
|
||||
|
||||
# description de l'évaluation
|
||||
if evaluation_id is not None:
|
||||
H = [sco_evaluations.evaluation_describe(evaluation_id=evaluation_id)]
|
||||
page_title = f"Notes {evaluation.description or modimpl.module.code}"
|
||||
else:
|
||||
H = []
|
||||
page_title = f"Notes {modimpl.module.code}"
|
||||
# groupes
|
||||
groups = sco_groups.do_evaluation_listegroupes(evaluation.id, include_default=True)
|
||||
grlabs = [g["group_name"] or "tous" for g in groups] # legendes des boutons
|
||||
grnams = [str(g["group_id"]) for g in groups] # noms des checkbox
|
||||
|
||||
if len(evaluations) > 1:
|
||||
descr = [
|
||||
@ -109,37 +118,6 @@ def do_evaluation_listenotes(
|
||||
{"default": evaluation.id, "input_type": "hidden"},
|
||||
)
|
||||
]
|
||||
if len(grnams) > 1:
|
||||
descr += [
|
||||
(
|
||||
"s",
|
||||
{
|
||||
"input_type": "separator",
|
||||
"title": "<b>Choix du ou des groupes d'étudiants:</b>",
|
||||
},
|
||||
),
|
||||
(
|
||||
"group_ids",
|
||||
{
|
||||
"input_type": "checkbox",
|
||||
"title": "",
|
||||
"allowed_values": grnams,
|
||||
"labels": grlabs,
|
||||
"attributes": ('onclick="document.tf.submit();"',),
|
||||
},
|
||||
),
|
||||
]
|
||||
else:
|
||||
if grnams:
|
||||
def_nam = grnams[0]
|
||||
else:
|
||||
def_nam = ""
|
||||
descr += [
|
||||
(
|
||||
"group_ids",
|
||||
{"input_type": "hidden", "type": "list", "default": [def_nam]},
|
||||
)
|
||||
]
|
||||
descr += [
|
||||
(
|
||||
"anonymous_listing",
|
||||
@ -202,17 +180,16 @@ def do_evaluation_listenotes(
|
||||
request.base_url,
|
||||
scu.get_request_args(),
|
||||
descr,
|
||||
hidden_args=[("group_ids", gid) for gid in group_ids],
|
||||
cancelbutton=None,
|
||||
submitbutton=None,
|
||||
bottom_buttons=False,
|
||||
method="GET", # consultation
|
||||
cssclass="noprint",
|
||||
cssclass="noprint tf-liste-notes",
|
||||
name="tf",
|
||||
is_submitted=True, # toujours "soumis" (démarre avec liste complète)
|
||||
)
|
||||
if tf[0] == 0:
|
||||
return "\n".join(H) + "\n" + tf[1], page_title
|
||||
elif tf[0] == -1:
|
||||
if tf[0] == -1:
|
||||
return (
|
||||
flask.redirect(
|
||||
url_for(
|
||||
@ -223,24 +200,20 @@ def do_evaluation_listenotes(
|
||||
),
|
||||
"",
|
||||
)
|
||||
else:
|
||||
anonymous_listing = tf[2]["anonymous_listing"]
|
||||
note_sur_20 = tf[2]["note_sur_20"]
|
||||
hide_groups = tf[2]["hide_groups"]
|
||||
split_groups = tf[2]["split_groups"]
|
||||
with_emails = tf[2]["with_emails"]
|
||||
group_ids = [x for x in tf[2]["group_ids"] if x != ""]
|
||||
return (
|
||||
_make_table_notes(
|
||||
tf[1],
|
||||
evaluations,
|
||||
fmt=fmt,
|
||||
note_sur_20=note_sur_20,
|
||||
anonymous_listing=anonymous_listing,
|
||||
group_ids=group_ids,
|
||||
hide_groups=hide_groups,
|
||||
split_groups=split_groups,
|
||||
with_emails=with_emails,
|
||||
groups_infos=groups_infos,
|
||||
args={
|
||||
"note_sur_20": tf[2]["note_sur_20"],
|
||||
"anonymous_listing": tf[2]["anonymous_listing"],
|
||||
"group_ids": group_ids,
|
||||
"hide_groups": tf[2]["hide_groups"],
|
||||
"split_groups": tf[2]["split_groups"],
|
||||
"with_emails": tf[2]["with_emails"],
|
||||
},
|
||||
mode=mode,
|
||||
),
|
||||
page_title,
|
||||
@ -251,16 +224,19 @@ def _make_table_notes(
|
||||
html_form,
|
||||
evaluations: list[Evaluation],
|
||||
fmt: str = "",
|
||||
groups_infos: DisplayedGroupsInfos = None,
|
||||
args: dict = None,
|
||||
mode="module", # "eval" or "module"
|
||||
) -> str:
|
||||
"""Table liste notes (une seule évaluation ou toutes celles d'un module)
|
||||
args doit contenir:
|
||||
note_sur_20=False,
|
||||
anonymous_listing=False,
|
||||
hide_groups=False,
|
||||
split_groups=False,
|
||||
with_emails=False,
|
||||
group_ids: list[int] | None = None,
|
||||
mode="module", # "eval" or "module"
|
||||
) -> str:
|
||||
"""Table liste notes (une seule évaluation ou toutes celles d'un module)"""
|
||||
group_ids = group_ids or []
|
||||
with_emails=False
|
||||
"""
|
||||
args = args or {}
|
||||
if not evaluations:
|
||||
return "<p>Aucune évaluation !</p>"
|
||||
evaluation = evaluations[0]
|
||||
@ -286,15 +262,25 @@ def _make_table_notes(
|
||||
keep_numeric = True # pas de conversion des notes en strings
|
||||
else:
|
||||
keep_numeric = False
|
||||
# Si pas de groupe, affiche tout
|
||||
if not group_ids:
|
||||
group_ids = [sco_groups.get_default_group(formsemestre.id)]
|
||||
groups = sco_groups.listgroups(group_ids)
|
||||
# Menu groupes
|
||||
group_selector = (
|
||||
sco_groups_view.form_groups_choice(
|
||||
groups_infos, submit_on_change=True, args=args
|
||||
)
|
||||
if groups_infos
|
||||
else ""
|
||||
)
|
||||
|
||||
gr_title = sco_groups.listgroups_abbrev(groups)
|
||||
gr_title_filename = sco_groups.listgroups_filename(groups)
|
||||
# Si pas de groupe, affiche tout XXX TODO
|
||||
# if not groups_infos.group_ids:
|
||||
# groups_infos.group_ids = [sco_groups.get_default_group(formsemestre.id)]
|
||||
|
||||
if anonymous_listing:
|
||||
groups = sco_groups.listgroups(groups_infos.group_ids)
|
||||
|
||||
gr_title = groups_infos.groups_titles
|
||||
gr_title_filename = groups_infos.groups_filename
|
||||
|
||||
if args["anonymous_listing"]:
|
||||
columns_ids = ["code"] # cols in table
|
||||
else:
|
||||
if fmt in {"xls", "xml", "json"}:
|
||||
@ -302,12 +288,13 @@ def _make_table_notes(
|
||||
else:
|
||||
columns_ids = ["nomprenom"]
|
||||
partitions = []
|
||||
if split_groups:
|
||||
if not args["hide_groups"]:
|
||||
if args["split_groups"]:
|
||||
partitions = formsemestre.get_partitions_list(
|
||||
with_default=False, only_listed=True
|
||||
)
|
||||
columns_ids += [f"partition_{p.id}" for p in partitions]
|
||||
elif not hide_groups and fmt not in {"xml", "json"}:
|
||||
elif fmt not in {"xml", "json"}:
|
||||
# n'indique pas les groupes en xml et json car notation "humaine" ici
|
||||
columns_ids.append("group")
|
||||
|
||||
@ -456,13 +443,13 @@ def _make_table_notes(
|
||||
row_moys,
|
||||
is_apc,
|
||||
key_mgr,
|
||||
note_sur_20,
|
||||
args["note_sur_20"],
|
||||
keep_numeric,
|
||||
fmt=fmt,
|
||||
)
|
||||
columns_ids.append(e.id)
|
||||
#
|
||||
if anonymous_listing:
|
||||
if args["anonymous_listing"]:
|
||||
rows.sort(key=lambda x: x["code"] or "")
|
||||
else:
|
||||
# sort by nom, prenom, sans accents
|
||||
@ -504,7 +491,7 @@ def _make_table_notes(
|
||||
)
|
||||
|
||||
# Ajoute colonnes emails tout à droite:
|
||||
if with_emails:
|
||||
if args["with_emails"]:
|
||||
columns_ids += ["email", "emailperso"]
|
||||
# Ajoute lignes en tête et moyennes
|
||||
if len(evaluations) > 0 and fmt != "bordereau" and fmt != "json":
|
||||
@ -539,17 +526,10 @@ def _make_table_notes(
|
||||
columns_ids.append("signatures")
|
||||
|
||||
# titres divers:
|
||||
gl = "".join(["&group_ids%3Alist=" + str(g) for g in group_ids])
|
||||
if note_sur_20:
|
||||
gl = "¬e_sur_20%3Alist=yes" + gl
|
||||
if anonymous_listing:
|
||||
gl = "&anonymous_listing%3Alist=yes" + gl
|
||||
if hide_groups:
|
||||
gl = "&hide_groups%3Alist=yes" + gl
|
||||
if split_groups:
|
||||
gl = "&split_groups%3Alist=yes" + gl
|
||||
if with_emails:
|
||||
gl = "&with_emails%3Alist=yes" + gl
|
||||
gl = "".join(["&group_ids=" + str(g) for g in groups_infos.group_ids])
|
||||
for k, v in args.items():
|
||||
gl += f"&{k}%3Alist=yes" if v else ""
|
||||
|
||||
if len(evaluations) == 1:
|
||||
evalname = f"""{module.code}-{
|
||||
evaluation.date_debut.replace(tzinfo=None).isoformat()
|
||||
@ -582,7 +562,8 @@ def _make_table_notes(
|
||||
len(etudid_etats),
|
||||
)
|
||||
if evaluation.date_debut:
|
||||
pdf_title = f"{evaluation.description} ({evaluation.date_debut.strftime('%d/%m/%Y')})"
|
||||
pdf_title = f"""{evaluation.description} ({
|
||||
evaluation.date_debut.strftime('%d/%m/%Y')})"""
|
||||
else:
|
||||
pdf_title = evaluation.description or f"évaluation dans {module.code}"
|
||||
|
||||
@ -671,12 +652,14 @@ def _make_table_notes(
|
||||
Les moyennes sur le groupe sont estimées sans les absents
|
||||
(sauf pour les moyennes des moyennes d'UE) ni les démissionnaires.</span>"""
|
||||
eval_info += """</span>"""
|
||||
return html_form + eval_info + t + "<p></p>"
|
||||
return group_selector + html_form + eval_info + t + "<p></p>"
|
||||
|
||||
# Une seule evaluation: ajoute histogramme
|
||||
histo = histogram_notes(notes)
|
||||
# 2 colonnes: histo, comments
|
||||
C = [
|
||||
f"""<br><a class="stdlink" href="{base_url}&fmt=bordereau">Bordereau de Signatures (version PDF)</a>
|
||||
section_basse_html = [
|
||||
f"""<br><a class="stdlink" href="{base_url}&fmt=bordereau"
|
||||
>Bordereau de Signatures (version PDF)</a>
|
||||
<table>
|
||||
<tr><td>
|
||||
<div><h4>Répartition des notes:</h4>
|
||||
@ -689,15 +672,17 @@ def _make_table_notes(
|
||||
commentkeys = list(key_mgr.items()) # [ (comment, key), ... ]
|
||||
commentkeys.sort(key=lambda x: int(x[1]))
|
||||
for comment, key in commentkeys:
|
||||
C.append(f"""<span class="colcomment">({key})</span> <em>{comment}</em><br>""")
|
||||
section_basse_html.append(
|
||||
f"""<span class="colcomment">({key})</span> <em>{comment}</em><br>"""
|
||||
)
|
||||
if commentkeys:
|
||||
C.append(
|
||||
section_basse_html.append(
|
||||
f"""<span><a class=stdlink" href="{ url_for(
|
||||
'notes.evaluation_list_operations', scodoc_dept=g.scodoc_dept, evaluation_id=evaluation.id )
|
||||
}">Gérer les opérations</a></span><br>
|
||||
"""
|
||||
)
|
||||
eval_info = "xxx"
|
||||
eval_info = ""
|
||||
if evals_state[evaluation.id]["evalcomplete"]:
|
||||
eval_info = '<span class="eval_info eval_complete">Evaluation prise en compte dans les moyennes</span>'
|
||||
elif evals_state[evaluation.id]["evalattente"]:
|
||||
@ -708,9 +693,10 @@ def _make_table_notes(
|
||||
return (
|
||||
sco_evaluations.evaluation_describe(evaluation_id=evaluation.id)
|
||||
+ eval_info
|
||||
+ group_selector
|
||||
+ html_form
|
||||
+ t
|
||||
+ "\n".join(C)
|
||||
+ "\n".join(section_basse_html)
|
||||
)
|
||||
|
||||
|
||||
|
@ -1536,6 +1536,10 @@ span.eval_title {
|
||||
padding-top: 24px;
|
||||
}
|
||||
|
||||
.tf-liste-notes td.tf-field {
|
||||
max-width: var(--sco-content-max-width);
|
||||
}
|
||||
|
||||
/* #saisie_notes span.eval_title {
|
||||
border-bottom: 1px solid rgb(100,100,100);
|
||||
}
|
||||
@ -1581,8 +1585,10 @@ div.jury_footer>span {
|
||||
color: red;
|
||||
}
|
||||
|
||||
span.eval_info {
|
||||
.eval_info {
|
||||
font-style: italic;
|
||||
max-width: var(--sco-content-max-width);
|
||||
margin: 16px 0 16px 0;
|
||||
}
|
||||
|
||||
span.eval_complete {
|
||||
|
@ -1787,6 +1787,7 @@ def evaluation_listenotes():
|
||||
content=content,
|
||||
title=page_title,
|
||||
cssstyles=["css/verticalhisto.css"],
|
||||
javascripts=["js/groups_view.js"],
|
||||
)
|
||||
return content
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user