Assiduites : legendes, permissions, demissions

This commit is contained in:
iziram 2023-07-25 19:59:47 +02:00
parent fed626c043
commit 1e9796528f
15 changed files with 169 additions and 27 deletions

View File

@ -54,9 +54,12 @@ def sidebar_common():
<h2 class="insidebar">Scolarité</h2> <h2 class="insidebar">Scolarité</h2>
<a href="{scu.ScoURL()}" class="sidebar">Semestres</a> <br> <a href="{scu.ScoURL()}" class="sidebar">Semestres</a> <br>
<a href="{scu.NotesURL()}" class="sidebar">Programmes</a> <br> <a href="{scu.NotesURL()}" class="sidebar">Programmes</a> <br>
<a href="{scu.AssiduitesURL()}" class="sidebar">Assiduités</a> <br>
""" """
] ]
if current_user.has_permission(Permission.ScoAbsChange):
H.append(
f""" <a href="{scu.AssiduitesURL()}" class="sidebar">Assiduités</a> <br> """
)
if current_user.has_permission( if current_user.has_permission(
Permission.ScoUsersAdmin Permission.ScoUsersAdmin
) or current_user.has_permission(Permission.ScoUsersView): ) or current_user.has_permission(Permission.ScoUsersView):

View File

@ -97,7 +97,7 @@
.etud_row { .etud_row {
display: grid; display: grid;
grid-template-columns: auto auto 1fr auto; grid-template-columns: 2% 20% 55% auto;
gap: 16px; gap: 16px;
background-color: white; background-color: white;
border-radius: 15px; border-radius: 15px;
@ -118,6 +118,11 @@
} }
.etud_row.def,
.etud_row.dem {
background-color: #c8c8c8;
}
/* --- Index --- */ /* --- Index --- */
.etud_row .index_field { .etud_row .index_field {
grid-column: 1; grid-column: 1;
@ -127,6 +132,7 @@
.etud_row .name_field { .etud_row .name_field {
grid-column: 2; grid-column: 2;
height: 100%; height: 100%;
justify-content: start;
} }
.etud_row .name_field .name_set { .etud_row .name_field .name_set {
@ -135,6 +141,22 @@
margin: 0 5%; margin: 0 5%;
} }
.etud_row.def .nom::after,
.tr.def .td.sticky span::after {
display: block;
content: " (Déf.)";
color: #d61616;
margin-left: 2px;
}
.etud_row.dem .nom::after,
.tr.dem .td.sticky span::after {
display: block;
content: " (Dém.)";
color: #d61616;
margin-left: 2px;
}
.etud_row .name_field .name_set * { .etud_row .name_field .name_set * {
padding: 0; padding: 0;
margin: 0; margin: 0;
@ -190,24 +212,29 @@
background-color: #ff0000c2; background-color: #ff0000c2;
} }
.etud_row .assiduites_bar .absent { .etud_row .assiduites_bar .absent,
.demo.absent {
background-color: #F1A69C !important; background-color: #F1A69C !important;
} }
.etud_row .assiduites_bar .present { .etud_row .assiduites_bar .present,
.demo.present {
background-color: #9CF1AF !important; background-color: #9CF1AF !important;
} }
.etud_row .assiduites_bar .retard { .etud_row .assiduites_bar .retard,
.demo.retard {
background-color: #F1D99C !important; background-color: #F1D99C !important;
} }
.etud_row .assiduites_bar .justified { .etud_row .assiduites_bar .justified,
.demo.justified {
background-image: repeating-linear-gradient(135deg, transparent, transparent 4px, #7059FF 4px, #7059FF 8px); background-image: repeating-linear-gradient(135deg, transparent, transparent 4px, #7059FF 4px, #7059FF 8px);
} }
.etud_row .assiduites_bar .invalid_justified { .etud_row .assiduites_bar .invalid_justified,
background-image: repeating-linear-gradient(135deg, transparent, transparent 4px, #d61616 4px, #d61616 8px); .demo.invalid_justified {
background-image: repeating-linear-gradient(225deg, transparent, transparent 4px, #d61616 4px, #d61616 8px);
} }
@ -549,4 +576,11 @@
max-width: fit-content; max-width: fit-content;
padding: 5px; padding: 5px;
color: white; color: white;
}
.demo {
width: 23px;
height: 13px;
display: inline-block;
border: solid 1px #333;
} }

View File

@ -297,6 +297,7 @@ function executeMassActionQueue() {
(data, status) => { (data, status) => {
//error //error
console.error(data, status); console.error(data, status);
errorAlert();
} }
); );
return createQueue.length; return createQueue.length;
@ -320,6 +321,7 @@ function executeMassActionQueue() {
(data, status) => { (data, status) => {
//error //error
console.error(data, status); console.error(data, status);
errorAlert();
} }
); );
return editQueue.length; return editQueue.length;
@ -337,6 +339,7 @@ function executeMassActionQueue() {
(data, status) => { (data, status) => {
//error //error
console.error(data, status); console.error(data, status);
errorAlert();
} }
); );
return toDelete.length; return toDelete.length;
@ -859,6 +862,7 @@ function createAssiduite(etat, etudid) {
(data, status) => { (data, status) => {
//error //error
console.error(data, status); console.error(data, status);
errorAlert();
} }
); );
} }
@ -882,6 +886,7 @@ function deleteAssiduite(assiduite_id) {
(data, status) => { (data, status) => {
//error //error
console.error(data, status); console.error(data, status);
errorAlert();
} }
); );
} }
@ -911,6 +916,7 @@ function editAssiduite(assiduite_id, etat) {
(data, status) => { (data, status) => {
//error //error
console.error(data, status); console.error(data, status);
errorAlert();
} }
); );
@ -1159,14 +1165,25 @@ function generateEtudRow(
let assi = ""; let assi = "";
["present", "retard", "absent"].forEach((abs) => { ["present", "retard", "absent"].forEach((abs) => {
if (abs.toLowerCase() === assiduite.etatAssiduite.toLowerCase()) { if (abs.toLowerCase() === assiduite.etatAssiduite.toLowerCase()) {
assi += `<input checked type="checkbox" value="${abs}" name="btn_assiduites_${index}" id="rbtn_${abs}" class="rbtn ${abs}">`; assi += `<input checked type="checkbox" value="${abs}" name="btn_assiduites_${index}" id="rbtn_${abs}" class="rbtn ${abs}" title="${abs}">`;
} else { } else {
assi += `<input type="checkbox" value="${abs}" name="btn_assiduites_${index}" id="rbtn_${abs}" class="rbtn ${abs}">`; assi += `<input type="checkbox" value="${abs}" name="btn_assiduites_${index}" id="rbtn_${abs}" class="rbtn ${abs}" title="${abs}">`;
} }
}); });
const conflit = assiduite.type == "conflit" ? "conflit" : ""; const conflit = assiduite.type == "conflit" ? "conflit" : "";
const pdp_url = `${getUrl()}/api/etudiant/etudid/${etud.id}/photo?size=small`; const pdp_url = `${getUrl()}/api/etudiant/etudid/${etud.id}/photo?size=small`;
const HTML = `<div class="etud_row ${conflit}" id="etud_row_${etud.id}">
let defdem = "";
try {
if (etud.id in etudsDefDem) {
defdem = etudsDefDem[etud.id] == "D" ? "dem" : "def";
}
} catch (_) {}
const HTML = `<div class="etud_row ${conflit} ${defdem}" id="etud_row_${
etud.id
}">
<div class="index">${index}</div> <div class="index">${index}</div>
<div class="name_field"> <div class="name_field">
@ -1539,6 +1556,7 @@ function justifyAssiduite(assiduite_id, justified) {
(data, status) => { (data, status) => {
//error //error
console.error(data, status); console.error(data, status);
errorAlert();
} }
); );
@ -1550,6 +1568,7 @@ function createJustificatif(justif, success = () => {}) {
sync_post(path, [justif], success, (data, status) => { sync_post(path, [justif], success, (data, status) => {
//error //error
console.error(data, status); console.error(data, status);
errorAlert();
}); });
} }
@ -1581,6 +1600,20 @@ function deleteJustificatif(justif_id) {
(data, status) => { (data, status) => {
//error //error
console.error(data, status); console.error(data, status);
errorAlert();
} }
); );
} }
function errorAlert() {
const html = `
<h3>Avez vous les droits suffisant pour cette action ?</h3>
<p>Si c'est bien le cas : veuillez de l'aide sur le canal Assistance de ScoDoc</p>
<br>
<p><i>pour les développeurs : l'erreur est affichée dans la console JS</i></p>
`;
const div = document.createElement("div");
div.innerHTML = html;
openAlertModal("Une erreur s'est déclanchée", div);
}

