From 00efa7bcadb8776236c3ba709ce802e77ce343e7 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet <emmanuel.viennet@gmail.com> Date: Tue, 24 Sep 2024 19:23:42 +0200 Subject: [PATCH] Fix signal_assiduites_group: saisie si timezone client != serveur --- app/scodoc/sco_utils.py | 14 ++++++++++++++ app/static/js/assiduites.js | 16 ++++++++-------- .../assiduites/widgets/minitimeline.j2 | 4 ++-- app/templates/assiduites/widgets/timeline.j2 | 18 +++++++++++------- sco_version.py | 2 +- 5 files changed, 36 insertions(+), 18 deletions(-) diff --git a/app/scodoc/sco_utils.py b/app/scodoc/sco_utils.py index d4c710cc3..6b0e8fbc4 100644 --- a/app/scodoc/sco_utils.py +++ b/app/scodoc/sco_utils.py @@ -387,6 +387,20 @@ def localize_datetime(date: datetime.datetime) -> datetime.datetime: return new_date +def get_local_timezone_offset() -> str: + """Récupère l'offset de la timezone du serveur, sous la forme + "+HH:MM" + """ + local_time = datetime.datetime.now().astimezone() + utc_offset = local_time.utcoffset() + total_seconds = int(utc_offset.total_seconds()) + offset_hours = total_seconds // 3600 + offset_minutes = (abs(total_seconds) % 3600) // 60 + offset_sign = "+" if offset_hours >= 0 else "-" + offset_str = f"{offset_sign}{abs(offset_hours):02d}:{offset_minutes:02d}" + return offset_str + + def is_period_overlapping( periode: tuple[datetime.datetime, datetime.datetime], interval: tuple[datetime.datetime, datetime.datetime], diff --git a/app/static/js/assiduites.js b/app/static/js/assiduites.js index 446817247..ec4c1993a 100644 --- a/app/static/js/assiduites.js +++ b/app/static/js/assiduites.js @@ -223,27 +223,27 @@ function creerLigneEtudiant(etud, index) { </div> </div> <fieldset class="btns_field single" etudid="497" type="creation" assiduite_id="-1"> - <input + <input type="checkbox" value="present" name="btn_assiduites_1" - id="rbtn_present" + id="rbtn_present" class="rbtn present" title="present" > - <input + <input type="checkbox" value="retard" name="btn_assiduites_1" - id="rbtn_retard" + id="rbtn_retard" class="rbtn retard" title="retard" > - <input + <input type="checkbox" value="absent" name="btn_assiduites_1" - id="rbtn_absent" + id="rbtn_absent" class="rbtn absent" title="absent" > @@ -609,7 +609,7 @@ async function actionAssiduite(etud, etat, type, assiduite = null) { const modimpl_id = $("#moduleimpl_select").val(); if (assiduite && assiduite.etat.toLowerCase() === etat) type = "suppression"; - const { deb, fin } = getPeriodAsDate(); + const { deb, fin } = getPeriodAsDate(true); // en tz server // génération d'un objet assiduité basique qui sera complété let assiduiteObjet = assiduite ?? { date_debut: deb, @@ -709,7 +709,7 @@ function erreurModuleImpl(message) { function mettreToutLeMonde(etat, el = null) { const lignesEtuds = [...document.querySelectorAll("fieldset.btns_field")]; - const { deb, fin } = getPeriodAsDate(); + const { deb, fin } = getPeriodAsDate(true); // tz server const assiduiteObjet = { date_debut: deb, date_fin: fin, diff --git a/app/templates/assiduites/widgets/minitimeline.j2 b/app/templates/assiduites/widgets/minitimeline.j2 index feab40fd7..1698ae0fe 100644 --- a/app/templates/assiduites/widgets/minitimeline.j2 +++ b/app/templates/assiduites/widgets/minitimeline.j2 @@ -59,7 +59,7 @@ block.style.width = `${widthPercentage}%`; if (assiduité.etat != "CRENEAU") { - // Si on clique dessus on veut pouvoir + // Si on clique dessus on veut pouvoir // mettre à jour la timeline principale et modifier le moduleimpl_select block.addEventListener("click", () => { let deb = startDate.getHours() + startDate.getMinutes() / 60; @@ -71,7 +71,7 @@ $("#moduleimpl_select").val(getModuleImplId(assiduité)) setTimeout(()=>{ - $("#moduleimpl_select").trigger("change"); + $("#moduleimpl_select").trigger("change"); }, 0) }); //ajouter affichage assiduites on over diff --git a/app/templates/assiduites/widgets/timeline.j2 b/app/templates/assiduites/widgets/timeline.j2 index e16045f04..ddc96ad52 100644 --- a/app/templates/assiduites/widgets/timeline.j2 +++ b/app/templates/assiduites/widgets/timeline.j2 @@ -12,6 +12,7 @@ </div> </div> <script> + const SERVER_TIMEZONE_OFFSET = "{{ scu.get_local_timezone_offset() }}"; const timelineContainer = document.querySelector(".timeline-container"); const periodTimeLine = document.querySelector(".period"); const t_start = {{ t_start }}; @@ -21,7 +22,7 @@ const tick_time = 60 / {{ tick_time }}; const tick_delay = 1 / tick_time; - const period_default = 2; + const period_default = 2; // durée créneau par défaut: 2 heures let handleMoving = false; @@ -264,10 +265,10 @@ // On les arrondit aux ticks les plus proches const startValue = snapToQuarter(startHour); const endValue = snapToQuarter(endHour); - + // on verifie que les valeurs sont bien dans les bornes const computedValues = [Math.max(startValue, t_start), Math.min(t_end, endValue)]; - + // si les valeurs sont hors des bornes, on les ajuste if (computedValues[0] > t_end || computedValues[1] < t_start) { return [t_start, Math.min(t_end, t_start + period_default)]; @@ -338,19 +339,22 @@ // Renvoie les valeurs de la période sous forme de date // Les heures sont récupérées depuis la timeline // la date est récupérée depuis un champ "#date" (datepicker) - function getPeriodAsDate(){ + function getPeriodAsDate(add_server_tz = false) { let [deb, fin] = getPeriodValues(); deb = numberToTime(deb); - fin = numberToTime(fin); + fin = numberToTime(fin); const dateStr = $("#date") .datepicker("getDate") .format("yyyy-mm-dd") .substring(0, 10); // récupération que de la date, pas des heures + // Les heures deb et fin sont telles qu'affichées, c'est à dire + // en heure locale DU SERVEUR (des étudiants donc) + let offset = add_server_tz ? SERVER_TIMEZONE_OFFSET : ""; return { - deb: new Date(`${dateStr}T${deb}`), - fin: new Date(`${dateStr}T${fin}`) + deb: new Date(`${dateStr}T${deb}${offset}`), + fin: new Date(`${dateStr}T${fin}${offset}`) } } // Sauvegarde les valeurs de la période dans le local storage diff --git a/sco_version.py b/sco_version.py index 0fc172aa9..4891ff4db 100644 --- a/sco_version.py +++ b/sco_version.py @@ -1,7 +1,7 @@ # -*- mode: python -*- # -*- coding: utf-8 -*- -SCOVERSION = "9.7.25" +SCOVERSION = "9.7.26" SCONAME = "ScoDoc"