Assiduites : Gestion des justificatifs (rapide) WIP

Assiduites : ajout style justifié (minitimeline)
This commit is contained in:
iziram 2023-04-19 20:58:15 +02:00
parent f3b540b4c1
commit f26ecb1f8a
7 changed files with 246 additions and 106 deletions

View File

@ -316,10 +316,10 @@ def compute_assiduites_justified(
for justi in justificatifs: for justi in justificatifs:
assiduites: Assiduite = ( assiduites: Assiduite = (
Assiduite.query.join(Justificatif, Justificatif.etudid == Assiduite.etudid) Assiduite.query.join(Justificatif, Justificatif.etudid == Assiduite.etudid)
.filter(Assiduite.etat != EtatAssiduite.PRESENT) .filter(justi.etat == EtatJustificatif.VALIDE)
.filter( .filter(
Assiduite.date_debut <= justi.date_fin, Assiduite.date_debut < justi.date_fin,
Assiduite.date_fin >= justi.date_debut, Assiduite.date_fin > justi.date_debut,
) )
) )
@ -329,11 +329,9 @@ def compute_assiduites_justified(
db.session.add(assi) db.session.add(assi)
if reset: if reset:
un_justified: Assiduite = ( un_justified: Assiduite = Assiduite.query.filter(
Assiduite.query.filter(Assiduite.id.not_in(list_assiduites_id)) Assiduite.id.not_in(list_assiduites_id)
.filter(Assiduite.etat != EtatAssiduite.PRESENT) ).join(Justificatif, Justificatif.etudid == Assiduite.etudid)
.join(Justificatif, Justificatif.etudid == Assiduite.etudid)
)
for assi in un_justified: for assi in un_justified:
assi.est_just = False assi.est_just = False

View File

@ -20,7 +20,6 @@ class CountCalculator:
evening: time = time(18, 0), evening: time = time(18, 0),
skip_saturday: bool = True, skip_saturday: bool = True,
) -> None: ) -> None:
self.morning: time = morning self.morning: time = morning
self.noon: time = noon self.noon: time = noon
self.after_noon: time = after_noon self.after_noon: time = after_noon
@ -318,14 +317,12 @@ def justifies(justi: Justificatif, obj: bool = False) -> list[int]:
if justi.etat != scu.EtatJustificatif.VALIDE: if justi.etat != scu.EtatJustificatif.VALIDE:
return [] return []
assiduites_query: Assiduite = ( assiduites_query: Assiduite = Assiduite.query.join(
Assiduite.query.join(Justificatif, Assiduite.etudid == Justificatif.etudid) Justificatif, Assiduite.etudid == Justificatif.etudid
.filter(Assiduite.etat != scu.EtatAssiduite.PRESENT) ).filter(
.filter(
Assiduite.date_debut <= justi.date_fin, Assiduite.date_debut <= justi.date_fin,
Assiduite.date_fin >= justi.date_debut, Assiduite.date_fin >= justi.date_debut,
) )
)
if not obj: if not obj:
return [assi.id for assi in assiduites_query.all()] return [assi.id for assi in assiduites_query.all()]

View File

