forked from ScoDoc/ScoDoc
Interface modification
This commit is contained in:
parent
a3fc5b0def
commit
6a3c9a613e
@ -31,6 +31,126 @@ main h3 {
|
|||||||
font-weight: 400;
|
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 */
|
/* Zone Choix */
|
||||||
/*****************************/
|
/*****************************/
|
||||||
@ -46,7 +166,7 @@ main h3 {
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
row-gap: 2px;
|
row-gap: 2px;
|
||||||
margin: 4px 0;
|
margin: 8px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.filtres>div>div>div>div {
|
.filtres>div>div>div>div {
|
||||||
@ -55,14 +175,17 @@ main h3 {
|
|||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
padding: 8px 32px;
|
padding: 8px 32px;
|
||||||
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.25);
|
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
body:not(.editionActivated) .filtres>div>div>div>div {
|
||||||
cursor: pointer;
|
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);
|
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;
|
box-shadow: 0 0 0 #000;
|
||||||
transform: translateY(2px);
|
transform: translateY(2px);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
{# -*- mode: jinja-html -*- #}
|
||||||
<h1>{% if not read_only %}Édition des p{% else %}P{%endif%}artitions</h1>
|
<h1>{% if not read_only %}Édition des p{% else %}P{%endif%}artitions</h1>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label class="edition">
|
||||||
|
Edition des partitions
|
||||||
|
<input type="checkbox">
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<div class="wait"></div>
|
<div class="wait"></div>
|
||||||
|
|
||||||
<section id="zoneChoix">
|
<section id="zoneChoix">
|
||||||
<h2>Choix</h2>
|
<h2>Choix</h2>
|
||||||
<div class="filtres">
|
<div class="filtres">
|
||||||
@ -30,6 +38,7 @@
|
|||||||
|
|
||||||
go();
|
go();
|
||||||
async function go() {
|
async function go() {
|
||||||
|
document.querySelector('.wait').style.display = "";
|
||||||
let params = (new URL(document.location)).searchParams;
|
let params = (new URL(document.location)).searchParams;
|
||||||
let formsemestre_id = params.get('formsemestre_id');
|
let formsemestre_id = params.get('formsemestre_id');
|
||||||
|
|
||||||
@ -65,7 +74,7 @@
|
|||||||
let outputGroupes = "";
|
let outputGroupes = "";
|
||||||
Object.entries(partitions).forEach(([idPartition, partition]) => {
|
Object.entries(partitions).forEach(([idPartition, partition]) => {
|
||||||
// Filtres
|
// Filtres
|
||||||
outputPartitions += `<div data-idpartition="${idPartition}">${partition.partition_name}</div>`;
|
outputPartitions += `<div data-idpartition="${idPartition}"><span class="editing move">||</span><span>${partition.partition_name}</span><span class="editing modif">✏️</span><span class="editing suppr">❌</span></div>`;
|
||||||
outputMasques += `<div data-idpartition="${idPartition}"><div data-idpartition="${idPartition}" data-idgroupe=aucun>Non affectés - ${partition.partition_name}</div>`;
|
outputMasques += `<div data-idpartition="${idPartition}"><div data-idpartition="${idPartition}" data-idgroupe=aucun>Non affectés - ${partition.partition_name}</div>`;
|
||||||
|
|
||||||
// Groupes
|
// Groupes
|
||||||
@ -80,7 +89,7 @@
|
|||||||
let output = "";
|
let output = "";
|
||||||
Object.entries(partition.groups).forEach(([idGroupe, titreGroupe]) => {
|
Object.entries(partition.groups).forEach(([idGroupe, titreGroupe]) => {
|
||||||
/***************/
|
/***************/
|
||||||
outputMasques += `<div data-idgroupe="${idGroupe}">${titreGroupe.name}</div>`;
|
outputMasques += `<div data-idgroupe="${idGroupe}"><span class="editing move">||</span><span>${titreGroupe.name}</span><span class="editing modif">✏️</span><span class="editing suppr">❌</span></div>`;
|
||||||
/***************/
|
/***************/
|
||||||
output += `
|
output += `
|
||||||
<div class=groupe data-idgroupe="${idGroupe}">
|
<div class=groupe data-idgroupe="${idGroupe}">
|
||||||
@ -91,9 +100,13 @@
|
|||||||
return output;
|
return output;
|
||||||
})()}
|
})()}
|
||||||
</div>`;
|
</div>`;
|
||||||
outputMasques += "</div>"
|
outputMasques += `
|
||||||
|
<div class="editing ajoutGroupe">+</div>
|
||||||
|
</div>`;
|
||||||
})
|
})
|
||||||
document.querySelector(".filtres>.partitions>div").innerHTML = outputPartitions + "</div>";
|
document.querySelector(".filtres>.partitions>div").innerHTML = outputPartitions + `
|
||||||
|
<div class="editing ajoutPartition">+</div>
|
||||||
|
</div>`;
|
||||||
document.querySelector(".filtres>.masques>div").innerHTML = outputMasques;
|
document.querySelector(".filtres>.masques>div").innerHTML = outputMasques;
|
||||||
document.querySelector("#zoneGroupes>.groupes").innerHTML = outputGroupes;
|
document.querySelector("#zoneGroupes>.groupes").innerHTML = outputGroupes;
|
||||||
|
|
||||||
@ -141,19 +154,38 @@
|
|||||||
return `<div data-etudid="${etudiant.etudid}" data-nom="${etudiant.nom_disp}" data-prenom="${etudiant.prenom}">${etudiant.nom_disp} ${etudiant.prenom}</div>`
|
return `<div data-etudid="${etudiant.etudid}" data-nom="${etudiant.nom_disp}" data-prenom="${etudiant.prenom}">${etudiant.nom_disp} ${etudiant.prenom}</div>`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************/
|
||||||
|
/* Gestionnaire d'événements */
|
||||||
|
/******************************/
|
||||||
function processEvents() {
|
function processEvents() {
|
||||||
document.querySelectorAll(".filtres>div>div>div>div").forEach(btn => {
|
/*--------------------*/
|
||||||
btn.addEventListener("click", filtre);
|
/* Edition partitions */
|
||||||
btn.addEventListener("mousedown", (event) => { event.preventDefault() }) // Eviter de sélectionner le texte si on clique plusieurs fois frénétiquement
|
/*--------------------*/
|
||||||
});
|
document.querySelector(".edition>input").addEventListener("input", () => { document.querySelector("body").classList.toggle("editionActivated") });
|
||||||
document.querySelectorAll("#zoneChoix label").forEach(btn => { btn.addEventListener("mousedown", (event) => { event.preventDefault() }) });
|
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() {
|
function filtre() {
|
||||||
|
if (document.querySelector("body").classList.contains("editionActivated")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let nbUnselected = this.parentElement.querySelectorAll(".unselect").length;
|
let nbUnselected = this.parentElement.querySelectorAll(".unselect").length;
|
||||||
let nbBtn = this.parentElement.children.length;
|
let nbBtn = this.parentElement.children.length;
|
||||||
@ -192,20 +224,20 @@
|
|||||||
|
|
||||||
this.parentElement.parentElement.querySelectorAll("[data-idgroupe]:not(.unselect)").forEach(e => {
|
this.parentElement.parentElement.querySelectorAll("[data-idgroupe]:not(.unselect)").forEach(e => {
|
||||||
let idpartition = e.parentElement.dataset.idpartition;
|
let idpartition = e.parentElement.dataset.idpartition;
|
||||||
if(!groupesSelected[idpartition]){
|
if (!groupesSelected[idpartition]) {
|
||||||
groupesSelected[idpartition] = [];
|
groupesSelected[idpartition] = [];
|
||||||
}
|
}
|
||||||
groupesSelected[idpartition].push(e.dataset.idgroupe)
|
groupesSelected[idpartition].push(e.dataset.idgroupe)
|
||||||
})
|
})
|
||||||
document.querySelectorAll("#zoneChoix .etudiants>div").forEach(e => {
|
document.querySelectorAll("#zoneChoix .etudiants>div").forEach(e => {
|
||||||
let found = true;
|
let found = true;
|
||||||
Object.entries(groupesSelected).forEach(([idpartition, tabGroupes])=>{
|
Object.entries(groupesSelected).forEach(([idpartition, tabGroupes]) => {
|
||||||
if( !tabGroupes.includes(
|
if (!tabGroupes.includes(
|
||||||
e.querySelector(`[data-idpartition="${idpartition}"] input:checked`).value
|
e.querySelector(`[data-idpartition="${idpartition}"] input:checked`).value
|
||||||
)
|
)
|
||||||
){
|
) {
|
||||||
found = false
|
found = false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if (found) {
|
if (found) {
|
||||||
@ -216,7 +248,9 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/****************************/
|
||||||
|
/* Affectation à un groupe */
|
||||||
|
/****************************/
|
||||||
function assignment() {
|
function assignment() {
|
||||||
let groupe = this.parentElement.parentElement.parentElement.parentElement;
|
let groupe = this.parentElement.parentElement.parentElement.parentElement;
|
||||||
let nom = groupe.children[0].dataset.nom;
|
let nom = groupe.children[0].dataset.nom;
|
||||||
@ -267,4 +301,155 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************/
|
||||||
|
/* Ajout partition */
|
||||||
|
/*******************/
|
||||||
|
function addPartition() {
|
||||||
|
let div = document.createElement("div");
|
||||||
|
div.innerHTML = `
|
||||||
|
<span class="editing move">||</span>
|
||||||
|
<span>Nouveau</span>
|
||||||
|
<span class="editing modif">✏️</span>
|
||||||
|
<span class="editing suppr">❌</span>`;
|
||||||
|
|
||||||
|
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 = `
|
||||||
|
<div>
|
||||||
|
<h1>Vous être sur le point de supprimer <span>${this.previousElementSibling.previousElementSibling.innerText}</span>, 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() })
|
||||||
|
} 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)
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
Loading…
Reference in New Issue
Block a user