Tableau saisie jury basé sur recap_complet

This commit is contained in:
Emmanuel Viennet 2022-04-07 23:31:08 +02:00
parent ec57ba4ef7
commit 7a8c77add4
6 changed files with 260 additions and 197 deletions

View File

@ -18,7 +18,7 @@ from app.auth.models import User
from app.comp.res_cache import ResultatsCache from app.comp.res_cache import ResultatsCache
from app.comp import res_sem from app.comp import res_sem
from app.comp.moy_mod import ModuleImplResults from app.comp.moy_mod import ModuleImplResults
from app.models import FormSemestre, FormSemestreUECoef from app.models import FormSemestre, FormSemestreUECoef, formsemestre
from app.models import Identite from app.models import Identite
from app.models import ModuleImpl, ModuleImplInscription from app.models import ModuleImpl, ModuleImplInscription
from app.models.ues import UniteEns from app.models.ues import UniteEns
@ -388,7 +388,9 @@ class ResultatsSemestre(ResultatsCache):
# --- TABLEAU RECAP # --- TABLEAU RECAP
def get_table_recap(self, convert_values=False, include_evaluations=False): def get_table_recap(
self, convert_values=False, include_evaluations=False, modejury=False
):
"""Result: tuple avec """Result: tuple avec
- rows: liste de dicts { column_id : value } - rows: liste de dicts { column_id : value }
- titles: { column_id : title } - titles: { column_id : title }
@ -538,6 +540,9 @@ class ResultatsSemestre(ResultatsCache):
titles_bot[ titles_bot[
f"_{col_id}_target_attrs" f"_{col_id}_target_attrs"
] = f"""title="{ue.titre} S{ue.semestre_idx or '?'}" """ ] = f"""title="{ue.titre} S{ue.semestre_idx or '?'}" """
if modejury:
# pas d'autre colonnes de résultats
continue
# Bonus (sport) dans cette UE ? # Bonus (sport) dans cette UE ?
# Le bonus sport appliqué sur cette UE # Le bonus sport appliqué sur cette UE
if (self.bonus_ues is not None) and (ue.id in self.bonus_ues): if (self.bonus_ues is not None) and (ue.id in self.bonus_ues):
@ -632,6 +637,18 @@ class ResultatsSemestre(ResultatsCache):
elif nb_ues_validables < len(ues_sans_bonus): elif nb_ues_validables < len(ues_sans_bonus):
row["_ues_validables_class"] += " moy_inf" row["_ues_validables_class"] += " moy_inf"
row["_ues_validables_order"] = nb_ues_validables # pour tri row["_ues_validables_order"] = nb_ues_validables # pour tri
if modejury:
idx = add_cell(
row,
"jury_link",
"",
f"""<a href="{url_for('notes.formsemestre_validation_etud_form',
scodoc_dept=g.scodoc_dept, formsemestre_id=self.formsemestre.id, etudid=etudid
)
}">saisir décision</a>""",
"col_jury_link",
1000,
)
rows.append(row) rows.append(row)
self._recap_add_partitions(rows, titles) self._recap_add_partitions(rows, titles)

View File

@ -404,9 +404,6 @@ def formsemestre_status_menubar(sem):
"args": { "args": {
"formsemestre_id": formsemestre_id, "formsemestre_id": formsemestre_id,
"modejury": 1, "modejury": 1,
"hidemodules": 1,
"hidebac": 1,
"pref_override": 0,
}, },
"enabled": sco_permissions_check.can_validate_sem(formsemestre_id), "enabled": sco_permissions_check.can_validate_sem(formsemestre_id),
}, },

View File