View File

@ -189,6 +189,7 @@
createJustificatif(justificatif, (data) => { createJustificatif(justificatif, (data) => {
if (Object.keys(data.errors).length > 0) { if (Object.keys(data.errors).length > 0) {
console.error(data.errors); console.error(data.errors);
errorAlert();
} }
if (Object.keys(data.success).length > 0) { if (Object.keys(data.success).length > 0) {
couverture = data.success[0].couverture couverture = data.success[0].couverture

View File

@ -44,6 +44,7 @@
}, },
(data, status) => { (data, status) => {
console.error(data, status) console.error(data, status)
errorAlert();
} }
) )
} }

View File

@ -227,6 +227,7 @@
(data, status) => { (data, status) => {
//error //error
console.error(data, status); console.error(data, status);
errorAlert();
} }
); );
} }
@ -245,6 +246,7 @@
(data, status) => { (data, status) => {
//error //error
console.error(data, status); console.error(data, status);
errorAlert();
} }
); );
} }

View File

@ -17,6 +17,21 @@
{{diff | safe}} {{diff | safe}}
<script>
const etudsDefDem = {{ defdem | safe }}
window.addEventListener('load', () => {
[...document.querySelectorAll('.tr[etudid]')].forEach((a) => {
try {
if (a.getAttribute("etudid") in etudsDefDem) {
defdem = etudsDefDem[a.getAttribute("etudid")] == "D" ? "dem" : "def";
a.classList.add(defdem);
}
} catch (_) { }
})
})
</script>
{% include "assiduites/widgets/alert.j2" %} {% include "assiduites/widgets/alert.j2" %}