@ -192,6 +192,14 @@
background-color: #F1D99C !important; background-color: #F1D99C !important;
} }
.etud_row .assiduites_bar .justified {
background-image: repeating-linear-gradient(135deg, transparent, transparent 4px, #7059FF 4px, #7059FF 8px);
}
.etud_row .assiduites_bar .invalid_justified {
background-image: repeating-linear-gradient(135deg, transparent, transparent 4px, #d61616 4px, #d61616 8px);
}
/* --- Boutons assiduités --- */ /* --- Boutons assiduités --- */
.etud_row .btns_field { .etud_row .btns_field {

View File

@ -16,6 +16,7 @@ let currentValues = [8.0, 10.0];
//Objet stockant les étudiants et les assiduités //Objet stockant les étudiants et les assiduités
let etuds = {}; let etuds = {};
let assiduites = {}; let assiduites = {};
let justificatifs = {};
// Variable qui définit si le processus d'action de masse est lancé // Variable qui définit si le processus d'action de masse est lancé
let currentMassAction = false; let currentMassAction = false;
@ -1094,11 +1095,39 @@ function createMiniTimeline(assiduitesArray) {
setPeriodValues(deb, fin); setPeriodValues(deb, fin);
updateSelectedSelect(getCurrentAssiduiteModuleImplId()); updateSelectedSelect(getCurrentAssiduiteModuleImplId());
updateJustifyBtn();
}); });
} }
//ajouter affichage assiduites on over //ajouter affichage assiduites on over
setupAssiduiteBuble(block, assiduité); setupAssiduiteBuble(block, assiduité);
if (assiduité.est_just) {
block.classList.add("justified");
} }
}
const action = (justificatifs) => {
if (justificatifs.length > 0) {
let j = "invalid_justified";
justificatifs.forEach((ju) => {
if (ju.etat == "VALIDE") {
j = "justified";
}
});
block.classList.add(j);
}
};
getJustificatifFromPeriod(
{
deb: new moment.tz(assiduité.date_debut, TIMEZONE),
fin: new moment.tz(assiduité.date_fin, TIMEZONE),
},
assiduité.etudid,
action
);
switch (assiduité.etat) { switch (assiduité.etat) {
case "PRESENT": case "PRESENT":
@ -1773,45 +1802,135 @@ function getCurrentAssiduite(etudid) {
// <<== Gestion de la justification ==>> // <<== Gestion de la justification ==>>
function getJustificatifFromPeriod(date) { function getJustificatifFromPeriod(date, etudid, update) {
let justifs = []; $.ajax({
sync_get( async: true,
type: "GET",
url:
getUrl() + getUrl() +
`/api/justificatifs/${etudid}/query?date_debut=${date.deb.format()}&date_fin=${date.fin.format()}`, `/api/justificatifs/${etudid}/query?date_debut=${date.deb
(data) => { .add(1, "s")
justifs = data; .format()}&date_fin=${date.fin.subtract(1, "s").format()}`,
} success: (data) => {
); update(data);
},
return justifs; error: () => {},
});
} }
function updateJustifieButton(isJustified, isDisabled = true) { function updateJustifyBtn() {
if (isSingleEtud()) {
const assi = getCurrentAssiduite(etudid);
const just = assi ? !assi.est_just : false;
const btn = document.getElementById("justif-rapide"); const btn = document.getElementById("justif-rapide");
if (isJustified) { if (!just) {
btn.classList.add("justifie");
} else {
btn.classList.remove("justifie");
}
if (isDisabled) {
btn.setAttribute("disabled", "true"); btn.setAttribute("disabled", "true");
} else { } else {
btn.removeAttribute("disabled"); btn.removeAttribute("disabled");
} }
} }
}
function fastJustify(assiduite) { function fastJustify(assiduite) {
const period = { const period = {
deb: new moment.tz(assiduite.date_debut, TIMEZONE), deb: new moment.tz(assiduite.date_debut, TIMEZONE),
fin: new moment.tz(assiduite.date_fin, TIMEZONE), fin: new moment.tz(assiduite.date_fin, TIMEZONE),
}; };
const justifs = getJustificatifFromPeriod(period); const action = (justifs) => {
if (justifs.length > 0) { if (justifs.length > 0) {
//modifier l'assiduité justifyAssiduite(assiduite.assiduite_id, !assiduite.est_just);
} else { } else {
console.debug("WIP");
//créer un nouveau justificatif //créer un nouveau justificatif
// Afficher prompt -> demander raison et état // Afficher prompt -> demander raison et état
const success = () => {
const raison = document.getElementById("promptText").value;
const etat = document.getElementById("promptSelect").value;
//créer justificatif
const justif = {
date_debut: new moment.tz(assiduite.date_debut, TIMEZONE)
.add(1, "s")
.format(),
date_fin: new moment.tz(assiduite.date_fin, TIMEZONE)
.subtract(1, "s")
.format(),
raison: raison,
etat: etat,
};
createJustificatif(justif);
// justifyAssiduite(assiduite.assiduite_id, true);
generateAllEtudRow();
};
const content = document.createElement("fieldset");
const htmlPrompt = `<legend>Entrez l'état du justificatif :</legend>
<select name="promptSelect" id="promptSelect" required>
<option value="valide">Valide</option>
<option value="attente">En Attente de validation</option>
<option value="non_valide">Non Valide</option>
<option value="modifie">Modifié</option>
</select>
<legend>Raison:</legend>
<textarea type="text" placeholder="Explication du justificatif (non obligatoire)" id="promptText" style="width:100%;"></textarea>
`;
content.innerHTML = htmlPrompt;
openPromptModal(
"Nouveau justificatif (Rapide)",
content,
success,
() => {},
"#7059FF"
);
} }
};
getJustificatifFromPeriod(period, assiduite.etudid, action);
}
function justifyAssiduite(assiduite_id, justified) {
const assiduite = {
est_just: justified,
};
const path = getUrl() + `/api/assiduite/${assiduite_id}/edit`;
let bool = false;
sync_post(
path,
assiduite,
(data, status) => {
bool = true;
},
(data, status) => {
//error
console.error(data, status);
}
);
return bool;
}
function createJustificatif(justif) {
const path = getUrl() + `/api/justificatif/${etudid}/create`;
sync_post(
path,
[justif],
(data, status) => {
//success
if (data.success.length > 0) {
console.table(data[0]);
}
console.warn(data);
},
(data, status) => {
//error
console.error(data, status);
}
);
} }

View File

@ -29,6 +29,8 @@
</div> </div>
</div> </div>
{% include "assiduites/toast.j2" %} {% include "assiduites/toast.j2" %}
{% include "assiduites/alert.j2" %}
{% include "assiduites/prompt.j2" %}
<div id="page-assiduite-content"> <div id="page-assiduite-content">
{% block content %} {% block content %}
<h2>Signalement de l'assiduité de <span class="rouge">{{sco.etud.nomprenom}}</span></h2> <h2>Signalement de l'assiduité de <span class="rouge">{{sco.etud.nomprenom}}</span></h2>
@ -43,13 +45,13 @@
<div> <div>
{% include "assiduites/moduleimpl_dynamic_selector.j2" %} {% include "assiduites/moduleimpl_dynamic_selector.j2" %}
<button class="btn" onclick="justify()" disabled id="justif-rapide">Justifier</button> <button class="btn" onclick="fastJustify(getCurrentAssiduite(etudid))" id="justif-rapide">Justifier</button>
</div> </div>
<div class="btn_group"> <div class="btn_group">
<button class="btn" onclick="setPeriodValues(8,18)">Journée</button> <button class="btn" onclick="setTimeLineTimes(8,18)">Journée</button>
<button class="btn" onclick="setPeriodValues(8,13)">Matin</button> <button class="btn" onclick="setTimeLineTimes(8,13)">Matin</button>
<button class="btn" onclick="setPeriodValues(13,18)">Après-midi</button> <button class="btn" onclick="setTimeLineTimes(13,18)">Après-midi</button>
</div> </div>
<div class="etud_holder"> <div class="etud_holder">
@ -64,8 +66,7 @@
<div class="loader"></div> <div class="loader"></div>
</div> </div>
{% include "assiduites/alert.j2" %}
{% include "assiduites/prompt.j2" %}
<script> <script>
const etudid = {{ sco.etud.id }}; const etudid = {{ sco.etud.id }};
@ -74,20 +75,29 @@
updateSelect() updateSelect()
}); });
setupTimeLine(() => {
updateJustifyBtn();
});
updateDate(); updateDate();
getSingleEtud({{ sco.etud.id }}); getSingleEtud({{ sco.etud.id }});
actualizeEtud({{ sco.etud.id }}); actualizeEtud({{ sco.etud.id }});
updateSelect() updateSelect()
updateJustifyBtn();
function setTimeLineTimes(a, b) {
setPeriodValues(a, b);
updateJustifyBtn();
}
</script> </script>
<style> <style>
.rouge {
color: crimson;
}
.justifie { .justifie {
background-color: rgb(104, 104, 252); background-color: rgb(104, 104, 252);
color: whitesmoke; color: whitesmoke;

View File

@ -72,5 +72,6 @@
<script> <script>
updateDate(); updateDate();
setupDate(); setupDate();
setupTimeLine();
</script> </script>
</section> </section>

View File

@ -38,6 +38,8 @@
return Math.round(value * 4) / 4; return Math.round(value * 4) / 4;
} }
function setupTimeLine(callback) {
const func_call = callback ? callback : () => { }
timelineContainer.addEventListener("mousedown", (event) => { timelineContainer.addEventListener("mousedown", (event) => {
const startX = event.clientX; const startX = event.clientX;
@ -59,6 +61,7 @@
generateAllEtudRow(); generateAllEtudRow();
snapHandlesToQuarters() snapHandlesToQuarters()
document.removeEventListener("mousemove", onMouseMove); document.removeEventListener("mousemove", onMouseMove);
func_call()
}, },
{ once: true } { once: true }
); );
@ -89,11 +92,15 @@
generateAllEtudRow(); generateAllEtudRow();
document.removeEventListener("mousemove", onMouseMove); document.removeEventListener("mousemove", onMouseMove);
func_call()
}, },
{ once: true } { once: true }
); );
} }
}); });
}
function adjustPeriodPosition(newLeft, newWidth) { function adjustPeriodPosition(newLeft, newWidth) {