Update opolka/ScoDoc from ScoDoc/ScoDoc #2

Merged
opolka merged 1272 commits from ScoDoc/ScoDoc:master into master 2024-05-27 09:11:04 +02:00
8 changed files with 287 additions and 69 deletions
Showing only changes of commit e5b1082e1d - Show all commits

View File

@ -838,9 +838,6 @@ def _make_listes_sem(formsemestre: FormSemestre, with_absences=True):
weekday = datetime.datetime.today().weekday() weekday = datetime.datetime.today().weekday()
try: try:
if with_absences: if with_absences:
first_monday = sco_abs.ddmmyyyy(
formsemestre.date_debut.strftime("%d/%m/%Y")
).prev_monday()
form_abs_tmpl = f""" form_abs_tmpl = f"""
<td> <td>
<a class="btn" href="{ <a class="btn" href="{
@ -857,7 +854,13 @@ def _make_listes_sem(formsemestre: FormSemestre, with_absences=True):
</td> </td>
""" """
else: else:
form_abs_tmpl = "" form_abs_tmpl = f"""
<td>
<a class="btn" href="{
url_for("assiduites.visu_assiduites_group", scodoc_dept=g.scodoc_dept)
}?group_ids=%(group_id)s&jour={datetime.date.today().isoformat()}&formsemestre_id={formsemestre.id}"><button>Voir l'assiduité</button></a>
</td>
"""
except ScoInvalidDateError: # dates incorrectes dans semestres ? except ScoInvalidDateError: # dates incorrectes dans semestres ?
form_abs_tmpl = "" form_abs_tmpl = ""
# #
@ -904,8 +907,7 @@ def _make_listes_sem(formsemestre: FormSemestre, with_absences=True):
""" """
) )
if with_absences: H.append(form_abs_tmpl % group)
H.append(form_abs_tmpl % group)
H.append("</tr>") H.append("</tr>")
H.append("</table>") H.append("</table>")

View File

