Assiduite: diverses améliorations, styles tableaux

This commit is contained in:
Emmanuel Viennet 2023-12-07 22:10:51 +01:00
parent 04335e521a
commit a5c927db75
10 changed files with 58 additions and 35 deletions

View File

@ -1254,20 +1254,25 @@ def annee_scolaire_debut(year, month) -> int:
return int(year) - 1
def date_debut_anne_scolaire(annee_sco: int) -> datetime:
def date_debut_anne_scolaire(annee_sco: int | None = None) -> datetime.datetime:
"""La date de début de l'année scolaire
(par défaut, le 1er aout)
Si annee_sco n'est pas spécifié, année courante
(par défaut, l'année scolaire en métropole commence le 1er aout)
"""
if annee_sco is None:
annee_sco = annee_scolaire()
return datetime.datetime(year=annee_sco, month=MONTH_DEBUT_ANNEE_SCOLAIRE, day=1)
def date_fin_anne_scolaire(annee_sco: int) -> datetime:
def date_fin_anne_scolaire(annee_sco: int | None = None) -> datetime.datetime:
"""La date de fin de l'année scolaire
(par défaut, le 31 juillet de l'année suivante)
"""
# on prend la date de début de l'année scolaire suivante,
# et on lui retre 1 jour.
# et on lui retire 1 jour.
# On s'affranchit ainsi des problèmes de durées de mois.
if annee_sco is None:
annee_sco = annee_scolaire()
return datetime.datetime(
year=annee_sco + 1, month=MONTH_DEBUT_ANNEE_SCOLAIRE, day=1
) - datetime.timedelta(days=1)

View File