@ -31,6 +31,7 @@ import time
import flask import flask
from flask import url_for, g, request from flask import url_for, g, request
from app.models.etudiants import Identite
import app.scodoc.notesdb as ndb import app.scodoc.notesdb as ndb
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
@ -107,29 +108,57 @@ def formsemestre_validation_etud_form(
if not Se.sem["etat"]: if not Se.sem["etat"]:
raise ScoValueError("validation: semestre verrouille") raise ScoValueError("validation: semestre verrouille")
url_tableau = url_for(
"notes.formsemestre_recapcomplet",
scodoc_dept=g.scodoc_dept,
modejury=1,
formsemestre_id=formsemestre_id,
selected_etudid=etudid, # va a la bonne ligne
)
H = [ H = [
html_sco_header.sco_header( html_sco_header.sco_header(
page_title="Parcours %(nomprenom)s" % etud, page_title=f"Parcours {etud['nomprenom']}",
javascripts=["js/recap_parcours.js"], javascripts=["js/recap_parcours.js"],
) )
] ]
Footer = ["<p>"]
# Navigation suivant/precedent # Navigation suivant/precedent
if etud_index_prev != None: if etud_index_prev is not None:
etud_p = sco_etud.get_etud_info(etudid=T[etud_index_prev][-1], filled=True)[0] etud_prev = Identite.query.get(T[etud_index_prev][-1])
Footer.append( url_prev = url_for(
'<span><a href="formsemestre_validation_etud_form?formsemestre_id=%s&etud_index=%s">Etud. précédent (%s)</a></span>' "notes.formsemestre_validation_etud_form",
% (formsemestre_id, etud_index_prev, etud_p["nomprenom"]) scodoc_dept=g.scodoc_dept,
formsemestre_id=formsemestre_id,
etud_index=etud_index_prev,
) )
if etud_index_next != None: else:
etud_n = sco_etud.get_etud_info(etudid=T[etud_index_next][-1], filled=True)[0] url_prev = None
Footer.append( if etud_index_next is not None:
'<span style="padding-left: 50px;"><a href="formsemestre_validation_etud_form?formsemestre_id=%s&etud_index=%s">Etud. suivant (%s)</a></span>' etud_next = Identite.query.get(T[etud_index_next][-1])
% (formsemestre_id, etud_index_next, etud_n["nomprenom"]) url_next = url_for(
"notes.formsemestre_validation_etud_form",
scodoc_dept=g.scodoc_dept,
formsemestre_id=formsemestre_id,
etud_index=etud_index_next,
) )
Footer.append("</p>") else:
Footer.append(html_sco_header.sco_footer()) url_next = None
footer = ["""<div class="jury_footer"><span>"""]
if url_prev:
footer.append(
f'< <a class="stdlink" href="{url_prev}">{etud_prev.nomprenom}</a>'
)
footer.append(
f"""</span><span><a class="stdlink" href="{url_tableau}">retour à la liste</a></span><span>"""
)
if url_next:
footer.append(
f'<a class="stdlink" href="{url_next}">{etud_next.nomprenom}</a> >'
)
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:
@ -171,7 +200,7 @@ def formsemestre_validation_etud_form(
""" """
) )
) )
return "\n".join(H + Footer) return "\n".join(H + footer)
H.append( H.append(
formsemestre_recap_parcours_table( formsemestre_recap_parcours_table(
@ -180,18 +209,10 @@ def formsemestre_validation_etud_form(
) )
if check: if check:
if not desturl: if not desturl:
desturl = url_for( desturl = url_tableau
"notes.formsemestre_recapcomplet",
scodoc_dept=g.scodoc_dept,
modejury=1,
formsemestre_id=formsemestre_id,
sortcol=sortcol
or None, # pour refaire tri sorttable du tableau de notes
_anchor="etudid%s" % etudid, # va a la bonne ligne
)
H.append(f'<ul><li><a href="{desturl}">Continuer</a></li></ul>') H.append(f'<ul><li><a href="{desturl}">Continuer</a></li></ul>')
return "\n".join(H + Footer) return "\n".join(H + footer)
decision_jury = Se.nt.get_etud_decision_sem(etudid) decision_jury = Se.nt.get_etud_decision_sem(etudid)
@ -207,7 +228,7 @@ def formsemestre_validation_etud_form(
""" """
) )
) )
return "\n".join(H + Footer) return "\n".join(H + footer)
# Infos si pas de semestre précédent # Infos si pas de semestre précédent
if not Se.prev: if not Se.prev:
@ -345,7 +366,7 @@ 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 "".join(H + footer)
def formsemestre_validation_etud( def formsemestre_validation_etud(
@ -937,19 +958,23 @@ def do_formsemestre_validation_auto(formsemestre_id):
) )
if conflicts: if conflicts:
H.append( H.append(
"""<p><b>Attention:</b> %d étudiants non modifiés car décisions différentes f"""<p><b>Attention:</b> {len(conflicts)} étudiants non modifiés
déja saisies :<ul>""" car décisions différentes déja saisies :
% len(conflicts) <ul>"""
) )
for etud in conflicts: for etud in conflicts:
H.append( H.append(
'<li><a href="formsemestre_validation_etud_form?formsemestre_id=%s&etudid=%s&check=1">%s</li>' f"""<li><a href="{
% (formsemestre_id, etud["etudid"], etud["nomprenom"]) url_for('notes.formsemestre_validation_etud_form',
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id,
etudid=etud["etudid"], check=1)
}">{etud["nomprenom"]}</li>"""
) )
H.append("</ul>") H.append("</ul>")
H.append( H.append(
'<a href="formsemestre_recapcomplet?formsemestre_id=%s&modejury=1&hidemodules=1&hidebac=1&pref_override=0">continuer</a>' f"""<a href="{url_for('notes.formsemestre_recapcomplet',
% formsemestre_id scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id, modejury=1)
}">continuer</a>"""
) )
H.append(html_sco_header.sco_footer()) H.append(html_sco_header.sco_footer())
return "\n".join(H) return "\n".join(H)