View File

@ -47,11 +47,16 @@
Correspondance des couleurs : Correspondance des couleurs :
</p> </p>
<ul> <ul>
<li>Vert -> présence de l'étudiant lors de la période</li> <li><span title="Vert" class="present demo"></span> &rightarrow; présence de l'étudiant lors de la période
<li>Orange -> retard de l'étudiant lors de la période</li> </li>
<li>Rouge -> absence de l'étudiant lors de la période</li> <li><span title="Orange" class="retard demo"></span> &rightarrow; retard de l'étudiant lors de la période
<li>Hachure Bleu -> l'assiduité est justifiée par un justificatif valide</li> </li>
<li>Hachure Rouge -> l'assiduité est justifiée par un justificatif non valide / en attente de validation <li><span title="Rouge" class="absent demo"></span> &rightarrow; absence de l'étudiant lors de la période
</li>
<li><span title="Hachure Bleue" class="justified demo"></span> &rightarrow; l'assiduité est justifiée par un
justificatif valide</li>
<li><span title="Hachure Rouge" class="invalid_justified demo"></span> &rightarrow; l'assiduité est
justifiée par un justificatif non valide / en attente de validation
</li> </li>
</ul> </ul>
<p>Vous pouvez justifier rapidement une assiduité en saisisant l'assiduité puis en appuyant sur "Justifier"</p> <p>Vous pouvez justifier rapidement une assiduité en saisisant l'assiduité puis en appuyant sur "Justifier"</p>

View File

