{# -*- mode: jinja-html -*- #} <h1>{% if not read_only %}Édition des p{% else %}P{%endif%}artitions</h1> <main> <div class="wait"></div> <section id="zonePartitions"> <h2>Filtres</h2> <div> <label class="edition"> <input type="checkbox" autocomplete="off" id="inputModif" {% if edit_partition %}checked{% endif %}> Modifier les partitions et groupes </label> <div class="filtres"></div> <div style="display: flex; justify-content: space-between;"> <div class="editing ajoutPartition">Ajouter une partition</div> <label class="editing valider" for="inputModif">Fini</label> </div> </div> </section> <section id="zoneChoix"> <h2>Étudiants</h2> <details> <summary>Outils d'affectation</summary> <div class="autoAffectation"> <a href="students_groups_auto_assignment?formsemestre_id={{formsemestre.id}}"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#0b0b0b" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> <path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4M10 17l5-5-5-5M13.8 12H3" /> </svg> Aide à l'affectation dans les parcours</a> <div>Importer les résultats : <form class=dropZone> <div> Déposez le fichier .xlsx ou <br> <label> <input type=file accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"> </label> </div> </form> </div> </div> <div class="autoAffectation"> Affecter automatiquement les étudiants du groupe<br> <select name="affectationFrom" id="affectationFrom"></select> vers le groupe <select name="affectationTo" id="affectationTo"></select> <div class="affectationGo">Valider</div> <div class="progress"> <div></div> </div> </div> </details> <div class="etudiants"></div> </section> <section id="zoneGroupes"> <h2>Groupes</h2> <div class="groupes"></div> </section> </main> <script src="{{scu.STATIC_DIR}}/libjs/xlsx-populate-1.21.0.min.js"></script> <script> go(); async function go() { document.querySelector('.wait').style.display = ""; let params = (new URL(document.location)).searchParams; let formsemestre_id = params.get('formsemestre_id'); let partitions = await fetchData("/ScoDoc/{{formsemestre.departement.acronym}}/api/formsemestre/" + formsemestre_id + "/partitions"); let etudiants = await fetchData("/ScoDoc/{{formsemestre.departement.acronym}}/api/formsemestre/" + formsemestre_id + "/resultats"); etudiants.sort((a, b) => { return a.nom_short.localeCompare(b.nom_short) }) processDatas(partitions, etudiants); processEvents(); listeGroupesAutoaffectation(); document.querySelector("body").classList.add("loaded"); document.querySelector('.wait').style.display = "none"; {% if edit_partition %} setEditMode(); {% endif %} } 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 divFiltres = document.querySelector(".filtres"); let outputGroupes = ""; let arrayPartitions = Object.values(partitions).sort((a, b) => { return a.numero - b.numero; }) arrayPartitions.forEach((partition) => { let divPartition = templateFiltres_partition(partition); divFiltres.appendChild(divPartition); let arrayGroups = Object.values(partition.groups).sort((a, b) => { return a.numero - b.numero; }) arrayGroups.forEach((groupe) => { let divPlus = divPartition.querySelector(".ajoutGroupe"); divPlus.parentElement.insertBefore(templateFiltres_groupe(groupe), divPlus); }) // Groupes outputGroupes += ` <div class=partition data-idpartition="${partition.id}"> <h3>${partition.partition_name}</h3> <div class=groupe data-idgroupe=aucun> <div>Non affecté(s)</div> <div class=etudiants></div> </div> ${(() => { let arrayGroups = Object.values(partition.groups).sort((a, b) => { return a.numero - b.numero; }) let output = ""; arrayGroups.forEach((groupe) => { output += templateGroupe_zoneGroupes(groupe.id, groupe.group_name); }) return output; })()} </div>`; }) document.querySelector("#zoneGroupes>.groupes").innerHTML = outputGroupes; /* Etudiants */ output = ""; etudiants.forEach(etudiant => { output += ` <div data-etudid="${etudiant.etudid}" > <div class=nom data-etudid="${etudiant.etudid}" data-nom="${etudiant.nom_disp}" data-prenom="${etudiant.prenom}"><a href="ficheEtud?etudid=${etudiant.etudid}">${etudiant.nom_disp} ${etudiant.prenom}</a><div class=small>${etudiant.bac}</div></div> ${(() => { let output = "<div class=grpPartitions>"; arrayPartitions.forEach((partition) => { output += ` <div class=partition data-idpartition="${partition.id}"> <div>${partition.partition_name}</div> ${(() => { let output = ""; let affected = false; let arrayGroups = Object.values(partition.groups).sort((a, b) => { return a.numero - b.numero; }) arrayGroups.forEach((groupe) => { output += ` <label><input type=radio name="${partition.id}-${etudiant.etudid}" value="${groupe.id}" ${(etudiant.partitions[partition.id] == groupe.id) ? "checked" : ""}><span data-grpname="${groupe.group_name}">${groupe.group_name}</span></label>`; if (etudiant.partitions[partition.id] == groupe.id) { affected = true; document.querySelector(`#zoneGroupes [data-idgroupe="${groupe.id}"]>.etudiants`).innerHTML += templateEtudiant_zoneGroupes(etudiant); } }) if (!affected) { document.querySelector(`#zoneGroupes [data-idpartition="${partition.id}"]>[data-idgroupe="aucun"]>.etudiants`).innerHTML += templateEtudiant_zoneGroupes(etudiant); } return `<label title="Aucun groupe"><input type=radio name="${partition.id}-${etudiant.etudid}" value="aucun" ${(!affected) ? "checked" : ""}><span class=aucun> - </span></label>` + output; })()} </div>`; }) return output + "</div>"; })()} </div>`; }) document.querySelector("#zoneChoix>.etudiants").innerHTML = output; } function templateFiltres_partition(partition) { let div = document.createElement("div"); div.dataset.idpartition = partition.id; if (partition.groups_editable == false) { div.classList.add("nonEditable"); } div.innerHTML = ` <!-- Partition --> <h3 data-idpartition="${partition.id}"> <span class="editing move">||</span> <span>${partition.partition_name}</span> <span class="editing modif">✏️</span> <span class="editing suppr">❌</span> <div class=onoff>Masquer<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#0b0b0b" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path><circle cx="12" cy="12" r="3"></circle></svg></div> </h3> <!-- Groupes --> <div class=groupes> <button class="dt-button" data-idgroupe=aucun> Non affectés </button> <div class="editing ajoutGroupe">+</div> </div> <!-- Config --> <div class=config> Configuration <hr> <label title="Calculer et afficher les rangs dans les groupes de cette partition ?"> <input class=rang type=checkbox ${partition.bul_show_rank ? "checked" : ""} data-attr=bul_show_rank> Rang bulletins </label> <label title="Doit-on afficher les groupes de cette partition dans les listes ?"> <input class=groupe type=checkbox ${partition.show_in_lists ? "checked" : ""} data-attr=show_in_lists> Afficher sur bulletins et tableaux </label> <label> <a class="stdlink" href="{{scu.ScoURL() }}/groups_auto_repartition/${partition.id}">Répartir les étudiants</a> </label> </div> `; div.querySelector(".move").addEventListener("mousedown", moveStart); div.querySelector(".modif").addEventListener("click", editText); div.querySelector(".suppr").addEventListener("click", suppr); div.querySelector(".onoff").addEventListener("click", masquerPartitions); div.querySelector("[data-idgroupe]").addEventListener("click", filtre); div.querySelector(".ajoutGroupe").addEventListener("click", addGroupe); div.querySelector(".rang").addEventListener("input", setAttribute); div.querySelector(".groupe").addEventListener("input", setAttribute); return div; } function templateFiltres_groupe(groupe) { let div = document.createElement("button"); div.classList.add("dt-button"); div.dataset.idgroupe = groupe.id; let edt_id_str = groupe.edt_id ? `<tt class="edt_id" title="id edt">[${groupe.edt_id}]</tt>` : ""; div.innerHTML = ` <span class="editing move">||</span> <span>${groupe.group_name} ${edt_id_str}</span> <span class="editing rename"><a href="/ScoDoc/{{formsemestre.departement.acronym}}/Scolarite/group_rename?group_id=${groupe.id}">✏️</a></span> <span class="editing suppr">❌</span>`; div.addEventListener("click", filtre); div.querySelector(".move").addEventListener("mousedown", moveStart); div.querySelector(".suppr").addEventListener("click", suppr); return div; } function templateGroupe_zoneGroupes(idGroupe, name) { return `<div class=groupe data-idgroupe="${idGroupe}"> <div>${name}</div> <div class=etudiants></div> </div>`; } function templateEtudiant_zoneGroupes(etudiant) { return `<div data-etudid="${etudiant.etudid}" data-nom="${etudiant.nom_disp}" data-prenom="${etudiant.prenom}">${etudiant.nom_disp} ${etudiant.prenom}</div>` } function listeGroupesAutoaffectation() { let output = '<option value disabled selected hidden>Choisir</option>'; document.querySelectorAll('#zonePartitions .filtres>div').forEach(partition => { output += ` <optgroup label="${partition.children[0].children[1].innerText}"> <option value="non-${partition.dataset.idpartition}">Non affectés ${partition.children[0].children[1].innerText}</option>`; partition.querySelectorAll('[data-idgroupe]:not([data-idgroupe="aucun"])').forEach(groupe => { output += `<option value=${groupe.dataset.idgroupe}>${groupe.children[1].innerText}</option>`; }) output += "</optgroup>"; }) document.querySelector("#affectationFrom").innerHTML = output; document.querySelector("#affectationTo").innerHTML = output; } /******************************/ /* Gestionnaire d'événements */ /******************************/ function setEditMode() { let editing = document.querySelector("[contentEditable=true]"); if (!editing) { document.querySelector("body").classList.toggle("editionActivated"); return; } this.checked = true; if (!editing.classList.contains("highlight")) { editing.classList.add("highlight"); setTimeout(() => { editing.classList.remove("highlight") }, 1000); } } function processEvents() { /*--------------------*/ /* Edition partitions */ /*--------------------*/ document.querySelector(".edition>input").addEventListener("input", setEditMode); document.querySelectorAll(".ajoutPartition").forEach(btnPlus => { btnPlus.addEventListener("click", addPartition) }) /*--------------------*/ /* Changement groupe */ /*--------------------*/ document.querySelectorAll("label").forEach(btn => { btn.addEventListener("mousedown", (event) => { event.preventDefault() }) }); document.querySelectorAll(".etudiants input").forEach(input => { input.addEventListener("input", assignment) }) document.querySelector(".affectationGo").addEventListener("click", affectationGo); } /**********************/ /* Filtrage */ /**********************/ function masquerPartitions() { let idPartition = this.closest("[data-idpartition]").dataset.idpartition; document.querySelectorAll(`[data-idpartition="${idPartition}"]`).forEach(e => { e.classList.toggle("hide"); }) } function filtre() { if (document.querySelector("body").classList.contains("editionActivated")) { return; } 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"); }) } // Groupes let groupesSelected = {}; document.querySelectorAll(".filtres [data-idgroupe]:not(.unselect)").forEach(e => { let idpartition = e.closest("[data-idpartition]").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") } }) } /*****************************************/ /* Import des résultats auto affectation */ /*****************************************/ document.querySelector(".dropZone").addEventListener("drop", dropFile); document.querySelector(".dropZone input").addEventListener("change", dropFile); document.querySelector(".dropZone").addEventListener("dragover", dragOver); document.querySelector(".dropZone").addEventListener("dragleave", dragLeave); function dropFile(event) { event.preventDefault(); this.classList.remove("fileOver"); if (event.target.files?.[0] || event.dataTransfer.items[0].type.match('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')) { let file = event.target.files?.[0] || event.dataTransfer.items[0].getAsFile(); let reader = new FileReader(); reader.readAsArrayBuffer(file); reader.onloadend = () => { manageFile(reader.result) } } } function manageFile(file) { XlsxPopulate.fromDataAsync(file) .then(function (workbook) { const sheet = workbook.sheet(0); let ligne = 1; let colonne = 1; let parcours; let etudid; while (parcours = sheet.row(ligne).cell(colonne).value()) { ligne += 2; while (etudid = sheet.row(ligne).cell(colonne).value()) { console.log(parcours, etudid); document.querySelector(`#zoneChoix .etudiants [data-etudid="${etudid}"] [data-grpname="${parcours}"]`)?.click(); ligne++; } ligne = 1; colonne += 3; } }) } function dragOver(event) { event.preventDefault(); this.classList.add("fileOver") } function dragLeave() { this.classList.remove("fileOver") } /****************************/ /* Affectation à un groupe */ /****************************/ var progressNb = 0; var progressRef = 0; function affectationGo() { let from = document.querySelector("#affectationFrom").value; let to = document.querySelector("#affectationTo").value; if (!from || !to) { return; } let elements = []; if (from[0] != "n") { elements = document.querySelectorAll(`#zoneChoix .etudiants [value="${from}"]:checked`) } else { document.querySelectorAll(`#zoneChoix .etudiants [data-idpartition="${from.split("-")[1]}"]`).forEach(element => { if (!element.querySelector('input:not([value="aucun"]):checked')) { elements.push(element); } }) } let progress = document.querySelector("#zoneChoix .autoAffectation .progress"); if (elements.length > 1) { progress.style.setProperty('--reference', elements.length); progress.style.setProperty('--nombre', 0); progressRef = elements.length; progressNb = 0; } elements.forEach(groupeSelected => { if (to[0] != "n") { groupeSelected.closest(".grpPartitions").querySelector(`[value="${to}"]`).click(); } else { let toNumber = to.split("-")[1]; groupeSelected.closest(".grpPartitions").querySelector(`[data-idpartition="${toNumber}"] [value="aucun"]`).click(); } }) } 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 += templateEtudiant_zoneGroupes(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/{{formsemestre.departement.acronym}}/api/partition/${idPartition}/remove_etudiant/${etudid}`; } else { var url = `/ScoDoc/{{formsemestre.departement.acronym}}/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); let progress = document.querySelector("#zoneChoix .autoAffectation .progress"); progress.style.setProperty('--nombre', ++progressNb); if (progressNb == progressRef) { sco_message("Tous les étudiants sont affectés"); } return; } throw ('Les données retournées ne sont pas valides : ' + r.status + ' ' + r.message); }) .catch(error => { document.querySelector("main").innerHTML = "<h2>" + error + "</h2>"; }) } /****************************/ /* Ajout partition / groupe */ /****************************/ function addPartition() { let date = new Date; var name = "Nouvelle " + date.getSeconds(); let params = (new URL(document.location)).searchParams; let formsemestre_id = params.get('formsemestre_id'); var url = "/ScoDoc/{{formsemestre.departement.acronym}}/api/formsemestre/" + formsemestre_id + "/partition/create"; var payload = { partition_name: name, show_in_lists: true }; // Save fetch(url, { method: "POST", headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }) .then(r => { return r.json() }) .then(r => { if (r.message == "invalid partition_name" || r.message == "invalid group_name") { sco_message("Le nom " + name + " existe déjà"); div.remove(); return; } // Ajout dans la zone filtres let partition = { id: r.id, partition_name: name, show_in_lists: true } let divPartition = templateFiltres_partition(partition); document.querySelector("#zonePartitions .filtres").appendChild(divPartition); divPartition.querySelector(".modif").click(); // Ajout de la zone pour chaque étudiant let outputGroupes = ""; document.querySelectorAll("#zoneChoix .grpPartitions").forEach(e => { let etudid = e.previousElementSibling.dataset.etudid; // Préparation pour la section suivante let etudiant = { etudid: etudid, nom_disp: e.previousElementSibling.dataset.nom, prenom: e.previousElementSibling.dataset.prenom } outputGroupes += templateEtudiant_zoneGroupes(etudiant); //////////////////////// let div = document.createElement("div"); div.className = "partition"; div.dataset.idpartition = r.id; div.innerHTML = ` <div>${name}</div> <label title="Aucun groupe"> <input type="radio" name="${r.id}-${etudid}" value="aucun" checked> <span class="aucun">-</span> </label> `; div.querySelector("input").addEventListener("input", assignment); e.appendChild(div); }); // Ajout de la zone groupes document.querySelector("#zoneGroupes>.groupes").innerHTML += ` <div class=partition data-idpartition="${r.id}"> <h3>${name}</h3> <div class=groupe data-idgroupe=aucun> <div>Non affecté(s)</div> <div class=etudiants>${outputGroupes}</div> </div> </div>`; listeGroupesAutoaffectation(); }) .catch(error => { document.querySelector("main").innerHTML = "<h2>Une erreur s'est produite lors de la sauvegarde des données (1).</h2>"; }) } function addGroupe() { let date = new Date; // Groupe var name = "Nouveau " + date.getSeconds(); let idPartition = this.parentElement.previousElementSibling.dataset.idpartition; var url = `/ScoDoc/{{formsemestre.departement.acronym}}/api/partition/${idPartition}/group/create`; var payload = { group_name: name }; fetch(url, { method: "POST", headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }) .then(r => { return r.json() }) .then(r => { if (r.message == "invalid partition_name" || r.message == "invalid group_name") { sco_message("Le nom " + name + " existe déjà"); return; } let groupe = { id: r.id, group_name: name } let divGroupe = templateFiltres_groupe(groupe); this.parentElement.insertBefore(divGroupe, this); // Ajout du bouton pour chaque étudiant document.querySelectorAll(`#zoneChoix .etudiants [data-idpartition="${idPartition}"]`).forEach(e => { let etudid = e.parentElement.previousElementSibling.dataset.etudid; let label = document.createElement("label"); label.innerHTML = `<input type=radio name="${idPartition}-${etudid}" value="${r.id}"><span>${name}</span>`; label.querySelector("input").addEventListener("input", assignment); e.appendChild(label); }) // Ajout du groupe dans la zone Groupes document.querySelector(`#zoneGroupes .partition[data-idpartition="${idPartition}"]`).innerHTML += templateGroupe_zoneGroupes(r.id, name); // Lancement de l'édition du nom // divGroupe.querySelector(".modif").click(); listeGroupesAutoaffectation(); }) .catch(error => { document.querySelector("main").innerHTML = "<h2>Une erreur s'est produite lors de la sauvegarde des données (4).</h2>"; }); } /********************/ /* Edition du texte */ /********************/ function editText() { let e = this.previousElementSibling; e.classList.add("editingText"); e.setAttribute("contenteditable", "true"); e.addEventListener("keydown", writing); e.addEventListener("focusout", () => { saveEditing(this.previousElementSibling) }); // On sélectionne la zone const range = document.createRange(); const selection = window.getSelection(); selection.removeAllRanges(); range.selectNodeContents(e); selection.addRange(range); } function writing(event) { switch (event.key) { case 'Enter': saveEditing(this); event.preventDefault(); break; case 'Escape': saveEditing(this); event.preventDefault(); break; } } function saveEditing(obj) { // Vérification que le champ est non vide if (obj.innerText == "") { event.preventDefault(); sco_message("Ce champ ne peut rester vide."); obj.focus(); return; } // Fin de l'édition obj.classList.remove("editingText"); obj.setAttribute("contenteditable", "false"); obj.removeEventListener("keydown", writing); // Save if (obj.parentElement.dataset.idpartition) { var url = `/ScoDoc/{{formsemestre.departement.acronym}}/api/partition/${obj.parentElement.dataset.idpartition}/edit`; var payload = { partition_name: obj.innerText } document.querySelectorAll(`#zoneChoix .etudiants [data-idpartition="${obj.parentElement.dataset.idpartition}"]>div`).forEach(e => { e.innerText = obj.innerText }); document.querySelector(`#zoneGroupes [data-idpartition="${obj.parentElement.dataset.idpartition}"]>h3`).innerText = obj.innerText; } else { var url = `/ScoDoc/{{formsemestre.departement.acronym}}/api/group/${obj.parentElement.dataset.idgroupe}/edit`; var payload = { group_name: obj.innerText } document.querySelectorAll(`#zoneChoix .etudiants [value="${obj.parentElement.dataset.idgroupe}"]+span`).forEach(e => { e.innerText = obj.innerText }); document.querySelector(`#zoneGroupes [data-idgroupe="${obj.parentElement.dataset.idgroupe}"]>div`).innerText = obj.innerText; } fetch(url, { method: "POST", headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }) .then(r => { return r.json() }) .then(r => { if (!r) { document.querySelector("main").innerHTML = "<h2>Une erreur s'est produite lors de la sauvegarde des données (2).</h2>"; } listeGroupesAutoaffectation(); }) .catch(error => { document.querySelector("main").innerHTML = "<h2>Une erreur s'est produite lors de la sauvegarde des données (3).</h2>"; }) } /*********************************/ /* Suppression parcours / groupe */ /*********************************/ function suppr() { if (this.parentElement.dataset.idpartition) { var data = `data-idpartition="${this.parentElement.dataset.idpartition}"`; } else { var data = `data-idgroupe="${this.parentElement.dataset.idgroupe}"`; } let div = document.createElement("div"); div.className = "confirm"; div.innerHTML = ` <div> <h1>Vous être sur le point de supprimer <span>${this.previousElementSibling.previousElementSibling.innerText}</span>,<br>cette opération est irréversible</h1> <div> <div class="ok" ${data}>Supprimer</div> <div class="nok">Annuler</div> </div> </div> `; document.body.append(div); document.querySelector(".ok").addEventListener("click", supprConfirmed); document.querySelector(".nok").addEventListener("click", closeConfirm); } function supprConfirmed() { closeConfirm(); /* Suppression des éléments dans la page */ if (this.dataset.idpartition) { document.querySelectorAll(`[data-idpartition="${this.dataset.idpartition}"]`).forEach(e => { e.remove() }) var url = "/ScoDoc/{{formsemestre.departement.acronym}}/api/partition/" + this.dataset.idpartition + "/delete"; } else { document.querySelectorAll(`[value="${this.dataset.idgroupe}"]`).forEach(e => { if (e.checked == true) { e.parentElement.parentElement.querySelector("label").click() } e.parentElement.remove() }) document.querySelectorAll(`[data-idgroupe="${this.dataset.idgroupe}"]`).forEach(e => { e.remove() }) var url = "/ScoDoc/{{formsemestre.departement.acronym}}/api/group/" + this.dataset.idgroupe + "/delete"; } //Save fetch(url, { method: "POST" }) .then(r => { return r.json() }) .then(r => { if (r.OK != true) { document.querySelector("main").innerHTML = "<h2>Une erreur s'est produite lors de la sauvegarde des données (5).</h2>"; } listeGroupesAutoaffectation(); }) } function closeConfirm() { document.querySelector(".confirm").remove(); } /*************************/ /* Changement de l'ordre */ /*************************/ let moveData = {}; function moveStart(event) { moveData.x = event.pageX; moveData.y = event.pageY; if (this.parentElement.dataset.idpartition) { moveData.element = this.parentElement.parentElement; } else { moveData.element = this.parentElement; } moveData.element.classList.add("moving"); moveData.element.parentElement.classList.add('grabbing'); document.body.addEventListener("mousemove", move); document.body.addEventListener("mouseup", moveEnd); Array.from(moveData.element.parentElement.children).forEach(e => { if ((e.dataset.idpartition && e.classname != "nonEditable") || (e.dataset.idgroupe != "aucun")) { e.addEventListener("mouseup", newPosition) } }) } function move(event) { event.preventDefault(); moveData.element.style.transform = `translate(${event.pageX - moveData.x}px, ${event.pageY - moveData.y}px)` } function moveEnd() { document.body.removeEventListener("mousemove", move); document.body.removeEventListener("mouseup", moveEnd); moveData.element.parentElement.classList.remove('grabbing'); moveData.element.style.transform = ""; moveData.element.classList.remove("moving"); Array.from(moveData.element.parentElement.children).forEach(e => { if ((e.dataset.idpartition && e.classname != "nonEditable") || (e.dataset.idgroupe && e.dataset.idgroupe != "aucun")) { e.removeEventListener("mouseup", newPosition) } }) moveData = {}; } function newPosition(event) { moveData.element.parentElement.insertBefore(moveData.element, this); let positions = []; Array.from(moveData.element.parentElement.children).forEach(e => { if ((e.dataset.idpartition && e.classname != "nonEditable") || (e.dataset.idgroupe && e.dataset.idgroupe != "aucun")) { positions.push(parseInt(e.dataset.idpartition || e.dataset.idgroupe)) } }) // Save positions if (this.dataset.idpartition) { let params = (new URL(document.location)).searchParams; let formsemestre_id = params.get('formsemestre_id'); var url = `/ScoDoc/{{formsemestre.departement.acronym}}/api/formsemestre/${formsemestre_id}/partitions/order`; document.querySelectorAll(`#zonePartitions .masques>div`).forEach(parent => { positions.forEach(position => { parent.append(parent.querySelector(`[data-idpartition="${position}"]`)) }) }) document.querySelectorAll(`#zoneChoix .grpPartitions`).forEach(parent => { positions.forEach(position => { parent.append(parent.querySelector(`[data-idpartition="${position}"]`)) }) }) document.querySelectorAll(`#zoneGroupes>.groupes`).forEach(parent => { positions.forEach(position => { parent.append(parent.querySelector(`[data-idpartition="${position}"]`)) }) }) } else { let idPartition = this.closest("[data-idpartition]").dataset.idpartition; var url = `/ScoDoc/{{formsemestre.departement.acronym}}/api/partition/${idPartition}/groups/order`; document.querySelectorAll(`#zoneChoix .etudiants .partition[data-idpartition="${idPartition}"]`).forEach(partition => { positions.forEach(position => { partition.append(partition.querySelector(`[value="${position}"]`).parentElement) }) }) document.querySelectorAll(`#zoneGroupes .partition[data-idpartition="${idPartition}"]`).forEach(partition => { positions.forEach(position => { partition.append(partition.querySelector(`[data-idgroupe="${position}"]`)) }) }) } fetch(url, { method: "POST", headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify(positions) }) .then(r => { return r.json() }) .then(r => { if (!r) { document.querySelector("main").innerHTML = "<h2>Une erreur s'est produite lors de la sauvegarde des données (6).</h2>"; } listeGroupesAutoaffectation(); }) .catch(error => { document.querySelector("main").innerHTML = "<h2>Une erreur s'est produite lors de la sauvegarde des données (7).</h2>"; }) } /*****************/ /* Config */ /*****************/ function setAttribute() { fetch("partition_set_attr", { method: "post", headers: { "Content-type": "application/x-www-form-urlencoded; charset=UTF-8" }, body: `partition_id=${this.closest("[data-idpartition]").dataset.idpartition}&attr=${this.dataset.attr}&value=${this.checked ? 1 : 0}` } ).then(function (response) { return response.text(); }) .then(function (txt) { sco_message(txt); }); } </script>