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.target = "_blank";
|
||||||
modifs.href = `tableau_assiduite_actions?type=assiduite&action=modifier&obj_id=${assiduite.assiduite_id}`;
|
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");
|
const actionsDiv = document.createElement("div");
|
||||||
actionsDiv.className = "assiduite-actions";
|
actionsDiv.className = "assiduite-actions";
|
||||||
actionsDiv.appendChild(modifs);
|
actionsDiv.appendChild(modifs);
|
||||||
actionsDiv.appendChild(infos);
|
actionsDiv.appendChild(infos);
|
||||||
|
actionsDiv.appendChild(supprs);
|
||||||
bubble.appendChild(actionsDiv);
|
bubble.appendChild(actionsDiv);
|
||||||
|
|
||||||
const idDiv = document.createElement("div");
|
const idDiv = document.createElement("div");
|
||||||
|
@ -132,8 +132,248 @@
|
|||||||
<script src="{{scu.STATIC_DIR}}/js/date_utils.js"></script>
|
<script src="{{scu.STATIC_DIR}}/js/date_utils.js"></script>
|
||||||
{% include "sco_timepicker.j2" %}
|
{% 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
|
* 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
|
* 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];
|
const assiduites = data[etudid];
|
||||||
// Si l'étudiant n'a pas d'assiduité, on crée les boutons assiduité
|
// Si l'étudiant n'a pas d'assiduité, on crée les boutons assiduité
|
||||||
if (assiduites.length == 0) {
|
if (assiduites.length == 0) {
|
||||||
|
setupButtons(cell, etudid, periodId);
|
||||||
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);
|
|
||||||
} else {
|
} else {
|
||||||
// Si une (ou plus) assiduité sont trouvée pour la période
|
// Si une (ou plus) assiduité sont trouvée pour la période
|
||||||
// alors on affiche les informations de la première assiduité
|
// alors on affiche les informations de la première assiduité
|
||||||
setupAssiduiteBubble(cell, assiduites[0]);
|
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>
|
<button id="add_periode" onclick="nouvellePeriode()">Ajouter une plage</button>
|
||||||
</div>
|
</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>
|
</div>
|
||||||
<!-- Boutons d'actions
|
<!-- Boutons d'actions
|
||||||
- Sauvegarder
|
- Sauvegarder
|
||||||
@ -614,13 +843,12 @@ window.addEventListener("load", main);
|
|||||||
--->
|
--->
|
||||||
<br>
|
<br>
|
||||||
<div id="actions" class="flex">
|
<div id="actions" class="flex">
|
||||||
<button id="save" onclick="sauvegarderAssiduites()">ENREGISTRER</button>
|
|
||||||
<label for="pdp">
|
<label for="pdp">
|
||||||
Photo de profil :
|
Photo de profil :
|
||||||
<input type="checkbox" name="pdp" id="pdp" checked onclick="afficherPDP(this.checked)">
|
<input type="checkbox" name="pdp" id="pdp" checked onclick="afficherPDP(this.checked)">
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label for="etatDef">
|
{# <label for="etatDef">
|
||||||
Intialiser les étudiants comme :
|
Intialiser les étudiants comme :
|
||||||
<select name="etatDef" id="etatDef">
|
<select name="etatDef" id="etatDef">
|
||||||
<option value="">-</option>
|
<option value="">-</option>
|
||||||
@ -630,7 +858,7 @@ window.addEventListener("load", main);
|
|||||||
<option value="retard">en retard</option>
|
<option value="retard">en retard</option>
|
||||||
<option value="absent">absents</option>
|
<option value="absent">absents</option>
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label> #}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user