@ -49,11 +49,16 @@
Correspondance des couleurs : Correspondance des couleurs :
</p> </p>
<ul> <ul>
<li>Vert -> présence de l'étudiant lors de la période</li> <li><span title="Vert" class="present demo"></span> &rightarrow; présence de l'étudiant lors de la période
<li>Orange -> retard de l'étudiant lors de la période</li> </li>
<li>Rouge -> absence de l'étudiant lors de la période</li> <li><span title="Orange" class="retard demo"></span> &rightarrow; retard de l'étudiant lors de la période
<li>Hachure Bleu -> l'assiduité est justifiée par un justificatif valide</li> </li>
<li>Hachure Rouge -> l'assiduité est justifiée par un justificatif non valide / en attente de validation <li><span title="Rouge" class="absent demo"></span> &rightarrow; absence de l'étudiant lors de la période
</li>
<li><span title="Hachure Bleue" class="justified demo"></span> &rightarrow; l'assiduité est justifiée par un
justificatif valide</li>
<li><span title="Hachure Rouge" class="invalid_justified demo"></span> &rightarrow; l'assiduité est
justifiée par un justificatif non valide / en attente de validation
</li> </li>
</ul> </ul>
</div> </div>
@ -77,6 +82,8 @@
window.forceModule = "{{ forcer_module }}" window.forceModule = "{{ forcer_module }}"
window.forceModule = window.forceModule == "True" ? true : false window.forceModule = window.forceModule == "True" ? true : false
const etudsDefDem = {{ defdem | safe }}
if (window.forceModule) { if (window.forceModule) {
const btn = document.getElementById("validate_selectors"); const btn = document.getElementById("validate_selectors");

View File

@ -295,6 +295,7 @@
(data, status) => { (data, status) => {
//error //error
console.error(data, status); console.error(data, status);
errorAlert();
} }
); );
@ -378,7 +379,7 @@
//Placement de la période conflictuelle sur la timeline //Placement de la période conflictuelle sur la timeline
const specialAssiduiteEl = document.querySelector(".assiduite-special"); const specialAssiduiteEl = document.querySelector(".assiduite-special");
console.error("special")
specialAssiduiteEl.style.width = getWidth( specialAssiduiteEl.style.width = getWidth(
this.conflictPeriod.deb, this.conflictPeriod.deb,
this.conflictPeriod.fin this.conflictPeriod.fin
@ -387,8 +388,8 @@
specialAssiduiteEl.style.top = "0"; specialAssiduiteEl.style.top = "0";
specialAssiduiteEl.style.zIndex = "0"; // Place l'assiduité spéciale en arrière-plan specialAssiduiteEl.style.zIndex = "0"; // Place l'assiduité spéciale en arrière-plan
assiduitesContainer.appendChild(specialAssiduiteEl); assiduitesContainer.appendChild(specialAssiduiteEl);
console.error(this.conflictPeriod)
console.error(specialAssiduiteEl)
//Placement des assiduités sur la timeline //Placement des assiduités sur la timeline
this.list.forEach((assiduite) => { this.list.forEach((assiduite) => {
@ -402,7 +403,7 @@
const el = document.createElement("div"); const el = document.createElement("div");
el.className = "assiduite"; el.className = "assiduite";
el.style.backgroundColor = getColor(assiduite.etat); el.style.backgroundColor = getColor(assiduite.etat);
console.error("normal")
el.style.width = getWidth(assiduite.date_debut, assiduite.date_fin); el.style.width = getWidth(assiduite.date_debut, assiduite.date_fin);
el.style.left = getLeftPosition(assiduite.date_debut); el.style.left = getLeftPosition(assiduite.date_debut);

View File

@ -774,6 +774,7 @@
(data, status) => { (data, status) => {
//error //error
console.error(data, status); console.error(data, status);
errorAlert();
} }
); );
} }
@ -787,6 +788,7 @@
(data, status) => { (data, status) => {
//error //error
console.error(data, status); console.error(data, status);
errorAlert();
} }
); );
} }
@ -800,6 +802,7 @@
(data, status) => { (data, status) => {
//error //error
console.error(data, status); console.error(data, status);
errorAlert();
} }
); );
} }
@ -813,6 +816,7 @@
(data, status) => { (data, status) => {
//error //error
console.error(data, status); console.error(data, status);
errorAlert();
} }
); );
} }
@ -825,6 +829,7 @@
callback, callback,
(data, status) => { (data, status) => {
console.error(data, status); console.error(data, status);
errorAlert();
} }
); );
} }
@ -838,6 +843,7 @@
(data, status) => { (data, status) => {
//error //error
console.error(data, status); console.error(data, status);
errorAlert();
} }
); );
} }

