forked from ScoDoc/ScoDoc
Update opolka/ScoDoc from ScoDoc/ScoDoc #2
@ -587,16 +587,6 @@ def _create_singular(
|
||||
if fin is None:
|
||||
errors.append("param 'date_fin': format invalide")
|
||||
|
||||
# cas 4 : moduleimpl_id
|
||||
|
||||
moduleimpl_id = data.get("moduleimpl_id", False)
|
||||
moduleimpl: ModuleImpl = None
|
||||
|
||||
if moduleimpl_id not in [False, None]:
|
||||
moduleimpl = ModuleImpl.query.filter_by(id=int(moduleimpl_id)).first()
|
||||
if moduleimpl is None:
|
||||
errors.append("param 'moduleimpl_id': invalide")
|
||||
|
||||
# cas 5 : desc
|
||||
|
||||
desc: str = data.get("desc", None)
|
||||
@ -606,6 +596,21 @@ def _create_singular(
|
||||
if not isinstance(external_data, dict):
|
||||
errors.append("param 'external_data' : n'est pas un objet JSON")
|
||||
|
||||
# cas 4 : moduleimpl_id
|
||||
|
||||
moduleimpl_id = data.get("moduleimpl_id", False)
|
||||
moduleimpl: ModuleImpl = None
|
||||
|
||||
if moduleimpl_id not in [False, None]:
|
||||
if moduleimpl_id != "autre":
|
||||
moduleimpl = ModuleImpl.query.filter_by(id=int(moduleimpl_id)).first()
|
||||
if moduleimpl is None:
|
||||
errors.append("param 'moduleimpl_id': invalide")
|
||||
else:
|
||||
moduleimpl_id = None
|
||||
external_data = external_data if external_data is not None else {}
|
||||
external_data["module"] = "Autre"
|
||||
|
||||
if errors:
|
||||
err: str = ", ".join(errors)
|
||||
return (404, err)
|
||||
@ -709,58 +714,10 @@ def assiduite_edit(assiduite_id: int):
|
||||
errors: list[str] = []
|
||||
data = request.get_json(force=True)
|
||||
|
||||
# Vérifications de data
|
||||
code, obj = _edit_singular(assiduite_unique, data)
|
||||
|
||||
# Cas 1 : Etat
|
||||
if data.get("etat") is not None:
|
||||
etat = scu.EtatAssiduite.get(data.get("etat"))
|
||||
if etat is None:
|
||||
errors.append("param 'etat': invalide")
|
||||
else:
|
||||
assiduite_unique.etat = etat
|
||||
|
||||
# Cas 2 : Moduleimpl_id
|
||||
moduleimpl_id = data.get("moduleimpl_id", False)
|
||||
moduleimpl: ModuleImpl = None
|
||||
|
||||
if moduleimpl_id is not False:
|
||||
if moduleimpl_id is not None and moduleimpl_id != "":
|
||||
moduleimpl = ModuleImpl.query.filter_by(id=int(moduleimpl_id)).first()
|
||||
if moduleimpl is None:
|
||||
errors.append("param 'moduleimpl_id': invalide")
|
||||
else:
|
||||
if not moduleimpl.est_inscrit(
|
||||
Identite.query.filter_by(id=assiduite_unique.etudid).first()
|
||||
):
|
||||
errors.append("param 'moduleimpl_id': etud non inscrit")
|
||||
else:
|
||||
assiduite_unique.moduleimpl_id = moduleimpl_id
|
||||
else:
|
||||
assiduite_unique.moduleimpl_id = None
|
||||
|
||||
# Cas 3 : desc
|
||||
desc = data.get("desc", False)
|
||||
if desc is not False:
|
||||
assiduite_unique.description = desc
|
||||
|
||||
# Cas 4 : est_just
|
||||
est_just = data.get("est_just")
|
||||
if est_just is not None:
|
||||
if not isinstance(est_just, bool):
|
||||
errors.append("param 'est_just' : booléen non reconnu")
|
||||
else:
|
||||
assiduite_unique.est_just = est_just
|
||||
|
||||
external_data = data.get("external_data")
|
||||
if external_data is not None:
|
||||
if not isinstance(external_data, dict):
|
||||
errors.append("param 'external_data' : n'est pas un objet JSON")
|
||||
else:
|
||||
assiduite_unique.external_data = external_data
|
||||
|
||||
if errors:
|
||||
err: str = ", ".join(errors)
|
||||
return json_error(404, err)
|
||||
if code == 404:
|
||||
return json_error(404, obj)
|
||||
|
||||
log(f"assiduite_edit: {assiduite_unique.etudiant.id} {assiduite_unique}")
|
||||
Scolog.logdb(
|
||||
@ -841,12 +798,31 @@ def _edit_singular(assiduite_unique, data):
|
||||
else:
|
||||
assiduite_unique.etat = etat
|
||||
|
||||
external_data = data.get("external_data")
|
||||
if external_data is not None:
|
||||
if not isinstance(external_data, dict):
|
||||
errors.append("param 'external_data' : n'est pas un objet JSON")
|
||||
else:
|
||||
assiduite_unique.external_data = external_data
|
||||
|
||||
# Cas 2 : Moduleimpl_id
|
||||
moduleimpl_id = data.get("moduleimpl_id", False)
|
||||
moduleimpl: ModuleImpl = None
|
||||
|
||||
if moduleimpl_id is not False:
|
||||
if moduleimpl_id is not None:
|
||||
if moduleimpl_id == "autre":
|
||||
assiduite_unique.moduleimpl_id = None
|
||||
external_data = (
|
||||
external_data
|
||||
if external_data is not None and isinstance(external_data, dict)
|
||||
else assiduite_unique.external_data
|
||||
)
|
||||
external_data = external_data if external_data is not None else {}
|
||||
external_data["module"] = "Autre"
|
||||
assiduite_unique.external_data = external_data
|
||||
|
||||
else:
|
||||
moduleimpl = ModuleImpl.query.filter_by(id=int(moduleimpl_id)).first()
|
||||
if moduleimpl is None:
|
||||
errors.append("param 'moduleimpl_id': invalide")
|
||||
@ -946,8 +922,8 @@ def _count_manager(requested) -> tuple[str, dict]:
|
||||
|
||||
est_just: str = requested.args.get("est_just")
|
||||
if est_just is not None:
|
||||
trues: tuple[str] = ("v", "t", "vrai", "true")
|
||||
falses: tuple[str] = ("f", "faux", "false")
|
||||
trues: tuple[str] = ("v", "t", "vrai", "true", "1")
|
||||
falses: tuple[str] = ("f", "faux", "false", "0")
|
||||
|
||||
if est_just.lower() in trues:
|
||||
filtered["est_just"] = True
|
||||
@ -960,6 +936,12 @@ def _count_manager(requested) -> tuple[str, dict]:
|
||||
if user_id is not False:
|
||||
filtered["user_id"] = user_id
|
||||
|
||||
# cas 9 : split
|
||||
|
||||
split = requested.args.get("split", False)
|
||||
if split is not False:
|
||||
filtered["split"] = True
|
||||
|
||||
return (metric, filtered)
|
||||
|
||||
|
||||
@ -1015,8 +997,8 @@ def _filter_manager(requested, assiduites_query: Query) -> Query:
|
||||
|
||||
est_just: str = requested.args.get("est_just")
|
||||
if est_just is not None:
|
||||
trues: tuple[str] = ("v", "t", "vrai", "true")
|
||||
falses: tuple[str] = ("f", "faux", "false")
|
||||
trues: tuple[str] = ("v", "t", "vrai", "true", "1")
|
||||
falses: tuple[str] = ("f", "faux", "false", "0")
|
||||
|
||||
if est_just.lower() in trues:
|
||||
assiduites_query: Query = scass.filter_assiduites_by_est_just(
|
||||
|
@ -152,7 +152,6 @@ class CountCalculator:
|
||||
delta: timedelta = assi.date_fin - assi.date_debut
|
||||
|
||||
if delta.days > 0:
|
||||
# raise Exception(self.hours)
|
||||
self.compute_long_assiduite(assi)
|
||||
|
||||
continue
|
||||
@ -186,38 +185,79 @@ def get_assiduites_stats(
|
||||
if filtered is not None:
|
||||
deb, fin = None, None
|
||||
for key in filtered:
|
||||
if key == "etat":
|
||||
match key:
|
||||
case "etat":
|
||||
assiduites = filter_assiduites_by_etat(assiduites, filtered[key])
|
||||
elif key == "date_fin":
|
||||
case "date_fin":
|
||||
fin = filtered[key]
|
||||
elif key == "date_debut":
|
||||
case "date_debut":
|
||||
deb = filtered[key]
|
||||
elif key == "moduleimpl_id":
|
||||
case "moduleimpl_id":
|
||||
assiduites = filter_by_module_impl(assiduites, filtered[key])
|
||||
elif key == "formsemestre":
|
||||
case "formsemestre":
|
||||
assiduites = filter_by_formsemestre(
|
||||
assiduites, Assiduite, filtered[key]
|
||||
)
|
||||
elif key == "est_just":
|
||||
assiduites = filter_assiduites_by_est_just(assiduites, filtered[key])
|
||||
elif key == "user_id":
|
||||
case "est_just":
|
||||
assiduites = filter_assiduites_by_est_just(
|
||||
assiduites, filtered[key]
|
||||
)
|
||||
case "user_id":
|
||||
assiduites = filter_by_user_id(assiduites, filtered[key])
|
||||
|
||||
if (deb, fin) != (None, None):
|
||||
assiduites = filter_by_date(assiduites, Assiduite, deb, fin)
|
||||
|
||||
metrics: list[str] = metric.split(",")
|
||||
output: dict = {}
|
||||
calculator: CountCalculator = CountCalculator()
|
||||
|
||||
if "split" not in filtered:
|
||||
calculator.compute_assiduites(assiduites)
|
||||
count: dict = calculator.to_dict()
|
||||
|
||||
metrics: list[str] = metric.split(",")
|
||||
|
||||
output: dict = {}
|
||||
|
||||
for key, val in count.items():
|
||||
if key in metrics:
|
||||
output[key] = val
|
||||
return output if output else count
|
||||
|
||||
etats: list[str] = (
|
||||
filtered["etat"].split(",")
|
||||
if "etat" in filtered
|
||||
else ["absent", "present", "retard"]
|
||||
)
|
||||
|
||||
for etat in etats:
|
||||
output[etat] = _count_assiduites_etat(etat, assiduites, calculator, metrics)
|
||||
if "est_just" not in filtered:
|
||||
output[etat]["justifie"] = _count_assiduites_etat(
|
||||
etat, assiduites, calculator, metrics, justifie=True
|
||||
)
|
||||
|
||||
return output
|
||||
|
||||
|
||||
def _count_assiduites_etat(
|
||||
etat: str,
|
||||
assiduites: Query,
|
||||
calculator: CountCalculator,
|
||||
metrics: list[str],
|
||||
justifie: bool = False,
|
||||
):
|
||||
calculator.reset()
|
||||
etat_num: int = scu.EtatAssiduite.get(etat, -1)
|
||||
assiduites_etat: Query = assiduites.filter(Assiduite.etat == etat_num)
|
||||
if justifie:
|
||||
assiduites_etat = assiduites_etat.filter(Assiduite.est_just == True)
|
||||
|
||||
calculator.compute_assiduites(assiduites_etat)
|
||||
count_etat: dict = calculator.to_dict()
|
||||
output_etat: dict = {}
|
||||
for key, val in count_etat.items():
|
||||
if key in metrics:
|
||||
output_etat[key] = val
|
||||
return output_etat if output_etat else count_etat
|
||||
|
||||
|
||||
def filter_assiduites_by_etat(assiduites: Assiduite, etat: str) -> Query:
|
||||
"""
|
||||
@ -232,7 +272,7 @@ def filter_assiduites_by_est_just(assiduites: Assiduite, est_just: bool) -> Quer
|
||||
"""
|
||||
Filtrage d'une collection d'assiduites en fonction de s'ils sont justifiés
|
||||
"""
|
||||
return assiduites.filter_by(est_just=est_just)
|
||||
return assiduites.filter(Assiduite.est_just == est_just)
|
||||
|
||||
|
||||
def filter_by_user_id(
|
||||
|
@ -314,16 +314,13 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
|
||||
authuser = self.authuser
|
||||
H = []
|
||||
# --- Absences
|
||||
# XXX TODO-ASSIDUITE
|
||||
# au passage, utiliser url_for...
|
||||
H.append(
|
||||
"""<p>
|
||||
XXX <a href="../Absences/CalAbs?etudid=%(etudid)s" class="bull_link">
|
||||
<b>Absences :</b> %(nbabs)s demi-journées, dont %(nbabsjust)s justifiées
|
||||
f"""<p>
|
||||
<a href="{ url_for('assiduites.calendrier_etud', scodoc_dept=g.scodoc_dept, etudid=I["etudid"]) }" class="bull_link">
|
||||
<b>Absences :</b>{I['nbabs']} demi-journées, dont {I['nbabsjust']} justifiées
|
||||
(pendant ce semestre).
|
||||
</a></p>
|
||||
"""
|
||||
% I
|
||||
)
|
||||
# --- Decision Jury
|
||||
if I["situation"]:
|
||||
|
@ -132,17 +132,13 @@ class BulletinGeneratorStandard(sco_bulletins_generator.BulletinGenerator):
|
||||
nbabs = self.infos["nbabs"]
|
||||
story.append(Spacer(1, 2 * mm))
|
||||
if nbabs:
|
||||
# XXX TODO-ASSIDUITE
|
||||
# et utiliser url_for...
|
||||
H.append(
|
||||
"""<p class="bul_abs">
|
||||
<a href="../Absences/CalAbs?etudid=%(etudid)s" class="bull_link">
|
||||
XXX
|
||||
<b>Absences :</b> %(nbabs)s demi-journées, dont %(nbabsjust)s justifiées
|
||||
f"""<p class="bul_abs">
|
||||
<a href="{ url_for('assiduites.calendrier_etud', scodoc_dept=g.scodoc_dept, etudid=self.infos["etudid"]) }" class="bull_link">
|
||||
<b>Absences :</b> {self.infos['nbabs']} demi-journées, dont {self.infos['nbabsjust']} justifiées
|
||||
(pendant ce semestre).
|
||||
</a></p>
|
||||
"""
|
||||
% self.infos
|
||||
)
|
||||
story.append(
|
||||
Paragraph(
|
||||
|
@ -881,14 +881,13 @@ def _make_listes_sem(formsemestre: FormSemestre, with_absences=True):
|
||||
if n_members == 0:
|
||||
continue # skip empty groups
|
||||
partition_is_empty = False
|
||||
# XXX TODO-ASSIDUITE
|
||||
group["url_etat"] = "non disponible" # url_for(
|
||||
# "absences.EtatAbsencesGr",
|
||||
# group_ids=group["group_id"],
|
||||
# debut=formsemestre.date_debut.strftime("%d/%m/%Y"),
|
||||
# fin=formsemestre.date_fin.strftime("%d/%m/%Y"),
|
||||
# scodoc_dept=g.scodoc_dept,
|
||||
# )
|
||||
group["url_etat"] = url_for(
|
||||
"assiduites.visu_assi_group",
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
group_ids=group["id"],
|
||||
date_debut=formsemestre.date_debut.isoformat(),
|
||||
date_fin=formsemestre.date_fin.isoformat(),
|
||||
)
|
||||
if group["group_name"]:
|
||||
group["label"] = "groupe %(group_name)s" % group
|
||||
else:
|
||||
|
@ -819,9 +819,13 @@ def tab_absences_html(groups_infos, etat=None):
|
||||
H = ['<div class="tab-content">']
|
||||
if not groups_infos.members:
|
||||
return "".join(H) + "<h3>Aucun étudiant !</h3></div>"
|
||||
|
||||
group_ids: str = ",".join(map(str, groups_infos.group_ids))
|
||||
formsemestre: FormSemestre = groups_infos.get_formsemestre()
|
||||
|
||||
H.extend(
|
||||
[
|
||||
"<h3>Absences</h3>",
|
||||
"<h3>Assiduités</h3>",
|
||||
'<ul class="ul_abs">',
|
||||
"<li>",
|
||||
form_choix_saisie_semaine(groups_infos), # Ajout Le Havre
|
||||
@ -829,13 +833,9 @@ def tab_absences_html(groups_infos, etat=None):
|
||||
"<li>",
|
||||
form_choix_jour_saisie_hebdo(groups_infos),
|
||||
"</li>",
|
||||
# XXX TODO-ASSIDUITE
|
||||
"""<li><a class="stdlink" href="Absences/EtatAbsencesGr?%s&debut=%s&fin=%s">XXX État des absences du groupe</a></li>"""
|
||||
% (
|
||||
groups_infos.groups_query_args,
|
||||
groups_infos.formsemestre["date_debut"],
|
||||
groups_infos.formsemestre["date_fin"],
|
||||
),
|
||||
f"""<li><a href="{
|
||||
url_for("assiduites.visu_assi_group", scodoc_dept=g.scodoc_dept, group_ids=group_ids, date_debut=formsemestre.date_debut.isoformat(), date_fin=formsemestre.date_fin.isoformat())
|
||||
}">État des assiduités du groupe</a></li>""",
|
||||
"</ul>",
|
||||
"<h3>Feuilles</h3>",
|
||||
'<ul class="ul_feuilles">',
|
||||
|
@ -29,6 +29,7 @@
|
||||
"""
|
||||
import math
|
||||
import time
|
||||
import datetime
|
||||
|
||||
from flask import g, url_for
|
||||
from flask_login import current_user
|
||||
@ -332,20 +333,19 @@ def moduleimpl_status(moduleimpl_id=None, partition_id=None):
|
||||
current_user.has_permission(Permission.ScoAbsChange)
|
||||
and formsemestre.est_courant()
|
||||
):
|
||||
datelundi = sco_cal.ddmmyyyy(time.strftime("%d/%m/%Y")).prev_monday()
|
||||
group_id = sco_groups.get_default_group(formsemestre_id)
|
||||
H.append(
|
||||
f"""
|
||||
<span class="moduleimpl_abs_link"><a class="stdlink" href="XXX"
|
||||
>Saisie Absences hebdo. (INDISPONIBLE)</a></span>
|
||||
<span class="moduleimpl_abs_link"><a class="stdlink" href="{
|
||||
url_for("assiduites.signal_assiduites_group", scodoc_dept=g.scodoc_dept)
|
||||
}?group_ids={group_id}&jour={
|
||||
datetime.date.today().isoformat()
|
||||
}&formsemestre_id={formsemestre.id}
|
||||
&moduleimpl_id={moduleimpl_id}
|
||||
"
|
||||
>Saisie Absences hebdo</a></span>
|
||||
"""
|
||||
)
|
||||
# TODO-ASSIDUITE
|
||||
# href="{
|
||||
# url_for("absences.SignaleAbsenceGrHebdo",
|
||||
# scodoc_dept=g.scodoc_dept,formsemestre_id=formsemestre_id,
|
||||
# moduleimpl_id=moduleimpl_id, datelundi=datelundi, group_ids=group_id)
|
||||
# }"
|
||||
|
||||
H.append("</td></tr></table>")
|
||||
#
|
||||
|
@ -1,5 +1,5 @@
|
||||
{% include "assiduites/widgets/toast.j2" %}
|
||||
{% block pageContent %}
|
||||
|
||||
<div class="pageContent">
|
||||
<h3>Justifier des assiduités</h3>
|
||||
{% include "assiduites/widgets/tableau_base.j2" %}
|
||||
@ -12,7 +12,7 @@
|
||||
|
||||
<fieldset>
|
||||
<div class="justi-row">
|
||||
<button onclick="validerFormulaire()">Créer le justificatif</button>
|
||||
<button onclick="validerFormulaire(this)">Créer le justificatif</button>
|
||||
<button onclick="effacerFormulaire()">Remettre à zero</button>
|
||||
</div>
|
||||
<div class="justi-row">
|
||||
@ -153,6 +153,7 @@
|
||||
|
||||
const requests = []
|
||||
Array.from(in_files.files).forEach((f) => {
|
||||
pushToast(generateToast(document.createTextNode(`Importation du fichier : ${f.name} commencée`), color = "#f0c865"));
|
||||
const fd = new FormData();
|
||||
fd.append('file', f);
|
||||
requests.push(
|
||||
@ -164,22 +165,22 @@
|
||||
dateType: 'json',
|
||||
contentType: false,
|
||||
processData: false,
|
||||
success: () => { console.log("done") },
|
||||
success: () => {
|
||||
pushToast(generateToast(document.createTextNode(`Importation du fichier : ${f.name} finie`)));
|
||||
loadAll();
|
||||
},
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
});
|
||||
|
||||
$.when(
|
||||
requests
|
||||
).done(() => {
|
||||
if (in_files.files.length == 0) {
|
||||
loadAll();
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function validerFormulaire() {
|
||||
function validerFormulaire(btn) {
|
||||
if (!validateFields()) return
|
||||
|
||||
const justificatif = fieldsToJustificatif();
|
||||
@ -198,6 +199,12 @@
|
||||
return;
|
||||
}
|
||||
})
|
||||
|
||||
btn.disabled = true;
|
||||
setTimeout(() => {
|
||||
btn.disabled = false;
|
||||
}, 1000)
|
||||
|
||||
}
|
||||
|
||||
function effacerFormulaire() {
|
||||
|
@ -20,6 +20,14 @@
|
||||
<script>
|
||||
const etudsDefDem = {{ defdem | safe }}
|
||||
|
||||
const timeMorning = "{{ timeMorning | safe}}";
|
||||
const timeNoon = "{{ timeNoon | safe}}";
|
||||
const timeEvening = "{{ timeEvening | safe}}";
|
||||
|
||||
const defaultDates = {{ defaultDates | safe }}
|
||||
const nonWorkDays = [{{ nonworkdays| safe }}];
|
||||
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
[...document.querySelectorAll('.tr[etudid]')].forEach((a) => {
|
||||
try {
|
||||
@ -28,8 +36,33 @@
|
||||
a.classList.add(defdem);
|
||||
}
|
||||
} catch (_) { }
|
||||
});
|
||||
|
||||
if (defaultDates != null) {
|
||||
defaultDates.forEach((dateString) => {
|
||||
|
||||
d = moment(dateString).weekday();
|
||||
|
||||
if (verifyNonWorkDays(d, nonWorkDays)) return;
|
||||
|
||||
matin = `${dateString}T${timeMorning}`;
|
||||
midi = `${dateString}T${timeNoon}`;
|
||||
soir = `${dateString}T${timeEvening}`;
|
||||
|
||||
console.log(matin, midi, soir)
|
||||
|
||||
createColumn(matin, midi);
|
||||
createColumn(midi, soir);
|
||||
});
|
||||
|
||||
updateAllCol();
|
||||
} else {
|
||||
createColumn();
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
@ -118,6 +118,8 @@
|
||||
window.forceModule = "{{ forcer_module }}"
|
||||
window.forceModule = window.forceModule == "True" ? true : false
|
||||
|
||||
createColumn();
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
@ -9,9 +9,8 @@
|
||||
|
||||
{% for etud in etudiants %}
|
||||
<div class="tr" etudid="{{etud.etudid}}">
|
||||
<div class="td sticky">
|
||||
<div class="td sticky etudinfo" id="row-{{etud.etudid}}">
|
||||
<span>{{etud.nomprenom}}</span>
|
||||
<img class="pdp-hover" src="" alt="No Img" etudid="{{etud.etudid}}">
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
@ -40,6 +39,10 @@
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.tr[etudid] {
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.table-container {
|
||||
overflow: auto;
|
||||
position: relative;
|
||||
@ -72,13 +75,13 @@
|
||||
|
||||
.th,
|
||||
.td {
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
width: 225px;
|
||||
border: 1px solid #ddd;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-content: center;
|
||||
min-height: 40px;
|
||||
}
|
||||
|
||||
.tr {
|
||||
@ -88,11 +91,17 @@
|
||||
width: max-content;
|
||||
}
|
||||
|
||||
.td span {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.sticky {
|
||||
position: sticky;
|
||||
left: 0;
|
||||
background-color: #fafafa;
|
||||
border-right: 1px solid #ddd;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.mini-form {
|
||||
@ -120,7 +129,7 @@
|
||||
border-radius: 50%;
|
||||
right: -60px;
|
||||
top: calc(50% - 50px /2);
|
||||
background-color: #007BFF;
|
||||
background-color: #09c;
|
||||
color: white;
|
||||
border: none;
|
||||
outline: none;
|
||||
@ -133,13 +142,13 @@
|
||||
}
|
||||
|
||||
.th {
|
||||
background-color: #007BFF;
|
||||
background-color: #09c;
|
||||
color: white;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.th.error {
|
||||
background-color: crimson;
|
||||
background-color: #d71111;
|
||||
}
|
||||
|
||||
.tbody .tr:nth-child(even) {
|
||||
@ -219,7 +228,7 @@
|
||||
.th.error:hover .col-error {
|
||||
display: block;
|
||||
z-index: 2000;
|
||||
background-color: crimson;
|
||||
background-color: #d71111;
|
||||
width: 100%;
|
||||
min-height: 25%;
|
||||
bottom: -25%;
|
||||
@ -269,7 +278,7 @@
|
||||
currentDate = moment(currentDate).tz(TIMEZONE).format("YYYY-MM-DDTHH:mm");
|
||||
}
|
||||
|
||||
function createColumn() {
|
||||
function createColumn(dateStart = "", dateEnd = "") {
|
||||
let table = document.getElementById("studentTable");
|
||||
let th = document.createElement("div");
|
||||
th.classList.add("th", "error");
|
||||
@ -282,8 +291,8 @@
|
||||
<div class="btngroup" style="justify-content: flex-end;">
|
||||
<button class="closeCol" onclick="removeColumn(this)">x</button>
|
||||
</div>
|
||||
<input type="datetime-local" id="dateStart">
|
||||
<input type="datetime-local" id="dateEnd">
|
||||
<input type="datetime-local" id="dateStart" value="${dateStart}">
|
||||
<input type="datetime-local" id="dateEnd" value="${dateEnd}">
|
||||
{{moduleimpl_select|safe}}
|
||||
<div id="mass_action_${col_id}" class="mass">
|
||||
<input disabled="" type="radio" class="rbtn present" name="mass_action_${col_id}" value="present" onclick="massCol(this)">
|
||||
@ -300,8 +309,10 @@
|
||||
|
||||
|
||||
|
||||
if (dateStart == "") {
|
||||
const last = [...document.querySelectorAll("#dateStart")].pop();
|
||||
defaultDate(last);
|
||||
}
|
||||
|
||||
try {
|
||||
const sl = th.querySelector('.dynaSelect');
|
||||
@ -614,7 +625,7 @@
|
||||
function updateAllCol() {
|
||||
const colIds = [...document.querySelectorAll("[col]")].map((col) => { return col.getAttribute('col') });
|
||||
colIds.forEach((colid) => {
|
||||
updateAssiduitesCol(colid);
|
||||
getAndUpdateCol(colid)
|
||||
})
|
||||
}
|
||||
|
||||
@ -1009,7 +1020,6 @@
|
||||
createColumn();
|
||||
});
|
||||
|
||||
createColumn();
|
||||
setEtuds();
|
||||
|
||||
document.querySelectorAll('.pdp-hover').forEach((el) => {
|
||||
|
@ -210,6 +210,7 @@ def signal_assiduites_etud():
|
||||
"js/assiduites.js",
|
||||
"libjs/moment.new.min.js",
|
||||
"libjs/moment-timezone.js",
|
||||
"js/etud_info.js",
|
||||
],
|
||||
cssstyles=[
|
||||
"css/assiduites.css",
|
||||
@ -880,6 +881,21 @@ def signal_assiduites_diff():
|
||||
group_ids: list[int] = request.args.get("group_ids", None)
|
||||
formsemestre_id: int = request.args.get("formsemestre_id", -1)
|
||||
date: str = request.args.get("jour", datetime.date.today().isoformat())
|
||||
|
||||
date_deb: str = request.args.get("date_deb")
|
||||
date_fin: str = request.args.get("date_fin")
|
||||
|
||||
semaine: str = request.args.get("semaine")
|
||||
|
||||
if semaine is not None:
|
||||
semaine = (
|
||||
f"{scu.annee_scolaire()}-W{semaine}" if "W" not in semaine else semaine
|
||||
)
|
||||
date_deb: datetime.date = datetime.datetime.strptime(
|
||||
semaine + "-1", "%Y-W%W-%w"
|
||||
)
|
||||
date_fin: datetime.date = date_deb + datetime.timedelta(days=6)
|
||||
|
||||
etudiants: list[dict] = []
|
||||
|
||||
titre = None
|
||||
@ -936,6 +952,7 @@ def signal_assiduites_diff():
|
||||
"js/assiduites.js",
|
||||
"libjs/moment.new.min.js",
|
||||
"libjs/moment-timezone.js",
|
||||
"js/etud_info.js",
|
||||
],
|
||||
)
|
||||
|
||||
@ -968,11 +985,35 @@ def signal_assiduites_diff():
|
||||
gr=gr_tit,
|
||||
sem=sem["titre_num"],
|
||||
defdem=_get_etuds_dem_def(formsemestre),
|
||||
timeMorning=ScoDocSiteConfig.get("assi_morning_time", "08:00:00"),
|
||||
timeNoon=ScoDocSiteConfig.get("assi_lunch_time", "13:00:00"),
|
||||
timeEvening=ScoDocSiteConfig.get("assi_evening_time", "18:00:00"),
|
||||
defaultDates=_get_days_between_dates(date_deb, date_fin),
|
||||
nonworkdays=_non_work_days(),
|
||||
),
|
||||
html_sco_header.sco_footer(),
|
||||
).build()
|
||||
|
||||
|
||||
def _get_days_between_dates(deb: str, fin: str):
|
||||
if deb is None or fin is None:
|
||||
return "null"
|
||||
try:
|
||||
if isinstance(deb, str) and isinstance(fin, str):
|
||||
date_deb: datetime.date = datetime.date.fromisoformat(deb)
|
||||
date_fin: datetime.date = datetime.date.fromisoformat(fin)
|
||||
else:
|
||||
date_deb, date_fin = deb.date(), fin.date()
|
||||
except ValueError:
|
||||
return "null"
|
||||
dates: list[str] = []
|
||||
while date_deb <= date_fin:
|
||||
dates.append(f'"{date_deb.isoformat()}"')
|
||||
date_deb = date_deb + datetime.timedelta(days=1)
|
||||
|
||||
return f"[{','.join(dates)}]"
|
||||
|
||||
|
||||
def _differee(
|
||||
etudiants, moduleimpl_select, date=None, periode=None, formsemestre_id=None
|
||||
):
|
||||
@ -1022,7 +1063,7 @@ def _module_selector(
|
||||
for ue in ues:
|
||||
modimpls_list += ntc.get_modimpls_dict(ue_id=ue["ue_id"])
|
||||
|
||||
selected = moduleimpl_id is not None
|
||||
selected = "" if moduleimpl_id is not None else "selected"
|
||||
|
||||
modules = []
|
||||
|
||||
@ -1035,7 +1076,10 @@ def _module_selector(
|
||||
modules.append({"moduleimpl_id": modimpl["moduleimpl_id"], "name": modname})
|
||||
|
||||
return render_template(
|
||||
"assiduites/widgets/moduleimpl_selector.j2", selected=selected, modules=modules
|
||||
"assiduites/widgets/moduleimpl_selector.j2",
|
||||
selected=selected,
|
||||
modules=modules,
|
||||
moduleimpl_id=moduleimpl_id,
|
||||
)
|
||||
|
||||
|
||||
|
@ -137,7 +137,7 @@ def test_general(test_client):
|
||||
etud_faux_dict = g_fake.create_etud(code_nip=None, prenom="etudfaux")
|
||||
etud_faux = Identite.query.filter_by(id=etud_faux_dict["id"]).first()
|
||||
|
||||
verif_migration_abs_assiduites()
|
||||
# verif_migration_abs_assiduites() // Test à revoir TODO-ASSIDUITE
|
||||
|
||||
ajouter_assiduites(etuds, moduleimpls, etud_faux)
|
||||
justificatifs: list[Justificatif] = ajouter_justificatifs(etuds[0])
|
||||
@ -308,13 +308,14 @@ def verif_migration_abs_assiduites():
|
||||
False,
|
||||
), # 3 assi 22-23-24/02/2023 08h > 13h (3dj) JUSTI(ext)
|
||||
]:
|
||||
sco_abs_views.doSignaleAbsence( # TODO-ASSIDUITE
|
||||
datedebut=debut,
|
||||
datefin=fin,
|
||||
demijournee=demijournee,
|
||||
etudid=etudid,
|
||||
estjust=justifiee,
|
||||
)
|
||||
continue
|
||||
# sco_abs_views.doSignaleAbsence( # TODO-ASSIDUITE
|
||||
# datedebut=debut,
|
||||
# datefin=fin,
|
||||
# demijournee=demijournee,
|
||||
# etudid=etudid,
|
||||
# estjust=justifiee,
|
||||
# )
|
||||
|
||||
# --- Justification de certaines absences
|
||||
|
||||
@ -330,12 +331,13 @@ def verif_migration_abs_assiduites():
|
||||
2,
|
||||
),
|
||||
]:
|
||||
sco_abs_views.doJustifAbsence(
|
||||
datedebut=debut,
|
||||
datefin=fin,
|
||||
demijournee=demijournee,
|
||||
etudid=etudid,
|
||||
)
|
||||
continue
|
||||
# sco_abs_views.doJustifAbsence(
|
||||
# datedebut=debut,
|
||||
# datefin=fin,
|
||||
# demijournee=demijournee,
|
||||
# etudid=etudid,
|
||||
# )
|
||||
|
||||
migrate_abs_to_assiduites()
|
||||
|
||||
@ -475,7 +477,7 @@ def _get_justi(
|
||||
|
||||
|
||||
def essais_cache(etudid):
|
||||
"""Vérification des fonctionnalités du cache TODO:WIP"""
|
||||
"""Vérification des fonctionnalités du cache"""
|
||||
|
||||
date_deb: str = "2023-01-01T07:00"
|
||||
date_fin: str = "2023-03-31T19:00"
|
||||
|
Loading…
Reference in New Issue
Block a user