Page état de évaluations (closes #142). Améliore tableau recap. Cosmétique.
This commit is contained in:
parent
705aa54d77
commit
570e2dc308
@ -92,6 +92,8 @@ class ModuleImplResults:
|
|||||||
ou NaN si les évaluations (dans lesquelles l'étudiant a des notes)
|
ou NaN si les évaluations (dans lesquelles l'étudiant a des notes)
|
||||||
ne donnent pas de coef vers cette UE.
|
ne donnent pas de coef vers cette UE.
|
||||||
"""
|
"""
|
||||||
|
self.evals_etudids_sans_note = {}
|
||||||
|
"""dict: evaluation_id : set des etudids non notés dans cette eval, sans les démissions."""
|
||||||
self.load_notes()
|
self.load_notes()
|
||||||
self.etuds_use_session2 = pd.Series(False, index=self.evals_notes.index)
|
self.etuds_use_session2 = pd.Series(False, index=self.evals_notes.index)
|
||||||
"""1 bool par etud, indique si sa moyenne de module vient de la session2"""
|
"""1 bool par etud, indique si sa moyenne de module vient de la session2"""
|
||||||
@ -142,12 +144,13 @@ class ModuleImplResults:
|
|||||||
# ou évaluation déclarée "à prise en compte immédiate"
|
# ou évaluation déclarée "à prise en compte immédiate"
|
||||||
# Les évaluations de rattrapage et 2eme session sont toujours incomplètes
|
# Les évaluations de rattrapage et 2eme session sont toujours incomplètes
|
||||||
# car on calcule leur moyenne à part.
|
# car on calcule leur moyenne à part.
|
||||||
|
etudids_sans_note = inscrits_module - set(eval_df.index) # sans les dem.
|
||||||
is_complete = (evaluation.evaluation_type == scu.EVALUATION_NORMALE) and (
|
is_complete = (evaluation.evaluation_type == scu.EVALUATION_NORMALE) and (
|
||||||
evaluation.publish_incomplete
|
evaluation.publish_incomplete or (not etudids_sans_note)
|
||||||
or (not (inscrits_module - set(eval_df.index)))
|
|
||||||
)
|
)
|
||||||
self.evaluations_completes.append(is_complete)
|
self.evaluations_completes.append(is_complete)
|
||||||
self.evaluations_completes_dict[evaluation.id] = is_complete
|
self.evaluations_completes_dict[evaluation.id] = is_complete
|
||||||
|
self.evals_etudids_sans_note[evaluation.id] = etudids_sans_note
|
||||||
|
|
||||||
# NULL en base => ABS (= -999)
|
# NULL en base => ABS (= -999)
|
||||||
eval_df.fillna(scu.NOTES_ABSENCE, inplace=True)
|
eval_df.fillna(scu.NOTES_ABSENCE, inplace=True)
|
||||||
@ -193,7 +196,9 @@ class ModuleImplResults:
|
|||||||
return eval_df
|
return eval_df
|
||||||
|
|
||||||
def _etudids(self):
|
def _etudids(self):
|
||||||
"""L'index du dataframe est la liste de tous les étudiants inscrits au semestre"""
|
"""L'index du dataframe est la liste de tous les étudiants inscrits au semestre
|
||||||
|
(incluant les DEM et DEF)
|
||||||
|
"""
|
||||||
return [
|
return [
|
||||||
inscr.etudid
|
inscr.etudid
|
||||||
for inscr in ModuleImpl.query.get(
|
for inscr in ModuleImpl.query.get(
|
||||||
|
@ -862,20 +862,27 @@ class ResultatsSemestre(ResultatsCache):
|
|||||||
"_tr_class": "bottom_info",
|
"_tr_class": "bottom_info",
|
||||||
"_title": "Description évaluation",
|
"_title": "Description évaluation",
|
||||||
}
|
}
|
||||||
first = True
|
first_eval = True
|
||||||
|
index_col = 9000 # à droite
|
||||||
for modimpl in self.formsemestre.modimpls_sorted:
|
for modimpl in self.formsemestre.modimpls_sorted:
|
||||||
evals = self.modimpls_results[modimpl.id].get_evaluations_completes(modimpl)
|
evals = self.modimpls_results[modimpl.id].get_evaluations_completes(modimpl)
|
||||||
eval_index = len(evals) - 1
|
eval_index = len(evals) - 1
|
||||||
inscrits = {i.etudid for i in modimpl.inscriptions}
|
inscrits = {i.etudid for i in modimpl.inscriptions}
|
||||||
klass = "evaluation first" if first else "evaluation"
|
first_eval_of_mod = True
|
||||||
first = False
|
for e in evals:
|
||||||
for i, e in enumerate(evals):
|
|
||||||
cid = f"eval_{e.id}"
|
cid = f"eval_{e.id}"
|
||||||
titles[
|
titles[
|
||||||
cid
|
cid
|
||||||
] = f'{modimpl.module.code} {eval_index} {e.jour.isoformat() if e.jour else ""}'
|
] = f'{modimpl.module.code} {eval_index} {e.jour.isoformat() if e.jour else ""}'
|
||||||
|
klass = "evaluation"
|
||||||
|
if first_eval:
|
||||||
|
klass += " first"
|
||||||
|
elif first_eval_of_mod:
|
||||||
|
klass += " first_of_mod"
|
||||||
titles[f"_{cid}_class"] = klass
|
titles[f"_{cid}_class"] = klass
|
||||||
titles[f"_{cid}_col_order"] = 9000 + i # à droite
|
first_eval_of_mod = first_eval = False
|
||||||
|
titles[f"_{cid}_col_order"] = index_col
|
||||||
|
index_col += 1
|
||||||
eval_index -= 1
|
eval_index -= 1
|
||||||
notes_db = sco_evaluation_db.do_evaluation_get_all_notes(
|
notes_db = sco_evaluation_db.do_evaluation_get_all_notes(
|
||||||
e.evaluation_id
|
e.evaluation_id
|
||||||
@ -889,7 +896,15 @@ class ResultatsSemestre(ResultatsCache):
|
|||||||
# Note manquante mais prise en compte immédiate: affiche ATT
|
# Note manquante mais prise en compte immédiate: affiche ATT
|
||||||
val = scu.NOTES_ATTENTE
|
val = scu.NOTES_ATTENTE
|
||||||
row[cid] = scu.fmt_note(val)
|
row[cid] = scu.fmt_note(val)
|
||||||
row[f"_{cid}_class"] = klass
|
row[f"_{cid}_class"] = klass + {
|
||||||
|
"ABS": " abs",
|
||||||
|
"ATT": " att",
|
||||||
|
"EXC": " exc",
|
||||||
|
}.get(row[cid], "")
|
||||||
|
else:
|
||||||
|
row[cid] = "ni"
|
||||||
|
row[f"_{cid}_class"] = klass + " non_inscrit"
|
||||||
|
|
||||||
bottom_infos["coef"][cid] = e.coefficient
|
bottom_infos["coef"][cid] = e.coefficient
|
||||||
bottom_infos["min"][cid] = "0"
|
bottom_infos["min"][cid] = "0"
|
||||||
bottom_infos["max"][cid] = scu.fmt_note(e.note_max)
|
bottom_infos["max"][cid] = scu.fmt_note(e.note_max)
|
||||||
|
@ -9,7 +9,6 @@ from app.comp import df_cache
|
|||||||
from app.models.etudiants import Identite
|
from app.models.etudiants import Identite
|
||||||
from app.models.modules import Module
|
from app.models.modules import Module
|
||||||
|
|
||||||
import app.scodoc.notesdb as ndb
|
|
||||||
from app.scodoc import sco_utils as scu
|
from app.scodoc import sco_utils as scu
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
#
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
"""Vérification des abasneces à une évaluation
|
"""Vérification des absences à une évaluation
|
||||||
"""
|
"""
|
||||||
from flask import url_for, g
|
from flask import url_for, g
|
||||||
|
|
||||||
|
144
app/scodoc/sco_evaluation_recap.py
Normal file
144
app/scodoc/sco_evaluation_recap.py
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
##############################################################################
|
||||||
|
# ScoDoc
|
||||||
|
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
|
||||||
|
# See LICENSE
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
"""Tableau recap. de toutes les évaluations d'un semestre
|
||||||
|
avec leur état.
|
||||||
|
|
||||||
|
Sur une idée de Pascal Bouron, de Lyon.
|
||||||
|
"""
|
||||||
|
import time
|
||||||
|
from flask import g, url_for
|
||||||
|
|
||||||
|
from app.models import Evaluation, FormSemestre
|
||||||
|
from app.comp import res_sem
|
||||||
|
from app.comp.res_compat import NotesTableCompat
|
||||||
|
from app.comp.moy_mod import ModuleImplResults
|
||||||
|
from app.scodoc import html_sco_header
|
||||||
|
import app.scodoc.sco_utils as scu
|
||||||
|
|
||||||
|
|
||||||
|
def evaluations_recap(formsemestre_id: int) -> str:
|
||||||
|
"""Page récap. de toutes les évaluations d'un semestre"""
|
||||||
|
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
||||||
|
rows, titles = evaluations_recap_table(formsemestre)
|
||||||
|
column_ids = titles.keys()
|
||||||
|
filename = scu.sanitize_filename(
|
||||||
|
f"""evaluations-{formsemestre.titre_num()}-{time.strftime("%Y-%m-%d")}"""
|
||||||
|
)
|
||||||
|
if not rows:
|
||||||
|
return '<div class="evaluations_recap"><div class="message">aucune évaluation</div></div>'
|
||||||
|
H = [
|
||||||
|
html_sco_header.sco_header(
|
||||||
|
page_title="Évaluations du semestre",
|
||||||
|
javascripts=["js/evaluations_recap.js"],
|
||||||
|
),
|
||||||
|
f"""<div class="evaluations_recap"><table class="evaluations_recap compact {
|
||||||
|
'apc' if formsemestre.formation.is_apc() else 'classic'
|
||||||
|
}"
|
||||||
|
data-filename="{filename}">""",
|
||||||
|
]
|
||||||
|
# header
|
||||||
|
H.append(
|
||||||
|
f"""
|
||||||
|
<thead>
|
||||||
|
{scu.gen_row(column_ids, titles, "th", with_col_classes=True)}
|
||||||
|
</thead>
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
# body
|
||||||
|
H.append("<tbody>")
|
||||||
|
for row in rows:
|
||||||
|
H.append(f"{scu.gen_row(column_ids, row, with_col_classes=True)}\n")
|
||||||
|
|
||||||
|
H.append("""</tbody></table></div>""")
|
||||||
|
H.append(
|
||||||
|
html_sco_header.sco_footer(),
|
||||||
|
)
|
||||||
|
return "".join(H)
|
||||||
|
|
||||||
|
|
||||||
|
def evaluations_recap_table(formsemestre: FormSemestre) -> list[dict]:
|
||||||
|
"""Tableau recap. de toutes les évaluations d'un semestre
|
||||||
|
Colonnes:
|
||||||
|
- code (UE ou module),
|
||||||
|
- titre
|
||||||
|
- complete
|
||||||
|
- publiée
|
||||||
|
- inscrits (non dem. ni def.)
|
||||||
|
- nb notes manquantes
|
||||||
|
- nb ATT
|
||||||
|
- nb ABS
|
||||||
|
- nb EXC
|
||||||
|
"""
|
||||||
|
rows = []
|
||||||
|
titles = {
|
||||||
|
"type": "",
|
||||||
|
"code": "Code",
|
||||||
|
"titre": "",
|
||||||
|
"date": "Date",
|
||||||
|
"complete": "Comptée",
|
||||||
|
"inscrits": "Inscrits",
|
||||||
|
"manquantes": "Manquantes", # notes eval non entrées
|
||||||
|
"nb_abs": "ABS",
|
||||||
|
"nb_att": "ATT",
|
||||||
|
"nb_exc": "EXC",
|
||||||
|
}
|
||||||
|
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
||||||
|
line_idx = 0
|
||||||
|
for modimpl in nt.formsemestre.modimpls_sorted:
|
||||||
|
modimpl_results: ModuleImplResults = nt.modimpls_results[modimpl.id]
|
||||||
|
row = {
|
||||||
|
"type": modimpl.module.type_abbrv().upper(),
|
||||||
|
"_type_order": f"{line_idx:04d}",
|
||||||
|
"code": modimpl.module.code,
|
||||||
|
"_code_target": url_for(
|
||||||
|
"notes.moduleimpl_status",
|
||||||
|
scodoc_dept=g.scodoc_dept,
|
||||||
|
moduleimpl_id=modimpl.id,
|
||||||
|
),
|
||||||
|
"titre": modimpl.module.titre,
|
||||||
|
"_titre_class": "titre",
|
||||||
|
"inscrits": modimpl_results.nb_inscrits_module,
|
||||||
|
"date": "-",
|
||||||
|
"_date_order": "",
|
||||||
|
"_tr_class": f"module {modimpl.module.type_abbrv()}",
|
||||||
|
}
|
||||||
|
rows.append(row)
|
||||||
|
line_idx += 1
|
||||||
|
for evaluation_id in modimpl_results.evals_notes:
|
||||||
|
e = Evaluation.query.get(evaluation_id)
|
||||||
|
eval_etat = modimpl_results.evaluations_etat[evaluation_id]
|
||||||
|
row = {
|
||||||
|
"type": "",
|
||||||
|
"_type_order": f"{line_idx:04d}",
|
||||||
|
"titre": e.description or "sans titre",
|
||||||
|
"_titre_target": url_for(
|
||||||
|
"notes.evaluation_listenotes",
|
||||||
|
scodoc_dept=g.scodoc_dept,
|
||||||
|
evaluation_id=evaluation_id,
|
||||||
|
),
|
||||||
|
"_titre_target_attrs": 'class="discretelink"',
|
||||||
|
"date": e.jour.strftime("%d/%m/%Y") if e.jour else "",
|
||||||
|
"_date_order": e.jour.isoformat() if e.jour else "",
|
||||||
|
"complete": "oui" if eval_etat.is_complete else "non",
|
||||||
|
"_complete_target": "#",
|
||||||
|
"_complete_target_attrs": 'class="bull_link" title="prise en compte dans les moyennes"'
|
||||||
|
if eval_etat.is_complete
|
||||||
|
else 'class="bull_link incomplete" title="il manque des notes"',
|
||||||
|
"manquantes": len(modimpl_results.evals_etudids_sans_note[e.id]),
|
||||||
|
"inscrits": modimpl_results.nb_inscrits_module,
|
||||||
|
"nb_abs": sum(modimpl_results.evals_notes[e.id] == scu.NOTES_ABSENCE),
|
||||||
|
"nb_att": eval_etat.nb_attente,
|
||||||
|
"nb_exc": sum(
|
||||||
|
modimpl_results.evals_notes[e.id] == scu.NOTES_NEUTRALISE
|
||||||
|
),
|
||||||
|
"_tr_class": "evaluation"
|
||||||
|
+ (" incomplete" if not eval_etat.is_complete else ""),
|
||||||
|
}
|
||||||
|
rows.append(row)
|
||||||
|
line_idx += 1
|
||||||
|
|
||||||
|
return rows, titles
|
@ -357,6 +357,11 @@ def formsemestre_status_menubar(sem):
|
|||||||
"endpoint": "notes.formsemestre_recapcomplet",
|
"endpoint": "notes.formsemestre_recapcomplet",
|
||||||
"args": {"formsemestre_id": formsemestre_id},
|
"args": {"formsemestre_id": formsemestre_id},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"title": "État des évaluations",
|
||||||
|
"endpoint": "notes.evaluations_recap",
|
||||||
|
"args": {"formsemestre_id": formsemestre_id},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"title": "Saisie des notes",
|
"title": "Saisie des notes",
|
||||||
"endpoint": "notes.formsemestre_status",
|
"endpoint": "notes.formsemestre_status",
|
||||||
|
@ -698,7 +698,7 @@ def _add_eval_columns(
|
|||||||
# calcul moyenne SANS LES ABSENTS ni les DEMISSIONNAIRES
|
# calcul moyenne SANS LES ABSENTS ni les DEMISSIONNAIRES
|
||||||
if (
|
if (
|
||||||
(etudid in inscrits)
|
(etudid in inscrits)
|
||||||
and val != None
|
and val is not None
|
||||||
and val != scu.NOTES_NEUTRALISE
|
and val != scu.NOTES_NEUTRALISE
|
||||||
and val != scu.NOTES_ATTENTE
|
and val != scu.NOTES_ATTENTE
|
||||||
):
|
):
|
||||||
@ -721,16 +721,26 @@ def _add_eval_columns(
|
|||||||
comment,
|
comment,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
explanation = ""
|
if (etudid in inscrits) and e["publish_incomplete"]:
|
||||||
val_fmt = ""
|
# Note manquante mais prise en compte immédiate: affiche ATT
|
||||||
val = None
|
val = scu.NOTES_ATTENTE
|
||||||
|
val_fmt = "ATT"
|
||||||
|
explanation = "non saisie mais prise en compte immédiate"
|
||||||
|
else:
|
||||||
|
explanation = ""
|
||||||
|
val_fmt = ""
|
||||||
|
val = None
|
||||||
|
|
||||||
|
cell_class = klass + {"ATT": " att", "ABS": " abs", "EXC": " exc"}.get(
|
||||||
|
val_fmt, ""
|
||||||
|
)
|
||||||
|
|
||||||
if val is None:
|
if val is None:
|
||||||
row[f"_{evaluation_id}_td_attrs"] = f'class="etudabs {klass}" '
|
row[f"_{evaluation_id}_td_attrs"] = f'class="etudabs {cell_class}" '
|
||||||
if not row.get("_css_row_class", ""):
|
if not row.get("_css_row_class", ""):
|
||||||
row["_css_row_class"] = "etudabs"
|
row["_css_row_class"] = "etudabs"
|
||||||
else:
|
else:
|
||||||
row[f"_{evaluation_id}_td_attrs"] = f'class="{klass}" '
|
row[f"_{evaluation_id}_td_attrs"] = f'class="{cell_class}" '
|
||||||
# regroupe les commentaires
|
# regroupe les commentaires
|
||||||
if explanation:
|
if explanation:
|
||||||
if explanation in K:
|
if explanation in K:
|
||||||
|
@ -357,31 +357,6 @@ def formsemestres_bulletins(annee_scolaire):
|
|||||||
return scu.sendJSON(js_list)
|
return scu.sendJSON(js_list)
|
||||||
|
|
||||||
|
|
||||||
def _gen_cell(key: str, row: dict, elt="td"):
|
|
||||||
"html table cell"
|
|
||||||
klass = row.get(f"_{key}_class")
|
|
||||||
attrs = f'class="{klass}"' if klass else ""
|
|
||||||
order = row.get(f"_{key}_order")
|
|
||||||
if order:
|
|
||||||
attrs += f' data-order="{order}"'
|
|
||||||
content = row.get(key, "")
|
|
||||||
target = row.get(f"_{key}_target")
|
|
||||||
target_attrs = row.get(f"_{key}_target_attrs", "")
|
|
||||||
if target or target_attrs: # avec lien
|
|
||||||
href = f'href="{target}"' if target else ""
|
|
||||||
content = f"<a {href} {target_attrs}>{content}</a>"
|
|
||||||
return f"<{elt} {attrs}>{content}</{elt}>"
|
|
||||||
|
|
||||||
|
|
||||||
def _gen_row(keys: list[str], row, elt="td", selected_etudid=None):
|
|
||||||
klass = row.get("_tr_class")
|
|
||||||
tr_class = f'class="{klass}"' if klass else ""
|
|
||||||
tr_id = (
|
|
||||||
f"""id="row_selected" """ if (row.get("etudid", "") == selected_etudid) else ""
|
|
||||||
)
|
|
||||||
return f'<tr {tr_id} {tr_class}>{"".join([_gen_cell(key, row, elt) for key in keys])}</tr>'
|
|
||||||
|
|
||||||
|
|
||||||
def gen_formsemestre_recapcomplet_html(
|
def gen_formsemestre_recapcomplet_html(
|
||||||
formsemestre: FormSemestre,
|
formsemestre: FormSemestre,
|
||||||
res: NotesTableCompat,
|
res: NotesTableCompat,
|
||||||
@ -448,20 +423,20 @@ def _gen_formsemestre_recapcomplet_html(
|
|||||||
H.append(
|
H.append(
|
||||||
f"""
|
f"""
|
||||||
<thead>
|
<thead>
|
||||||
{_gen_row(column_ids, titles, "th")}
|
{scu.gen_row(column_ids, titles, "th")}
|
||||||
</thead>
|
</thead>
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
# body
|
# body
|
||||||
H.append("<tbody>")
|
H.append("<tbody>")
|
||||||
for row in rows:
|
for row in rows:
|
||||||
H.append(f"{_gen_row(column_ids, row, selected_etudid=selected_etudid)}\n")
|
H.append(f"{scu.gen_row(column_ids, row, selected_etudid=selected_etudid)}\n")
|
||||||
H.append("</tbody>\n")
|
H.append("</tbody>\n")
|
||||||
# footer
|
# footer
|
||||||
H.append("<tfoot>")
|
H.append("<tfoot>")
|
||||||
idx_last = len(footer_rows) - 1
|
idx_last = len(footer_rows) - 1
|
||||||
for i, row in enumerate(footer_rows):
|
for i, row in enumerate(footer_rows):
|
||||||
H.append(f'{_gen_row(column_ids, row, "th" if i == idx_last else "td")}\n')
|
H.append(f'{scu.gen_row(column_ids, row, "th" if i == idx_last else "td")}\n')
|
||||||
H.append(
|
H.append(
|
||||||
"""
|
"""
|
||||||
</tfoot>
|
</tfoot>
|
||||||
|
@ -1077,6 +1077,36 @@ def objects_renumber(db, obj_list) -> None:
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
|
|
||||||
|
def gen_cell(key: str, row: dict, elt="td", with_col_class=False):
|
||||||
|
"html table cell"
|
||||||
|
klass = row.get(f"_{key}_class", "")
|
||||||
|
if with_col_class:
|
||||||
|
klass = key + " " + klass
|
||||||
|
attrs = f'class="{klass}"' if klass else ""
|
||||||
|
order = row.get(f"_{key}_order")
|
||||||
|
if order:
|
||||||
|
attrs += f' data-order="{order}"'
|
||||||
|
content = row.get(key, "")
|
||||||
|
target = row.get(f"_{key}_target")
|
||||||
|
target_attrs = row.get(f"_{key}_target_attrs", "")
|
||||||
|
if target or target_attrs: # avec lien
|
||||||
|
href = f'href="{target}"' if target else ""
|
||||||
|
content = f"<a {href} {target_attrs}>{content}</a>"
|
||||||
|
return f"<{elt} {attrs}>{content}</{elt}>"
|
||||||
|
|
||||||
|
|
||||||
|
def gen_row(
|
||||||
|
keys: list[str], row, elt="td", selected_etudid=None, with_col_classes=False
|
||||||
|
):
|
||||||
|
"html table row"
|
||||||
|
klass = row.get("_tr_class")
|
||||||
|
tr_class = f'class="{klass}"' if klass else ""
|
||||||
|
tr_id = (
|
||||||
|
f"""id="row_selected" """ if (row.get("etudid", "") == selected_etudid) else ""
|
||||||
|
)
|
||||||
|
return f"""<tr {tr_id} {tr_class}>{"".join([gen_cell(key, row, elt, with_col_class=with_col_classes) for key in keys if not key.startswith('_')])}</tr>"""
|
||||||
|
|
||||||
|
|
||||||
# Pour accès depuis les templates jinja
|
# Pour accès depuis les templates jinja
|
||||||
def is_entreprises_enabled():
|
def is_entreprises_enabled():
|
||||||
from app.models import ScoDocSiteConfig
|
from app.models import ScoDocSiteConfig
|
||||||
|
@ -1076,7 +1076,7 @@ tr.etuddem td {
|
|||||||
td.etudabs,
|
td.etudabs,
|
||||||
td.etudabs a.discretelink,
|
td.etudabs a.discretelink,
|
||||||
tr.etudabs td.moyenne a.discretelink {
|
tr.etudabs td.moyenne a.discretelink {
|
||||||
color: rgb(180, 0, 0);
|
color: rgb(195, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
tr.moyenne td {
|
tr.moyenne td {
|
||||||
@ -1103,6 +1103,17 @@ table.notes_evaluation th.eval_attente {
|
|||||||
width: 80px;
|
width: 80px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table.notes_evaluation td.att a {
|
||||||
|
color: rgb(255, 0, 217);
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.notes_evaluation td.exc a {
|
||||||
|
font-style: italic;
|
||||||
|
color: rgb(0, 131, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
table.notes_evaluation tr td a.discretelink:hover {
|
table.notes_evaluation tr td a.discretelink:hover {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
@ -3554,7 +3565,7 @@ table.dataTable td.group {
|
|||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Nouveau tableau recap */
|
/* ------------- Nouveau tableau recap ------------ */
|
||||||
div.table_recap {
|
div.table_recap {
|
||||||
margin-top: 6px;
|
margin-top: 6px;
|
||||||
}
|
}
|
||||||
@ -3756,4 +3767,78 @@ table.table_recap tr.apo td {
|
|||||||
table.table_recap td.evaluation.first,
|
table.table_recap td.evaluation.first,
|
||||||
table.table_recap th.evaluation.first {
|
table.table_recap th.evaluation.first {
|
||||||
border-left: 2px solid rgb(4, 16, 159);
|
border-left: 2px solid rgb(4, 16, 159);
|
||||||
|
}
|
||||||
|
|
||||||
|
table.table_recap td.evaluation.first_of_mod,
|
||||||
|
table.table_recap th.evaluation.first_of_mod {
|
||||||
|
border-left: 1px dashed rgb(4, 16, 159);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
table.table_recap td.evaluation.att {
|
||||||
|
color: rgb(255, 0, 217);
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.table_recap td.evaluation.abs {
|
||||||
|
color: rgb(231, 0, 0);
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.table_recap td.evaluation.exc {
|
||||||
|
font-style: italic;
|
||||||
|
color: rgb(0, 131, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
table.table_recap td.evaluation.non_inscrit {
|
||||||
|
font-style: italic;
|
||||||
|
color: rgb(101, 101, 101);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------- Tableau etat evals ------------ */
|
||||||
|
|
||||||
|
div.evaluations_recap table.evaluations_recap {
|
||||||
|
width: auto !important;
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.evaluations_recap tr.odd td {
|
||||||
|
background-color: #fff4e4;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.evaluations_recap tr.res td {
|
||||||
|
background-color: #f7d372;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.evaluations_recap tr.sae td {
|
||||||
|
background-color: #d8fcc8;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
table.evaluations_recap tr.module td {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.evaluations_recap tr.evaluation td.titre {
|
||||||
|
font-style: italic;
|
||||||
|
padding-left: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.evaluations_recap td.titre,
|
||||||
|
table.evaluations_recap th.titre {
|
||||||
|
max-width: 350px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.evaluations_recap td.complete,
|
||||||
|
table.evaluations_recap th.complete {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.evaluations_recap tr.evaluation.incomplete td,
|
||||||
|
table.evaluations_recap tr.evaluation.incomplete td a {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.evaluations_recap tr.evaluation.incomplete td a.incomplete {
|
||||||
|
font-weight: bold;
|
||||||
}
|
}
|
38
app/static/js/evaluations_recap.js
Normal file
38
app/static/js/evaluations_recap.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// Tableau recap evaluations du semestre
|
||||||
|
$(function () {
|
||||||
|
$('table.evaluations_recap').DataTable(
|
||||||
|
{
|
||||||
|
paging: false,
|
||||||
|
searching: true,
|
||||||
|
info: false,
|
||||||
|
autoWidth: false,
|
||||||
|
fixedHeader: {
|
||||||
|
header: true,
|
||||||
|
footer: false
|
||||||
|
},
|
||||||
|
orderCellsTop: true, // cellules ligne 1 pour tri
|
||||||
|
aaSorting: [], // Prevent initial sorting
|
||||||
|
colReorder: true,
|
||||||
|
"columnDefs": [
|
||||||
|
{
|
||||||
|
// colonne date, triable (XXX ne fonctionne pas)
|
||||||
|
targets: ["date"],
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
dom: 'Bfrtip',
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
extend: 'copyHtml5',
|
||||||
|
text: 'Copier',
|
||||||
|
exportOptions: { orthogonal: 'export' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
extend: 'excelHtml5',
|
||||||
|
exportOptions: { orthogonal: 'export' },
|
||||||
|
title: document.querySelector('table.evaluations_recap').dataset.filename
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
})
|
||||||
|
});
|
@ -100,6 +100,7 @@ from app.scodoc import sco_evaluations
|
|||||||
from app.scodoc import sco_evaluation_check_abs
|
from app.scodoc import sco_evaluation_check_abs
|
||||||
from app.scodoc import sco_evaluation_db
|
from app.scodoc import sco_evaluation_db
|
||||||
from app.scodoc import sco_evaluation_edit
|
from app.scodoc import sco_evaluation_edit
|
||||||
|
from app.scodoc import sco_evaluation_recap
|
||||||
from app.scodoc import sco_export_results
|
from app.scodoc import sco_export_results
|
||||||
from app.scodoc import sco_formations
|
from app.scodoc import sco_formations
|
||||||
from app.scodoc import sco_formsemestre
|
from app.scodoc import sco_formsemestre
|
||||||
@ -109,22 +110,18 @@ from app.scodoc import sco_formsemestre_exterieurs
|
|||||||
from app.scodoc import sco_formsemestre_inscriptions
|
from app.scodoc import sco_formsemestre_inscriptions
|
||||||
from app.scodoc import sco_formsemestre_status
|
from app.scodoc import sco_formsemestre_status
|
||||||
from app.scodoc import sco_formsemestre_validation
|
from app.scodoc import sco_formsemestre_validation
|
||||||
from app.scodoc import sco_groups
|
|
||||||
from app.scodoc import sco_inscr_passage
|
from app.scodoc import sco_inscr_passage
|
||||||
from app.scodoc import sco_liste_notes
|
from app.scodoc import sco_liste_notes
|
||||||
from app.scodoc import sco_lycee
|
from app.scodoc import sco_lycee
|
||||||
from app.scodoc import sco_moduleimpl
|
from app.scodoc import sco_moduleimpl
|
||||||
from app.scodoc import sco_moduleimpl_inscriptions
|
from app.scodoc import sco_moduleimpl_inscriptions
|
||||||
from app.scodoc import sco_moduleimpl_status
|
from app.scodoc import sco_moduleimpl_status
|
||||||
from app.scodoc import sco_news
|
|
||||||
from app.scodoc import sco_parcours_dut
|
|
||||||
from app.scodoc import sco_permissions_check
|
from app.scodoc import sco_permissions_check
|
||||||
from app.scodoc import sco_placement
|
from app.scodoc import sco_placement
|
||||||
from app.scodoc import sco_poursuite_dut
|
from app.scodoc import sco_poursuite_dut
|
||||||
from app.scodoc import sco_preferences
|
from app.scodoc import sco_preferences
|
||||||
from app.scodoc import sco_prepajury
|
from app.scodoc import sco_prepajury
|
||||||
from app.scodoc import sco_pvjury
|
from app.scodoc import sco_pvjury
|
||||||
from app.scodoc import sco_pvpdf
|
|
||||||
from app.scodoc import sco_recapcomplet
|
from app.scodoc import sco_recapcomplet
|
||||||
from app.scodoc import sco_report
|
from app.scodoc import sco_report
|
||||||
from app.scodoc import sco_saisie_notes
|
from app.scodoc import sco_saisie_notes
|
||||||
@ -136,7 +133,6 @@ from app.scodoc import sco_undo_notes
|
|||||||
from app.scodoc import sco_users
|
from app.scodoc import sco_users
|
||||||
from app.scodoc import sco_xml
|
from app.scodoc import sco_xml
|
||||||
from app.scodoc.gen_tables import GenTable
|
from app.scodoc.gen_tables import GenTable
|
||||||
from app.scodoc.sco_pdf import PDFLOCK
|
|
||||||
from app.scodoc.sco_permissions import Permission
|
from app.scodoc.sco_permissions import Permission
|
||||||
from app.scodoc.TrivialFormulator import TrivialFormulator
|
from app.scodoc.TrivialFormulator import TrivialFormulator
|
||||||
from app.views import ScoData
|
from app.views import ScoData
|
||||||
@ -235,6 +231,11 @@ sco_publish(
|
|||||||
sco_recapcomplet.formsemestre_recapcomplet,
|
sco_recapcomplet.formsemestre_recapcomplet,
|
||||||
Permission.ScoView,
|
Permission.ScoView,
|
||||||
)
|
)
|
||||||
|
sco_publish(
|
||||||
|
"/evaluations_recap",
|
||||||
|
sco_evaluation_recap.evaluations_recap,
|
||||||
|
Permission.ScoView,
|
||||||
|
)
|
||||||
sco_publish(
|
sco_publish(
|
||||||
"/formsemestres_bulletins",
|
"/formsemestres_bulletins",
|
||||||
sco_recapcomplet.formsemestres_bulletins,
|
sco_recapcomplet.formsemestres_bulletins,
|
||||||
|
Loading…
Reference in New Issue
Block a user