466 lines
20 KiB
Django/Jinja
466 lines
20 KiB
Django/Jinja
<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>
|