View File

@ -32,7 +32,7 @@ import time
from xml.etree import ElementTree from xml.etree import ElementTree
from flask import g, request from flask import g, request
from flask import make_response, url_for from flask import url_for
from app import log from app import log
from app.but import bulletin_but from app.but import bulletin_but
@ -40,39 +40,29 @@ from app.comp import res_sem
from app.comp.res_compat import NotesTableCompat from app.comp.res_compat import NotesTableCompat
from app.models import FormSemestre from app.models import FormSemestre
from app.models.etudiants import Identite from app.models.etudiants import Identite
from app.models.evaluations import Evaluation
from app.scodoc.gen_tables import GenTable from app.scodoc.gen_tables import GenTable
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
from app.scodoc import html_sco_header from app.scodoc import html_sco_header
from app.scodoc import sco_bulletins_json from app.scodoc import sco_bulletins_json
from app.scodoc import sco_bulletins_xml from app.scodoc import sco_bulletins_xml
from app.scodoc import sco_bulletins, sco_excel
from app.scodoc import sco_cache from app.scodoc import sco_cache
from app.scodoc import sco_codes_parcours
from app.scodoc import sco_evaluations from app.scodoc import sco_evaluations
from app.scodoc import sco_evaluation_db
from app.scodoc.sco_exceptions import ScoValueError from app.scodoc.sco_exceptions import ScoValueError
from app.scodoc import sco_formations
from app.scodoc import sco_formsemestre from app.scodoc import sco_formsemestre
from app.scodoc import sco_formsemestre_status from app.scodoc import sco_formsemestre_status
from app.scodoc import sco_groups
from app.scodoc import sco_permissions_check from app.scodoc import sco_permissions_check
from app.scodoc import sco_preferences from app.scodoc import sco_preferences
from app.scodoc import sco_etud
from app.scodoc import sco_users
from app.scodoc import sco_xml
from app.scodoc.sco_codes_parcours import DEF, UE_SPORT
def formsemestre_recapcomplet( def formsemestre_recapcomplet(
formsemestre_id=None, formsemestre_id=None,
modejury=False, # affiche lien saisie decision jury modejury=False,
tabformat="html", tabformat="html",
sortcol=None, sortcol=None,
xml_with_decisions=False, # XML avec decisions xml_with_decisions=False,
rank_partition_id=None, # si None, calcul rang global force_publishing=True,
force_publishing=True, # publie les XML/JSON meme si bulletins non publiés selected_etudid=None,
): ):
"""Page récapitulant les notes d'un semestre. """Page récapitulant les notes d'un semestre.
Grand tableau récapitulatif avec toutes les notes de modules Grand tableau récapitulatif avec toutes les notes de modules
@ -89,7 +79,9 @@ def formsemestre_recapcomplet(
pdf : NON SUPPORTE (car tableau trop grand pour générer un pdf utilisable) pdf : NON SUPPORTE (car tableau trop grand pour générer un pdf utilisable)
modejury: cache modules, affiche lien saisie decision jury modejury: cache modules, affiche lien saisie decision jury
xml_with_decisions: publie décisions de jury dans xml et json
force_publishing: publie les xml et json même si bulletins non publiés
selected_etudid: etudid sélectionné (pour scroller au bon endroit)
""" """
formsemestre = FormSemestre.query.get_or_404(formsemestre_id) formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
@ -98,98 +90,92 @@ def formsemestre_recapcomplet(
xml_with_decisions = int(xml_with_decisions) xml_with_decisions = int(xml_with_decisions)
force_publishing = int(force_publishing) force_publishing = int(force_publishing)
is_file = tabformat in {"csv", "json", "xls", "xlsx", "xlsall", "xml"} is_file = tabformat in {"csv", "json", "xls", "xlsx", "xlsall", "xml"}
H = [] data = _do_formsemestre_recapcomplet(
if not is_file:
H += [
html_sco_header.sco_header(
page_title="Récapitulatif",
no_side_bar=True,
init_qtip=True,
javascripts=["js/etud_info.js", "js/table_recap.js"],
),
sco_formsemestre_status.formsemestre_status_head(
formsemestre_id=formsemestre_id
),
]
if len(formsemestre.inscriptions) > 0:
H.append(
f"""<form name="f" method="get" action="{request.base_url}">
<input type="hidden" name="formsemestre_id" value="{formsemestre_id}"></input>
"""
)
if modejury:
H.append(
f'<input type="hidden" name="modejury" value="{modejury}"></input>'
)
H.append(
'<select name="tabformat" onchange="document.f.submit()" class="noprint">'
)
for (format, label) in (
("html", "Tableau"),
("evals", "Avec toutes les évaluations"),
("xml", "Bulletins XML (obsolète)"),
("json", "Bulletins JSON"),
):
if format == tabformat:
selected = " selected"
else:
selected = ""
H.append(f'<option value="{format}"{selected}>{label}</option>')
H.append("</select>")
H.append(
f"""&nbsp;(cliquer sur un nom pour afficher son bulletin ou <a class="stdlink"
href="{url_for('notes.formsemestre_bulletins_pdf',
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id)
}">ici avoir le classeur papier</a>)
"""
)
data = do_formsemestre_recapcomplet(
formsemestre_id, formsemestre_id,
format=tabformat, format=tabformat,
modejury=modejury, modejury=modejury,
sortcol=sortcol, sortcol=sortcol,
xml_with_decisions=xml_with_decisions, xml_with_decisions=xml_with_decisions,
rank_partition_id=rank_partition_id,
force_publishing=force_publishing, force_publishing=force_publishing,
selected_etudid=selected_etudid,
) )
if tabformat == "xml": if is_file:
response = make_response(data) return data
response.headers["Content-Type"] = scu.XML_MIMETYPE H = [
return response html_sco_header.sco_header(
page_title="Récapitulatif",
no_side_bar=True,
init_qtip=True,
javascripts=["js/etud_info.js", "js/table_recap.js"],
),
sco_formsemestre_status.formsemestre_status_head(
formsemestre_id=formsemestre_id
),
]
if len(formsemestre.inscriptions) > 0:
H.append(
f"""<form name="f" method="get" action="{request.base_url}">
<input type="hidden" name="formsemestre_id" value="{formsemestre_id}"></input>
"""
)
if modejury:
H.append(
f'<input type="hidden" name="modejury" value="{modejury}"></input>'
)
H.append(
'<select name="tabformat" onchange="document.f.submit()" class="noprint">'
)
for (format, label) in (
("html", "Tableau"),
("evals", "Avec toutes les évaluations"),
("xml", "Bulletins XML (obsolète)"),
("json", "Bulletins JSON"),
):
if format == tabformat:
selected = " selected"
else:
selected = ""
H.append(f'<option value="{format}"{selected}>{label}</option>')
H.append("</select>")
H.append(
f"""&nbsp;(cliquer sur un nom pour afficher son bulletin ou <a class="stdlink"
href="{url_for('notes.formsemestre_bulletins_pdf',
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id)
}">ici avoir le classeur papier</a>)
"""
)
H.append(data) H.append(data)
if not is_file: if len(formsemestre.inscriptions) > 0:
if len(formsemestre.inscriptions) > 0: H.append("</form>")
H.append("</form>") H.append(
H.append( f"""<p><a class="stdlink" href="{url_for('notes.formsemestre_pvjury',
f"""<p><a class="stdlink" href="{url_for('notes.formsemestre_pvjury', scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id)
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id) }">Voir les décisions du jury</a></p>"""
}">Voir les décisions du jury</a></p>""" )
) if sco_permissions_check.can_validate_sem(formsemestre_id):
if sco_permissions_check.can_validate_sem(formsemestre_id): H.append("<p>")
H.append("<p>") if modejury:
if modejury:
H.append(
f"""<a class="stdlink" href="{url_for('formsemestre_validation_auto',
formsemestre_id=formsemestre_id)
}">Calcul automatique des décisions du jury</a></p>"""
)
else:
H.append(
f"""<a class="stdlink" href="{url_for('notes.formsemestre_recapcomplet',
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id, modejury=1)
}">Saisie des décisions du jury</a>"""
)
H.append("</p>")
if sco_preferences.get_preference("use_ue_coefs", formsemestre_id):
H.append( H.append(
""" f"""<a class="stdlink" href="{url_for('notes.formsemestre_validation_auto',
<p class="infop">utilise les coefficients d'UE pour calculer la moyenne générale.</p> scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id)
""" }">Calcul automatique des décisions du jury</a></p>"""
) )
H.append(html_sco_header.sco_footer()) else:
H.append(
f"""<a class="stdlink" href="{url_for('notes.formsemestre_recapcomplet',
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id, modejury=1)
}">Saisie des décisions du jury</a>"""
)
H.append("</p>")
if sco_preferences.get_preference("use_ue_coefs", formsemestre_id):
H.append(
"""
<p class="infop">utilise les coefficients d'UE pour calculer la moyenne générale.</p>
"""
)
H.append(html_sco_header.sco_footer())
# HTML or binary data ? # HTML or binary data ?
if len(H) > 1: if len(H) > 1:
return "".join(H) return "".join(H)
@ -199,18 +185,15 @@ def formsemestre_recapcomplet(
return H return H
def do_formsemestre_recapcomplet( def _do_formsemestre_recapcomplet(
formsemestre_id=None, formsemestre_id=None,
format="html", # html, xml, xls, xlsall, json format="html", # html, xml, xls, xlsall, json
hidemodules=False, # ne pas montrer les modules (ignoré en XML)
hidebac=False, # pas de colonne Bac (ignoré en XML)
xml_nodate=False, # format XML sans dates (sert pour debug cache: comparaison de XML) xml_nodate=False, # format XML sans dates (sert pour debug cache: comparaison de XML)
modejury=False, # saisie décisions jury modejury=False, # saisie décisions jury
sortcol=None, # indice colonne a trier dans table T sortcol=None, # indice colonne a trier dans table T
xml_with_decisions=False, xml_with_decisions=False,
disable_etudlink=False,
rank_partition_id=None, # si None, calcul rang global
force_publishing=True, force_publishing=True,
selected_etudid=None,
): ):
"""Calcule et renvoie le tableau récapitulatif.""" """Calcule et renvoie le tableau récapitulatif."""
formsemestre = FormSemestre.query.get_or_404(formsemestre_id) formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
@ -219,13 +202,15 @@ def do_formsemestre_recapcomplet(
f"""recap-{formsemestre.titre_num()}-{time.strftime("%Y-%m-%d")}""" f"""recap-{formsemestre.titre_num()}-{time.strftime("%Y-%m-%d")}"""
) )
if (format == "html" or format == "evals") and not modejury: if format == "html" or format == "evals":
res: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre) res: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
data = gen_formsemestre_recapcomplet_html( data = gen_formsemestre_recapcomplet_html(
formsemestre, formsemestre,
res, res,
include_evaluations=(format == "evals"), include_evaluations=(format == "evals"),
modejury=modejury,
filename=filename, filename=filename,
selected_etudid=selected_etudid,
) )
return data return data
elif format.startswith("xls") or format == "csv": elif format.startswith("xls") or format == "csv":
@ -388,35 +373,51 @@ def _gen_cell(key: str, row: dict, elt="td"):
return f"<{elt} {attrs}>{content}</{elt}>" return f"<{elt} {attrs}>{content}</{elt}>"
def _gen_row(keys: list[str], row, elt="td"): def _gen_row(keys: list[str], row, elt="td", selected_etudid=None):
klass = row.get("_tr_class") klass = row.get("_tr_class")
tr_class = f'class="{klass}"' if klass else "" tr_class = f'class="{klass}"' if klass else ""
return f'<tr {tr_class}>{"".join([_gen_cell(key, row, elt) for key in keys])}</tr>' 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,
include_evaluations=False, include_evaluations=False,
modejury=False,
filename="", filename="",
selected_etudid=None,
): ):
"""Construit table recap pour le BUT """Construit table recap pour le BUT
Cache le résultat pour le semestre. Cache le résultat pour le semestre (sauf en mode jury).
Si modejury, cache colonnes modules et affiche un lien vers la saisie de la décision de jury
Return: data, filename Return: data, filename
data est une chaine, le <div>...</div> incluant le tableau. data est une chaine, le <div>...</div> incluant le tableau.
""" """
if include_evaluations: table_html = None
table_html = sco_cache.TableRecapWithEvalsCache.get(formsemestre.id) if not (modejury or selected_etudid):
else:
table_html = sco_cache.TableRecapCache.get(formsemestre.id)
if table_html is None:
table_html = _gen_formsemestre_recapcomplet_html(
formsemestre, res, include_evaluations, filename
)
if include_evaluations: if include_evaluations:
sco_cache.TableRecapWithEvalsCache.set(formsemestre.id, table_html) table_html = sco_cache.TableRecapWithEvalsCache.get(formsemestre.id)
else: else:
sco_cache.TableRecapCache.set(formsemestre.id, table_html) table_html = sco_cache.TableRecapCache.get(formsemestre.id)
if modejury or (table_html is None):
table_html = _gen_formsemestre_recapcomplet_html(
formsemestre,
res,
include_evaluations,
modejury,
filename,
selected_etudid=selected_etudid,
)
if not modejury:
if include_evaluations:
sco_cache.TableRecapWithEvalsCache.set(formsemestre.id, table_html)
else:
sco_cache.TableRecapCache.set(formsemestre.id, table_html)
return table_html return table_html
@ -425,11 +426,13 @@ def _gen_formsemestre_recapcomplet_html(
formsemestre: FormSemestre, formsemestre: FormSemestre,
res: NotesTableCompat, res: NotesTableCompat,
include_evaluations=False, include_evaluations=False,
modejury=False,
filename: str = "", filename: str = "",
selected_etudid=None,
) -> str: ) -> str:
"""Génère le html""" """Génère le html"""
rows, footer_rows, titles, column_ids = res.get_table_recap( rows, footer_rows, titles, column_ids = res.get_table_recap(
convert_values=True, include_evaluations=include_evaluations convert_values=True, include_evaluations=include_evaluations, modejury=modejury
) )
if not rows: if not rows:
return ( return (
@ -437,7 +440,8 @@ def _gen_formsemestre_recapcomplet_html(
) )
H = [ H = [
f"""<div class="table_recap"><table class="table_recap { f"""<div class="table_recap"><table class="table_recap {
'apc' if formsemestre.formation.is_apc() else 'classic'}" 'apc' if formsemestre.formation.is_apc() else 'classic'
} {'jury' if modejury else ''}"
data-filename="{filename}">""" data-filename="{filename}">"""
] ]
# header # header
@ -451,7 +455,7 @@ def _gen_formsemestre_recapcomplet_html(
# body # body
H.append("<tbody>") H.append("<tbody>")
for row in rows: for row in rows:
H.append(f"{_gen_row(column_ids, row)}\n") H.append(f"{_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>")

View File

@ -1146,6 +1146,18 @@ span.jurylink a {
text-decoration: underline; text-decoration: underline;
} }
div.jury_footer {
display: flex;
justify-content: space-evenly;
}
div.jury_footer>span {
border: 2px solid rgb(90, 90, 90);
border-radius: 4px;
padding: 4px;
background-color: rgb(230, 242, 230);
}
.eval_description p { .eval_description p {
margin-left: 15px; margin-left: 15px;
margin-bottom: 2px; margin-bottom: 2px;

View File

@ -21,43 +21,54 @@ $(function () {
dt.columns(".partition_aux").visible(!visible); dt.columns(".partition_aux").visible(!visible);
dt.buttons('toggle_partitions:name').text(visible ? "Toutes les partitions" : "Cacher les partitions"); dt.buttons('toggle_partitions:name').text(visible ? "Toutes les partitions" : "Cacher les partitions");
} }
}, }];
$('table.table_recap').hasClass("apc") ? if (!$('table.table_recap').hasClass("jury")) {
{ buttons.push(
name: "toggle_res", $('table.table_recap').hasClass("apc") ?
text: "Cacher les ressources", {
action: function (e, dt, node, config) { name: "toggle_res",
let visible = dt.columns(".col_res").visible()[0]; text: "Cacher les ressources",
dt.columns(".col_res").visible(!visible); action: function (e, dt, node, config) {
dt.columns(".col_ue_bonus").visible(!visible); let visible = dt.columns(".col_res").visible()[0];
dt.columns(".col_malus").visible(!visible); dt.columns(".col_res").visible(!visible);
dt.buttons('toggle_res:name').text(visible ? "Montrer les ressources" : "Cacher les ressources"); dt.columns(".col_ue_bonus").visible(!visible);
dt.columns(".col_malus").visible(!visible);
dt.buttons('toggle_res:name').text(visible ? "Montrer les ressources" : "Cacher les ressources");
}
} : {
name: "toggle_mod",
text: "Cacher les modules",
action: function (e, dt, node, config) {
let visible = dt.columns(".col_mod:not(.col_empty)").visible()[0];
dt.columns(".col_mod:not(.col_empty)").visible(!visible);
dt.columns(".col_ue_bonus").visible(!visible);
dt.columns(".col_malus").visible(!visible);
dt.buttons('toggle_mod:name').text(visible ? "Montrer les modules" : "Cacher les modules");
visible = dt.columns(".col_empty").visible()[0];
dt.buttons('toggle_col_empty:name').text(visible ? "Cacher mod. vides" : "Montrer mod. vides");
}
} }
} : { );
name: "toggle_mod", if ($('table.table_recap').hasClass("apc")) {
text: "Cacher les modules", buttons.push({
name: "toggle_sae",
text: "Cacher les SAÉs",
action: function (e, dt, node, config) { action: function (e, dt, node, config) {
let visible = dt.columns(".col_mod:not(.col_empty)").visible()[0]; let visible = dt.columns(".col_sae").visible()[0];
dt.columns(".col_mod:not(.col_empty)").visible(!visible); dt.columns(".col_sae").visible(!visible);
dt.columns(".col_ue_bonus").visible(!visible); dt.buttons('toggle_sae:name').text(visible ? "Montrer les SAÉs" : "Cacher les SAÉs");
dt.columns(".col_malus").visible(!visible);
dt.buttons('toggle_mod:name').text(visible ? "Montrer les modules" : "Cacher les modules");
visible = dt.columns(".col_empty").visible()[0];
dt.buttons('toggle_col_empty:name').text(visible ? "Cacher mod. vides" : "Montrer mod. vides");
} }
} })
]; }
if ($('table.table_recap').hasClass("apc")) {
buttons.push({ buttons.push({
name: "toggle_sae", name: "toggle_col_empty",
text: "Cacher les SAÉs", text: "Montrer mod. vides",
action: function (e, dt, node, config) { action: function (e, dt, node, config) {
let visible = dt.columns(".col_sae").visible()[0]; let visible = dt.columns(".col_empty").visible()[0];
dt.columns(".col_sae").visible(!visible); dt.columns(".col_empty").visible(!visible);
dt.buttons('toggle_sae:name').text(visible ? "Montrer les SAÉs" : "Cacher les SAÉs"); dt.buttons('toggle_col_empty:name').text(visible ? "Montrer mod. vides" : "Cacher mod. vides");
} }
}) })
} }
buttons.push({ buttons.push({
name: "toggle_admission", name: "toggle_admission",
@ -68,15 +79,6 @@ $(function () {
dt.buttons('toggle_admission:name').text(visible ? "Montrer infos admission" : "Cacher infos admission"); dt.buttons('toggle_admission:name').text(visible ? "Montrer infos admission" : "Cacher infos admission");
} }
}) })
buttons.push({
name: "toggle_col_empty",
text: "Montrer mod. vides",
action: function (e, dt, node, config) {
let visible = dt.columns(".col_empty").visible()[0];
dt.columns(".col_empty").visible(!visible);
dt.buttons('toggle_col_empty:name').text(visible ? "Montrer mod. vides" : "Cacher mod. vides");
}
})
$('table.table_recap').DataTable( $('table.table_recap').DataTable(
{ {
paging: false, paging: false,
@ -143,4 +145,10 @@ $(function () {
$(this).addClass('selected'); $(this).addClass('selected');
} }
}); });
// Pour montrer et highlihter l'étudiant sélectionné:
$(function () {
document.querySelector("#row_selected").scrollIntoView();
window.scrollBy(0, -50);
document.querySelector("#row_selected").classList.add("selected");
});
}); });