forked from ScoDoc/ScoDoc
Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
6dcc4611cc | ||
|
fc8208f061 | ||
|
06433e9063 | ||
|
89dbac2514 | ||
|
63f21c2dd6 | ||
|
7322cc5b56 | ||
|
12dc837f64 | ||
|
f106b26203 | ||
|
53bc91a1b5 |
@ -870,10 +870,19 @@ function setupAssiduiteBubble(el, assiduite) {
|
||||
modifs.target = "_blank";
|
||||
modifs.href = `tableau_assiduite_actions?type=assiduite&action=modifier&obj_id=${assiduite.assiduite_id}`;
|
||||
|
||||
// Ajout d'un lien pour supprimer l'assiduité
|
||||
const supprs = document.createElement("a");
|
||||
supprs.className = "";
|
||||
supprs.textContent = `❌`;
|
||||
supprs.title = "Cliquez pour supprimer l'assiduité";
|
||||
supprs.target = "_blank";
|
||||
supprs.href = `tableau_assiduite_actions?type=assiduite&action=supprimer&obj_id=${assiduite.assiduite_id}`;
|
||||
|
||||
const actionsDiv = document.createElement("div");
|
||||
actionsDiv.className = "assiduite-actions";
|
||||
actionsDiv.appendChild(modifs);
|
||||
actionsDiv.appendChild(infos);
|
||||
actionsDiv.appendChild(supprs);
|
||||
bubble.appendChild(actionsDiv);
|
||||
|
||||
const idDiv = document.createElement("div");
|
||||
|
@ -132,8 +132,248 @@
|
||||
<script src="{{scu.STATIC_DIR}}/js/date_utils.js"></script>
|
||||
{% include "sco_timepicker.j2" %}
|
||||
|
||||
<script>
|
||||
|
||||
{# Gestion de l'historique #}
|
||||
<script>
|
||||
/**
|
||||
* Enregistre une action dans l'historique
|
||||
* @param {string} action - L'action à enregistrer
|
||||
* @param {Object} data - Les données associées à l'action
|
||||
*/
|
||||
function recordAction(action, data) {
|
||||
historyStack.push({ action: action, data: data });
|
||||
}
|
||||
|
||||
/**
|
||||
* Permet de revenir en arrière sur la dernière action
|
||||
*/
|
||||
async function revertAction() {
|
||||
const lastAction = historyStack.pop();
|
||||
if (lastAction) {
|
||||
switch (lastAction.action) {
|
||||
case "create":
|
||||
await deleteAssiduite(lastAction.data, false);
|
||||
break;
|
||||
case "delete":
|
||||
await createAssiduite(lastAction.data, false);
|
||||
break;
|
||||
}
|
||||
// On met à jour l'affichage
|
||||
updateCell(
|
||||
lastAction.data.periodId,
|
||||
lastAction.data.etudid,
|
||||
lastAction.data.assiduite_id
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Permet de vider l'historique
|
||||
*/
|
||||
function clearHistory() {
|
||||
historyStack = [];
|
||||
}
|
||||
|
||||
window.addEventListener('keyup', (event) => {
|
||||
if (event.ctrlKey && event.key === 'z') {
|
||||
revertAction();
|
||||
}
|
||||
});
|
||||
|
||||
let historyStack = [];
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
{# Gestion des actions d'assiduité #}
|
||||
<script>
|
||||
/**
|
||||
* Permet de générer un nouvel objet assiduité à partir du plageId, etudid et etat
|
||||
* @param {int} plageId - L'id de la plage
|
||||
* @param {int} etudid - L'id de l'étudiant
|
||||
* @param {string} etat - L'état de l'assiduité (present, retard, absent)
|
||||
*/
|
||||
function generateNewAssiduite(plageId, etudid, etat) {
|
||||
const periode = periodes.get(plageId);
|
||||
if (!periode) return;
|
||||
return {
|
||||
etudid: etudid,
|
||||
etat: etat,
|
||||
date_debut: periode.date_debut.toFakeIso(),
|
||||
date_fin: periode.date_fin.toFakeIso(),
|
||||
moduleimpl_id: periode.moduleimpl_id,
|
||||
periodId: plageId,
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Permet de récuppérer une assiduité à partir de son assiduite_id
|
||||
* @param {int} assiduite_id
|
||||
* Retourne une promise
|
||||
*/
|
||||
async function getAssiduite(assiduite_id) {
|
||||
return await fetch(`../../api/assiduite/${assiduite_id}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
if (!res.ok) {
|
||||
throw new Error("Network response was not ok");
|
||||
}
|
||||
return res.json();
|
||||
})
|
||||
.then((data) => {
|
||||
return data;
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Crée une nouvelle assiduité.
|
||||
*
|
||||
* @param {Object} newAssiduite - Les informations de la nouvelle assiduité.
|
||||
* @param {boolean} [record=true] - Indique si l'action doit être enregistrée.
|
||||
* @returns {Promise<void>} - Une promesse qui se résout lorsque la création de l'assiduité est terminée.
|
||||
*/
|
||||
async function createAssiduite(newAssiduite, record = true) {
|
||||
if (!newAssiduite) return;
|
||||
|
||||
await async_post(
|
||||
`../../api/assiduite/${newAssiduite.etudid}/create`,
|
||||
[newAssiduite],
|
||||
(data) => {
|
||||
if (data.success.length > 0) {
|
||||
newAssiduite.assiduite_id = data.success[0].message.assiduite_id;
|
||||
// On enregistre l'action si elle est réussie
|
||||
if (record) recordAction("create", newAssiduite);
|
||||
} else {
|
||||
console.error(data.errors["0"].message);
|
||||
erreurModuleImpl(data.errors["0"].message);
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
console.error("Erreur lors de la création de l'assiduité", error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Supprime une assiduité.
|
||||
*
|
||||
* @param {Object} assiduite - L'assiduité à supprimer.
|
||||
* @param {boolean} [record=true] - Indique si l'action de suppression doit être enregistrée.
|
||||
* @returns {Promise<void>} - Une promesse qui se résout lorsque la suppression est terminée.
|
||||
*/
|
||||
async function deleteAssiduite(assiduite, record = true) {
|
||||
if (!assiduite) return;
|
||||
await async_post(
|
||||
`../../api/assiduite/delete`,
|
||||
[assiduite.assiduite_id],
|
||||
(data) => {
|
||||
if (data.success.length > 0) {
|
||||
// On enregistre l'action si elle est réussie
|
||||
assiduite.assiduite_id = null;
|
||||
if (record) recordAction("delete", assiduite);
|
||||
} else {
|
||||
console.error(data.errors["0"].message);
|
||||
erreurModuleImpl(data.errors["0"].message);
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
console.error("Erreur lors de la suppression de l'assiduité", error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée une action d'assiduité.
|
||||
*
|
||||
* @param {string} plageId - L'identifiant de la plage horaire.
|
||||
* @param {string} etudid - L'identifiant de l'étudiant.
|
||||
* @param {string} etat - L'état de l'assiduité.
|
||||
* @returns {Promise<void>} Une promesse qui se résout lorsque l'assiduité est créée avec succès.
|
||||
*/
|
||||
async function createAssiduiteAction(plageId, etudid, etat) {
|
||||
// création de l'assiduité
|
||||
const newAssiduite = generateNewAssiduite(plageId, etudid, etat);
|
||||
await createAssiduite(newAssiduite);
|
||||
|
||||
updateCell(plageId, etudid, newAssiduite.assiduite_id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Met à jour une cellule du tableau
|
||||
*
|
||||
* @param {string} plageId - L'identifiant de la plage horaire.
|
||||
* @param {string} etudid - L'identifiant de l'étudiant.
|
||||
* @param {string|null} assiduite_id - L'identifiant de l'assiduité (facultatif).
|
||||
*/
|
||||
function updateCell(plageId, etudid, assiduite_id = null) {
|
||||
// Vérifie si la plage horaire existe
|
||||
if (!periodes.has(plageId)) return;
|
||||
|
||||
// Mise à jour de la cellule
|
||||
const cell = document.querySelector(`#cell-${etudid}-${plageId}`);
|
||||
|
||||
if (!cell) return;
|
||||
|
||||
cell.innerHTML = "";
|
||||
|
||||
if (assiduite_id) {
|
||||
// Récupère les informations de l'assiduité
|
||||
getAssiduite(assiduite_id).then((data) => {
|
||||
setupAssiduiteBubble(cell, data);
|
||||
const suppr = cell.querySelector('.assiduite-actions a:last-child')
|
||||
suppr?.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
data.periodId = plageId;
|
||||
deleteAssiduite(data);
|
||||
updateCell(plageId, etudid);
|
||||
});
|
||||
}).catch(()=>{
|
||||
setupButtons(cell, etudid, plageId);
|
||||
});
|
||||
} else {
|
||||
setupButtons(cell, etudid, plageId);
|
||||
}
|
||||
}
|
||||
|
||||
function setupButtons(cell, etudid, plageId){
|
||||
const etats = ["retard", "absent"];
|
||||
const assi_btns = document.createElement("div");
|
||||
assi_btns.classList.add("assi-btns");
|
||||
|
||||
if (!window.nonPresent) {
|
||||
etats.splice(0, 0, "present");
|
||||
}
|
||||
|
||||
etats.forEach((value) => {
|
||||
const cbox = document.createElement("input");
|
||||
cbox.type = "checkbox";
|
||||
cbox.value = value;
|
||||
cbox.name = `rbtn_${etudid}_${plageId}`;
|
||||
cbox.classList.add("rbtn", value);
|
||||
|
||||
// Événement pour s'assurer qu'un seul bouton est coché à la fois
|
||||
cbox.addEventListener("click", (event) => {
|
||||
const parent = event.target.parentElement;
|
||||
parent.querySelectorAll(".rbtn").forEach((ele) => {
|
||||
if (ele.value != value) {
|
||||
ele.checked = false;
|
||||
}
|
||||
});
|
||||
createAssiduiteAction(plageId, etudid, value);
|
||||
});
|
||||
|
||||
assi_btns.appendChild(cbox);
|
||||
});
|
||||
cell.appendChild(assi_btns);
|
||||
}
|
||||
</script>
|
||||
{# Gestion des plages et MAIN #}
|
||||
<script>
|
||||
/**
|
||||
* Permet d'ajouter une nouvelle période au tableau
|
||||
* Par défaut la période est générèe avec les valeurs des inputs
|
||||
@ -307,41 +547,18 @@ async function nouvellePeriode(period = null) {
|
||||
const assiduites = data[etudid];
|
||||
// Si l'étudiant n'a pas d'assiduité, on crée les boutons assiduité
|
||||
if (assiduites.length == 0) {
|
||||
|
||||
const assi_btns = document.createElement('div');
|
||||
assi_btns.classList.add('assi-btns');
|
||||
const etats = ["retard", "absent"];
|
||||
|
||||
if(!window.nonPresent){
|
||||
etats.splice(0,0,"present");
|
||||
}
|
||||
|
||||
etats.forEach((value) => {
|
||||
const cbox = document.createElement("input");
|
||||
cbox.type = "checkbox";
|
||||
cbox.value = value;
|
||||
cbox.name = `rbtn_${etudid}_${periodId}`;
|
||||
cbox.classList.add("rbtn", value);
|
||||
|
||||
// Event pour être sur qu'un seul bouton est coché à la fois
|
||||
cbox.addEventListener("click", (event) => {
|
||||
const parent = event.target.parentElement;
|
||||
parent.querySelectorAll(".rbtn").forEach((ele) => {
|
||||
if (ele.value != value) {
|
||||
ele.checked = false;
|
||||
}
|
||||
});
|
||||
});
|
||||
// Si une valeur par défaut est donnée alors on l'applique
|
||||
cbox.checked = etatDef.value == value;
|
||||
|
||||
assi_btns.appendChild(cbox);
|
||||
});
|
||||
cell.appendChild(assi_btns);
|
||||
setupButtons(cell, etudid, periodId);
|
||||
} else {
|
||||
// Si une (ou plus) assiduité sont trouvée pour la période
|
||||
// alors on affiche les informations de la première assiduité
|
||||
setupAssiduiteBubble(cell, assiduites[0]);
|
||||
const suppr = cell.querySelector('.assiduite-actions a:last-child')
|
||||
suppr?.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
assiduites[0].periodId = periodId;
|
||||
deleteAssiduite(assiduites[0]);
|
||||
updateCell(periodId, etudid);
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -606,6 +823,18 @@ window.addEventListener("load", main);
|
||||
|
||||
<button id="add_periode" onclick="nouvellePeriode()">Ajouter une plage</button>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
|
||||
<p>Cette page enregistre automatiquement la saisie effectuée.</p>
|
||||
<p>La page enregistre un historique des dernières saisies.
|
||||
<br>En cas d'erreur, appuyez sur le bouton "Annuler"
|
||||
<br>ou appuyez sur "Ctrl + Z" pour annuler la dernière saisie.
|
||||
</p>
|
||||
<p>Vous pouvez également vider l'historique en appuyant sur le bouton "Vider l'historique".</p>
|
||||
<button onclick="revertAction()">Annuler la dernière saisie</button>
|
||||
<button onclick="clearHistory()">Vider l'historique</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Boutons d'actions
|
||||
- Sauvegarder
|
||||
@ -614,13 +843,12 @@ window.addEventListener("load", main);
|
||||
--->
|
||||
<br>
|
||||
<div id="actions" class="flex">
|
||||
<button id="save" onclick="sauvegarderAssiduites()">ENREGISTRER</button>
|
||||
<label for="pdp">
|
||||
Photo de profil :
|
||||
<input type="checkbox" name="pdp" id="pdp" checked onclick="afficherPDP(this.checked)">
|
||||
</label>
|
||||
|
||||
<label for="etatDef">
|
||||
{# <label for="etatDef">
|
||||
Intialiser les étudiants comme :
|
||||
<select name="etatDef" id="etatDef">
|
||||
<option value="">-</option>
|
||||
@ -630,7 +858,7 @@ window.addEventListener("load", main);
|
||||
<option value="retard">en retard</option>
|
||||
<option value="absent">absents</option>
|
||||
</select>
|
||||
</label>
|
||||
</label> #}
|
||||
|
||||
</div>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user