Assiduites : Signalement différé
This commit is contained in:
parent
36bc67fffc
commit
d5f01e0628
@ -390,7 +390,6 @@ class BulletinBUT:
|
|||||||
"H.": "Heure(s)",
|
"H.": "Heure(s)",
|
||||||
"J.": "Journée(s)",
|
"J.": "Journée(s)",
|
||||||
"1/2 J.": "1/2 Jour.",
|
"1/2 J.": "1/2 Jour.",
|
||||||
"N.": "Nombre",
|
|
||||||
}.get(sco_preferences.get_preference("assi_metrique")),
|
}.get(sco_preferences.get_preference("assi_metrique")),
|
||||||
}
|
}
|
||||||
decisions_ues = self.res.get_etud_decisions_ue(etud.id) or {}
|
decisions_ues = self.res.get_etud_decisions_ue(etud.id) or {}
|
||||||
|
@ -823,34 +823,20 @@ def _make_listes_sem(formsemestre: FormSemestre, with_absences=True):
|
|||||||
first_monday = sco_abs.ddmmyyyy(
|
first_monday = sco_abs.ddmmyyyy(
|
||||||
formsemestre.date_debut.strftime("%d/%m/%Y")
|
formsemestre.date_debut.strftime("%d/%m/%Y")
|
||||||
).prev_monday()
|
).prev_monday()
|
||||||
form_abs_tmpl = f"""
|
form_abs_tmpl = """
|
||||||
<td>
|
<td>
|
||||||
<a href="%(url_etat)s">absences</a>
|
<a class="btn" href="%(url_etat)s"><button>Voir l'assiduité</button></a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<form action="{url_for(
|
|
||||||
"assiduites.signal_assiduites_group", scodoc_dept=g.scodoc_dept
|
|
||||||
)}" method="get">
|
|
||||||
<input type="hidden" name="date" value="{
|
|
||||||
formsemestre.date_fin.strftime("%d/%m/%Y")}"/>
|
|
||||||
<input type="hidden" name="group_ids" value="%(group_id)s"/>
|
|
||||||
<input type="hidden" name="destination" value="{destination}"/>
|
|
||||||
<input type="submit" value="Saisir abs des" />
|
|
||||||
<select name="datedebut" class="noprint">
|
|
||||||
"""
|
"""
|
||||||
date = first_monday
|
|
||||||
for idx, jour in enumerate(sco_abs.day_names()):
|
|
||||||
form_abs_tmpl += f"""<option value="{date}" {
|
|
||||||
'selected' if idx == weekday else ''
|
|
||||||
}>{jour}s</option>"""
|
|
||||||
date = date.next_day()
|
|
||||||
form_abs_tmpl += f"""
|
form_abs_tmpl += f"""
|
||||||
</select>
|
<a class="btn" href="{
|
||||||
|
|
||||||
<a href="{
|
|
||||||
url_for("assiduites.signal_assiduites_group", scodoc_dept=g.scodoc_dept)
|
url_for("assiduites.signal_assiduites_group", scodoc_dept=g.scodoc_dept)
|
||||||
}?group_ids=%(group_id)s&jour={datetime.date.today().isoformat()}&formsemestre_id={formsemestre.id}">saisie par semaine</a>
|
}?group_ids=%(group_id)s&jour={datetime.date.today().isoformat()}&formsemestre_id={formsemestre.id}"><button>Saisie Journalière</button></a>
|
||||||
</form></td>
|
<a class="btn" href="{
|
||||||
|
url_for("assiduites.signal_assiduites_diff", scodoc_dept=g.scodoc_dept)
|
||||||
|
}?group_ids=%(group_id)s&formsemestre_id={formsemestre.formsemestre_id}"><button>Saisie Différée</button></a>
|
||||||
|
</td>
|
||||||
"""
|
"""
|
||||||
else:
|
else:
|
||||||
form_abs_tmpl = ""
|
form_abs_tmpl = ""
|
||||||
|
@ -632,7 +632,7 @@ class BasePreferences(object):
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"etat_defaut",
|
"assi_etat_defaut",
|
||||||
{
|
{
|
||||||
"initvalue": "aucun",
|
"initvalue": "aucun",
|
||||||
"input_type": "menu",
|
"input_type": "menu",
|
||||||
@ -658,10 +658,10 @@ class BasePreferences(object):
|
|||||||
{
|
{
|
||||||
"initvalue": "1/2 J.",
|
"initvalue": "1/2 J.",
|
||||||
"input_type": "menu",
|
"input_type": "menu",
|
||||||
"labels": ["1/2 J.", "J.", "H.", "N."],
|
"labels": ["1/2 J.", "J.", "H."],
|
||||||
"allowed_values": ["1/2 J.", "J.", "H.", "N."],
|
"allowed_values": ["1/2 J.", "J.", "H."],
|
||||||
"title": "Métrique de l'assiduité",
|
"title": "Métrique de l'assiduité",
|
||||||
"explanation": "Unité affichée dans la fiche étudiante et le bilan\n(J. = journée, H. = heure, N. = nombre)",
|
"explanation": "Unité affichée dans la fiche étudiante et le bilan\n(J. = journée, H. = heure)",
|
||||||
"category": "assi",
|
"category": "assi",
|
||||||
"only_global": True,
|
"only_global": True,
|
||||||
},
|
},
|
||||||
|
372
app/templates/assiduites/signal_assiduites_diff.j2
Normal file
372
app/templates/assiduites/signal_assiduites_diff.j2
Normal file
@ -0,0 +1,372 @@
|
|||||||
|
<h2>Signalement différé des assiduités {{gr |safe}}</h2>
|
||||||
|
<h3>{{sem | safe }}</h3>
|
||||||
|
<button onclick="getAndVerify()">Valider les assiduités</button>
|
||||||
|
<div id="studentTable">
|
||||||
|
<div class="thead">
|
||||||
|
<div class="tr">
|
||||||
|
<div class="th sticky">Noms</div>
|
||||||
|
<button id="addColumn" class="floating-button">+</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tbody">
|
||||||
|
|
||||||
|
{% for etud in etudiants %}
|
||||||
|
<div class="tr" etudid="{{etud.etudid}}">
|
||||||
|
<div class="td sticky">{{etud.nomprenom}}</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% include "assiduites/alert.j2" %}
|
||||||
|
{% include "assiduites/prompt.j2" %}
|
||||||
|
|
||||||
|
|
||||||
|
<style>
|
||||||
|
button {
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.err-assi {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
gap: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container {
|
||||||
|
overflow: auto;
|
||||||
|
position: relative;
|
||||||
|
max-width: 100%;
|
||||||
|
margin: 0 auto;
|
||||||
|
box-shadow: 0 0 1rem 0 rgba(0, 0, 0, .2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thead .tr {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thead .tr .th {
|
||||||
|
height: 125px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
font-size: larger;
|
||||||
|
}
|
||||||
|
|
||||||
|
.th.sticky {
|
||||||
|
z-index: 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.th,
|
||||||
|
.td {
|
||||||
|
padding: 10px;
|
||||||
|
text-align: center;
|
||||||
|
width: 200px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tr {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
width: max-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sticky {
|
||||||
|
position: sticky;
|
||||||
|
left: 0;
|
||||||
|
background-color: #fafafa;
|
||||||
|
border-right: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mini-form {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mini-form input,
|
||||||
|
.mini-form select {
|
||||||
|
display: block;
|
||||||
|
margin: 5px;
|
||||||
|
padding: 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
#addColumn {
|
||||||
|
font-size: 24px;
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
border-radius: 50%;
|
||||||
|
right: -60px;
|
||||||
|
top: calc(50% - 50px /2);
|
||||||
|
background-color: #007BFF;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#addColumn:hover {
|
||||||
|
background-color: #0056b3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.th {
|
||||||
|
background-color: #007BFF;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tbody .tr:nth-child(even) {
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tbody .tr:hover {
|
||||||
|
background-color: #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.etat {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 33% 33% 33%;
|
||||||
|
grid-template-rows: 50% 50%;
|
||||||
|
|
||||||
|
font-size: small;
|
||||||
|
}
|
||||||
|
|
||||||
|
#moduleimpl_select {
|
||||||
|
max-width: 175px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
let verified = false;
|
||||||
|
const etatDef = "{{etat_def}}";
|
||||||
|
moment.tz.setDefault("Etc/UTC");
|
||||||
|
function createColumn() {
|
||||||
|
let table = document.getElementById("studentTable");
|
||||||
|
let th = document.createElement("div");
|
||||||
|
th.classList.add("th");
|
||||||
|
const col_id = `${document.querySelectorAll("[col]").length + 1}`;
|
||||||
|
th.setAttribute("col", col_id);
|
||||||
|
th.innerHTML = `
|
||||||
|
<div class="mini-form">
|
||||||
|
<input type="datetime-local" id="dateStart">
|
||||||
|
<input type="datetime-local" id="dateEnd">
|
||||||
|
{{moduleimpl_select|safe}}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
table
|
||||||
|
.querySelector(".thead .tr")
|
||||||
|
.insertBefore(th, document.querySelector("#addColumn"));
|
||||||
|
|
||||||
|
const last = [...document.querySelectorAll("#dateStart")].pop();
|
||||||
|
defaultDate(last);
|
||||||
|
|
||||||
|
let rows = table.querySelector(".tbody").querySelectorAll(".tr");
|
||||||
|
for (let i = 0; i < rows.length; i++) {
|
||||||
|
let td = document.createElement("div");
|
||||||
|
td.setAttribute("colid", col_id)
|
||||||
|
td.classList.add("td", "etat");
|
||||||
|
const etudid = rows[i].getAttribute("etudid");
|
||||||
|
td.innerHTML = `
|
||||||
|
<input type="radio" name="etat_${col_id}_${etudid}" value="present">
|
||||||
|
<input type="radio" name="etat_${col_id}_${etudid}" value="retard">
|
||||||
|
<input type="radio" name="etat_${col_id}_${etudid}" value="absent">
|
||||||
|
<span>Present</span>
|
||||||
|
<span>Retard</span>
|
||||||
|
<span>Absent</span>
|
||||||
|
`;
|
||||||
|
|
||||||
|
|
||||||
|
rows[i].appendChild(td);
|
||||||
|
if (etatDef != "" && etatDef != "aucun") {
|
||||||
|
const inp = td.querySelector(`[value='${etatDef}']`).checked = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function defaultDate(element) {
|
||||||
|
const num = element.parentElement.parentElement.getAttribute("col") - 1;
|
||||||
|
const last = [...document.querySelectorAll(`[col='${num}'] #dateEnd`)].pop();
|
||||||
|
let date = undefined;
|
||||||
|
if (last == undefined) {
|
||||||
|
date = moment().tz("Europe/Paris").format("YYYY-MM-DDTHH:mm");
|
||||||
|
} else {
|
||||||
|
date = last.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
element.value = date;
|
||||||
|
|
||||||
|
element.addEventListener(
|
||||||
|
"focusout",
|
||||||
|
() => {
|
||||||
|
const el = element.parentElement.querySelector("#dateEnd");
|
||||||
|
const el2 = element.parentElement.querySelector("#dateStart");
|
||||||
|
el.value = moment(el2.valueAsDate)
|
||||||
|
.add(2, "hours")
|
||||||
|
.format("YYYY-MM-DDTHH:mm");
|
||||||
|
},
|
||||||
|
{ once: true }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getEtatCol(colId) {
|
||||||
|
const etats = {};
|
||||||
|
const tds = [...document.querySelectorAll(`.td[colid='${colId}']`)]
|
||||||
|
tds.forEach((td) => {
|
||||||
|
const tr = td.parentElement
|
||||||
|
const etudid = tr.getAttribute("etudid");
|
||||||
|
let inputs = [...td.querySelectorAll("input")]
|
||||||
|
|
||||||
|
etatInput = inputs.filter((e) => e.checked).pop()
|
||||||
|
|
||||||
|
if (etatInput == undefined) {
|
||||||
|
etats[etudid] = "";
|
||||||
|
} else {
|
||||||
|
etats[etudid] = etatInput.value;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return etats;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _createAssiduites(inputDeb, inputFin, moduleSelect, etudid, etat, colId) {
|
||||||
|
if (moduleSelect == "") {
|
||||||
|
return {
|
||||||
|
"date_debut": inputDeb,
|
||||||
|
"date_fin": inputFin,
|
||||||
|
"etudid": etudid,
|
||||||
|
"etat": etat,
|
||||||
|
"colid": colId,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
"date_debut": inputDeb,
|
||||||
|
"date_fin": inputFin,
|
||||||
|
"etudid": etudid,
|
||||||
|
"moduleimpl_id": moduleSelect,
|
||||||
|
"etat": etat,
|
||||||
|
"colid": colId,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAndVerify() {
|
||||||
|
const assiduites = [];
|
||||||
|
const cols = [...document.querySelectorAll("[col]")];
|
||||||
|
const errors = [];
|
||||||
|
|
||||||
|
cols.forEach((col) => {
|
||||||
|
const col_id = col.getAttribute("col");
|
||||||
|
const etats = getEtatCol(col_id);
|
||||||
|
|
||||||
|
const inputDeb = col.querySelector("#dateStart").value;
|
||||||
|
const inputFin = col.querySelector("#dateEnd").value;
|
||||||
|
const moduleSelect = col.querySelector("#moduleimpl_select").value;
|
||||||
|
|
||||||
|
if (inputDeb == "" || inputFin == "") {
|
||||||
|
errors.push(`La colonne n°${col_id} n'est pas valide`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// TODO Mettre une erreur lorsque moduleimpl forcé (pref)
|
||||||
|
// TODO Mettre une erreur lorsque assiduité forcé (pref)
|
||||||
|
|
||||||
|
Object.keys(etats).forEach((key) => {
|
||||||
|
const etat = etats[key];
|
||||||
|
|
||||||
|
if (etat != "") {
|
||||||
|
assiduites.push(_createAssiduites(inputDeb, inputFin, moduleSelect, key, etat, col_id))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
if (errors.length > 0) {
|
||||||
|
const texte = document.createElement("div");
|
||||||
|
errors.map((err) => document.createTextNode(err)).forEach((err) => {
|
||||||
|
texte.appendChild(err);
|
||||||
|
texte.appendChild(document.createElement('br'));
|
||||||
|
})
|
||||||
|
|
||||||
|
openAlertModal("Erreur(s) détéctée(s)", texte)
|
||||||
|
} else {
|
||||||
|
createAllAssiduites(assiduites);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function createAllAssiduites(createQueue) {
|
||||||
|
if (createQueue.length < 0)
|
||||||
|
return;
|
||||||
|
const path = getUrl() + `/api/assiduites/create`;
|
||||||
|
sync_post(
|
||||||
|
path,
|
||||||
|
createQueue,
|
||||||
|
(data, status) => {
|
||||||
|
verified = true;
|
||||||
|
const { success, errors } = data;
|
||||||
|
|
||||||
|
const indexes = [...Object.keys(errors)];
|
||||||
|
if (indexes.length > 0) {
|
||||||
|
const incriminated = indexes.map((i) => {
|
||||||
|
return createQueue[Number.parseInt(i)];
|
||||||
|
})
|
||||||
|
|
||||||
|
const error_message = document.createElement('div');
|
||||||
|
|
||||||
|
for (let i = 0; i < incriminated.length; i++) {
|
||||||
|
const err = errors[indexes[i]];
|
||||||
|
const crimi = incriminated[i];
|
||||||
|
const nom = document.querySelector(`[etudid='${crimi.etudid}']`).firstElementChild.textContent.trim();
|
||||||
|
const col = crimi.colid;
|
||||||
|
|
||||||
|
const div = document.createElement('div');
|
||||||
|
div.classList.add("err-assi")
|
||||||
|
const span = document.createElement("span");
|
||||||
|
span.setAttribute("title", err);
|
||||||
|
span.textContent = "ℹ️"
|
||||||
|
|
||||||
|
const span2 = document.createElement("span");
|
||||||
|
span2.textContent = `L'assiduité (Colonne n°${col}) de ${nom} n'a pas pu être enregistrée`;
|
||||||
|
|
||||||
|
div.appendChild(span2);
|
||||||
|
div.appendChild(span);
|
||||||
|
|
||||||
|
error_message.appendChild(div);
|
||||||
|
}
|
||||||
|
|
||||||
|
openAlertModal("Certaines assiduités non pas été enregistrées", error_message)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
openAlertModal("Tous les assiduités ont bien été enregistrée", document.createTextNode(""), null, "#09AD2A")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(data, status) => {
|
||||||
|
//error
|
||||||
|
console.error(data, status);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
document.getElementById("addColumn").addEventListener("click", () => {
|
||||||
|
createColumn();
|
||||||
|
});
|
||||||
|
|
||||||
|
const onConfirmRefresh = function (event) {
|
||||||
|
if (!verified)
|
||||||
|
return event.returnValue = "Attention, certaines données n'ont pas été enregistrées";
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("beforeunload", onConfirmRefresh, { capture: true });
|
||||||
|
createColumn();
|
||||||
|
|
||||||
|
</script>
|
@ -325,6 +325,7 @@ def signal_assiduites_group():
|
|||||||
|
|
||||||
# --- Filtrage par formsemestre ---
|
# --- Filtrage par formsemestre ---
|
||||||
formsemestre_id = groups_infos.formsemestre_id
|
formsemestre_id = groups_infos.formsemestre_id
|
||||||
|
|
||||||
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
||||||
if formsemestre.dept_id != g.scodoc_dept_id:
|
if formsemestre.dept_id != g.scodoc_dept_id:
|
||||||
abort(404, "groupes inexistants dans ce département")
|
abort(404, "groupes inexistants dans ce département")
|
||||||
@ -414,7 +415,7 @@ def signal_assiduites_group():
|
|||||||
|
|
||||||
@bp.route("/EtatAbsencesDate")
|
@bp.route("/EtatAbsencesDate")
|
||||||
@scodoc
|
@scodoc
|
||||||
@permission_required(Permission.ScoAbsChange)
|
@permission_required(Permission.ScoView)
|
||||||
def get_etat_abs_date():
|
def get_etat_abs_date():
|
||||||
evaluation = {
|
evaluation = {
|
||||||
"jour": request.args.get("jour"),
|
"jour": request.args.get("jour"),
|
||||||
@ -483,6 +484,84 @@ def get_etat_abs_date():
|
|||||||
).build()
|
).build()
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/SignalAssiduiteDifferee")
|
||||||
|
@scodoc
|
||||||
|
@permission_required(Permission.ScoAbsChange)
|
||||||
|
def signal_assiduites_diff():
|
||||||
|
group_ids: list[int] = request.args.get("group_ids", None)
|
||||||
|
etudid: int = request.args.get("etudid", None)
|
||||||
|
formsemestre_id: int = request.args.get("formsemestre_id", -1)
|
||||||
|
etudiants: list[dict] = []
|
||||||
|
|
||||||
|
titre = None
|
||||||
|
|
||||||
|
# Vérification du formsemestre_id
|
||||||
|
try:
|
||||||
|
formsemestre_id = int(formsemestre_id)
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
formsemestre_id = None
|
||||||
|
|
||||||
|
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
||||||
|
|
||||||
|
if etudid is not None:
|
||||||
|
etudiants.append(sco_etud.get_etud_info(etudid=int(etudid), filled=True)[0])
|
||||||
|
|
||||||
|
if group_ids is None:
|
||||||
|
group_ids = []
|
||||||
|
else:
|
||||||
|
group_ids = group_ids.split(",")
|
||||||
|
map(str, group_ids)
|
||||||
|
|
||||||
|
groups_infos = sco_groups_view.DisplayedGroupsInfos(group_ids)
|
||||||
|
|
||||||
|
etudiants.extend(
|
||||||
|
[
|
||||||
|
sco_etud.get_etud_info(etudid=m["etudid"], filled=True)[0]
|
||||||
|
for m in groups_infos.members
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
etudiants = list(sorted(etudiants, key=lambda x: x["nom"]))
|
||||||
|
|
||||||
|
header: str = html_sco_header.sco_header(
|
||||||
|
page_title="Assiduités Différées",
|
||||||
|
init_qtip=True,
|
||||||
|
javascripts=html_sco_header.BOOTSTRAP_MULTISELECT_JS
|
||||||
|
+ [
|
||||||
|
"js/assiduites.js",
|
||||||
|
"libjs/moment.new.min.js",
|
||||||
|
"libjs/moment-timezone.js",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
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>"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
return HTMLBuilder(
|
||||||
|
header,
|
||||||
|
render_template(
|
||||||
|
"assiduites/signal_assiduites_diff.j2",
|
||||||
|
etudiants=etudiants,
|
||||||
|
etat_def=sco_preferences.get_preference("assi_etat_defaut"),
|
||||||
|
moduleimpl_select=_module_selector(formsemestre),
|
||||||
|
gr=gr_tit,
|
||||||
|
sem=sem["titre_num"],
|
||||||
|
),
|
||||||
|
html_sco_header.sco_footer(),
|
||||||
|
).build()
|
||||||
|
|
||||||
|
|
||||||
def _module_selector(
|
def _module_selector(
|
||||||
formsemestre: FormSemestre, moduleimpl_id: int = None
|
formsemestre: FormSemestre, moduleimpl_id: int = None
|
||||||
) -> HTMLElement:
|
) -> HTMLElement:
|
||||||
|
Loading…
Reference in New Issue
Block a user