Assiduité : signal_assiduites_diff : sauvegarde auto + historique action WIP

This commit is contained in:
Iziram 2024-04-24 17:31:46 +02:00
parent 63f21c2dd6
commit 89dbac2514
1 changed files with 248 additions and 8 deletions

View File

@ -132,8 +132,238 @@
<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
*/
function revertAction() {
const lastAction = historyStack.pop();
if (lastAction) {
switch (lastAction.action) {
case "create":
deleteAssiduite(lastAction.data, false);
break;
case "delete":
createAssiduite(lastAction.data, false);
break;
}
// On met à jour l'affichage
updateCell(
lastAction.data.periodId,
lastAction.data.etudid,
lastAction.action == "create" ? null : 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;
})
.catch((error) => {
console.error("Error:", error);
});
}
/**
* 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
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);
});
} else {
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
@ -308,8 +538,8 @@ async function nouvellePeriode(period = null) {
// 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 assi_btns = document.createElement('div');
assi_btns.classList.add('assi-btns');
const etats = ["retard", "absent"];
if(!window.nonPresent){
@ -331,9 +561,8 @@ async function nouvellePeriode(period = null) {
ele.checked = false;
}
});
createAssiduiteAction(periodId,etudid, value);
});
// Si une valeur par défaut est donnée alors on l'applique
cbox.checked = etatDef.value == value;
assi_btns.appendChild(cbox);
});
@ -606,6 +835,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 +855,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 +870,7 @@ window.addEventListener("load", main);
<option value="retard">en retard</option>
<option value="absent">absents</option>
</select>
</label>
</label> #}
</div>