@ -11,7 +11,7 @@
} }
#validate_selectors { #validate_selectors {
margin-top: 5vh; margin: 15px 0;
} }
.no-display { .no-display {
@ -91,9 +91,6 @@
/* === Gestion des etuds row === */ /* === Gestion des etuds row === */
.etud_holder {
margin-top: 5vh;
}
.etud_row { .etud_row {
display: grid; display: grid;

View File

@ -84,19 +84,19 @@ function validateSelectors(btn) {
); );
}); });
if (getModuleImplId() == null && window.forceModule) { // if (getModuleImplId() == null && window.forceModule) {
const HTML = ` // const HTML = `
<p>Attention, le module doit obligatoirement être renseigné.</p> // <p>Attention, le module doit obligatoirement être renseigné.</p>
<p>Cela vient de la configuration du semestre ou plus largement du département.</p> // <p>Cela vient de la configuration du semestre ou plus largement du département.</p>
<p>Si c'est une erreur, veuillez voir avec le ou les responsables de votre scodoc.</p> // <p>Si c'est une erreur, veuillez voir avec le ou les responsables de votre scodoc.</p>
`; // `;
const content = document.createElement("div"); // const content = document.createElement("div");
content.innerHTML = HTML; // content.innerHTML = HTML;
openAlertModal("Sélection du module", content); // openAlertModal("Sélection du module", content);
return; // return;
} // }
getAssiduitesFromEtuds(true); getAssiduitesFromEtuds(true);
@ -269,6 +269,15 @@ function executeMassActionQueue() {
}; };
assiduite = setModuleImplId(assiduite); assiduite = setModuleImplId(assiduite);
if (assiduite.moduleimpl_id == null && window.forceModule) {
const html = `
<h3>Aucun module n'a été spécifié</h3>
`;
const div = document.createElement("div");
div.innerHTML = html;
openAlertModal("Erreur Module", div);
return 0;
}
const createQueue = []; //liste des assiduités qui seront créées. const createQueue = []; //liste des assiduités qui seront créées.
@ -311,6 +320,16 @@ function executeMassActionQueue() {
return assiduite; return assiduite;
}); });
if (getModuleImplId() == null && window.forceModule) {
const html = `
<h3>Aucun module n'a été spécifié</h3>
`;
const div = document.createElement("div");
div.innerHTML = html;
openAlertModal("Erreur Module", div);
return 0;
}
const path = getUrl() + `/api/assiduites/edit`; const path = getUrl() + `/api/assiduites/edit`;
sync_post( sync_post(
path, path,
@ -496,7 +515,7 @@ function generateMassAssiduites() {
}); });
}); });
if (!verifyDateInSemester()) { if (!verifyDateInSemester() || readOnly) {
content.querySelector(".btns_field.mass").setAttribute("disabled", "true"); content.querySelector(".btns_field.mass").setAttribute("disabled", "true");
} }
} }
@ -849,6 +868,16 @@ function createAssiduite(etat, etudid) {
assiduite = setModuleImplId(assiduite); assiduite = setModuleImplId(assiduite);
if (assiduite.moduleimpl_id == null && window.forceModule) {
const html = `
<h3>Aucun module n'a été spécifié</h3>
`;
const div = document.createElement("div");
div.innerHTML = html;
openAlertModal("Erreur Module", div);
return false;
}
const path = getUrl() + `/api/assiduite/${etudid}/create`; const path = getUrl() + `/api/assiduite/${etudid}/create`;
sync_post( sync_post(
path, path,
@ -865,6 +894,7 @@ function createAssiduite(etat, etudid) {
errorAlert(); errorAlert();
} }
); );
return true;
} }
/** /**
@ -889,6 +919,7 @@ function deleteAssiduite(assiduite_id) {
errorAlert(); errorAlert();
} }
); );
return true;
} }
/** /**
@ -905,6 +936,15 @@ function editAssiduite(assiduite_id, etat) {
}; };
assiduite = setModuleImplId(assiduite); assiduite = setModuleImplId(assiduite);
if (assiduite.moduleimpl_id == null && window.forceModule) {
const html = `
<h3>Aucun module n'a été spécifié</h3>
`;
const div = document.createElement("div");
div.innerHTML = html;
openAlertModal("Erreur Module", div);
return;
}
const path = getUrl() + `/api/assiduite/${assiduite_id}/edit`; const path = getUrl() + `/api/assiduite/${assiduite_id}/edit`;
let bool = false; let bool = false;
sync_post( sync_post(
@ -1072,15 +1112,16 @@ function assiduiteAction(element) {
} }
} else { } else {
// Cas normal -> mise à jour en base // Cas normal -> mise à jour en base
let done = false;
switch (type) { switch (type) {
case "création": case "création":
createAssiduite(etat, etudid); done = createAssiduite(etat, etudid);
break; break;
case "édition": case "édition":
if (etat === "remove") { if (etat === "remove") {
deleteAssiduite(assiduite_id); done = deleteAssiduite(assiduite_id);
} else { } else {
editAssiduite(assiduite_id, etat); done = editAssiduite(assiduite_id, etat);
} }
break; break;
case "conflit": case "conflit":
@ -1105,7 +1146,7 @@ function assiduiteAction(element) {
return; return;
} }
if (type != "conflit") { if (type != "conflit" && done) {
let etatAffiche; let etatAffiche;
switch (etat.toUpperCase()) { switch (etat.toUpperCase()) {
@ -1262,7 +1303,7 @@ function insertEtudRow(etud, index, output = false) {
bar.appendChild(createMiniTimeline(assiduites[etud.id])); bar.appendChild(createMiniTimeline(assiduites[etud.id]));
if (!verifyDateInSemester()) { if (!verifyDateInSemester() || readOnly) {
row.querySelector(".btns_field.single").setAttribute("disabled", "true"); row.querySelector(".btns_field.single").setAttribute("disabled", "true");
} }
} }
@ -1485,7 +1526,6 @@ function fastJustify(assiduite) {
if (justifs.length > 0) { if (justifs.length > 0) {
justifyAssiduite(assiduite.assiduite_id, !assiduite.est_just); 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
@ -1617,3 +1657,37 @@ function errorAlert() {
div.innerHTML = html; div.innerHTML = html;
openAlertModal("Une erreur s'est produite", div); openAlertModal("Une erreur s'est produite", div);
} }
const moduleimpls = {};
function getModuleImpl(assiduite) {
const id = assiduite.moduleimpl_id;
if (id == null || id == undefined) {
if (
"desc" in assiduite &&
assiduite.desc != null &&
assiduite.desc.indexOf("Module:Autre") != -1
) {
return "Autre";
} else {
return "Pas de module";
}
}
if (id in moduleimpls) {
return moduleimpls[id];
}
const url_api = getUrl() + `/api/moduleimpl/${id}`;
sync_get(
url_api,
(data) => {
moduleimpls[id] = `${data.module.code} ${data.module.abbrev}`;
},
(data) => {
moduleimpls[id] = "Pas de module";
}
);
return moduleimpls[id];
}

View File

@ -2,34 +2,50 @@
<section id="content"> <section id="content">
<div class="no-display"> <div class="no-display">
<span class="formsemestre_id">{{formsemestre_id}}</span> <span class="formsemestre_id">{{formsemestre_id}}</span>
<span id="formsemestre_date_debut">{{formsemestre_date_debut}}</span> <span id="formsemestre_date_debut">{{formsemestre_date_debut}}</span>
<span id="formsemestre_date_fin">{{formsemestre_date_fin}}</span> <span id="formsemestre_date_fin">{{formsemestre_date_fin}}</span>
</div> </div>
<h2> <h2>
Saisie des assiduités {{gr_tit|safe}} {{sem}} Saisie des assiduités {{gr_tit|safe}} {{sem}}
</h2> </h2>
{% if readonly == "true" %}
<h1 style="font-weight: bolder;color:crimson">La page est en lecture seule.</h1>
{% endif %}
<fieldset class="selectors"> <fieldset class="selectors">
<div>Groupes : {{grp|safe}}</div> <div>Groupes : {{grp|safe}}</div>
<div id="forcemodule" style="display: none;">Une préférence du semestre vous impose d'indiquer le module !</div>
<div>Module :{{moduleimpl_select|safe}}</div>
<div class="infos"> <div class="infos">
Date: <span id="datestr"></span> Date: <span id="datestr"></span>
<input type="date" name="tl_date" id="tl_date" value="{{ date }}" onchange="updateDate()"> <input type="date" name="tl_date" id="tl_date" value="{{ date }}" onchange="updateDate()">
</div> </div>
</fieldset> </fieldset>
{% if readonly == "true" %}
{{timeline|safe}} <button id="validate_selectors" onclick="validateSelectors(this)">
Voir la saisie
</button>
{% else %}
<button id="validate_selectors" onclick="validateSelectors(this)"> <button id="validate_selectors" onclick="validateSelectors(this)">
Faire la saisie Faire la saisie
</button> </button>
{% endif %}
{{timeline|safe}}
{% if readonly == "false" %}
<div style="margin: 1vh 0;">
<div id="forcemodule" style="display: none; margin:10px 0px;">Une préférence du semestre vous impose d'indiquer
le module !</div>
<div>Module :{{moduleimpl_select|safe}}</div>
</div>
{% else %}
{% endif %}
<div class="etud_holder"> <div class="etud_holder">
<p class="placeholder"> <p class="placeholder">
Veillez à choisir le groupe concerné par la saisie ainsi que la date de la saisie. Veillez à choisir le groupe concerné par la saisie ainsi que la date de la saisie.
@ -75,6 +91,9 @@
const nonWorkDays = [{{ nonworkdays| safe }}]; const nonWorkDays = [{{ nonworkdays| safe }}];
const readOnly = {{ readonly }};
updateDate(); updateDate();
setupDate(); setupDate();
setupTimeLine(); setupTimeLine();
@ -89,17 +108,14 @@
const select = document.getElementById("moduleimpl_select"); const select = document.getElementById("moduleimpl_select");
if (select.value == "") { if (!readOnly && select.value == "") {
btn.disabled = true;
document.getElementById('forcemodule').style.display = "block"; document.getElementById('forcemodule').style.display = "block";
} }
select.addEventListener('change', (e) => { select?.addEventListener('change', (e) => {
if (e.target.value != "") { if (e.target.value != "") {
btn.disabled = false;
document.getElementById('forcemodule').style.display = "none"; document.getElementById('forcemodule').style.display = "none";
} else { } else {
btn.disabled = true;
document.getElementById('forcemodule').style.display = "block"; document.getElementById('forcemodule').style.display = "block";
} }
}); });

View File

@ -38,15 +38,15 @@
} }
array.forEach((assiduité) => { array.forEach((assiduité) => {
const startDate = moment(assiduité.date_debut); let startDate = moment(assiduité.date_debut);
const endDate = moment(assiduité.date_fin); let endDate = moment(assiduité.date_fin);
if (startDate.isBefore(dayStart)) { if (startDate.isBefore(dayStart)) {
startDate.startOf("day").add(mt_start, "hours"); startDate = dayEnd.clone().startOf("day").add(mt_start, "hours");
} }
if (endDate.isAfter(dayEnd)) { if (endDate.isAfter(dayEnd)) {
endDate.startOf("day").add(mt_end, "hours"); endDate = dayEnd.clone().startOf("day").add(mt_end, "hours");
} }
const block = document.createElement("div"); const block = document.createElement("div");
@ -140,7 +140,7 @@
const idDiv = document.createElement("div"); const idDiv = document.createElement("div");
idDiv.className = "assiduite-id"; idDiv.className = "assiduite-id";
idDiv.textContent = `ID: ${assiduite.assiduite_id}`; idDiv.textContent = `${getModuleImpl(assiduite)}`;
bubble.appendChild(idDiv); bubble.appendChild(idDiv);
const periodDivDeb = document.createElement("div"); const periodDivDeb = document.createElement("div");

View File

@ -63,30 +63,7 @@
try { stats() } catch (_) { } try { stats() } catch (_) { }
} }
const moduleimpls = {}
function getModuleImpl(assiduite) {
const id = assiduite.moduleimpl_id;
if (id == null || id == undefined) {
if ("desc" in assiduite && assiduite.desc != null && assiduite.desc.indexOf('Module:Autre') != -1) {
return "Autre"
} else {
return "Pas de module"
}
}
if (id in moduleimpls) {
return moduleimpls[id];
}
const url_api = getUrl() + `/api/moduleimpl/${id}`;
sync_get(url_api, (data) => {
moduleimpls[id] = `${data.module.code} ${data.module.abbrev}`;
}, (data) => { moduleimpls[id] = "Pas de module" });
return moduleimpls[id];
}
function renderTableAssiduites(page, assiduités) { function renderTableAssiduites(page, assiduités) {

View File

@ -234,11 +234,12 @@
<style> <style>
.timeline-container { .timeline-container {
width: 75%; width: 75%;
margin-left: 5%; margin-left: 25px;
background-color: white; background-color: white;
border-radius: 15px; border-radius: 15px;
position: relative; position: relative;
height: 40px; height: 40px;
margin-bottom: 25px;
} }
/* ... */ /* ... */

