This commit is contained in:
Emmanuel Viennet 2024-03-26 14:37:02 +01:00
commit 70e3006981
9 changed files with 128 additions and 61 deletions

View File

@ -449,7 +449,7 @@
transform: translateX(-50%); transform: translateX(-50%);
} }
.assiduite-infos { .assiduite-actions {
position: absolute; position: absolute;
right: 0; right: 0;
margin: 5px; margin: 5px;

View File

@ -217,13 +217,11 @@ function creerLigneEtudiant(etud, index) {
const nameField = document.createElement("div"); const nameField = document.createElement("div");
nameField.classList.add("name_field"); nameField.classList.add("name_field");
if ($("#pdp").is(":checked")) { const pdp = document.createElement("img");
const pdp = document.createElement("img"); pdp.src = `../../api/etudiant/etudid/${etud.id}/photo?size=small`;
pdp.src = `../../api/etudiant/etudid/${etud.id}/photo?size=small`; pdp.alt = `${etud.nom} ${etud.prenom}`;
pdp.alt = `${etud.nom} ${etud.prenom}`; pdp.classList.add("pdp");
pdp.classList.add("pdp"); nameField.appendChild(pdp);
nameField.appendChild(pdp);
}
const nameSet = document.createElement("a"); const nameSet = document.createElement("a");
nameSet.classList.add("name_set"); nameSet.classList.add("name_set");
@ -857,13 +855,25 @@ function setupAssiduiteBubble(el, assiduite) {
// Ajout d'un lien pour plus d'informations // Ajout d'un lien pour plus d'informations
const infos = document.createElement("a"); const infos = document.createElement("a");
infos.className = "assiduite-infos"; infos.className = "";
infos.textContent = ``; infos.textContent = ``;
infos.title = "Cliquez pour plus d'informations"; infos.title = "Cliquez pour plus d'informations";
infos.target = "_blank"; infos.target = "_blank";
infos.href = `tableau_assiduite_actions?type=assiduite&action=details&obj_id=${assiduite.assiduite_id}`; infos.href = `tableau_assiduite_actions?type=assiduite&action=details&obj_id=${assiduite.assiduite_id}`;
bubble.appendChild(infos); // Ajout d'un lien pour modifier l'assiduité
const modifs = document.createElement("a");
modifs.className = "";
modifs.textContent = `📝`;
modifs.title = "Cliquez pour modifier l'assiduité";
modifs.target = "_blank";
modifs.href = `tableau_assiduite_actions?type=assiduite&action=modifier&obj_id=${assiduite.assiduite_id}`;
const actionsDiv = document.createElement("div");
actionsDiv.className = "assiduite-actions";
actionsDiv.appendChild(modifs);
actionsDiv.appendChild(infos);
bubble.appendChild(actionsDiv);
const idDiv = document.createElement("div"); const idDiv = document.createElement("div");
idDiv.className = "assiduite-id"; idDiv.className = "assiduite-id";

View File

@ -391,11 +391,11 @@ class RowAssiJusti(tb.Row):
multi_days = self.ligne["date_debut"].date() != self.ligne["date_fin"].date() multi_days = self.ligne["date_debut"].date() != self.ligne["date_fin"].date()
date_affichees: list[str] = [ date_affichees: list[str] = [
self.ligne["date_debut"].strftime("%d/%m/%y de %H:%M"), # date début self.ligne["date_debut"].strftime("%d/%m/%y %H:%M"), # date début
self.ligne["date_fin"].strftime("%d/%m/%y de %H:%M"), # date fin self.ligne["date_fin"].strftime("%d/%m/%y %H:%M"), # date fin
] ]
if multi_days: if multi_days and self.ligne["type"] != "justificatif":
date_affichees[0] = self.ligne["date_debut"].strftime("%d/%m/%y") date_affichees[0] = self.ligne["date_debut"].strftime("%d/%m/%y")
date_affichees[1] = self.ligne["date_fin"].strftime("%d/%m/%y") date_affichees[1] = self.ligne["date_fin"].strftime("%d/%m/%y")

View File

@ -74,8 +74,6 @@ div.submit > input {
<div> <div>
{{ form.date_fin.label }}&nbsp;: {{ form.date_fin }} {{ form.date_fin.label }}&nbsp;: {{ form.date_fin }}
<span class="help">si le jour de fin est différent,
les heures seront ignorées (journées complètes)</span>
{{ render_field_errors(form, 'date_fin') }} {{ render_field_errors(form, 'date_fin') }}
</div> </div>
</div> </div>

View File

@ -20,7 +20,7 @@
#actions { #actions {
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
margin-bottom: 5px; margin: 5px 0;
} }
#actions label{ #actions label{
margin: 0; margin: 0;
@ -174,6 +174,48 @@ async function nouvellePeriode(period = null) {
} }
} }
// Vérification de la plage horaire
// On génère une date de début et de fin de la période
const date_debut = new Date(
$("#date").datepicker("getDate").format("YYYY-MM-DD") + "T" + debut
);
const date_fin = new Date(
$("#date").datepicker("getDate").format("YYYY-MM-DD") + "T" + fin
);
date_debut.add(1, "seconds");
// On vérifie que les dates sont valides
if (!date_debut.isValid()){
const p = document.createElement("p");
p.textContent = "La date de début n'est pas valide.";
openAlertModal(
"Erreur",
p,
);
return;
}
if (!date_fin.isValid()){
const p = document.createElement("p");
p.textContent = "La date de fin n'est pas valide.";
openAlertModal(
"Erreur",
p,
);
return;
}
// On vérifie que l'heure de fin est supérieure à l'heure de début
if (date_debut >= date_fin) {
const p = document.createElement("p");
p.textContent = "La plage horaire n'est pas valide. L'heure de fin doit être "+
"supérieure à l'heure de début.";
openAlertModal(
"Erreur",
p,
);
return;
}
// On ajoute la nouvelle période au tableau // On ajoute la nouvelle période au tableau
let periodeDiv = document.createElement("div"); let periodeDiv = document.createElement("div");
periodeDiv.classList.add("cell", "header"); periodeDiv.classList.add("cell", "header");
@ -211,15 +253,6 @@ async function nouvellePeriode(period = null) {
...document.querySelectorAll(".ligne[data-etudid]"), ...document.querySelectorAll(".ligne[data-etudid]"),
].map((e) => e.getAttribute("data-etudid")); ].map((e) => e.getAttribute("data-etudid"));
// On génère une date de début et de fin de la période
const date_debut = new Date(
$("#date").datepicker("getDate").format("YYYY-MM-DD") + "T" + debut
);
const date_fin = new Date(
$("#date").datepicker("getDate").format("YYYY-MM-DD") + "T" + fin
);
date_debut.add(1, "seconds");
// Préparation de la requête // Préparation de la requête
const url = const url =
`../../api/assiduites/group/query?date_debut=${date_debut.toFakeIso()}` + `../../api/assiduites/group/query?date_debut=${date_debut.toFakeIso()}` +

