270 lines
8.9 KiB
HTML
270 lines
8.9 KiB
HTML
{# -*- mode: jinja-html -*- #}
|
|
<h1>{% if not read_only %}Édition des p{% else %}P{%endif%}artitions</h1>
|
|
|
|
<main>
|
|
<div class="wait"></div>
|
|
<section id="zoneChoix">
|
|
<h2>Choix</h2>
|
|
<div class="filtres">
|
|
<div class="partitions">
|
|
<h3>Afficher les partitions</h3>
|
|
<div></div>
|
|
</div>
|
|
<div class="masques">
|
|
<h3>
|
|
Afficher les étudiants affectés aux groupes<br>
|
|
<small>Ne s'actualise pas automatiquement lors d'une modification</small>
|
|
</h3>
|
|
<div></div>
|
|
</div>
|
|
</div>
|
|
<div class="etudiants"></div>
|
|
</section>
|
|
<section id="zoneGroupes">
|
|
<h2>Groupes</h2>
|
|
<div class="groupes"></div>
|
|
</section>
|
|
</main>
|
|
|
|
<script>
|
|
|
|
go();
|
|
async function go() {
|
|
let params = (new URL(document.location)).searchParams;
|
|
let formsemestre_id = params.get('formsemestre_id');
|
|
|
|
let partitions = await fetchData("/ScoDoc/api/formsemestre/" + formsemestre_id + "/partitions");
|
|
let etudiants = await fetchData("/ScoDoc/api/formsemestre/" + formsemestre_id + "/resultats");
|
|
|
|
etudiants.sort((a, b) => {
|
|
return a.nom_short.localeCompare(b.nom_short)
|
|
})
|
|
|
|
processDatas(partitions, etudiants);
|
|
processEvents();
|
|
|
|
document.querySelector('.wait').style.display = "none";
|
|
}
|
|
|
|
function fetchData(request) {
|
|
return fetch(request)
|
|
.then(r => { return r.json() })
|
|
.then(data => {
|
|
return data;
|
|
}).catch(error => {
|
|
document.querySelector("main").innerHTML = "<h2>Une erreur s'est produite lors du transfert des données.</h2>";
|
|
throw 'Fin du script - données invalides';
|
|
})
|
|
}
|
|
|
|
function processDatas(partitions, etudiants) {
|
|
|
|
/* Filtres et groupes */
|
|
let outputPartitions = "<div>";
|
|
let outputMasques = "";
|
|
let outputGroupes = "";
|
|
Object.entries(partitions).forEach(([idPartition, partition]) => {
|
|
// Filtres
|
|
outputPartitions += `<div data-idpartition="${idPartition}">${partition.partition_name}</div>`;
|
|
outputMasques += `<div data-idpartition="${idPartition}"><div data-idpartition="${idPartition}" data-idgroupe=aucun>Non affectés - ${partition.partition_name}</div>`;
|
|
|
|
// Groupes
|
|
outputGroupes += `
|
|
<div class=partition data-idpartition="${idPartition}">
|
|
<h3>${partition.partition_name}</h3>
|
|
<div class=groupe data-idgroupe=aucun>
|
|
<div>Non affecté(s)</div>
|
|
<div class=etudiants></div>
|
|
</div>
|
|
${(() => {
|
|
let output = "";
|
|
Object.entries(partition.groups).forEach(([idGroupe, titreGroupe]) => {
|
|
/***************/
|
|
outputMasques += `<div data-idgroupe="${idGroupe}">${titreGroupe.name}</div>`;
|
|
/***************/
|
|
output += `
|
|
<div class=groupe data-idgroupe="${idGroupe}">
|
|
<div>${titreGroupe.name}</div>
|
|
<div class=etudiants></div>
|
|
</div>`;
|
|
})
|
|
return output;
|
|
})()}
|
|
</div>`;
|
|
outputMasques += "</div>"
|
|
})
|
|
document.querySelector(".filtres>.partitions>div").innerHTML = outputPartitions + "</div>";
|
|
document.querySelector(".filtres>.masques>div").innerHTML = outputMasques;
|
|
document.querySelector("#zoneGroupes>.groupes").innerHTML = outputGroupes;
|
|
|
|
|
|
/* Etudiants */
|
|
output = "";
|
|
etudiants.forEach(etudiant => {
|
|
output += `
|
|
<div>
|
|
<div class=nom data-etudid="${etudiant.etudid}" data-nom="${etudiant.nom_disp}" data-prenom="${etudiant.prenom}">${etudiant.nom_disp} ${etudiant.prenom}<br><small>${etudiant.bac}</small></div>
|
|
${(() => {
|
|
let output = "<div class=grpPartitions>";
|
|
Object.entries(partitions).forEach(([idPartition, dataPartition]) => {
|
|
output += `
|
|
<div class=partition data-idpartition="${idPartition}">
|
|
<div>${dataPartition.partition_name}</div>
|
|
${(() => {
|
|
let output = "";
|
|
let affected = false;
|
|
Object.entries(dataPartition.groups).forEach(([idGroupe, titreGroupe]) => {
|
|
output += `
|
|
<label><input type=radio name="${idPartition}-${etudiant.etudid}" value="${idGroupe}" ${(etudiant.partitions[idPartition] == idGroupe) ? "checked" : ""}><span>${titreGroupe.name}</span></label>`;
|
|
|
|
if (etudiant.partitions[idPartition] == idGroupe) {
|
|
affected = true;
|
|
document.querySelector(`#zoneGroupes [data-idgroupe="${idGroupe}"]>.etudiants`).innerHTML += templateEtudiantGroupes(etudiant);
|
|
}
|
|
})
|
|
if (!affected) {
|
|
document.querySelector(`#zoneGroupes [data-idpartition="${idPartition}"]>[data-idgroupe="aucun"]>.etudiants`).innerHTML += templateEtudiantGroupes(etudiant);
|
|
}
|
|
return `<label title="Aucun groupe"><input type=radio name="${idPartition}-${etudiant.etudid}" value="aucun" ${(!affected) ? "checked" : ""}><span class=aucun>❌</span></label>` + output;
|
|
})()}
|
|
</div>`;
|
|
})
|
|
return output + "</div>";
|
|
})()}
|
|
</div>`;
|
|
})
|
|
document.querySelector("#zoneChoix>.etudiants").innerHTML = output;
|
|
|
|
}
|
|
|
|
function templateEtudiantGroupes(etudiant) {
|
|
return `<div data-etudid="${etudiant.etudid}" data-nom="${etudiant.nom_disp}" data-prenom="${etudiant.prenom}">${etudiant.nom_disp} ${etudiant.prenom}</div>`
|
|
}
|
|
|
|
function processEvents() {
|
|
document.querySelectorAll(".filtres>div>div>div>div").forEach(btn => {
|
|
btn.addEventListener("click", filtre);
|
|
btn.addEventListener("mousedown", (event) => { event.preventDefault() }) // Eviter de sélectionner le texte si on clique plusieurs fois frénétiquement
|
|
});
|
|
document.querySelectorAll("#zoneChoix label").forEach(btn => { btn.addEventListener("mousedown", (event) => { event.preventDefault() }) });
|
|
|
|
document.querySelectorAll(".etudiants input").forEach(input => {
|
|
input.addEventListener("input", assignment);
|
|
})
|
|
}
|
|
|
|
function filtre() {
|
|
|
|
let nbUnselected = this.parentElement.querySelectorAll(".unselect").length;
|
|
let nbBtn = this.parentElement.children.length;
|
|
|
|
if (nbUnselected == 0) {
|
|
Array.from(this.parentElement.children).forEach(e => {
|
|
e.classList.toggle("unselect");
|
|
})
|
|
}
|
|
this.classList.toggle("unselect");
|
|
|
|
nbUnselected = this.parentElement.querySelectorAll(".unselect").length;
|
|
if (nbUnselected == nbBtn) {
|
|
Array.from(this.parentElement.children).forEach(e => {
|
|
e.classList.toggle("unselect");
|
|
})
|
|
}
|
|
|
|
if (!this.dataset.idgroupe) {
|
|
let groupesSelected = [];
|
|
this.parentElement.querySelectorAll(":not(.unselect)").forEach(e => {
|
|
groupesSelected.push(e.dataset.idpartition);
|
|
})
|
|
document.querySelectorAll(`
|
|
.etudiants .partition[data-idpartition],
|
|
#zoneGroupes [data-idpartition]
|
|
`).forEach(e => {
|
|
if (groupesSelected.includes(e.dataset.idpartition)) {
|
|
e.classList.remove("hide")
|
|
} else {
|
|
e.classList.add("hide")
|
|
}
|
|
})
|
|
} else {
|
|
let groupesSelected = {};
|
|
|
|
this.parentElement.parentElement.querySelectorAll("[data-idgroupe]:not(.unselect)").forEach(e => {
|
|
let idpartition = e.parentElement.dataset.idpartition;
|
|
if(!groupesSelected[idpartition]){
|
|
groupesSelected[idpartition] = [];
|
|
}
|
|
groupesSelected[idpartition].push(e.dataset.idgroupe)
|
|
})
|
|
document.querySelectorAll("#zoneChoix .etudiants>div").forEach(e => {
|
|
let found = true;
|
|
Object.entries(groupesSelected).forEach(([idpartition, tabGroupes])=>{
|
|
if( !tabGroupes.includes(
|
|
e.querySelector(`[data-idpartition="${idpartition}"] input:checked`).value
|
|
)
|
|
){
|
|
found = false
|
|
}
|
|
})
|
|
|
|
if (found) {
|
|
e.classList.remove("hide")
|
|
} else {
|
|
e.classList.add("hide")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
function assignment() {
|
|
let groupe = this.parentElement.parentElement.parentElement.parentElement;
|
|
let nom = groupe.children[0].dataset.nom;
|
|
let prenom = groupe.children[0].dataset.prenom;
|
|
let etudid = groupe.children[0].dataset.etudid;
|
|
let idPartition = this.parentElement.parentElement.dataset.idpartition;
|
|
let idGroupe = this.value;
|
|
|
|
document.querySelector(`#zoneGroupes [data-idPartition="${idPartition}"] [data-etudid="${etudid}"]`).remove();
|
|
|
|
let etudiant = {
|
|
etudid: etudid,
|
|
nom_disp: nom,
|
|
prenom: prenom
|
|
}
|
|
|
|
let results = document.querySelector(`#zoneGroupes [data-idPartition="${idPartition}"] [data-idgroupe="${idGroupe}"]>.etudiants`);
|
|
results.innerHTML += templateEtudiantGroupes(etudiant);
|
|
|
|
/* Tri */
|
|
let results2 = [...results.children];
|
|
results2.sort((a, b) => {
|
|
return (a.dataset.nom + a.dataset.prenom).localeCompare(b.dataset.nom + b.dataset.prenom)
|
|
})
|
|
results.innerHTML = "";
|
|
results.append(...results2);
|
|
|
|
/* Save */
|
|
this.classList.add("saving");
|
|
if (idGroupe == "aucun") {
|
|
var url = `/ScoDoc/api/partition/${idPartition}/remove_etudiant/${etudid}`;
|
|
} else {
|
|
var url = `/ScoDoc/api/group/${idGroupe}/set_etudiant/${etudid}`
|
|
}
|
|
fetch(url, { method: "POST" })
|
|
.then(r => { return r.json() })
|
|
.then(r => {
|
|
if (r.etudid == etudid) {
|
|
this.classList.remove("saving");
|
|
this.classList.add("saved");
|
|
setTimeout(() => { this.classList.remove("saved") }, 800);
|
|
return;
|
|
}
|
|
throw 'Les données retournées ne sont pas valides';
|
|
})
|
|
.catch(error => {
|
|
document.querySelector("main").innerHTML = "<h2>Une erreur s'est produite lors de la sauvegarde des données.</h2>";
|
|
})
|
|
}
|
|
|
|
</script> |