View File

@ -276,6 +276,7 @@
(data, status) => { (data, status) => {
//error //error
console.error(data, status); console.error(data, status);
errorAlert();
} }
); );
} }

View File

@ -401,6 +401,7 @@
(data, status) => { (data, status) => {
//error //error
console.error(data, status); console.error(data, status);
errorAlert();
} }
); );
} }

View File

@ -24,8 +24,10 @@
<h2 class="insidebar">Scolarité</h2> <h2 class="insidebar">Scolarité</h2>
<a href="{{url_for('scolar.index_html', scodoc_dept=g.scodoc_dept)}}" class="sidebar">Semestres</a> <br> <a href="{{url_for('scolar.index_html', scodoc_dept=g.scodoc_dept)}}" class="sidebar">Semestres</a> <br>
<a href="{{url_for('notes.index_html', scodoc_dept=g.scodoc_dept)}}" class="sidebar">Programmes</a> <br> <a href="{{url_for('notes.index_html', scodoc_dept=g.scodoc_dept)}}" class="sidebar">Programmes</a> <br>
<a href="{{url_for('assiduites.index_html', scodoc_dept=g.scodoc_dept)}}" class="sidebar">Assiduités</a> <br>
{% if current_user.has_permission(sco.Permission.ScoAbsChange)%}
<a href="{{url_for('assiduites.index_html', scodoc_dept=g.scodoc_dept)}}" class="sidebar">Assiduités</a> <br>
{% endif %}
{% if current_user.has_permission(sco.Permission.ScoUsersAdmin) {% if current_user.has_permission(sco.Permission.ScoUsersAdmin)
or current_user.has_permission(sco.Permission.ScoUsersView) or current_user.has_permission(sco.Permission.ScoUsersView)
%} %}

View File

@ -10,7 +10,14 @@ from app.decorators import (
scodoc, scodoc,
permission_required, permission_required,
) )
from app.models import FormSemestre, Identite, ScoDocSiteConfig, Assiduite, Departement from app.models import (
FormSemestre,
Identite,
ScoDocSiteConfig,
Assiduite,
Departement,
FormSemestreInscription,
)
from app.views import assiduites_bp as bp from app.views import assiduites_bp as bp
from app.views import ScoData from app.views import ScoData
@ -563,6 +570,7 @@ def signal_assiduites_group():
formsemestre_id=formsemestre_id, formsemestre_id=formsemestre_id,
dept_id=g.scodoc_dept_id, dept_id=g.scodoc_dept_id,
), ),
defdem=_get_etuds_dem_def(formsemestre),
), ),
html_sco_header.sco_footer(), html_sco_header.sco_footer(),
).build() ).build()
@ -793,6 +801,7 @@ def signal_assiduites_diff():
), ),
gr=gr_tit, gr=gr_tit,
sem=sem["titre_num"], sem=sem["titre_num"],
defdem=_get_etuds_dem_def(formsemestre),
), ),
html_sco_header.sco_footer(), html_sco_header.sco_footer(),
).build() ).build()
@ -907,3 +916,24 @@ def get_time(label: str, default: str):
def _get_seuil(): def _get_seuil():
return sco_preferences.get_preference("assi_seuil", dept_id=g.scodoc_dept_id) return sco_preferences.get_preference("assi_seuil", dept_id=g.scodoc_dept_id)
def _get_etuds_dem_def(formsemestre):
etuds_dem_def = [
(f.etudid, f.etat)
for f in FormSemestreInscription.query.filter(
FormSemestreInscription.formsemestre_id == formsemestre.id,
FormSemestreInscription.etat != "I",
).all()
]
template: str = '"£" : "$",'
json_str: str = "{"
for etud in etuds_dem_def:
json_str += template.replace("£", str(etud[0])).replace("$", etud[1])
json_str = json_str[:-1] + "}"
return json_str