View File

@ -446,6 +446,8 @@ def signal_assiduites_group():
date: str = request.args.get("jour", datetime.date.today().isoformat()) date: str = request.args.get("jour", datetime.date.today().isoformat())
group_ids: list[int] = request.args.get("group_ids", None) group_ids: list[int] = request.args.get("group_ids", None)
readonly: str = "false"
if group_ids is None: if group_ids is None:
group_ids = [] group_ids = []
else: else:
@ -571,6 +573,155 @@ def signal_assiduites_group():
dept_id=g.scodoc_dept_id, dept_id=g.scodoc_dept_id,
), ),
defdem=_get_etuds_dem_def(formsemestre), defdem=_get_etuds_dem_def(formsemestre),
readonly=readonly,
),
html_sco_header.sco_footer(),
).build()
@bp.route("/VisuAssiduiteGr")
@scodoc
@permission_required(Permission.ScoView)
def visu_assiduites_group():
"""
signal_assiduites_group Saisie des assiduités des groupes pour le jour donnée
Returns:
str: l'html généré
"""
formsemestre_id: int = request.args.get("formsemestre_id", -1)
moduleimpl_id: int = request.args.get("moduleimpl_id")
date: str = request.args.get("jour", datetime.date.today().isoformat())
group_ids: list[int] = request.args.get("group_ids", None)
readonly: str = "true"
if group_ids is None:
group_ids = []
else:
group_ids = group_ids.split(",")
map(str, group_ids)
# Vérification du moduleimpl_id
try:
moduleimpl_id = int(moduleimpl_id)
except (TypeError, ValueError):
moduleimpl_id = None
# Vérification du formsemestre_id
try:
formsemestre_id = int(formsemestre_id)
except (TypeError, ValueError):
formsemestre_id = None
groups_infos = sco_groups_view.DisplayedGroupsInfos(
group_ids, moduleimpl_id=moduleimpl_id, formsemestre_id=formsemestre_id
)
if not groups_infos.members:
return (
html_sco_header.sco_header(page_title="Saisie journalière des Assiduités")
+ "<h3>Aucun étudiant ! </h3>"
+ html_sco_header.sco_footer()
)
# --- URL DEFAULT ---
base_url: str = f"SignalAssiduiteGr?date={date}&{groups_infos.groups_query_args}"
# --- Filtrage par formsemestre ---
formsemestre_id = groups_infos.formsemestre_id
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id)
if formsemestre.dept_id != g.scodoc_dept_id:
abort(404, "groupes inexistants dans ce département")
require_module = sco_preferences.get_preference(
"abs_require_module", formsemestre_id
)
etuds = [
sco_etud.get_etud_info(etudid=m["etudid"], filled=True)[0]
for m in groups_infos.members
]
# --- Vérification de la date ---
real_date = scu.is_iso_formated(date, True).date()
if real_date < formsemestre.date_debut:
date = formsemestre.date_debut.isoformat()
elif real_date > formsemestre.date_fin:
date = formsemestre.date_fin.isoformat()
# --- Restriction en fonction du moduleimpl_id ---
if moduleimpl_id:
mod_inscrits = {
x["etudid"]
for x in sco_moduleimpl.do_moduleimpl_inscription_list(
moduleimpl_id=moduleimpl_id
)
}
etuds_inscrits_module = [e for e in etuds if e["etudid"] in mod_inscrits]
if etuds_inscrits_module:
etuds = etuds_inscrits_module
else:
# Si aucun etudiant n'est inscrit au module choisi...
moduleimpl_id = None
# --- Génération de l'HTML ---
sem = formsemestre.to_dict()
if groups_infos.tous_les_etuds_du_sem:
gr_tit = "en"
else:
if len(groups_infos.group_ids) > 1:
grp = "des groupes"
else:
grp = "du groupe"
gr_tit = (
grp + ' <span class="fontred">' + groups_infos.groups_titles + "</span>"
)
header: str = html_sco_header.sco_header(
page_title="Saisie journalière des assiduités",
init_qtip=True,
javascripts=html_sco_header.BOOTSTRAP_MULTISELECT_JS
+ [
# Voir fonctionnement JS
"js/etud_info.js",
"js/abs_ajax.js",
"js/groups_view.js",
"js/assiduites.js",
"libjs/moment.new.min.js",
"libjs/moment-timezone.js",
],
cssstyles=CSSSTYLES
+ [
"css/assiduites.css",
],
)
return HTMLBuilder(
header,
_mini_timeline(),
render_template(
"assiduites/pages/signal_assiduites_group.j2",
gr_tit=gr_tit,
sem=sem["titre_num"],
date=date,
formsemestre_id=formsemestre_id,
grp=sco_groups_view.menu_groups_choice(groups_infos),
moduleimpl_select=_module_selector(formsemestre, moduleimpl_id),
timeline=_timeline(),
nonworkdays=_non_work_days(),
formsemestre_date_debut=str(formsemestre.date_debut),
formsemestre_date_fin=str(formsemestre.date_fin),
forcer_module=sco_preferences.get_preference(
"forcer_module",
formsemestre_id=formsemestre_id,
dept_id=g.scodoc_dept_id,
),
defdem=_get_etuds_dem_def(formsemestre),
readonly=readonly,
), ),
html_sco_header.sco_footer(), html_sco_header.sco_footer(),
).build() ).build()