View File

@ -54,7 +54,8 @@
} }
document.getElementById("pdp").addEventListener("change", (e) => { document.getElementById("pdp").addEventListener("change", (e) => {
creerTousLesEtudiants(etuds); afficherPDP(e.target.checked);
//creerTousLesEtudiants(etuds);
}); });
$('#date').on('change', async function(d) { $('#date').on('change', async function(d) {
@ -87,6 +88,8 @@
} }
creerTousLesEtudiants(etuds); creerTousLesEtudiants(etuds);
// affichage ou non des PDP
afficherPDP(localStorage.getItem("scodoc-etud-pdp") == "true" )
} }
setTimeout(main, 0); setTimeout(main, 0);

View File

@ -83,6 +83,7 @@ table.semlist tbody tr td.modalite {
padding-right: 1em; padding-right: 1em;
} }
<<<<<<< HEAD
div.modalite { div.modalite {
font-size: 16px; font-size: 16px;
font-weight: bold; font-weight: bold;
@ -147,6 +148,8 @@ span.effectif {
} }
=======
>>>>>>> b1055a4ebe841f17860d2556cc4b03aa12ec3ab1
</style> </style>
{# News #} {# News #}

View File

@ -299,7 +299,7 @@ def ajout_assiduite_etud() -> str | Response:
def _get_dates_from_assi_form( def _get_dates_from_assi_form(
form: AjoutAssiOrJustForm, form: AjoutAssiOrJustForm,
all_day: bool = False, from_justif: bool = False,
) -> tuple[ ) -> tuple[
bool, datetime.datetime | None, datetime.datetime | None, datetime.datetime | None bool, datetime.datetime | None, datetime.datetime | None, datetime.datetime | None
]: ]:
@ -327,32 +327,15 @@ def _get_dates_from_assi_form(
date_fin = None date_fin = None
form.set_error("date fin invalide", form.date_fin) form.set_error("date fin invalide", form.date_fin)
if date_fin: if not from_justif and date_fin:
# ignore les heures si plusieurs jours # Ne prends pas en compte les heures pour les assiduités sur plusieurs jours
heure_debut = datetime.time.fromisoformat(debut_jour)
# Assiduité : garde les heures inscritent dans le formulaire heure_fin = datetime.time.fromisoformat(fin_jour)
# Justificatif : ignore les heures inscrites dans le formulaire (0h -> 23h59)
heure_debut = (
datetime.time.fromisoformat(debut_jour)
if not all_day
else datetime.time(0, 0, 0)
) # 0h ou ConfigAssiduite.MorningTime
heure_fin = (
datetime.time.fromisoformat(fin_jour)
if not all_day
else datetime.time(23, 59, 59)
) # 23h59 ou ConfigAssiduite.AfternoonTime
else: else:
try: try:
if all_day: heure_debut = datetime.time.fromisoformat(
heure_debut = datetime.time.fromisoformat( form.heure_debut.data or debut_jour
form.heure_debut.data or "00:00" )
)
else:
heure_debut = datetime.time.fromisoformat(
form.heure_debut.data or debut_jour
)
except ValueError: except ValueError:
form.set_error("heure début invalide", form.heure_debut) form.set_error("heure début invalide", form.heure_debut)
if bool(form.heure_debut.data) != bool(form.heure_fin.data): if bool(form.heure_debut.data) != bool(form.heure_fin.data):
@ -360,10 +343,7 @@ def _get_dates_from_assi_form(
"Les deux heures début et fin doivent être spécifiées, ou aucune" "Les deux heures début et fin doivent être spécifiées, ou aucune"
) )
try: try:
if all_day: heure_fin = datetime.time.fromisoformat(form.heure_fin.data or fin_jour)
heure_fin = datetime.time.fromisoformat(form.heure_fin.data or "23:59")
else:
heure_fin = datetime.time.fromisoformat(form.heure_fin.data or fin_jour)
except ValueError: except ValueError:
form.set_error("heure fin invalide", form.heure_fin) form.set_error("heure fin invalide", form.heure_fin)
@ -398,6 +378,19 @@ def _get_dates_from_assi_form(
# Ajoute time zone serveur # Ajoute time zone serveur
dt_debut_tz_server = scu.TIME_ZONE.localize(dt_debut) dt_debut_tz_server = scu.TIME_ZONE.localize(dt_debut)
dt_fin_tz_server = scu.TIME_ZONE.localize(dt_fin) dt_fin_tz_server = scu.TIME_ZONE.localize(dt_fin)
if from_justif:
cas: list[bool] = [
# cas 1 (date de fin vide et pas d'heure de début)
not form.date_fin.data and not form.heure_debut.data,
# cas 2 (date de fin et pas d'heures)
form.date_fin.data != "" and not form.heure_debut.data,
]
if any(cas):
dt_debut_tz_server = dt_debut_tz_server.replace(hour=0, minute=0)
dt_fin_tz_server = dt_fin_tz_server.replace(hour=23, minute=59)
dt_entry_date_tz_server = ( dt_entry_date_tz_server = (
scu.TIME_ZONE.localize(dt_entry_date) if dt_entry_date else None scu.TIME_ZONE.localize(dt_entry_date) if dt_entry_date else None
) )
@ -753,6 +746,34 @@ def ajout_justificatif_etud():
) )
def _verif_date_form_justif(
form: AjoutJustificatifEtudForm, deb: datetime.datetime, fin: datetime.datetime
) -> tuple[datetime.datetime, datetime.datetime]:
"""Gère les cas suivants :
- si on indique seulement une date de debut : journée 0h-23h59
- si on indique date de debut et heures : journée +heure deb/fin
(déjà géré par _get_dates_from_assi_form)
- Si on indique une date de début et de fin sans heures : Journées 0h-23h59
- Si on indique une date de début et de fin avec heures : On fait un objet avec
datedeb/heuredeb + datefin/heurefin (déjà géré par _get_dates_from_assi_form)
"""
cas: list[bool] = [
# cas 1
not form.date_fin.data and not form.heure_debut.data,
# cas 3
form.date_fin.data != "" and not form.heure_debut.data,
]
if any(cas):
deb = deb.replace(hour=0, minute=0)
fin = fin.replace(hour=23, minute=59)
print(f"DEBUG {cas=}")
return deb, fin
def _record_justificatif_etud( def _record_justificatif_etud(
etud: Identite, form: AjoutJustificatifEtudForm, justif: Justificatif | None = None etud: Identite, form: AjoutJustificatifEtudForm, justif: Justificatif | None = None
) -> bool: ) -> bool:
@ -769,7 +790,7 @@ def _record_justificatif_etud(
dt_debut_tz_server, dt_debut_tz_server,
dt_fin_tz_server, dt_fin_tz_server,
dt_entry_date_tz_server, dt_entry_date_tz_server,
) = _get_dates_from_assi_form(form, all_day=True) ) = _get_dates_from_assi_form(form, from_justif=True)
if not ok: if not ok:
log("_record_justificatif_etud: dates invalides") log("_record_justificatif_etud: dates invalides")
form.set_error("Erreur: dates invalides") form.set_error("Erreur: dates invalides")
@ -831,11 +852,6 @@ def _record_justificatif_etud(
db.session.rollback() db.session.rollback()
return False return False
db.session.commit() db.session.commit()
# FIX TEMPORAIRE:
# on reprend toutes les assiduités et tous les justificatifs
# pour utiliser le "reset" (remise en "non_just") des assiduités
# (à terme, il faudrait ne recalculer que les assiduités impactées)
# VOIR TODO dans compute_assiduites_justified
justif.justifier_assiduites() justif.justifier_assiduites()
scass.simple_invalidate_cache(justif.to_dict(), etud.id) scass.simple_invalidate_cache(justif.to_dict(), etud.id)
flash(message) flash(message)

View File

@ -1,7 +1,11 @@
# -*- mode: python -*- # -*- mode: python -*-
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
<<<<<<< HEAD
SCOVERSION = "9.6.955" SCOVERSION = "9.6.955"
=======
SCOVERSION = "9.6.954"
>>>>>>> b1055a4ebe841f17860d2556cc4b03aa12ec3ab1
SCONAME = "ScoDoc" SCONAME = "ScoDoc"