<table id="assiduiteTable"> <thead> <tr> <th> <div> <span>Début</span> <a class="icon order" onclick="order('date_debut', assiduiteCallBack, this)"></a> </div> </th> <th> <div> <span>Fin</span> <a class="icon order" onclick="order('date_fin', assiduiteCallBack, this)"></a> </div> </th> <th> <div> <span>État</span> <a class="icon order" onclick="order('etat', assiduiteCallBack, this)"></a> </div> </th> <th> <div> <span>Module</span> <a class="icon order" onclick="order('moduleimpl_id', assiduiteCallBack, this)"></a> </div> </th> <th> <div> <span>Justifiée</span> <a class="icon order" onclick="order('est_just', assiduiteCallBack, this)"></a> </div> </th> </tr> </thead> <tbody id="tableBodyAssiduites"> </tbody> </table> <div id="paginationContainerAssiduites" class="pagination-container"> </div> <div style="display: none;" id="cache-module"> {% include "assiduites/widgets/moduleimpl_dynamic_selector.j2" %} </div> <script> const paginationContainerAssiduites = document.getElementById("paginationContainerAssiduites"); let currentPageAssiduites = 1; let orderAssiduites = true; let filterAssiduites = { columns: [ "entry_date", "date_debut", "date_fin", "etat", "moduleimpl_id", "est_just" ], filters: {} } const tableBodyAssiduites = document.getElementById("tableBodyAssiduites"); function assiduiteCallBack(assi) { assi = filterArray(assi, filterAssiduites.filters) renderTableAssiduites(currentPageAssiduites, assi); renderPaginationButtons(assi); try { stats() } catch (_) { } } function renderTableAssiduites(page, assiduités) { generateTableHead(filterAssiduites.columns, true) tableBodyAssiduites.innerHTML = ""; const start = (page - 1) * itemsPerPage; const end = start + itemsPerPage; assiduités.slice(start, end).forEach((assiduite) => { const row = document.createElement("tr"); row.setAttribute('type', "assiduite"); row.setAttribute('obj_id', assiduite.assiduite_id); const etat = assiduite.etat.toLowerCase(); row.classList.add(`l-${etat}`); filterAssiduites.columns.forEach((k) => { const td = document.createElement('td'); if (k.indexOf('date') != -1) { td.textContent = new Date(Date.removeUTC(assiduite[k])).format(`DD/MM/Y HH:mm`) } else if (k.indexOf("module") != -1) { td.textContent = getModuleImpl(assiduite); } else if (k.indexOf('est_just') != -1) { td.textContent = assiduite[k] ? "Oui" : "Non" if (assiduite[k]) row.classList.add("est_just") } else if (k.indexOf('etudid') != -1) { const e = getEtudiant(assiduite.etudid); td.innerHTML = `<a class="etudinfo" id="line-${assiduite.etudid}" href="bilan_etud?etudid=${assiduite.etudid}">${e.prenom.capitalize()} ${e.nom.toUpperCase()}</a>`; } else { td.textContent = assiduite[k].capitalize() } row.appendChild(td) }) row.addEventListener("contextmenu", openContext); tableBodyAssiduites.appendChild(row); }); updateActivePaginationButton(); } function detailAssiduites(assiduite_id) { const path = getUrl() + `/api/assiduite/${assiduite_id}`; async_get( path, (data) => { const user = getUser(data); const module = getModuleImpl(data); const date_debut = new Date(Date.removeUTC(data.date_debut)).format("DD/MM/YYYY HH:mm"); const date_fin = new Date(Date.removeUTC(data.date_fin)).format("DD/MM/YYYY HH:mm"); const entry_date = new Date(Date.removeUTC(data.entry_date)).format("DD/MM/YYYY HH:mm"); const etat = data.etat.capitalize(); const desc = data.desc == null ? "" : data.desc; const id = data.assiduite_id; const est_just = data.est_just ? "Oui" : "Non"; const html = ` <div class="obj-detail"> <div class="obj-dates"> <div id="date_debut" class="obj-part"> <span class="obj-title">Date de début</span> <span class="obj-content">${date_debut}</span> </div> <div id="date_fin" class="obj-part"> <span class="obj-title">Date de fin</span> <span class="obj-content">${date_fin}</span> </div> <div id="entry_date" class="obj-part"> <span class="obj-title">Date de saisie</span> <span class="obj-content">${entry_date}</span> </div> </div> <div class="obj-mod"> <div id="module" class="obj-part"> <span class="obj-title">Module</span> <span class="obj-content">${module}</span> </div> <div id="etat" class="obj-part"> <span class="obj-title">Etat</span> <span class="obj-content">${etat}</span> </div> <div id="user" class="obj-part"> <span class="obj-title">par</span> <span class="obj-content">${user}</span> </div> </div> <div class="obj-rest"> <div id="est_just" class="obj-part"> <span class="obj-title">Justifié</span> <span class="obj-content">${est_just}</span> </div> <div id="desc" class="obj-part"> <span class="obj-title">Description</span> <p class="obj-content">${desc}</p> </div> <div id="id" class="obj-part" data-assiduite-id="${id}"> </div> </div> </div> ` const el = document.createElement('div'); el.innerHTML = html; openAlertModal("Détails", el.firstElementChild, null, "var(--color-information)") } ) } function editionAssiduites(assiduite_id) { const path = getUrl() + `/api/assiduite/${assiduite_id}`; async_get( path, (data) => { let module = data.moduleimpl_id; if ( module == null && data.hasOwnProperty("external_data") && data.external_data != null && data.external_data.hasOwnProperty('module') ) { module = data.external_data.module.toLowerCase(); } const etat = data.etat; let desc = data.desc == null ? "" : data.desc; const html = ` <div class="assi-edit"> <div class="assi-edit-part"> <legend>État de l'assiduité</legend> <select name="etat" id="etat"> <option value="present">Présent</option> <option value="retard">En Retard</option> <option value="absent">Absent</option> </select> </div> <div class="assi-edit-part"> <legend>Module</legend> <select name="module" id="module"> </select> </div> <div class="assi-edit-part"> <legend>Description</legend> <textarea name="desc" id="desc" cols="50" rows="10" maxlength="500"></textarea> </div> </div> ` const el = document.createElement('div') el.innerHTML = html; const assiEdit = el.firstElementChild; assiEdit.querySelector('#etat').value = etat.toLowerCase(); assiEdit.querySelector('#desc').value = desc != null ? desc : ""; updateSelect(module, '#moduleimpl_select', data.date_debut.split('T')[0]) assiEdit.querySelector('#module').replaceWith(document.querySelector('#moduleimpl_select').cloneNode(true)); openPromptModal("Modification de l'assiduité", assiEdit, () => { const prompt = document.querySelector('.assi-edit'); const etat = prompt.querySelector('#etat').value; const desc = prompt.querySelector('#desc').value; let module = prompt.querySelector('#moduleimpl_select').value; let edit = { "etat": etat, "desc": desc, "external_data": data.external_data } edit = setModuleImplId(edit, module); fullEditAssiduites(data.assiduite_id, edit, () => { loadAll(); }) }, () => { }, "var(--color-information)"); } ); } function fullEditAssiduites(assiduite_id, obj, call = () => { }) { const path = getUrl() + `/api/assiduite/${assiduite_id}/edit`; async_post( path, obj, call, (data, status) => { //error console.error(data, status); errorAlert(); } ); } function filterAssi() { let html = ` <div class="filter-body"> <h3>Affichage des colonnes:</h3> <div class="filter-head"> <label> Date de saisie <input class="chk" type="checkbox" name="entry_date" id="entry_date"> </label> <label> Date de Début <input class="chk" type="checkbox" name="date_debut" id="date_debut" checked> </label> <label> Date de Fin <input class="chk" type="checkbox" name="date_fin" id="date_fin" checked> </label> <label> Etat <input class="chk" type="checkbox" name="etat" id="etat" checked> </label> <label> Module <input class="chk" type="checkbox" name="moduleimpl_id" id="moduleimpl_id" checked> </label> <label> Justifiée <input class="chk" type="checkbox" name="est_just" id="est_just" checked> </label> </div> <hr> <h3>Filtrage des colonnes:</h3> <span class="filter-line"> <span class="filter-title" for="entry_date">Date de saisie</span> <select name="entry_date_pref" id="entry_date_pref"> <option value="-1">Avant</option> <option value="0">Égal</option> <option value="1">Après</option> </select> <input type="datetime-local" name="entry_date_time" id="entry_date_time"> </span> <span class="filter-line"> <span class="filter-title" for="date_debut">Date de début</span> <select name="date_debut_pref" id="date_debut_pref"> <option value="-1">Avant</option> <option value="0">Égal</option> <option value="1">Après</option> </select> <input type="datetime-local" name="date_debut_time" id="date_debut_time"> </span> <span class="filter-line"> <span class="filter-title" for="date_fin">Date de fin</span> <select name="date_fin_pref" id="date_fin_pref"> <option value="-1">Avant</option> <option value="0">Égal</option> <option value="1">Après</option> </select> <input type="datetime-local" name="date_fin_time" id="date_fin_time"> </span> <span class="filter-line"> <span class="filter-title" for="etat">Etat</span> <input checked type="checkbox" name="etat_present" id="etat_present" class="rbtn present" value="present"> <input checked type="checkbox" name="etat_retard" id="etat_retard" class="rbtn retard" value="retard"> <input checked type="checkbox" name="etat_absent" id="etat_absent" class="rbtn absent" value="absent"> </span> <span class="filter-line"> <span class="filter-title" for="moduleimpl_id">Module</span> <select id="moduleimpl_id"> <option value="">Pas de filtre</option> </select> </span> <span class="filter-line"> <span class="filter-title" for="est_just">Est Justifiée</span> <select id="est_just"> <option value="">Pas de filtre</option> <option value="true">Oui</option> <option value="false">Non</option> </select> </span> <span class="filter-line"> <span class="filter-title" for="etud">Rechercher dans les étudiants</span> <input type="text" name="etud" id="etud" placeholder="Anne Onymous" > </span> </div> `; const span = document.createElement('span'); span.innerHTML = html html = span.firstElementChild const filterHead = html.querySelector('.filter-head'); filterHead.innerHTML = "" let cols = ["etudid", "entry_date", "date_debut", "date_fin", "etat", "moduleimpl_id", "est_just"]; cols.forEach((k) => { const label = document.createElement('label') label.classList.add('f-label') const s = document.createElement('span'); s.textContent = columnTranslator(k); const input = document.createElement('input'); input.classList.add('chk') input.type = "checkbox" input.name = k input.id = k; input.checked = filterAssiduites.columns.includes(k) label.appendChild(s) label.appendChild(input) filterHead.appendChild(label) }) const sl = html.querySelector('.filter-line #moduleimpl_id'); let opts = [] Object.keys(moduleimpls).forEach((k) => { const opt = document.createElement('option'); opt.value = k == null ? "null" : k; opt.textContent = moduleimpls[k]; opts.push(opt); }) opts = opts.sort((a, b) => { return a.value < b.value }) sl.append(...opts); // Mise à jour des filtres Object.keys(filterAssiduites.filters).forEach((key) => { const l = html.querySelector(`.filter-title[for="${key}"]`).parentElement; if (key.indexOf('date') != -1) { l.querySelector(`#${key}_pref`).value = filterAssiduites.filters[key].pref; l.querySelector(`#${key}_time`).value = filterAssiduites.filters[key].time.format("YYYY-MM-DDTHH:mm"); } else if (key.indexOf('etat') != -1) { l.querySelectorAll('input').forEach((e) => { e.checked = filterAssiduites.filters[key].includes(e.value) }) } else if (key.indexOf("module") != -1) { l.querySelector('#moduleimpl_id').value = filterAssiduites.filters[key]; } else if (key.indexOf("est_just") != -1) { l.querySelector('#est_just').value = filterAssiduites.filters[key]; } else if (key == "etud") { l.querySelector('#etud').value = filterAssiduites.filters["etud"]; } }) openPromptModal("Filtrage des assiduités", html, () => { const columns = [...document.querySelectorAll('.chk')] .map((el) => { if (el.checked) return el.id }) .filter((el) => el) filterAssiduites.columns = columns filterAssiduites.filters = {} //reste des filtres const lines = [...document.querySelectorAll('.filter-line')]; lines.forEach((l) => { const key = l.querySelector('.filter-title').getAttribute('for'); if (key.indexOf('date') != -1) { const pref = l.querySelector(`#${key}_pref`).value; const time = l.querySelector(`#${key}_time`).value; if (l.querySelector(`#${key}_time`).value != "") { filterAssiduites.filters[key] = { pref: pref, time: new Date(Date.removeUTC(time)) } } } else if (key.indexOf('etat') != -1) { filterAssiduites.filters[key] = [...l.querySelectorAll("input:checked")].map((e) => e.value); } else if (key.indexOf("module") != -1) { filterAssiduites.filters[key] = l.querySelector('#moduleimpl_id').value; } else if (key.indexOf("est_just") != -1) { filterAssiduites.filters[key] = l.querySelector('#est_just').value; } else if (key == "etud") { filterAssiduites.filters["etud"] = l.querySelector('#etud').value; } }) getAssi(assiduiteCallBack) }, () => { }, "var(--color-primary)"); } function downloadAssi() { getAssi((d) => { toCSV(d, filterAssiduites) }) } function getAssi(action) { try { getAllAssiduitesFromEtud(etudid, action, true, true, assi_limit_annee) } catch (_) { } } </script>