formsemestre_status: refonte cadre groupes/assiduité

This commit is contained in:
Emmanuel Viennet 2023-09-19 21:39:36 +02:00
parent b124468399
commit 3bf36c1119
5 changed files with 151 additions and 103 deletions

View File

@ -771,6 +771,15 @@ class FormSemestre(db.Model):
etuds.sort(key=lambda e: e.sort_key)
return etuds
def get_partitions_list(self, with_default=True) -> list[Partition]:
"""Liste des partitions pour ce semestre (list of dicts),
triées par numéro, avec la partition par défaut en fin de liste.
"""
partitions = [p for p in self.partitions if p.partition_name is not None]
if with_default:
partitions += [p for p in partitions if p.partition_name is None]
return partitions
@cached_property
def etudids_actifs(self) -> set:
"Set des etudids inscrits non démissionnaires et non défaillants"

View File

@ -818,101 +818,113 @@ def _make_listes_sem(formsemestre: FormSemestre) -> str:
can_edit_abs = current_user.has_permission(Permission.ScoAbsChange)
#
H.append(
f"""<h3>Listes de {formsemestre.titre}
<span class="infostitresem">({formsemestre.mois_debut()} - {formsemestre.mois_fin()})</span></h3>"""
f"""<h3>Groupes et absences de {formsemestre.titre}
<span class="infostitresem">({
formsemestre.mois_debut()} - {formsemestre.mois_fin()
})</span></h3>"""
)
form_abs_tmpl = f"""
<td>
<a class="btn" href="{
url_for("assiduites.visu_assi_group",
scodoc_dept=g.scodoc_dept,
date_debut=formsemestre.date_debut.isoformat(),
date_fin=formsemestre.date_fin.isoformat()
)}&group_ids=%(group_id)s">
<button>Bilan assiduité</button></a>
"""
if can_edit_abs:
form_abs_tmpl += f"""
<a class="btn" href="{
url_for("assiduites.visu_assiduites_group",
scodoc_dept=g.scodoc_dept,
formsemestre_id=formsemestre.id,
jour = datetime.date.today().isoformat()
)}&group_ids=%(group_id)s">
<button>Visualiser l'assiduité</button></a>
<a class="btn" href="{
url_for("assiduites.signal_assiduites_group",
scodoc_dept=g.scodoc_dept,
jour=datetime.date.today().isoformat(),
formsemestre_id=formsemestre.id,
)}&group_ids=%(group_id)s">
<button>Saisie journalière</button></a>
<a class="btn" href="{
url_for("assiduites.signal_assiduites_diff",
scodoc_dept=g.scodoc_dept,
formsemestre_id=formsemestre.id,
)}&group_ids=%(group_id)s">
<button>Saisie différée</button></a>
<a class="btn" href="{
url_for("assiduites.bilan_dept",
scodoc_dept=g.scodoc_dept,
formsemestre=formsemestre.id,
)}&group_id=%(group_id)s">
<button>Justificatifs en attente</button></a>
"""
form_abs_tmpl += "</td>"
#
H.append('<div id="grouplists">')
H.append('<div class="sem-groups-abs">')
# Genere liste pour chaque partition (categorie de groupes)
for partition in sco_groups.get_partitions_list(formsemestre.id):
if not partition["partition_name"]:
H.append("<h4>Tous les étudiants</h4>")
else:
H.append(f"""<h4>Groupes de {partition["partition_name"]}</h4>""")
partition_is_empty = True
groups = sco_groups.get_partition_groups(partition)
for partition in formsemestre.get_partitions_list():
groups = partition.groups.all()
effectifs = {g.id: g.etuds.count() for g in groups}
partition_is_empty = sum(effectifs.values()) == 0
H.append(
f"""
<div class="sem-groups-partition">
<div class="sem-groups-partition-titre">{
'Groupes de ' + partition.partition_name
if partition.partition_name else
'Tous les étudiants'}
</div>
<div class="sem-groups-partition-titre">{
"Gestion de l'assiduité" if not partition_is_empty else ""
}</div>
"""
)
if groups:
H.append("<table>")
for group in groups:
n_members = len(sco_groups.get_group_members(group["group_id"]))
n_members = effectifs[group.id]
if n_members == 0:
continue # skip empty groups
partition_is_empty = False
group["url_etat"] = url_for(
"assiduites.visu_assi_group",
scodoc_dept=g.scodoc_dept,
group_ids=group["id"],
date_debut=formsemestre.date_debut.isoformat(),
date_fin=formsemestre.date_fin.isoformat(),
)
if group["group_name"]:
group["label"] = "groupe %(group_name)s" % group
else:
group["label"] = "liste"
group_label = f"{group.group_name}" if group.group_name else "liste"
H.append(
f"""
<tr class="listegroupelink">
<td>
<a href="{
url_for("scolar.groups_view",
group_ids=group["group_id"],
scodoc_dept=g.scodoc_dept,
)
}">{group["label"]}</a>
</td><td>
</td>
<td>({n_members} étudiants)</td>
<div class="sem-groups-list">
<div>
<a href="{
url_for("scolar.groups_view",
group_ids=group.id,
scodoc_dept=g.scodoc_dept,
)
}">{group_label}
- {n_members} étudiants</a>
</div>
</div>
<div class="sem-groups-assi">
<div>
<a class="btn" href="{
url_for("assiduites.visu_assi_group",
scodoc_dept=g.scodoc_dept,
date_debut=formsemestre.date_debut.isoformat(),
date_fin=formsemestre.date_fin.isoformat(),
group_ids=group.id,
)}">
<button>Bilan assiduité</button></a>
</div>
"""
)
if can_edit_abs:
H.append(
f"""
<div>
<a class="btn" href="{
url_for("assiduites.visu_assiduites_group",
scodoc_dept=g.scodoc_dept,
formsemestre_id=formsemestre.id,
jour = datetime.date.today().isoformat(),
group_ids=group.id,
)}">
<button>Visualiser l'assiduité</button></a>
</div>
<div>
<a class="btn" href="{
url_for("assiduites.signal_assiduites_group",
scodoc_dept=g.scodoc_dept,
jour=datetime.date.today().isoformat(),
formsemestre_id=formsemestre.id,
group_ids=group.id,
)}">
<button>Saisie journalière</button></a>
</div>
<div>
<a class="btn" href="{
url_for("assiduites.signal_assiduites_diff",
scodoc_dept=g.scodoc_dept,
formsemestre_id=formsemestre.id,
group_ids=group.id,
)}">
<button>Saisie différée</button></a>
</div>
<div>
<a class="btn" href="{
url_for("assiduites.bilan_dept",
scodoc_dept=g.scodoc_dept,
formsemestre=formsemestre.id,
group_ids=group.id,
)}">
<button>Justificatifs en attente</button></a>
</div>
"""
)
H.append(form_abs_tmpl % group)
H.append("</tr>")
H.append("</table>")
H.append("</div>") # /sem-groups-assi
if partition_is_empty:
H.append('<p class="help indent">Aucun groupe peuplé dans cette partition')
H.append(
'<div class="help sem-groups-none">Aucun groupe peuplé dans cette partition'
)
if formsemestre.can_change_groups():
H.append(
f""" (<a href="{url_for("scolar.partition_editor",
@ -921,7 +933,9 @@ def _make_listes_sem(formsemestre: FormSemestre) -> str:
edit_partition=1)
}" class="stdlink">créer</a>)"""
)
H.append("</p>")
H.append("</div>")
H.append("</div>") # /sem-groups-partition
if formsemestre.can_change_groups():
H.append(
f"""<h4><a class="stdlink"
@ -1180,7 +1194,7 @@ def formsemestre_status(formsemestre_id=None, check_parcours=True):
)
# --- LISTE DES ETUDIANTS
H += [
'<div id="groupes">',
'<div class="formsemestre-groupes">',
_make_listes_sem(formsemestre),
"</div>",
]

View File

@ -131,6 +131,7 @@ def get_partition(partition_id): # OBSOLETE
def get_partitions_list(formsemestre_id, with_default=True) -> list[dict]:
"""Liste des partitions pour ce semestre (list of dicts),
triées par numéro, avec la partition par défaut en fin de liste.
OBSOLETE: utiliser FormSemestre.get_partitions_list
"""
partitions = ndb.SimpleDictFetch(
"""SELECT p.id AS partition_id, p.*

View File

@ -985,17 +985,6 @@ span.linktitresem a:visited {
color: red;
}
.listegroupelink a:link {
color: blue;
}
.listegroupelink a:visited {
color: blue;
}
.listegroupelink a:hover {
color: red;
}
a.stdlink,
a.stdlink:visited {
@ -1792,10 +1781,6 @@ td.formsemestre_status_inscrits {
text-align: center;
}
div.formsemestre_status button {
margin-left: 12px;;
}
td.rcp_titre_sem a.jury_link {
margin-left: 8px;
color: red;
@ -1857,15 +1842,54 @@ ul.ue_inscr_list li.etud {
margin-bottom: 5px;
}
#grouplists h4 {
.sem-groups-abs {
background-color: rgb(137,137,137);
border-radius: 16px;
padding: 16px;
width: fit-content;
}
.sem-groups-abs h4 {
font-style: italic;
margin-bottom: 0px;
margin-top: 5px;
}
#grouplists table {
/*border: 1px solid black;*/
border-spacing: 1px;
.sem-groups-partition-titre {
margin-left: 4px;
font-size: 110%;
}
.sem-groups-partition {
background-color: rgb(213,203,183);
border-radius: 12px;
margin-bottom: 8px;
padding: 12px;
display: grid;
grid-template-columns: 240px auto;
}
.sem-groups-list, .sem-groups-assi {
background-color: white;
border-radius: 6px;
margin: 4px;
}
.sem-groups-list > div {
margin: 4px;
}
.sem-groups-assi > div {
margin: 6px 8px 6px 8px;
}
.sem-groups-assi {
display: flex;
flex-direction: row;
justify-content: flex-start;
flex-wrap: wrap;
align-items: center;
}
.sem-groups-none {
grid-column: 1 / span 2;
}
/* Tableau de bord module */

View File

@ -1,7 +1,7 @@
# -*- mode: python -*-
# -*- coding: utf-8 -*-
SCOVERSION = "9.6.30"
SCOVERSION = "9.6.31"
SCONAME = "ScoDoc"