diff --git a/app/static/css/partition_editor.css b/app/static/css/partition_editor.css
index e1bd992d0..4f9915dc2 100644
--- a/app/static/css/partition_editor.css
+++ b/app/static/css/partition_editor.css
@@ -31,6 +31,126 @@ main h3 {
font-weight: 400;
}
+body:not(.editionActivated) .editing {
+ display: none !important;
+}
+
+.editionActivated #zoneChoix .etudiants>div {
+ pointer-events: none;
+ opacity: 0.5;
+}
+
+/****************/
+.ajoutPartition,
+.ajoutGroupe {
+ background: #0c9 !important;
+ padding: 8px 16px !important;
+ cursor: pointer;
+}
+
+.move,
+.modif,
+.suppr {
+ color: #000;
+ padding: 4px;
+ cursor: pointer;
+}
+
+.move {
+ cursor: grab;
+}
+
+.move:active {
+ cursor: grabbing;
+}
+
+body.editionActivated .filtres>div>div>div>div {
+ padding: 8px 16px;
+ position: relative;
+}
+
+.editingText {
+ background: #FFF;
+ color: #000;
+ border-radius: 4px;
+ outline: 4px solid #FFF;
+}
+
+/* Suppression */
+.confirm {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ z-index: 100;
+ background: rgba(0, 0, 0, 0.8);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.confirm span {
+ color: #09c;
+}
+
+.confirm>div {
+ background: #FFF;
+ margin: 32px;
+ padding: 32px 64px;
+ border-radius: 8px;
+ text-align: center;
+}
+
+.confirm>div>div {
+ display: flex;
+ gap: 32px;
+ justify-content: center;
+}
+
+.confirm>div>div>div {
+ padding: 16px 32px;
+ border-radius: 8px;
+ color: #FFF;
+ cursor: pointer;
+}
+
+.confirm .ok {
+ background: #0c9;
+}
+
+.confirm .nok {
+ background: #c44;
+}
+
+/* Déplacements */
+.moving {
+ opacity: 0.8;
+ pointer-events: none;
+ ;
+}
+
+.grabbing>div:not([data-idgroupe="aucun"]):hover:before {
+ content: "";
+ position: absolute;
+ bottom: -4px;
+ top: -4px;
+ right: calc(100% + 1px);
+ width: 2px;
+ background: #c44;
+ animation: insert 0.2s infinite alternate ease-in-out;
+}
+
+@keyframes insert {
+ 0% {
+ transform: translateY(-4px)
+ }
+
+ 100% {
+ transform: translateY(4px)
+ }
+}
+
/*****************************/
/* Zone Choix */
/*****************************/
@@ -46,7 +166,7 @@ main h3 {
flex-wrap: wrap;
gap: 4px;
row-gap: 2px;
- margin: 4px 0;
+ margin: 8px 0;
}
.filtres>div>div>div>div {
@@ -55,14 +175,17 @@ main h3 {
border-radius: 4px;
padding: 8px 32px;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.25);
+}
+
+body:not(.editionActivated) .filtres>div>div>div>div {
cursor: pointer;
}
-.filtres>div>div>div>div:hover {
+body:not(.editionActivated) .filtres>div>div>div>div:hover {
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
}
-.filtres>div>div>div>div:active {
+body:not(.editionActivated) .filtres>div>div>div>div:active {
box-shadow: 0 0 0 #000;
transform: translateY(2px);
}
diff --git a/app/templates/scolar/partition_editor.html b/app/templates/scolar/partition_editor.html
index 43465e365..7b6d8a9ec 100644
--- a/app/templates/scolar/partition_editor.html
+++ b/app/templates/scolar/partition_editor.html
@@ -1,8 +1,16 @@
{# -*- mode: jinja-html -*- #}
{% if not read_only %}Édition des p{% else %}P{%endif%}artitions
+
+
+
+
+
Choix
@@ -30,6 +38,7 @@
go();
async function go() {
+ document.querySelector('.wait').style.display = "";
let params = (new URL(document.location)).searchParams;
let formsemestre_id = params.get('formsemestre_id');
@@ -65,7 +74,7 @@
let outputGroupes = "";
Object.entries(partitions).forEach(([idPartition, partition]) => {
// Filtres
- outputPartitions += `
${partition.partition_name}
`;
+ outputPartitions += `
||${partition.partition_name}✏️❌
`;
outputMasques += `
Non affectés - ${partition.partition_name}
`;
// Groupes
@@ -80,7 +89,7 @@
let output = "";
Object.entries(partition.groups).forEach(([idGroupe, titreGroupe]) => {
/***************/
- outputMasques += `
${titreGroupe.name}
`;
+ outputMasques += `
||${titreGroupe.name}✏️❌
`;
/***************/
output += `
@@ -91,9 +100,13 @@
return output;
})()}
`;
- outputMasques += "
"
+ outputMasques += `
+
+
+
`;
})
- document.querySelector(".filtres>.partitions>div").innerHTML = outputPartitions + "";
+ document.querySelector(".filtres>.partitions>div").innerHTML = outputPartitions + `
+ +
+ `;
document.querySelector(".filtres>.masques>div").innerHTML = outputMasques;
document.querySelector("#zoneGroupes>.groupes").innerHTML = outputGroupes;
@@ -141,19 +154,38 @@
return `${etudiant.nom_disp} ${etudiant.prenom}
`
}
+ /******************************/
+ /* Gestionnaire d'événements */
+ /******************************/
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() }) });
+ /*--------------------*/
+ /* Edition partitions */
+ /*--------------------*/
+ document.querySelector(".edition>input").addEventListener("input", () => { document.querySelector("body").classList.toggle("editionActivated") });
+ document.querySelectorAll(".ajoutPartition, .ajoutGroupe").forEach(btnPlus => { btnPlus.addEventListener("click", addPartition) })
+ document.querySelectorAll(".modif").forEach(btn => { btn.addEventListener("click", editText) })
+ document.querySelectorAll(".suppr").forEach(btn => { btn.addEventListener("click", suppr) })
+ document.querySelectorAll(".move").forEach(btn => { btn.addEventListener("mousedown", moveStart) })
- document.querySelectorAll(".etudiants input").forEach(input => {
- input.addEventListener("input", assignment);
- })
+ /*---------*/
+ /* Filtres */
+ /*---------*/
+ document.querySelectorAll(".filtres>div>div>div>div:not(.editing)").forEach(btn => { btn.addEventListener("click", filtre) })
+
+ /*--------------------*/
+ /* Changement groupe */
+ /*--------------------*/
+ document.querySelectorAll("#zoneChoix label").forEach(btn => { btn.addEventListener("mousedown", (event) => { event.preventDefault() }) });
+ document.querySelectorAll(".etudiants input").forEach(input => { input.addEventListener("input", assignment) })
}
+ /**********************/
+ /* Filtrage */
+ /**********************/
function filtre() {
+ if (document.querySelector("body").classList.contains("editionActivated")) {
+ return;
+ }
let nbUnselected = this.parentElement.querySelectorAll(".unselect").length;
let nbBtn = this.parentElement.children.length;
@@ -192,20 +224,20 @@
this.parentElement.parentElement.querySelectorAll("[data-idgroupe]:not(.unselect)").forEach(e => {
let idpartition = e.parentElement.dataset.idpartition;
- if(!groupesSelected[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
- )
- ){
+ Object.entries(groupesSelected).forEach(([idpartition, tabGroupes]) => {
+ if (!tabGroupes.includes(
+ e.querySelector(`[data-idpartition="${idpartition}"] input:checked`).value
+ )
+ ) {
found = false
- }
+ }
})
if (found) {
@@ -216,7 +248,9 @@
})
}
}
-
+ /****************************/
+ /* Affectation à un groupe */
+ /****************************/
function assignment() {
let groupe = this.parentElement.parentElement.parentElement.parentElement;
let nom = groupe.children[0].dataset.nom;
@@ -267,4 +301,155 @@
})
}
+
+ /*******************/
+ /* Ajout partition */
+ /*******************/
+ function addPartition() {
+ let div = document.createElement("div");
+ div.innerHTML = `
+ ||
+ Nouveau
+ ✏️
+ ❌`;
+
+ div.querySelector(".modif").addEventListener("click", editText);
+ div.querySelector(".suppr").addEventListener("click", suppr);
+ div.querySelector(".move").addEventListener("mousedown", moveStart);
+ this.parentElement.insertBefore(div, this);
+
+ // Save
+ }
+
+ /********************/
+ /* Edition du texte */
+ /********************/
+ function editText() {
+ //this.addEventListener("click", saveEditing, { once: true })
+ this.previousElementSibling.classList.add("editingText");
+ this.previousElementSibling.setAttribute("contenteditable", "true");
+ this.previousElementSibling.focus();
+
+ this.previousElementSibling.addEventListener("keydown", writing);
+ }
+
+ function writing(event) {
+ switch (event.key) {
+ case 'Enter':
+ saveEditing(this);
+ event.preventDefault();
+ break;
+ case 'Escape':
+ saveEditing(this);
+ event.preventDefault();
+ break;
+ }
+ }
+
+ function saveEditing(obj) {
+ obj.classList.remove("editingText");
+ obj.setAttribute("contenteditable", "false");
+ obj.removeEventListener("keydown", writing);
+ // Save
+ console.log(
+ obj.parentElement.dataset.idpartition || obj.parentElement.dataset.idgroupe,
+ obj.innerText);
+ }
+
+ /*********************************/
+ /* 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 = `
+
+
Vous être sur le point de supprimer ${this.previousElementSibling.previousElementSibling.innerText}, cette opération est irréversible
+
+
+ `;
+ 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() })
+ } 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() })
+ }
+ //Save
+ console.log(this.dataset.idpartition || this.dataset.idgroupe);
+
+ }
+
+ function closeConfirm() {
+ document.querySelector(".confirm").remove();
+ }
+
+ /*************************/
+ /* Changement de l'ordre */
+ /*************************/
+ let moveData = {};
+ function moveStart(event) {
+ moveData.x = event.pageX;
+ moveData.y = event.pageY;
+ moveData.element = this.parentElement;
+ moveData.element.classList.add("moving");
+ moveData.element.parentElement.classList.add('grabbing');
+ document.body.addEventListener("mousemove", move);
+ moveData.element.parentElement.querySelectorAll("div:not([data-idgroupe=aucun])").forEach(e => {
+ e.addEventListener("mouseup", newPosition)
+ })
+ document.body.addEventListener("mouseup", moveEnd);
+ }
+
+ 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");
+ moveData.element.parentElement.querySelectorAll("div:not([data-idgroupe=aucun])").forEach(e => {
+ e.removeEventListener("mouseup", newPosition)
+ })
+ moveData = {};
+ }
+
+ function newPosition() {
+ moveData.element.parentElement.insertBefore(moveData.element, this);
+
+ let positions = [];
+ Array.from(moveData.element.parentElement.children).forEach(e => {
+ if (e.dataset.idpartition || (e.dataset.idgroupe && e.dataset.idgroupe != "aucun")) {
+ positions.push(e.dataset.idpartition || e.dataset.idgroupe)
+ }
+ })
+
+ // Save positions
+ console.log(positions)
+ }
+
\ No newline at end of file