@ -660,3 +660,16 @@ table.liste_assi td.date {
table.liste_assi td.actions {
white-space: nowrap; /* boutons horizontalement */
}
tr.row-assiduite td {
border-bottom: 1px solid grey;
}
tr.row-assiduite.absent td.assi-type {
background-color: var(--color-absent-clair);
}
tr.row-assiduite.retard td.assi-type {
background-color: var(--color-retard);
}
tr.row-assiduite.present td.assi-type {
background-color: var(--color-present);
}

View File

@ -1429,7 +1429,7 @@ function generateEtudRow(
<img class="pdp" src="${pdp_url}">
<a class="name_set" href="BilanEtud?etudid=${etud.id}">
<a class="name_set" href="bilan_etud?etudid=${etud.id}">
<h4 class="nom">${etud.nom}</h4>
<h5 class="prenom">${etud.prenom}</h5>
</a>

View File

@ -54,9 +54,10 @@ class ListeAssiJusti(tb.Table):
with_foot_titles=False,
)
self.ajouter_lignes()
self.add_assiduites()
def ajouter_lignes(self):
def add_assiduites(self):
"Ajoute le contenu de la table, avec assiduités et justificatif réunis"
# Générer les query assiduités et justificatifs
assiduites_query_etudiants: Query = None
justificatifs_query_etudiants: Query = None
@ -215,6 +216,8 @@ class ListeAssiJusti(tb.Table):
class RowAssiJusti(tb.Row):
"Ligne de table pour une assiduité"
def __init__(self, table: ListeAssiJusti, ligne: dict):
self.ligne: dict = ligne
self.etud: Identite = Identite.get_etud(ligne["etudid"])
@ -259,7 +262,7 @@ class RowAssiJusti(tb.Row):
# Ajout des colonnes optionnelles
self._optionnelles()
# Ajout de l'utilisateur ayant saisie l'objet
# Ajout de l'utilisateur ayant saisi l'objet
self._utilisateur()
# Date de saisie
@ -277,25 +280,27 @@ class RowAssiJusti(tb.Row):
obj_type: str = ""
is_assiduite: bool = self.ligne["type"] == "assiduite"
if is_assiduite:
self.classes.append("row-assiduite")
self.classes.append(EtatAssiduite(self.ligne["etat"]).name.lower())
etat: str = {
EtatAssiduite.PRESENT: "Présence",
EtatAssiduite.ABSENT: "Absence",
EtatAssiduite.RETARD: "Retard",
}.get(self.ligne["etat"])
justifiee: str = "Justifiée" if self.ligne["est_just"] else ""
obj_type = f"{etat} {justifiee}"
else:
self.classes.append("row-justificatif")
self.classes.append(EtatJustificatif(self.ligne["etat"]).name.lower())
etat: str = {
EtatJustificatif.VALIDE: "valide",
EtatJustificatif.ATTENTE: "soumis",
EtatJustificatif.MODIFIE: "modifié",
EtatJustificatif.NON_VALIDE: "invalide",
}.get(self.ligne["etat"])
obj_type = f"Justificatif {etat}"
self.add_cell("obj_type", "Type", obj_type)
self.add_cell("obj_type", "Type", obj_type, classes=["assi-type"])
def _etud(self, lien_redirection) -> None:
etud = self.etud

View File

@ -2,7 +2,7 @@
{% include "assiduites/widgets/tableau_base.j2" %}
<div class="pageContent">
<h2>Bilan de l'assiduité de <span class="rouge">{{sco.etud.nomprenom}}</span></h2>
<h2>Bilan de l'assiduité de {{sco.etud.html_link_fiche()|safe}}</span></h2>
<section class="alerte invisible">
<p>Attention, cet étudiant a trop d'absences</p>
@ -383,4 +383,4 @@
.suppr {
margin: 5px 0;
}
</style>
</style>

View File

@ -1,18 +1,18 @@
<h1>Détails {{type}} </h1>
<h2>Détails {{type}}</h2>
<div id="informations">
<div class="info-row">
<span class="info-label">Étudiant.e concerné.e:</span> <span class="etudinfo"
id="etudid-{{objet.etudid}}">{{objet.etud_nom}}</span>
<span class="info-label">Étudiant{{etud.e}} concerné{{etud.e}}:</span> <span class="etudinfo"
id="etudid-{{objet.etudid}}">{{etud.html_link_fiche()|safe}}</span>
</div>
<div class="info-row">
<span class="info-label">Période concernée :</span> {{objet.date_debut}} au {{objet.date_fin}}
<span class="info-label">Période :</span> {{objet.date_debut}} au {{objet.date_fin}}
</div>
{% if type == "Assiduité" %}
<div class="info-row">
<span class="info-label">Module concernée :</span> {{objet.module}}
<span class="info-label">Module :</span> {{objet.module}}
</div>
{% else %}
{% endif %}
@ -23,7 +23,7 @@
{% else %}
<span class="info-label">État de l'assiduité :</span>
{% endif %}
{{objet.etat}}
<b>{{objet.etat}}</b>
</div>
@ -59,7 +59,7 @@
{% endfor %}
</div>
{% else %}
<span class="text">Non</span>
<span class="text fontred">Non</span>
{% endif %}
</div>
{% endif %}
@ -103,4 +103,4 @@
<div class="info-row">
<span>Saisie par {{objet.saisie_par}} le {{objet.entry_date}}</span>
</div>
</div>

View File

@ -92,7 +92,7 @@
} else if (k.indexOf('etudid') != -1) {
const e = getEtudiant(assiduite.etudid);
td.innerHTML = `<a class="etudinfo" id="line-${assiduite.etudid}" href="BilanEtud?etudid=${assiduite.etudid}">${e.prenom.capitalize()} ${e.nom.toUpperCase()}</a>`;
td.innerHTML = `<a class="etudinfo" id="line-${assiduite.etudid}" href="bilan_etud?etudid=${assiduite.etudid}">${e.prenom.capitalize()} ${e.nom.toUpperCase()}</a>`;
} else {
td.textContent = assiduite[k].capitalize()
}
@ -217,7 +217,7 @@
<textarea name="desc" id="desc" cols="50" rows="10" maxlength="500"></textarea>
</div>
</div>
`
const el = document.createElement('div')
@ -462,4 +462,4 @@
try { getAllAssiduitesFromEtud(etudid, action, true, true, assi_limit_annee) } catch (_) { }
}
</script>
</script>

View File

@ -88,7 +88,7 @@
} else if (k.indexOf('etudid') != -1) {
const e = getEtudiant(justificatif.etudid);
td.innerHTML = `<a class="etudinfo" id="line-${justificatif.etudid}" href="BilanEtud?etudid=${justificatif.etudid}">${e.prenom.capitalize()} ${e.nom.toUpperCase()}</a>`;
td.innerHTML = `<a class="etudinfo" id="line-${justificatif.etudid}" href="bilan_etud?etudid=${justificatif.etudid}">${e.prenom.capitalize()} ${e.nom.toUpperCase()}</a>`;
} else if (k == "formsemestre") {
if (justificatif.hasOwnProperty("formsemestre")) {
td.textContent = justificatif.formsemestre.title.replaceAll('-', ' ');
@ -213,8 +213,8 @@
method: "POST"
})
// This returns a promise inside of which we are checking for errors from the server.
// The catch promise at the end of the call does not getting called when the server returns an error.
// This returns a promise inside of which we are checking for errors from the server.
// The catch promise at the end of the call does not getting called when the server returns an error.
// More information about the error catching can be found here: https://www.tjvantoll.com/2015/09/13/fetch-and-errors/.
.then((result) => {
if (!result.ok) {
@ -228,8 +228,8 @@
return result.blob();
})
// We use the download property for triggering the download of the file from our browser.
// More information about the following code can be found here: https://stackoverflow.com/questions/32545632/how-can-i-download-a-file-using-window-fetch.
// We use the download property for triggering the download of the file from our browser.
// More information about the following code can be found here: https://stackoverflow.com/questions/32545632/how-can-i-download-a-file-using-window-fetch.
// The filename from the first promise is used as name of the file.
.then((blob) => {
if (blob != null) {
@ -676,4 +676,4 @@
align-items: center;
gap: 5px;
}
</style>
</style>

View File

@ -524,7 +524,7 @@ def liste_assiduites_etud():
).build()
@bp.route("/BilanEtud")
@bp.route("/bilan_etud")
@scodoc
@permission_required(Permission.ScoView)
def bilan_etud():
@ -557,8 +557,8 @@ def bilan_etud():
)
# Gestion des dates du bilan (par défaut l'année scolaire)
date_debut: str = f"01/09/{scu.annee_scolaire()}"
date_fin: str = f"30/06/{scu.annee_scolaire()+1}"
date_debut = scu.date_debut_anne_scolaire().strftime("%d/%m/%Y")
date_fin: str = scu.date_fin_anne_scolaire().strftime("%d/%m/%Y")
# Récupération de la métrique d'assiduité
assi_metric = scu.translate_assiduites_metric(
@ -1251,7 +1251,7 @@ def _prepare_tableau(
)
@bp.route("/TableauAssiduiteActions", methods=["GET", "POST"])
@bp.route("/tableau_assiduite_actions", methods=["GET", "POST"])
@scodoc
@permission_required(Permission.AbsChange)
def tableau_assiduite_actions():
@ -1295,7 +1295,7 @@ def tableau_assiduite_actions():
module = _module_selector(formsemestre, module)
return render_template(
"assiduites/pages/tableau_actions.j2",
"assiduites/pages/tableau_assiduite_actions.j2",
sco=ScoData(etud=objet.etudiant),
# XXX type semble être utilisé qq part, ne pas changer
type="Justificatif" if obj_type == "justificatif" else "Assiduité",