1
0
forked from ScoDoc/ScoDoc

Filtrage par groupes dans els pages statistiques: fix #791

This commit is contained in:
Emmanuel Viennet 2024-03-31 23:04:54 +02:00
parent 126ea0741a
commit 28d46e413d
7 changed files with 356 additions and 355 deletions

View File

@ -676,6 +676,7 @@ class GenTable:
fmt="html", fmt="html",
page_title="", page_title="",
filename=None, filename=None,
cssstyles=[],
javascripts=[], javascripts=[],
with_html_headers=True, with_html_headers=True,
publish=True, publish=True,
@ -696,6 +697,7 @@ class GenTable:
H.append( H.append(
self.html_header self.html_header
or html_sco_header.sco_header( or html_sco_header.sco_header(
cssstyles=cssstyles,
page_title=page_title, page_title=page_title,
javascripts=javascripts, javascripts=javascripts,
init_qtip=init_qtip, init_qtip=init_qtip,
@ -721,7 +723,7 @@ class GenTable:
) )
else: else:
return pdf_doc return pdf_doc
elif fmt == "xls" or fmt == "xlsx": # dans les 2 cas retourne du xlsx elif fmt in ("xls", "xlsx"): # dans les 2 cas retourne du xlsx
xls = self.excel() xls = self.excel()
if publish: if publish:
return scu.send_file( return scu.send_file(
@ -730,7 +732,6 @@ class GenTable:
suffix=scu.XLSX_SUFFIX, suffix=scu.XLSX_SUFFIX,
mime=scu.XLSX_MIMETYPE, mime=scu.XLSX_MIMETYPE,
) )
else:
return xls return xls
elif fmt == "text": elif fmt == "text":
return self.text() return self.text()

View File

@ -453,6 +453,10 @@ class DisplayedGroupsInfos:
for i in to_remove: for i in to_remove:
del T[i] del T[i]
def get_etudids(self) -> set[int]:
"Les etudids des groupes choisis"
return {member["etudid"] for member in self.members}
def get_form_elem(self): def get_form_elem(self):
"""html hidden input with groups""" """html hidden input with groups"""
H = [] H = []

View File

@ -34,22 +34,28 @@ from operator import itemgetter
from flask import url_for, g, request from flask import url_for, g, request
import app import app
import app.scodoc.sco_utils as scu from app.scodoc import (
from app.scodoc import html_sco_header html_sco_header,
from app.scodoc import sco_formsemestre sco_formsemestre,
from app.scodoc import sco_preferences sco_groups_view,
from app.scodoc import sco_report sco_preferences,
from app.scodoc import sco_etud sco_report,
import sco_version sco_etud,
)
from app.models import FormSemestre
from app.scodoc.gen_tables import GenTable from app.scodoc.gen_tables import GenTable
import app.scodoc.sco_utils as scu
import sco_version
def formsemestre_table_etuds_lycees( def formsemestre_table_etuds_lycees(
formsemestre_id, group_lycees=True, only_primo=False formsemestre: FormSemestre, groups_infos, group_lycees=True, only_primo=False
): ):
"""Récupère liste d'etudiants avec etat et decision.""" """Récupère liste d'etudiants avec etat et decision."""
sem = sco_formsemestre.get_formsemestre(formsemestre_id) sem = sco_formsemestre.get_formsemestre(formsemestre.id)
etuds = sco_report.tsp_etud_list(formsemestre_id, only_primo=only_primo)[0] etuds = sco_report.tsp_etud_list(
formsemestre.id, groups_infos=groups_infos, only_primo=only_primo
)[0]
if only_primo: if only_primo:
primostr = "primo-entrants du " primostr = "primo-entrants du "
else: else:
@ -59,7 +65,7 @@ def formsemestre_table_etuds_lycees(
etuds, etuds,
group_lycees, group_lycees,
title, title,
sco_preferences.SemPreferences(formsemestre_id), sco_preferences.SemPreferences(formsemestre.id),
) )
@ -180,13 +186,20 @@ def _table_etuds_lycees(etuds, group_lycees, title, preferences, no_links=False)
def formsemestre_etuds_lycees( def formsemestre_etuds_lycees(
formsemestre_id, formsemestre_id,
group_ids: list[int] = None, # si indiqué, ne prend que ces groupes
fmt="html", fmt="html",
only_primo=False, only_primo=False,
no_grouping=False, no_grouping=False,
): ):
"""Table des lycées d'origine""" """Table des lycées d'origine"""
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
groups_infos = sco_groups_view.DisplayedGroupsInfos(
group_ids,
formsemestre_id=formsemestre.id,
select_all_when_unspecified=True,
)
tab, etuds_by_lycee = formsemestre_table_etuds_lycees( tab, etuds_by_lycee = formsemestre_table_etuds_lycees(
formsemestre_id, only_primo=only_primo, group_lycees=not no_grouping formsemestre, groups_infos, only_primo=only_primo, group_lycees=not no_grouping
) )
tab.base_url = "%s?formsemestre_id=%s" % (request.base_url, formsemestre_id) tab.base_url = "%s?formsemestre_id=%s" % (request.base_url, formsemestre_id)
if only_primo: if only_primo:
@ -196,13 +209,19 @@ def formsemestre_etuds_lycees(
t = tab.make_page(fmt=fmt, with_html_headers=False) t = tab.make_page(fmt=fmt, with_html_headers=False)
if fmt != "html": if fmt != "html":
return t return t
F = [sco_report.tsp_form_primo_group(only_primo, no_grouping, formsemestre_id, fmt)] F = [
sco_report.tsp_form_primo_group(
only_primo, no_grouping, formsemestre_id, fmt, groups_infos=groups_infos
)
]
H = [ H = [
html_sco_header.sco_header( html_sco_header.sco_header(
page_title=tab.page_title, page_title=tab.page_title,
init_google_maps=True, init_google_maps=True,
init_qtip=True, init_qtip=True,
javascripts=["js/etud_info.js", "js/map_lycees.js"], cssstyles=sco_groups_view.CSSSTYLES,
javascripts=sco_groups_view.JAVASCRIPTS
+ ["js/etud_info.js", "js/map_lycees.js"],
), ),
"""<h2 class="formsemestre">Lycées d'origine des étudiants</h2>""", """<h2 class="formsemestre">Lycées d'origine des étudiants</h2>""",
"\n".join(F), "\n".join(F),

View File

@ -40,6 +40,7 @@ from operator import itemgetter
from flask import url_for, g, request from flask import url_for, g, request
import pydot import pydot
from app import log
from app.but import jury_but from app.but import jury_but
from app.comp import res_sem from app.comp import res_sem
from app.comp.res_compat import NotesTableCompat from app.comp.res_compat import NotesTableCompat
@ -47,18 +48,21 @@ from app.models import FormSemestre, ScolarAutorisationInscription
from app.models import FormationModalite from app.models import FormationModalite
from app.models.etudiants import Identite from app.models.etudiants import Identite
import app.scodoc.sco_utils as scu from app.scodoc import (
from app.scodoc import notesdb as ndb codes_cursus,
from app.scodoc import html_sco_header html_sco_header,
from app.scodoc import codes_cursus sco_etud,
from app.scodoc import sco_etud sco_formsemestre,
from app.scodoc import sco_formsemestre sco_formsemestre_inscriptions,
from app.scodoc import sco_formsemestre_inscriptions sco_groups_view,
from app.scodoc import sco_preferences sco_preferences,
import sco_version )
from app.scodoc.gen_tables import GenTable from app.scodoc.gen_tables import GenTable
from app import log
from app.scodoc.codes_cursus import code_semestre_validant from app.scodoc.codes_cursus import code_semestre_validant
from app.scodoc.sco_exceptions import ScoValueError
from app.scodoc import notesdb as ndb
import app.scodoc.sco_utils as scu
import sco_version
MAX_ETUD_IN_DESCR = 20 MAX_ETUD_IN_DESCR = 20
@ -68,21 +72,25 @@ LEGENDES_CODES_BUT = {
} }
def formsemestre_etuds_stats(sem: dict, only_primo=False): def formsemestre_etuds_stats(
formsemestre: FormSemestre,
only_primo=False,
groups_infos: sco_groups_view.DisplayedGroupsInfos | None = None,
):
"""Récupère liste d'etudiants avec etat et decision.""" """Récupère liste d'etudiants avec etat et decision."""
formsemestre: FormSemestre = FormSemestre.query.get_or_404(sem["formsemestre_id"])
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre) nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
etudids = groups_infos.get_etudids() if groups_infos else set()
T = nt.get_table_moyennes_triees() rows = nt.get_table_moyennes_triees()
# Décisions de jury BUT pour les semestres pairs seulement # Décisions de jury BUT pour les semestres pairs seulement
jury_but_mode = ( jury_but_mode = (
formsemestre.formation.is_apc() and formsemestre.semestre_id % 2 == 0 formsemestre.formation.is_apc() and formsemestre.semestre_id % 2 == 0
) )
# Construit liste d'étudiants du semestre avec leur decision # Construit liste d'étudiants du semestre avec leur decision
etuds = [] etuds = []
for t in T: for t in rows:
etudid = t[-1] etudid = t[-1]
if etudids and etudid not in etudids:
continue
etudiant = Identite.get_etud(etudid) etudiant = Identite.get_etud(etudid)
etud = sco_etud.get_etud_info(etudid=etudid, filled=True)[0] etud = sco_etud.get_etud_info(etudid=etudid, filled=True)[0]
etud["annee_admission"] = etud["annee"] # plus explicite etud["annee_admission"] = etud["annee"] # plus explicite
@ -96,7 +104,7 @@ def formsemestre_etuds_stats(sem: dict, only_primo=False):
etud["codedecision"] = "(nd)" # pas de decision jury etud["codedecision"] = "(nd)" # pas de decision jury
# Ajout devenir (autorisations inscriptions), utile pour stats passage # Ajout devenir (autorisations inscriptions), utile pour stats passage
aut_list = ScolarAutorisationInscription.query.filter_by( aut_list = ScolarAutorisationInscription.query.filter_by(
etudid=etudid, origin_formsemestre_id=sem["formsemestre_id"] etudid=etudid, origin_formsemestre_id=formsemestre.id
).all() ).all()
autorisations = [f"S{a.semestre_id}" for a in aut_list] autorisations = [f"S{a.semestre_id}" for a in aut_list]
autorisations.sort() autorisations.sort()
@ -115,27 +123,27 @@ def formsemestre_etuds_stats(sem: dict, only_primo=False):
bs.append(etud["specialite"]) bs.append(etud["specialite"])
etud["bac-specialite"] = " ".join(bs) etud["bac-specialite"] = " ".join(bs)
# #
if (not only_primo) or is_primo_etud(etud, sem): if (not only_primo) or is_primo_etud(etud, formsemestre):
etuds.append(etud) etuds.append(etud)
return etuds return etuds
def is_primo_etud(etud: dict, sem: dict): def is_primo_etud(etud: dict, formsemestre: FormSemestre):
"""Determine si un (filled) etud a été inscrit avant ce semestre. """Determine si un (filled) etud a été inscrit avant ce semestre.
Regarde la liste des semestres dans lesquels l'étudiant est inscrit. Regarde la liste des semestres dans lesquels l'étudiant est inscrit.
Si semestre pair, considère comme primo-entrants ceux qui étaient Si semestre pair, considère comme primo-entrants ceux qui étaient
primo dans le précédent (S_{2n-1}). primo dans le précédent (S_{2n-1}).
""" """
debut_cur = sem["date_debut_iso"] debut_cur_iso = formsemestre.date_debut.isoformat()
# si semestre impair et sem. précédent contigu, recule date debut # si semestre impair et sem. précédent contigu, recule date debut
if ( if (
(len(etud["sems"]) > 1) (len(etud["sems"]) > 1)
and (sem["semestre_id"] % 2 == 0) and (formsemestre.semestre_id % 2 == 0)
and (etud["sems"][1]["semestre_id"] == (sem["semestre_id"] - 1)) and (etud["sems"][1]["semestre_id"] == (formsemestre.semestre_id - 1))
): ):
debut_cur = etud["sems"][1]["date_debut_iso"] debut_cur_iso = etud["sems"][1]["date_debut_iso"]
for s in etud["sems"]: # le + recent d'abord for s in etud["sems"]: # le + recent d'abord
if s["date_debut_iso"] < debut_cur: if s["date_debut_iso"] < debut_cur_iso:
return False return False
return True return True
@ -274,22 +282,6 @@ def formsemestre_report(
return tab return tab
# def formsemestre_report_bacs(formsemestre_id, fmt='html'):
# """
# Tableau sur résultats par type de bac
# """
# sem = sco_formsemestre.get_formsemestre( formsemestre_id)
# title = 'Statistiques bacs ' + sem['titreannee']
# etuds = formsemestre_etuds_stats(sem)
# tab = formsemestre_report(formsemestre_id, etuds,
# category='bac', result='codedecision',
# category_name='Bac',
# title=title)
# return tab.make_page(
# title = """<h2>Résultats de <a href="formsemestre_status?formsemestre_id=%(formsemestre_id)s">%(titreannee)s</a></h2>""" % sem,
# fmt=fmt, page_title = title)
def formsemestre_report_counts( def formsemestre_report_counts(
formsemestre_id: int, formsemestre_id: int,
fmt="html", fmt="html",
@ -297,6 +289,7 @@ def formsemestre_report_counts(
result: str = None, result: str = None,
allkeys: bool = False, allkeys: bool = False,
only_primo: bool = False, only_primo: bool = False,
group_ids: list[int] = None, # si indiqué, ne prend que ces groupes
): ):
""" """
Tableau comptage avec choix des categories Tableau comptage avec choix des categories
@ -307,8 +300,12 @@ def formsemestre_report_counts(
si vrai, toutes les valeurs présentes dans les données si vrai, toutes les valeurs présentes dans les données
sinon liste prédéfinie (voir ci-dessous) sinon liste prédéfinie (voir ci-dessous)
""" """
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id) formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
sem = sco_formsemestre.get_formsemestre(formsemestre_id) groups_infos = sco_groups_view.DisplayedGroupsInfos(
group_ids,
formsemestre_id=formsemestre.id,
select_all_when_unspecified=True,
)
# Décisions de jury BUT pour les semestres pairs seulement # Décisions de jury BUT pour les semestres pairs seulement
jury_but_mode = ( jury_but_mode = (
formsemestre.formation.is_apc() and formsemestre.semestre_id % 2 == 0 formsemestre.formation.is_apc() and formsemestre.semestre_id % 2 == 0
@ -319,7 +316,9 @@ def formsemestre_report_counts(
category_name = category.capitalize() category_name = category.capitalize()
title = "Comptages " + category_name title = "Comptages " + category_name
etuds = formsemestre_etuds_stats(sem, only_primo=only_primo) etuds = formsemestre_etuds_stats(
formsemestre, groups_infos=groups_infos, only_primo=only_primo
)
tab = formsemestre_report( tab = formsemestre_report(
formsemestre_id, formsemestre_id,
etuds, etuds,
@ -329,7 +328,7 @@ def formsemestre_report_counts(
title=title, title=title,
only_primo=only_primo, only_primo=only_primo,
) )
if not etuds: if len(formsemestre.inscriptions) == 0:
F = ["""<p><em>Aucun étudiant</em></p>"""] F = ["""<p><em>Aucun étudiant</em></p>"""]
else: else:
if allkeys: if allkeys:
@ -357,9 +356,10 @@ def formsemestre_report_counts(
keys += ["nb_rcue_valides", "decision_annee"] keys += ["nb_rcue_valides", "decision_annee"]
keys.sort(key=scu.heterogeneous_sorting_key) keys.sort(key=scu.heterogeneous_sorting_key)
F = [ F = [
"""<form name="f" method="get" action="%s"><p> f"""<form id="group_selector" name="f" method="get" action="{request.base_url}">
Colonnes: <select name="result" onchange="document.f.submit()">""" Colonnes:
% request.base_url <select name="result" onchange="document.f.submit()">
"""
] ]
for k in keys: for k in keys:
if k == result: if k == result:
@ -381,30 +381,38 @@ def formsemestre_report_counts(
'<option value="%s" %s>%s</option>' '<option value="%s" %s>%s</option>'
% (k, selected, LEGENDES_CODES_BUT.get(k, k)) % (k, selected, LEGENDES_CODES_BUT.get(k, k))
) )
F.append("</select>")
if only_primo:
checked = 'checked="1"'
else:
checked = ""
F.append( F.append(
'<br><input type="checkbox" name="only_primo" onchange="document.f.submit()" %s>Restreindre aux primo-entrants</input>' f"""
% checked </select>
<div style="margin-top:12px;">
<input type="checkbox" name="only_primo" onchange="document.f.submit()"
{'checked' if only_primo else ''}>
Restreindre aux primo-entrants</input>
<span style="margin: 12px;">
Restreindre au(x) groupe(s)&nbsp;:
{sco_groups_view.menu_groups_choice(groups_infos, submit_on_change=True)
if groups_infos else ''}
</span>
<input type="hidden" name="formsemestre_id" value="{formsemestre_id}"/>
</div>
</form>
"""
) )
F.append(
'<input type="hidden" name="formsemestre_id" value="%s"/>' % formsemestre_id
)
F.append("</p></form>")
t = tab.make_page( tableau = tab.make_page(
title="""<h2 class="formsemestre">Comptes croisés</h2>""",
fmt=fmt, fmt=fmt,
title="""<h2 class="formsemestre">Comptes croisés</h2>""",
with_html_headers=False, with_html_headers=False,
) )
if fmt != "html": if fmt != "html":
return t return tableau
H = [ H = [
html_sco_header.sco_header(page_title=title), html_sco_header.sco_header(
t, cssstyles=sco_groups_view.CSSSTYLES,
javascripts=sco_groups_view.JAVASCRIPTS,
page_title=title,
),
tableau,
"\n".join(F), "\n".join(F),
"""<p class="help">Le tableau affiche le nombre d'étudiants de ce semestre dans chacun """<p class="help">Le tableau affiche le nombre d'étudiants de ce semestre dans chacun
des cas choisis: à l'aide des deux menus, vous pouvez choisir les catégories utilisées des cas choisis: à l'aide des deux menus, vous pouvez choisir les catégories utilisées
@ -418,7 +426,8 @@ def formsemestre_report_counts(
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
def table_suivi_cohorte( def table_suivi_cohorte(
formsemestre_id, formsemestre: FormSemestre,
groups_infos,
percent=False, percent=False,
bac="", # selection sur type de bac bac="", # selection sur type de bac
bacspecialite="", bacspecialite="",
@ -441,9 +450,8 @@ def table_suivi_cohorte(
Determination des dates: on regroupe les semestres commençant à des dates proches Determination des dates: on regroupe les semestres commençant à des dates proches
""" """
sem = sco_formsemestre.get_formsemestre( sem = sco_formsemestre.get_formsemestre(formsemestre.id)
formsemestre_id # sem est le semestre origine
) # sem est le semestre origine
t0 = time.time() t0 = time.time()
def logt(op): def logt(op):
@ -452,12 +460,12 @@ def table_suivi_cohorte(
logt("table_suivi_cohorte: start") logt("table_suivi_cohorte: start")
# 1-- Liste des semestres posterieurs dans lesquels ont été les etudiants de sem # 1-- Liste des semestres posterieurs dans lesquels ont été les etudiants de sem
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre) nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
etudids = nt.get_etudids() etudids_inscrits = {ins.etudid for ins in formsemestre.inscriptions}
etudids_groups = groups_infos.get_etudids()
etudids = etudids_inscrits.intersection(etudids_groups)
logt("A: orig etuds set") logt("A: orig etuds set")
S = {formsemestre_id: sem} # ensemble de formsemestre_id S = {formsemestre.id: sem} # ensemble de formsemestre_id
orig_set = set() # ensemble d'etudid du semestre d'origine orig_set = set() # ensemble d'etudid du semestre d'origine
bacs = set() bacs = set()
bacspecialites = set() bacspecialites = set()
@ -479,7 +487,7 @@ def table_suivi_cohorte(
) )
and (not civilite or (civilite == etud["civilite"])) and (not civilite or (civilite == etud["civilite"]))
and (not statut or (statut == etud["statut"])) and (not statut or (statut == etud["statut"]))
and (not only_primo or is_primo_etud(etud, sem)) and (not only_primo or is_primo_etud(etud, formsemestre))
): ):
orig_set.add(etudid) orig_set.add(etudid)
# semestres suivants: # semestres suivants:
@ -524,17 +532,15 @@ def table_suivi_cohorte(
s["nb_dipl"] = nb_dipl s["nb_dipl"] = nb_dipl
# 3-- Regroupe les semestres par date de debut # 3-- Regroupe les semestres par date de debut
P = [] # liste de periodsem
class PeriodSem: class PeriodSem:
pass def __init__(self, datedebut: datetime.datetime, sems: list[dict]):
self.datedebut = datedebut
self.sems = sems
# semestre de depart: # semestre de depart:
porigin = PeriodSem()
d, m, y = [int(x) for x in sem["date_debut"].split("/")] d, m, y = [int(x) for x in sem["date_debut"].split("/")]
porigin.datedebut = datetime.datetime(y, m, d) porigin = PeriodSem(datetime.datetime(y, m, d), [sem])
porigin.sems = [sem] P = [] # liste de periodsem
# #
tolerance = datetime.timedelta(days=45) tolerance = datetime.timedelta(days=45)
for s in sems: for s in sems:
@ -545,9 +551,7 @@ def table_suivi_cohorte(
merged = True merged = True
break break
if not merged: if not merged:
p = PeriodSem() p = PeriodSem(s["date_debut_dt"], [s])
p.datedebut = s["date_debut_dt"]
p.sems = [s]
P.append(p) P.append(p)
# 4-- regroupe par indice de semestre S_i # 4-- regroupe par indice de semestre S_i
@ -602,7 +606,7 @@ def table_suivi_cohorte(
L.append(d) L.append(d)
# Compte nb de démissions et de ré-orientation par période # Compte nb de démissions et de ré-orientation par période
logt("D: cout dems reos") logt("D: cout dems reos")
sem["dems"], sem["reos"] = _count_dem_reo(formsemestre_id, sem["members"]) sem["dems"], sem["reos"] = _count_dem_reo(formsemestre.id, sem["members"])
for p in P: for p in P:
p.dems = set() p.dems = set()
p.reos = set() p.reos = set()
@ -703,7 +707,7 @@ def table_suivi_cohorte(
caption="Suivi cohorte " + pp + sem["titreannee"] + dbac, caption="Suivi cohorte " + pp + sem["titreannee"] + dbac,
page_title="Suivi cohorte " + sem["titreannee"], page_title="Suivi cohorte " + sem["titreannee"],
html_class="table_cohorte", html_class="table_cohorte",
preferences=sco_preferences.SemPreferences(formsemestre_id), preferences=sco_preferences.SemPreferences(formsemestre.id),
) )
# Explication: liste des semestres associés à chaque date # Explication: liste des semestres associés à chaque date
if not P: if not P:
@ -713,13 +717,10 @@ def table_suivi_cohorte(
else: else:
expl = ["<h3>Semestres associés à chaque date:</h3><ul>"] expl = ["<h3>Semestres associés à chaque date:</h3><ul>"]
for p in P: for p in P:
expl.append("<li><b>%s</b>:" % p.datedebut.strftime("%d/%m/%y")) expl.append(f"""<li><b>{p.datedebut.strftime("%d/%m/%y")}</b>:""")
ls = [] ls = []
for s in p.sems: for s in p.sems:
ls.append( ls.append(formsemestre.html_link_status())
'<a href="formsemestre_status?formsemestre_id=%(formsemestre_id)s">%(titreannee)s</a>'
% s
)
expl.append(", ".join(ls) + "</li>") expl.append(", ".join(ls) + "</li>")
expl.append("</ul>") expl.append("</ul>")
return ( return (
@ -737,6 +738,7 @@ def table_suivi_cohorte(
def formsemestre_suivi_cohorte( def formsemestre_suivi_cohorte(
formsemestre_id, formsemestre_id,
fmt="html", fmt="html",
group_ids: list[int] = None, # si indiqué, ne prend que ces groupes
percent=1, percent=1,
bac="", bac="",
bacspecialite="", bacspecialite="",
@ -747,9 +749,19 @@ def formsemestre_suivi_cohorte(
only_primo=False, only_primo=False,
) -> str: ) -> str:
"""Affiche suivi cohortes par numero de semestre""" """Affiche suivi cohortes par numero de semestre"""
try:
annee_bac = str(annee_bac or "") annee_bac = str(annee_bac or "")
annee_admission = str(annee_admission or "") annee_admission = str(annee_admission or "")
percent = int(percent) percent = int(percent)
except ValueError as exc:
raise ScoValueError("formsemestre_suivi_cohorte: argument invalide") from exc
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
groups_infos = sco_groups_view.DisplayedGroupsInfos(
group_ids,
formsemestre_id=formsemestre.id,
select_all_when_unspecified=True,
)
( (
tab, tab,
expl, expl,
@ -760,7 +772,8 @@ def formsemestre_suivi_cohorte(
civilites, civilites,
statuts, statuts,
) = table_suivi_cohorte( ) = table_suivi_cohorte(
formsemestre_id, formsemestre,
groups_infos=groups_infos,
percent=percent, percent=percent,
bac=bac, bac=bac,
bacspecialite=bacspecialite, bacspecialite=bacspecialite,
@ -772,7 +785,7 @@ def formsemestre_suivi_cohorte(
) )
tab.base_url = ( tab.base_url = (
"%s?formsemestre_id=%s&percent=%s&bac=%s&bacspecialite=%s&civilite=%s" "%s?formsemestre_id=%s&percent=%s&bac=%s&bacspecialite=%s&civilite=%s"
% (request.base_url, formsemestre_id, percent, bac, bacspecialite, civilite) % (request.base_url, formsemestre.id, percent, bac, bacspecialite, civilite)
) )
if only_primo: if only_primo:
tab.base_url += "&only_primo=on" tab.base_url += "&only_primo=on"
@ -783,25 +796,29 @@ def formsemestre_suivi_cohorte(
base_url = request.base_url base_url = request.base_url
burl = "%s?formsemestre_id=%s&bac=%s&bacspecialite=%s&civilite=%s&statut=%s" % ( burl = "%s?formsemestre_id=%s&bac=%s&bacspecialite=%s&civilite=%s&statut=%s" % (
base_url, base_url,
formsemestre_id, formsemestre.id,
bac, bac,
bacspecialite, bacspecialite,
civilite, civilite,
statut, statut,
) )
if percent: if percent:
pplink = '<p><a href="%s&percent=0">Afficher les résultats bruts</a></p>' % burl pplink = f"""<p><a class="stdlink"
href="{burl}&percent=0">Afficher les résultats bruts</a></p>"""
else: else:
pplink = ( pplink = f"""<p><a class="stdlink"
'<p><a href="%s&percent=1">Afficher les résultats en pourcentages</a></p>' href="{burl}&percent=1">Afficher les résultats en pourcentages</a></p>"""
% burl
)
H = [ H = [
html_sco_header.sco_header(page_title=tab.page_title), html_sco_header.sco_header(
cssstyles=sco_groups_view.CSSSTYLES,
javascripts=sco_groups_view.JAVASCRIPTS,
page_title=tab.page_title,
),
"""<h2 class="formsemestre">Suivi cohorte: devenir des étudiants de ce semestre</h2>""", """<h2 class="formsemestre">Suivi cohorte: devenir des étudiants de ce semestre</h2>""",
_gen_form_selectetuds( _gen_form_selectetuds(
formsemestre_id, formsemestre.id,
groups_infos=groups_infos,
only_primo=only_primo, only_primo=only_primo,
bac=bac, bac=bac,
bacspecialite=bacspecialite, bacspecialite=bacspecialite,
@ -854,6 +871,7 @@ def _gen_form_selectetuds(
annee_admissions=None, annee_admissions=None,
civilites=None, civilites=None,
statuts=None, statuts=None,
groups_infos: sco_groups_view.DisplayedGroupsInfos = None,
): ):
"""HTML form pour choix criteres selection etudiants""" """HTML form pour choix criteres selection etudiants"""
annee_bacs = annee_bacs or [] annee_bacs = annee_bacs or []
@ -877,8 +895,9 @@ def _gen_form_selectetuds(
else: else:
selected = 'selected="selected"' selected = 'selected="selected"'
F = [ F = [
f"""<form id="f" method="get" action="{request.base_url}"> f"""<form id="group_selector" name="f" method="get" action="{request.base_url}">
<p>Bac: <select name="bac" onchange="javascript: submit(this);"> <div>Bac:
<select name="bac" onchange="javascript: submit(this);">
<option value="" {selected}>tous</option> <option value="" {selected}>tous</option>
""" """
] ]
@ -894,7 +913,8 @@ def _gen_form_selectetuds(
else: else:
selected = 'selected="selected"' selected = 'selected="selected"'
F.append( F.append(
f"""&nbsp; Bac/Specialité: <select name="bacspecialite" onchange="javascript: submit(this);"> f"""&nbsp; Bac/Specialité:
<select name="bacspecialite" onchange="javascript: submit(this);">
<option value="" {selected}>tous</option> <option value="" {selected}>tous</option>
""" """
) )
@ -938,17 +958,24 @@ def _gen_form_selectetuds(
else: else:
selected = "" selected = ""
F.append(f'<option value="{b}" {selected}>{b}</option>') F.append(f'<option value="{b}" {selected}>{b}</option>')
F.append("</select>")
F.append( F.append(
f"""<br> f"""
</select>
<div style="margin-top:12px;">
<input type="checkbox" name="only_primo" <input type="checkbox" name="only_primo"
onchange="javascript: submit(this);" onchange="javascript: submit(this);"
{'checked="1"' if only_primo else ""}/>Restreindre aux primo-entrants {'checked="1"' if only_primo else ""}/>Restreindre aux primo-entrants
<span style="margin: 12px;">
Restreindre au(x) groupe(s)&nbsp;:
{sco_groups_view.menu_groups_choice(groups_infos, submit_on_change=True)
if groups_infos else ''}
</span>
<input type="hidden" name="formsemestre_id" value="{formsemestre_id}"/> <input type="hidden" name="formsemestre_id" value="{formsemestre_id}"/>
<input type="hidden" name="percent" value="{percent}"/> <input type="hidden" name="percent" value="{percent}"/>
</div>
</p> </div>
</form> </form>
""" """
) )
@ -1002,17 +1029,6 @@ def _count_dem_reo(formsemestre_id, etudids):
return dems, reos return dems, reos
"""OLDGEA:
27s pour S1 F.I. classique Semestre 1 2006-2007
B 2.3s
C 5.6s
D 5.9s
Z 27s => cache des semestres pour nt
à chaud: 3s
B: etuds sets: 2.4s => lent: N x getEtudInfo (non caché)
"""
EXP_LIC = re.compile(r"licence", re.I) EXP_LIC = re.compile(r"licence", re.I)
EXP_LPRO = re.compile(r"professionnelle", re.I) EXP_LPRO = re.compile(r"professionnelle", re.I)
@ -1125,6 +1141,7 @@ def get_code_cursus_etud(
def tsp_etud_list( def tsp_etud_list(
formsemestre_id, formsemestre_id,
groups_infos: sco_groups_view.DisplayedGroupsInfos | None = None,
only_primo=False, only_primo=False,
bac="", # selection sur type de bac bac="", # selection sur type de bac
bacspecialite="", bacspecialite="",
@ -1136,11 +1153,13 @@ def tsp_etud_list(
"""Liste des etuds a considerer dans table suivi cursus """Liste des etuds a considerer dans table suivi cursus
ramene aussi ensembles des bacs, genres, statuts de (tous) les etudiants ramene aussi ensembles des bacs, genres, statuts de (tous) les etudiants
""" """
# log('tsp_etud_list(%s, bac="%s")' % (formsemestre_id,bac))
sem = sco_formsemestre.get_formsemestre(formsemestre_id)
formsemestre = FormSemestre.get_formsemestre(formsemestre_id) formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre) etudids_inscrits = {ins.etudid for ins in formsemestre.inscriptions}
etudids = nt.get_etudids() if groups_infos:
etudids_groups = groups_infos.get_etudids()
etudids = etudids_inscrits.intersection(etudids_groups)
else:
etudids = etudids_inscrits
etuds = [] etuds = []
bacs = set() bacs = set()
bacspecialites = set() bacspecialites = set()
@ -1162,7 +1181,7 @@ def tsp_etud_list(
) )
and (not civilite or (civilite == etud["civilite"])) and (not civilite or (civilite == etud["civilite"]))
and (not statut or (statut == etud["statut"])) and (not statut or (statut == etud["statut"]))
and (not only_primo or is_primo_etud(etud, sem)) and (not only_primo or is_primo_etud(etud, formsemestre))
): ):
etuds.append(etud) etuds.append(etud)
@ -1173,7 +1192,6 @@ def tsp_etud_list(
civilites.add(etud["civilite"]) civilites.add(etud["civilite"])
if etud["statut"]: # ne montre pas les statuts non renseignés if etud["statut"]: # ne montre pas les statuts non renseignés
statuts.add(etud["statut"]) statuts.add(etud["statut"])
# log('tsp_etud_list: %s etuds' % len(etuds))
return etuds, bacs, bacspecialites, annee_bacs, annee_admissions, civilites, statuts return etuds, bacs, bacspecialites, annee_bacs, annee_admissions, civilites, statuts
@ -1290,31 +1308,30 @@ def table_suivi_cursus(formsemestre_id, only_primo=False, grouped_parcours=True)
return tab return tab
def tsp_form_primo_group(only_primo, no_grouping, formsemestre_id, fmt): def tsp_form_primo_group(
"""Element de formulaire pour choisir si restriction aux primos entrants et groupement par lycees""" only_primo, no_grouping, formsemestre_id, fmt, groups_infos=None
F = ["""<form name="f" method="get" action="%s">""" % request.base_url] ) -> str:
if only_primo: """Element de formulaire pour choisir si restriction aux primos entrants,
checked = 'checked="1"' groupement par lycees et groupes
else: """
checked = "" primo_checked = 'checked="1"' if only_primo else ""
F.append( no_grouping_checked = 'checked="1"' if no_grouping else ""
'<input type="checkbox" name="only_primo" onchange="document.f.submit()" %s>Restreindre aux primo-entrants</input>' return f"""
% checked <form id="group_selector" name="f" method="get" action="{request.base_url}">
) <input type="checkbox" name="only_primo"
if no_grouping: onchange="document.f.submit()" {primo_checked}>Restreindre aux primo-entrants</input>
checked = 'checked="1"' <input type="checkbox" name="no_grouping" onchange="document.f.submit()"
else: {no_grouping_checked}>Lister chaque étudiant</input>
checked = ""
F.append( <span style="margin: 12px;">
'<input type="checkbox" name="no_grouping" onchange="document.f.submit()" %s>Lister chaque étudiant</input>' Restreindre au(x) groupe(s)&nbsp;:
% checked {sco_groups_view.menu_groups_choice(groups_infos, submit_on_change=True)
) if groups_infos else ''}
F.append( </span>
'<input type="hidden" name="formsemestre_id" value="%s"/>' % formsemestre_id <input type="hidden" name="formsemestre_id" value="{formsemestre_id}"/>
) <input type="hidden" name="fmt" value="{fmt}"/>
F.append('<input type="hidden" name="fmt" value="%s"/>' % fmt) </form>
F.append("""</form>""") """
return "\n".join(F)
def formsemestre_suivi_cursus( def formsemestre_suivi_cursus(
@ -1337,7 +1354,11 @@ def formsemestre_suivi_cursus(
t = tab.make_page(fmt=fmt, with_html_headers=False) t = tab.make_page(fmt=fmt, with_html_headers=False)
if fmt != "html": if fmt != "html":
return t return t
F = [tsp_form_primo_group(only_primo, no_grouping, formsemestre_id, fmt)] F = [
tsp_form_primo_group(
only_primo, no_grouping, formsemestre_id, fmt, groups_infos=None
)
]
H = [ H = [
html_sco_header.sco_header( html_sco_header.sco_header(
@ -1356,6 +1377,7 @@ def formsemestre_suivi_cursus(
# ------------- # -------------
def graph_cursus( def graph_cursus(
formsemestre_id, formsemestre_id,
groups_infos: sco_groups_view.DisplayedGroupsInfos | None = None,
fmt="svg", fmt="svg",
only_primo=False, only_primo=False,
bac="", # selection sur type de bac bac="", # selection sur type de bac
@ -1376,6 +1398,7 @@ def graph_cursus(
statuts, statuts,
) = tsp_etud_list( ) = tsp_etud_list(
formsemestre_id, formsemestre_id,
groups_infos=groups_infos,
only_primo=only_primo, only_primo=only_primo,
bac=bac, bac=bac,
bacspecialite=bacspecialite, bacspecialite=bacspecialite,
@ -1606,6 +1629,7 @@ def graph_cursus(
def formsemestre_graph_cursus( def formsemestre_graph_cursus(
formsemestre_id, formsemestre_id,
group_ids: list[int] = None, # si indiqué, ne prend que ces groupes
fmt="html", fmt="html",
only_primo=False, only_primo=False,
bac="", # selection sur type de bac bac="", # selection sur type de bac
@ -1619,7 +1643,12 @@ def formsemestre_graph_cursus(
"""Graphe suivi cohortes""" """Graphe suivi cohortes"""
annee_bac = str(annee_bac or "") annee_bac = str(annee_bac or "")
annee_admission = str(annee_admission or "") annee_admission = str(annee_admission or "")
# log("formsemestre_graph_cursus") formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
groups_infos = sco_groups_view.DisplayedGroupsInfos(
group_ids,
formsemestre_id=formsemestre.id,
select_all_when_unspecified=True,
)
sem = sco_formsemestre.get_formsemestre(formsemestre_id) sem = sco_formsemestre.get_formsemestre(formsemestre_id)
if fmt == "pdf": if fmt == "pdf":
( (
@ -1633,6 +1662,7 @@ def formsemestre_graph_cursus(
statuts, statuts,
) = graph_cursus( ) = graph_cursus(
formsemestre_id, formsemestre_id,
groups_infos=groups_infos,
fmt="pdf", fmt="pdf",
only_primo=only_primo, only_primo=only_primo,
bac=bac, bac=bac,
@ -1657,6 +1687,7 @@ def formsemestre_graph_cursus(
statuts, statuts,
) = graph_cursus( ) = graph_cursus(
formsemestre_id, formsemestre_id,
groups_infos=groups_infos,
fmt="png", fmt="png",
only_primo=only_primo, only_primo=only_primo,
bac=bac, bac=bac,
@ -1695,6 +1726,7 @@ def formsemestre_graph_cursus(
statuts, statuts,
) = graph_cursus( ) = graph_cursus(
formsemestre_id, formsemestre_id,
groups_infos=groups_infos,
only_primo=only_primo, only_primo=only_primo,
bac=bac, bac=bac,
bacspecialite=bacspecialite, bacspecialite=bacspecialite,
@ -1706,14 +1738,17 @@ def formsemestre_graph_cursus(
H = [ H = [
html_sco_header.sco_header( html_sco_header.sco_header(
cssstyles=sco_groups_view.CSSSTYLES,
javascripts=sco_groups_view.JAVASCRIPTS,
page_title="Graphe cursus de %(titreannee)s" % sem, page_title="Graphe cursus de %(titreannee)s" % sem,
no_side_bar=True, no_side_bar=True,
), ),
"""<h2 class="formsemestre">Cursus des étudiants de ce semestre</h2>""", """<h2 class="formsemestre">Cursus des étudiants de ce semestre</h2>""",
doc, doc,
"<p>%d étudiants sélectionnés</p>" % len(etuds), f"<p>{len(etuds)} étudiants sélectionnés</p>",
_gen_form_selectetuds( _gen_form_selectetuds(
formsemestre_id, formsemestre_id,
groups_infos=groups_infos,
only_primo=only_primo, only_primo=only_primo,
bac=bac, bac=bac,
bacspecialite=bacspecialite, bacspecialite=bacspecialite,
@ -1743,6 +1778,10 @@ def formsemestre_graph_cursus(
passant d'un semestre à l'autre (s'il y en a moins de {MAX_ETUD_IN_DESCR}, vous passant d'un semestre à l'autre (s'il y en a moins de {MAX_ETUD_IN_DESCR}, vous
pouvez visualiser leurs noms en passant le curseur sur le chiffre). pouvez visualiser leurs noms en passant le curseur sur le chiffre).
</p> </p>
<p class="help">
Le menu <em>Restreindre au(x) groupe(s)</em> permet de restreindre l'étude aux
étudiants appartenant aux groupes indiqués <em>dans le semestre d'origine</em>.
</p>
""", """,
html_sco_header.sco_footer(), html_sco_header.sco_footer(),
] ]

View File

@ -420,13 +420,11 @@ table.dataTable td {
color: #333333 !important; color: #333333 !important;
border: 1px solid #979797; border: 1px solid #979797;
background-color: white; background-color: white;
background: -webkit-gradient( background: -webkit-gradient(linear,
linear,
left top, left top,
left bottom, left bottom,
color-stop(0%, white), color-stop(0%, white),
color-stop(100%, gainsboro) color-stop(100%, gainsboro));
);
/* Chrome,Safari4+ */ /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, white 0%, gainsboro 100%); background: -webkit-linear-gradient(top, white 0%, gainsboro 100%);
/* Chrome10+,Safari5.1+ */ /* Chrome10+,Safari5.1+ */
@ -454,13 +452,11 @@ table.dataTable td {
color: white !important; color: white !important;
border: 1px solid #111111; border: 1px solid #111111;
background-color: #585858; background-color: #585858;
background: -webkit-gradient( background: -webkit-gradient(linear,
linear,
left top, left top,
left bottom, left bottom,
color-stop(0%, #585858), color-stop(0%, #585858),
color-stop(100%, #111111) color-stop(100%, #111111));
);
/* Chrome,Safari4+ */ /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, #585858 0%, #111111 100%); background: -webkit-linear-gradient(top, #585858 0%, #111111 100%);
/* Chrome10+,Safari5.1+ */ /* Chrome10+,Safari5.1+ */
@ -477,13 +473,11 @@ table.dataTable td {
.dataTables_wrapper .dataTables_paginate .paginate_button:active { .dataTables_wrapper .dataTables_paginate .paginate_button:active {
outline: none; outline: none;
background-color: #2b2b2b; background-color: #2b2b2b;
background: -webkit-gradient( background: -webkit-gradient(linear,
linear,
left top, left top,
left bottom, left bottom,
color-stop(0%, #2b2b2b), color-stop(0%, #2b2b2b),
color-stop(100%, #0c0c0c) color-stop(100%, #0c0c0c));
);
/* Chrome,Safari4+ */ /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%); background: -webkit-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);
/* Chrome10+,Safari5.1+ */ /* Chrome10+,Safari5.1+ */
@ -514,50 +508,38 @@ table.dataTable td {
text-align: center; text-align: center;
font-size: 1.2em; font-size: 1.2em;
background-color: white; background-color: white;
background: -webkit-gradient( background: -webkit-gradient(linear,
linear,
left top, left top,
right top, right top,
color-stop(0%, rgba(255, 255, 255, 0)), color-stop(0%, rgba(255, 255, 255, 0)),
color-stop(25%, rgba(255, 255, 255, 0.9)), color-stop(25%, rgba(255, 255, 255, 0.9)),
color-stop(75%, rgba(255, 255, 255, 0.9)), color-stop(75%, rgba(255, 255, 255, 0.9)),
color-stop(100%, rgba(255, 255, 255, 0)) color-stop(100%, rgba(255, 255, 255, 0)));
); background: -webkit-linear-gradient(left,
background: -webkit-linear-gradient(
left,
rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0) 0%,
rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 25%,
rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0.9) 75%,
rgba(255, 255, 255, 0) 100% rgba(255, 255, 255, 0) 100%);
); background: -moz-linear-gradient(left,
background: -moz-linear-gradient(
left,
rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0) 0%,
rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 25%,
rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0.9) 75%,
rgba(255, 255, 255, 0) 100% rgba(255, 255, 255, 0) 100%);
); background: -ms-linear-gradient(left,
background: -ms-linear-gradient(
left,
rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0) 0%,
rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 25%,
rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0.9) 75%,
rgba(255, 255, 255, 0) 100% rgba(255, 255, 255, 0) 100%);
); background: -o-linear-gradient(left,
background: -o-linear-gradient(
left,
rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0) 0%,
rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 25%,
rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0.9) 75%,
rgba(255, 255, 255, 0) 100% rgba(255, 255, 255, 0) 100%);
); background: linear-gradient(to right,
background: linear-gradient(
to right,
rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0) 0%,
rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 25%,
rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0.9) 75%,
rgba(255, 255, 255, 0) 100% rgba(255, 255, 255, 0) 100%);
);
} }
.dataTables_wrapper .dataTables_length, .dataTables_wrapper .dataTables_length,
@ -577,69 +559,17 @@ table.dataTable td {
-webkit-overflow-scrolling: touch; -webkit-overflow-scrolling: touch;
} }
.dataTables_wrapper .dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>th,
.dataTables_scroll .dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>td,
div.dataTables_scrollBody .dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>th,
> table .dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>td {
> thead
> tr
> th,
.dataTables_wrapper
.dataTables_scroll
div.dataTables_scrollBody
> table
> thead
> tr
> td,
.dataTables_wrapper
.dataTables_scroll
div.dataTables_scrollBody
> table
> tbody
> tr
> th,
.dataTables_wrapper
.dataTables_scroll
div.dataTables_scrollBody
> table
> tbody
> tr
> td {
vertical-align: middle; vertical-align: middle;
} }
.dataTables_wrapper .dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>th>div.dataTables_sizing,
.dataTables_scroll .dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>td>div.dataTables_sizing,
div.dataTables_scrollBody .dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>th>div.dataTables_sizing,
> table .dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>td>div.dataTables_sizing {
> thead
> tr
> th
> div.dataTables_sizing,
.dataTables_wrapper
.dataTables_scroll
div.dataTables_scrollBody
> table
> thead
> tr
> td
> div.dataTables_sizing,
.dataTables_wrapper
.dataTables_scroll
div.dataTables_scrollBody
> table
> tbody
> tr
> th
> div.dataTables_sizing,
.dataTables_wrapper
.dataTables_scroll
div.dataTables_scrollBody
> table
> tbody
> tr
> td
> div.dataTables_sizing {
height: 0; height: 0;
overflow: hidden; overflow: hidden;
margin: 0 !important; margin: 0 !important;
@ -664,6 +594,7 @@ table.dataTable td {
} }
@media screen and (max-width: 767px) { @media screen and (max-width: 767px) {
.dataTables_wrapper .dataTables_info, .dataTables_wrapper .dataTables_info,
.dataTables_wrapper .dataTables_paginate { .dataTables_wrapper .dataTables_paginate {
float: none; float: none;
@ -676,6 +607,7 @@ table.dataTable td {
} }
@media screen and (max-width: 640px) { @media screen and (max-width: 640px) {
.dataTables_wrapper .dataTables_length, .dataTables_wrapper .dataTables_length,
.dataTables_wrapper .dataTables_filter { .dataTables_wrapper .dataTables_filter {
float: none; float: none;
@ -703,6 +635,10 @@ table.table_leftalign tr td {
text-align: left; text-align: left;
} }
p.gt_caption {
margin-top: 8px;
}
/* Ligne(s) de titre */ /* Ligne(s) de titre */
table.dataTable thead tr th { table.dataTable thead tr th {
background-color: rgb(90%, 90%, 90%); background-color: rgb(90%, 90%, 90%);
@ -757,6 +693,7 @@ table.dataTable.gt_table {
table.dataTable.gt_table.gt_left { table.dataTable.gt_table.gt_left {
margin-left: 16px; margin-left: 16px;
} }
table.dataTable.gt_table.gt_left td, table.dataTable.gt_table.gt_left td,
table.dataTable.gt_table.gt_left th { table.dataTable.gt_table.gt_left th {
text-align: left; text-align: left;

View File

@ -1188,10 +1188,11 @@ a.discretelink:hover {
.help { .help {
max-width: var(--sco-content-max-width); max-width: var(--sco-content-max-width);
font-style: italic;
} }
.help { .help em {
font-style: italic; font-style: normal;
} }
.help_important { .help_important {

View File

@ -23,7 +23,7 @@ function groups_view_url() {
url.param()["formsemestre_id"] = url.param()["formsemestre_id"] =
$("#group_selector")[0].formsemestre_id.value; $("#group_selector")[0].formsemestre_id.value;
var selected_groups = $("#group_selector select").val(); var selected_groups = $("#group_selector select#group_ids_sel").val();
url.param()["group_ids"] = selected_groups; // remplace par groupes selectionnes url.param()["group_ids"] = selected_groups; // remplace par groupes selectionnes
return url; return url;