{% include "assiduites/widgets/toast.j2" %} {% block pageContent %} <div class="pageContent"> <h3>Justifier des absences ou retards</h3> {% include "assiduites/widgets/tableau_base.j2" %} <section class="liste"> <a class="icon filter" onclick="filterJusti()"></a> {% include "assiduites/widgets/tableau_justi.j2" %} </section> <section class="justi-form page"> <fieldset> <div class="justi-row"> <div class="justi-label"> <legend for="justi_date_debut" required>Date de début</legend> <scodoc-datetime name="justi_date_debut" id="justi_date_debut"> </scodoc-datetime> <span>Journée entière</span> <input type="checkbox" name="justi_journee" id="justi_journee"> </div> <div class="justi-label" id="date_fin"> <legend for="justi_date_fin" required>Date de fin</legend> <scodoc-datetime name="justi_date_fin" id="justi_date_fin"></scodoc-datetime> </div> </div> <div class="justi-row"> <div class="justi-label"> <legend for="justi_etat" required>Etat du justificatif</legend> <select name="justi_etat" id="justi_etat"> <option value="attente" selected>En Attente de validation</option> <option value="non_valide">Non Valide</option> <option value="modifie">Modifié</option> <option value="valide">Valide</option> </select> </div> </div> <div class="justi-row"> <div class="justi-label"> <legend for="justi_raison">Raison</legend> <textarea name="justi_raison" id="justi_raison" cols="50" rows="10" maxlength="500"></textarea> </div> </div> <div class="justi-row"> <div class="justi-sect"> </div> <div class="justi-label"> <legend for="justi_fich">Importer un fichier</legend> <input type="file" name="justi_fich" id="justi_fich" multiple> </div> </div> <div class="justi-row"> <button onclick="validerFormulaire(this)">Créer le justificatif</button> <button onclick="effacerFormulaire()">Remettre à zero</button> </div> </fieldset> </section> <div class="legende"> <h3>Gestion des justificatifs</h3> <p> Faites <span style="font-style: italic;">clic droit</span> sur une ligne du tableau pour afficher le menu contextuel : <ul> <li>Détails : Affiche les détails du justificatif sélectionné</li> <li>Editer : Permet de modifier le justificatif (dates, etat, ajouter/supprimer fichier etc)</li> <li>Supprimer : Permet de supprimer le justificatif (Action Irréversible)</li> </ul> </p> <p>Cliquer sur l'icone d'entonoir afin de filtrer le tableau des justificatifs</p> </div> </div> <style> .justi-row { margin: 5px 0; } .justi-form fieldset { display: flex; flex-direction: column; justify-content: space-evenly; } .pageContent { max-width: var(--sco-content-max-width); margin-top: 15px; } .justi-label { margin: 0 10px; } [required]::after { content: "*"; color: crimson; } </style> <script> 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 == "" || !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; } 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; } return true } function fieldsToJustificatif() { const field = document.querySelector('.justi-form.page') const { deb, fin } = getDates() const etat = field.querySelector('#justi_etat').value; const raison = field.querySelector('#justi_raison').value; return { date_debut: new Date(deb).toIsoUtcString(), date_fin: new Date(fin).toIsoUtcString(), etat: etat, raison: raison, } } function importFiles(justif_id) { const field = document.querySelector('.justi-form') const in_files = field.querySelector('#justi_fich'); const path = getUrl() + `/api/justificatif/${justif_id}/import`; const requests = [] Array.from(in_files.files).forEach((f) => { pushToast(generateToast(document.createTextNode(`Importation du fichier : ${f.name} commencée`), color = "#f0c865")); const fd = new FormData(); fd.append('file', f); requests.push( $.ajax( { url: path, type: 'POST', data: fd, dateType: 'json', contentType: false, processData: false, success: () => { pushToast(generateToast(document.createTextNode(`Importation du fichier : ${f.name} finie`))); loadAll(); }, } ) ) }); if (in_files.files.length == 0) { loadAll(); } } function validerFormulaire(btn) { if (!validateFields()) return const justificatif = fieldsToJustificatif(); let justif_id = null; let couverture = null; createJustificatif(justificatif, (data) => { if (Object.keys(data.errors).length > 0) { console.error(data.errors); errorAlert(); } if (Object.keys(data.success).length > 0) { couverture = data.success[0].message.couverture justif_id = data.success[0].message.justif_id; importFiles(justif_id); return; } }) btn.disabled = true; setTimeout(() => { btn.disabled = false; }, 1000) } function effacerFormulaire() { const field = document.querySelector('.justi-form') field.querySelector('#justi_date_debut').value = ""; field.querySelector('#justi_date_fin').value = ""; field.querySelector('#justi_etat').value = "attente"; field.querySelector('#justi_raison').value = ""; field.querySelector('#justi_fich').value = ""; } function dayOnly() { const date_deb = document.getElementById("justi_date_debut"); const date_fin = document.getElementById("justi_date_fin"); if (document.getElementById('justi_journee').checked) { date_deb.setAttribute("show", "date") date_fin.setAttribute("show", "date") document.getElementById("date_fin").classList.add("hidden"); } else { date_deb.removeAttribute("show") date_fin.removeAttribute("show") document.getElementById("date_fin").classList.remove("hidden"); } } function getDates() { 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": deb, "fin": fin, } } const etudid = {{ sco.etud.id }}; const assi_limit_annee = "{{ assi_limit_annee }}" == "True" ? true : false; const assi_morning = '{{assi_morning}}'; const assi_evening = '{{assi_evening}}'; window.onload = () => { 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 } } </script> {% endblock pageContent %}