diff --git a/app/scodoc/sco_utils.py b/app/scodoc/sco_utils.py index bb26b58ad..6e04677dc 100644 --- a/app/scodoc/sco_utils.py +++ b/app/scodoc/sco_utils.py @@ -231,7 +231,7 @@ def is_iso_formated(date: str, convert=False) -> bool or datetime.datetime or No try: date: datetime.datetime = datetime.datetime.fromisoformat(date) return date if convert else True - except (dtparser.ParserError, ValueError, TypeError): + except (ValueError, TypeError): return None if convert else False diff --git a/app/static/js/date_utils.js b/app/static/js/date_utils.js index d22487d32..486de19ee 100644 --- a/app/static/js/date_utils.js +++ b/app/static/js/date_utils.js @@ -1,3 +1,8 @@ +Object.defineProperty(Date.prototype, "isValid", { + value: function () { + return !Number.isNaN(this.getTime()); + }, +}); Object.defineProperty(Date.prototype, "startOf", { /** * Génère u la date à la plus petite valeur pour la précision donnée. @@ -338,6 +343,7 @@ class ScoDocDateTimePicker extends HTMLElement { const timeInput = document.createElement("input"); timeInput.type = "time"; timeInput.id = "time"; + timeInput.step = 60; // Ajouter les inputs dans le shadow DOM shadow.appendChild(dateInput); @@ -362,6 +368,10 @@ class ScoDocDateTimePicker extends HTMLElement { shadow.appendChild(style); } + static get observedAttributes() { + return ["show"]; // Ajoute 'show' à la liste des attributs observés + } + connectedCallback() { // Récupérer l'attribut 'name' this.name = this.getAttribute("name"); @@ -386,6 +396,34 @@ class ScoDocDateTimePicker extends HTMLElement { : ""; } }); + this.updateDisplay(); + } + + attributeChangedCallback(name, oldValue, newValue) { + if (name === "show") { + this.updateDisplay(); // Met à jour l'affichage si l'attribut 'show' change + } + } + + updateDisplay() { + const mode = this.getAttribute("show") || "both"; + const dateInput = this.shadowRoot.querySelector("#date"); + const timeInput = this.shadowRoot.querySelector("#time"); + + switch (mode) { + case "date": + dateInput.style.display = "inline-block"; + timeInput.style.display = "none"; + break; + case "time": + dateInput.style.display = "none"; + timeInput.style.display = "inline-block"; + break; + case "both": + default: + dateInput.style.display = "inline-block"; + timeInput.style.display = "inline-block"; + } } // Vérifier si la valeur forme une date valide @@ -418,17 +456,13 @@ class ScoDocDateTimePicker extends HTMLElement { return this._value; } - // Setter pour définir la valeur. Sépare la valeur en date et heure et les définit individuellement. - set value(val) { - let [date, time] = val.split("T"); - this.shadowRoot.querySelector("#date").value = date; - - if ((time.match(/0/g) || []).length > 1) { - time = time.slice(0, time.indexOf(":") + 3); - } - - this.shadowRoot.querySelector("#time").value = time; - this._value = val; + get valueAsObject() { + const dateInput = this.shadowRoot.querySelector("#date"); + const timeInput = this.shadowRoot.querySelector("#time"); + return { + date: dateInput.value, + time: timeInput.value, + }; } // Getter pour obtenir la valeur en tant qu'objet Date. @@ -436,6 +470,34 @@ class ScoDocDateTimePicker extends HTMLElement { return new Date(this._value); } + // Setter pour définir la valeur. Sépare la valeur en date et heure et les définit individuellement. + set value(val) { + let [date, time] = val.split("T"); + this.shadowRoot.querySelector("#date").value = date; + + time = time.substring(0, 5); + + this.shadowRoot.querySelector("#time").value = time; + this._value = val; + } + + // Setter pour définir la valeur à partir d'un objet avec les propriétés 'date' et 'time'. + set valueAsObject(obj) { + const dateInput = this.shadowRoot.querySelector("#date"); + const timeInput = this.shadowRoot.querySelector("#time"); + + if (obj.hasOwnProperty("date")) { + dateInput.value = obj.date || ""; // Définit la valeur de l'input de date si elle est fournie + } + + if (obj.hasOwnProperty("time")) { + timeInput.value = obj.time.substring(0, 5) || ""; // Définit la valeur de l'input d'heure si elle est fournie + } + + // Met à jour la valeur interne en fonction des nouvelles valeurs des inputs + this.updateValue(); + } + // Setter pour définir la valeur à partir d'un objet Date. set valueAsDate(dateVal) { // Formatage de l'objet Date en string et mise à jour de la valeur. diff --git a/app/templates/assiduites/pages/ajout_justificatif.j2 b/app/templates/assiduites/pages/ajout_justificatif.j2 index 0c102cb13..0935ed60b 100644 --- a/app/templates/assiduites/pages/ajout_justificatif.j2 +++ b/app/templates/assiduites/pages/ajout_justificatif.j2 @@ -11,15 +11,11 @@
-
- - -
Date de début - Journée(s) entière(s) + Journée entière
Date de fin @@ -55,6 +51,10 @@
+
+ + +
@@ -112,15 +112,14 @@ function validateFields() { const field = document.querySelector('.justi-form') const { deb, fin } = getDates() + const date_debut = new Date(deb); + const date_fin = new Date(fin); - if (deb == "" || fin == "") { + if (deb == "" || fin == "" || !date_debut.isValid() || !date_fin.isValid()) { openAlertModal("Erreur détéctée", document.createTextNode("Il faut indiquer une date de début et une date de fin valide."), "", color = "crimson"); return false; } - const date_debut = new Date(deb); - const date_fin = new Date(fin); - if (date_fin.isBefore(date_debut)) { openAlertModal("Erreur détéctée", document.createTextNode("La date de fin doit se trouver après la date de début."), "", color = "crimson"); return false; @@ -219,39 +218,31 @@ } function dayOnly() { - const { deb, fin } = getDates(); + const date_deb = document.getElementById("justi_date_debut"); + const date_fin = document.getElementById("justi_date_fin"); if (document.getElementById('justi_journee').checked) { - document.getElementById("justi_date_debut").type = "date" - document.getElementById("justi_date_debut").value = deb.slice(0, deb.indexOf('T')) - - document.getElementById("justi_date_fin").type = "date" - document.getElementById("justi_date_fin").value = fin.slice(0, fin.indexOf('T')) + date_deb.setAttribute("show", "date") + date_fin.setAttribute("show", "date") + document.getElementById("date_fin").classList.add("hidden"); } else { - document.getElementById("justi_date_debut").type = "datetime-local" - document.getElementById("justi_date_debut").value = `${deb}T${assi_morning}` + date_deb.removeAttribute("show") + date_fin.removeAttribute("show") + document.getElementById("date_fin").classList.remove("hidden"); - document.getElementById("justi_date_fin").type = "datetime-local" - document.getElementById("justi_date_fin").value = `${fin}T${assi_evening}` } } function getDates() { - if (document.querySelector('.page #justi_journee').checked) { - const date_str_deb = document.querySelector(".page #justi_date_debut").value - const date_str_fin = document.querySelector(".page #justi_date_fin").value - - - - return { - "deb": date_str_deb ? `${date_str_deb}T${assi_morning}` : "", - "fin": date_str_fin ? `${date_str_fin}T${assi_evening}` : "", - } - } + const date_deb = document.querySelector(".page #justi_date_debut") + const date_fin = document.querySelector(".page #justi_date_fin") + const journee = document.querySelector('.page #justi_journee').checked + const deb = date_deb.valueAsObject.date + "T" + (journee ? assi_morning : date_deb.valueAsObject.time) + const fin = (journee ? date_deb.valueAsObject.date : date_fin.valueAsObject.date) + "T" + (journee ? assi_evening : date_fin.valueAsObject.time) return { - "deb": document.querySelector(".page #justi_date_debut").value, - "fin": document.querySelector(".page #justi_date_fin").value, + "deb": deb, + "fin": fin, } } @@ -265,6 +256,9 @@ loadAll(); document.getElementById('justi_journee').addEventListener('click', () => { dayOnly() }); dayOnly() + + document.getElementById("justi_date_debut").valueAsObject = { time: assi_morning } + document.getElementById("justi_date_fin").valueAsObject = { time: assi_evening } } {% endblock pageContent %} \ No newline at end of file