diff --git a/app/static/css/assiduites.css b/app/static/css/assiduites.css index 1cb99e38..5da0e5d9 100644 --- a/app/static/css/assiduites.css +++ b/app/static/css/assiduites.css @@ -449,7 +449,7 @@ transform: translateX(-50%); } -.assiduite-infos { +.assiduite-actions { position: absolute; right: 0; margin: 5px; diff --git a/app/static/js/assiduites.js b/app/static/js/assiduites.js index afcc2985..4fa75afa 100644 --- a/app/static/js/assiduites.js +++ b/app/static/js/assiduites.js @@ -217,13 +217,11 @@ function creerLigneEtudiant(etud, index) { const nameField = document.createElement("div"); nameField.classList.add("name_field"); - if ($("#pdp").is(":checked")) { - const pdp = document.createElement("img"); - pdp.src = `../../api/etudiant/etudid/${etud.id}/photo?size=small`; - pdp.alt = `${etud.nom} ${etud.prenom}`; - pdp.classList.add("pdp"); - nameField.appendChild(pdp); - } + const pdp = document.createElement("img"); + pdp.src = `../../api/etudiant/etudid/${etud.id}/photo?size=small`; + pdp.alt = `${etud.nom} ${etud.prenom}`; + pdp.classList.add("pdp"); + nameField.appendChild(pdp); const nameSet = document.createElement("a"); nameSet.classList.add("name_set"); @@ -857,13 +855,25 @@ function setupAssiduiteBubble(el, assiduite) { // Ajout d'un lien pour plus d'informations const infos = document.createElement("a"); - infos.className = "assiduite-infos"; + infos.className = ""; infos.textContent = `ℹ️`; infos.title = "Cliquez pour plus d'informations"; infos.target = "_blank"; 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"); idDiv.className = "assiduite-id"; diff --git a/app/tables/liste_assiduites.py b/app/tables/liste_assiduites.py index 28b347a9..d30c6348 100644 --- a/app/tables/liste_assiduites.py +++ b/app/tables/liste_assiduites.py @@ -391,11 +391,11 @@ class RowAssiJusti(tb.Row): multi_days = self.ligne["date_debut"].date() != self.ligne["date_fin"].date() date_affichees: list[str] = [ - self.ligne["date_debut"].strftime("%d/%m/%y de %H:%M"), # date début - self.ligne["date_fin"].strftime("%d/%m/%y de %H:%M"), # date fin + self.ligne["date_debut"].strftime("%d/%m/%y %H:%M"), # date début + 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[1] = self.ligne["date_fin"].strftime("%d/%m/%y") diff --git a/app/templates/assiduites/pages/ajout_justificatif_etud.j2 b/app/templates/assiduites/pages/ajout_justificatif_etud.j2 index e9f725e0..311d25c7 100644 --- a/app/templates/assiduites/pages/ajout_justificatif_etud.j2 +++ b/app/templates/assiduites/pages/ajout_justificatif_etud.j2 @@ -74,8 +74,6 @@ div.submit > input {
{{ form.date_fin.label }} : {{ form.date_fin }} - si le jour de fin est différent, - les heures seront ignorées (journées complètes) {{ render_field_errors(form, 'date_fin') }}
diff --git a/app/templates/assiduites/pages/signal_assiduites_diff.j2 b/app/templates/assiduites/pages/signal_assiduites_diff.j2 index 6847259e..f7b37a21 100644 --- a/app/templates/assiduites/pages/signal_assiduites_diff.j2 +++ b/app/templates/assiduites/pages/signal_assiduites_diff.j2 @@ -20,7 +20,7 @@ #actions { flex-direction: row; align-items: center; - margin-bottom: 5px; + margin: 5px 0; } #actions label{ 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 let periodeDiv = document.createElement("div"); periodeDiv.classList.add("cell", "header"); @@ -211,15 +253,6 @@ async function nouvellePeriode(period = null) { ...document.querySelectorAll(".ligne[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 const url = `../../api/assiduites/group/query?date_debut=${date_debut.toFakeIso()}` + diff --git a/app/templates/assiduites/pages/signal_assiduites_group.j2 b/app/templates/assiduites/pages/signal_assiduites_group.j2 index c3f43af4..bb665b4b 100644 --- a/app/templates/assiduites/pages/signal_assiduites_group.j2 +++ b/app/templates/assiduites/pages/signal_assiduites_group.j2 @@ -54,7 +54,8 @@ } document.getElementById("pdp").addEventListener("change", (e) => { - creerTousLesEtudiants(etuds); + afficherPDP(e.target.checked); + //creerTousLesEtudiants(etuds); }); $('#date').on('change', async function(d) { @@ -87,6 +88,8 @@ } creerTousLesEtudiants(etuds); + // affichage ou non des PDP + afficherPDP(localStorage.getItem("scodoc-etud-pdp") == "true" ) } setTimeout(main, 0); diff --git a/app/templates/scolar/index.j2 b/app/templates/scolar/index.j2 index 0e151691..01bc872f 100644 --- a/app/templates/scolar/index.j2 +++ b/app/templates/scolar/index.j2 @@ -83,6 +83,7 @@ table.semlist tbody tr td.modalite { padding-right: 1em; } +<<<<<<< HEAD div.modalite { font-size: 16px; font-weight: bold; @@ -147,6 +148,8 @@ span.effectif { } +======= +>>>>>>> b1055a4ebe841f17860d2556cc4b03aa12ec3ab1 {# News #} diff --git a/app/views/assiduites.py b/app/views/assiduites.py index 527d0404..cb776994 100644 --- a/app/views/assiduites.py +++ b/app/views/assiduites.py @@ -299,7 +299,7 @@ def ajout_assiduite_etud() -> str | Response: def _get_dates_from_assi_form( form: AjoutAssiOrJustForm, - all_day: bool = False, + from_justif: bool = False, ) -> tuple[ bool, datetime.datetime | None, datetime.datetime | None, datetime.datetime | None ]: @@ -327,32 +327,15 @@ def _get_dates_from_assi_form( date_fin = None form.set_error("date fin invalide", form.date_fin) - if date_fin: - # ignore les heures si plusieurs jours - - # Assiduité : garde les heures inscritent dans le formulaire - # 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 + if not from_justif and date_fin: + # Ne prends pas en compte les heures pour les assiduités sur plusieurs jours + heure_debut = datetime.time.fromisoformat(debut_jour) + heure_fin = datetime.time.fromisoformat(fin_jour) else: try: - if all_day: - heure_debut = datetime.time.fromisoformat( - form.heure_debut.data or "00:00" - ) - else: - heure_debut = datetime.time.fromisoformat( - form.heure_debut.data or debut_jour - ) + heure_debut = datetime.time.fromisoformat( + form.heure_debut.data or debut_jour + ) except ValueError: form.set_error("heure début invalide", form.heure_debut) 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" ) try: - if all_day: - 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) + heure_fin = datetime.time.fromisoformat(form.heure_fin.data or fin_jour) except ValueError: form.set_error("heure fin invalide", form.heure_fin) @@ -398,6 +378,19 @@ def _get_dates_from_assi_form( # Ajoute time zone serveur dt_debut_tz_server = scu.TIME_ZONE.localize(dt_debut) 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 = ( 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( etud: Identite, form: AjoutJustificatifEtudForm, justif: Justificatif | None = None ) -> bool: @@ -769,7 +790,7 @@ def _record_justificatif_etud( dt_debut_tz_server, dt_fin_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: log("_record_justificatif_etud: dates invalides") form.set_error("Erreur: dates invalides") @@ -831,11 +852,6 @@ def _record_justificatif_etud( db.session.rollback() return False 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() scass.simple_invalidate_cache(justif.to_dict(), etud.id) flash(message) diff --git a/sco_version.py b/sco_version.py index e0361b07..9e8a6b24 100644 --- a/sco_version.py +++ b/sco_version.py @@ -1,7 +1,11 @@ # -*- mode: python -*- # -*- coding: utf-8 -*- +<<<<<<< HEAD SCOVERSION = "9.6.955" +======= +SCOVERSION = "9.6.954" +>>>>>>> b1055a4ebe841f17860d2556cc4b03aa12ec3ab1 SCONAME = "ScoDoc"