forked from ScoDoc/ScoDoc
Merge branch 'iziram-modif_assi'
This commit is contained in:
commit
5c6935337e
@ -353,12 +353,12 @@ class Assiduite(ScoDocModel):
|
||||
|
||||
elif self.external_data is not None and "module" in self.external_data:
|
||||
return (
|
||||
"Tout module"
|
||||
"Autre module (pas dans la liste)"
|
||||
if self.external_data["module"] == "Autre"
|
||||
else self.external_data["module"]
|
||||
)
|
||||
|
||||
return "Non spécifié" if traduire else None
|
||||
return "Module non spécifié" if traduire else None
|
||||
|
||||
def get_saisie(self) -> str:
|
||||
"""
|
||||
|
@ -25,8 +25,7 @@
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
"""HTML Header/Footer for ScoDoc pages
|
||||
"""
|
||||
"""HTML Header/Footer for ScoDoc pages"""
|
||||
|
||||
import html
|
||||
|
||||
@ -101,7 +100,7 @@ _HTML_BEGIN = f"""<!DOCTYPE html>
|
||||
<script src="{scu.STATIC_DIR}/libjs/menu.js"></script>
|
||||
<script src="{scu.STATIC_DIR}/libjs/bubble.js"></script>
|
||||
<script>
|
||||
window.onload=function(){{enableTooltips("gtrcontent")}};
|
||||
window.onload=function(){{enableTooltips("gtrcontent"); enableTooltips("sidebar");}};
|
||||
</script>
|
||||
|
||||
<script src="{scu.STATIC_DIR}/jQuery/jquery.js"></script>
|
||||
@ -218,7 +217,7 @@ def sco_header(
|
||||
<script src="{scu.STATIC_DIR}/libjs/menu.js"></script>
|
||||
<script src="{scu.STATIC_DIR}/libjs/bubble.js"></script>
|
||||
<script>
|
||||
window.onload=function(){{enableTooltips("gtrcontent")}};
|
||||
window.onload=function(){{enableTooltips("gtrcontent"); enableTooltips("sidebar");}};
|
||||
|
||||
const SCO_URL="{url_for("scolar.index_html", scodoc_dept=g.scodoc_dept)}";
|
||||
const SCO_TIMEZONE="{scu.TIME_ZONE}";
|
||||
|
@ -28,6 +28,7 @@
|
||||
"""
|
||||
Génération de la "sidebar" (marge gauche des pages HTML)
|
||||
"""
|
||||
|
||||
from flask import render_template, url_for
|
||||
from flask import g, request
|
||||
from flask_login import current_user
|
||||
@ -151,7 +152,7 @@ def sidebar(etudid: int = None):
|
||||
H = [
|
||||
f"""
|
||||
<!-- sidebar py -->
|
||||
<div class="sidebar">
|
||||
<div class="sidebar" id="sidebar">
|
||||
{ sidebar_common() }
|
||||
<div class="box-chercheetud">Chercher étudiant:<br>
|
||||
<form method="get" id="form-chercheetud"
|
||||
@ -193,7 +194,7 @@ def sidebar(etudid: int = None):
|
||||
formsemestre.date_debut.strftime(scu.DATE_FMT)
|
||||
} au {
|
||||
formsemestre.date_fin.strftime(scu.DATE_FMT)
|
||||
}">({
|
||||
}" data-tooltip>({
|
||||
sco_preferences.get_preference("assi_metrique", None)})
|
||||
<br>{nbabsjust:1g} J., {nbabsnj:1g} N.J.</span>"""
|
||||
)
|
||||
@ -227,12 +228,9 @@ def sidebar(etudid: int = None):
|
||||
<li><a href="{ url_for('assiduites.calendrier_assi_etud',
|
||||
scodoc_dept=g.scodoc_dept, etudid=etudid)
|
||||
}">Calendrier</a></li>
|
||||
<li><a href="{ url_for('assiduites.liste_assiduites_etud',
|
||||
scodoc_dept=g.scodoc_dept, etudid=etudid)
|
||||
}">Liste</a></li>
|
||||
<li><a href="{ url_for('assiduites.bilan_etud',
|
||||
scodoc_dept=g.scodoc_dept, etudid=etudid)
|
||||
}">Bilan</a></li>
|
||||
}" title="Les pages bilan et liste ont été fusionnées">Liste/Bilan</a></li>
|
||||
</ul>
|
||||
"""
|
||||
)
|
||||
|
@ -822,6 +822,35 @@ def _make_listes_sem(formsemestre: FormSemestre) -> str:
|
||||
</div>
|
||||
</div>
|
||||
<div class="sem-groups-assi">
|
||||
|
||||
"""
|
||||
)
|
||||
if can_edit_abs:
|
||||
H.append(
|
||||
f"""
|
||||
<div>
|
||||
<a class="stdlink" href="{
|
||||
url_for("assiduites.signal_assiduites_group",
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
jour=datetime.date.today().isoformat(),
|
||||
formsemestre_id=formsemestre.id,
|
||||
group_ids=group.id,
|
||||
)}">
|
||||
Saisir l'assiduité</a>
|
||||
</div>
|
||||
<div>
|
||||
<a class="stdlink" href="{
|
||||
url_for("assiduites.bilan_dept",
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
formsemestre_id=formsemestre.id,
|
||||
group_ids=group.id,
|
||||
)}">
|
||||
Justificatifs en attente</a>
|
||||
</div>
|
||||
"""
|
||||
)
|
||||
H.append(
|
||||
f"""
|
||||
<div>
|
||||
<a class="stdlink" href="{
|
||||
url_for("assiduites.visu_assi_group",
|
||||
@ -834,48 +863,20 @@ def _make_listes_sem(formsemestre: FormSemestre) -> str:
|
||||
</div>
|
||||
"""
|
||||
)
|
||||
|
||||
if can_edit_abs:
|
||||
H.append(
|
||||
f"""
|
||||
<div>
|
||||
<a class="stdlink" href="{
|
||||
url_for("assiduites.visu_assiduites_group",
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
formsemestre_id=formsemestre.id,
|
||||
jour = datetime.date.today().isoformat(),
|
||||
group_ids=group.id,
|
||||
)}">
|
||||
Visualiser</a>
|
||||
</div>
|
||||
<div>
|
||||
<a class="stdlink" href="{
|
||||
url_for("assiduites.signal_assiduites_group",
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
jour=datetime.date.today().isoformat(),
|
||||
formsemestre_id=formsemestre.id,
|
||||
group_ids=group.id,
|
||||
)}">
|
||||
Saisie journalière</a>
|
||||
</div>
|
||||
<div>
|
||||
<a class="stdlink" href="{
|
||||
url_for("assiduites.signal_assiduites_diff",
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
formsemestre_id=formsemestre.id,
|
||||
group_ids=group.id,
|
||||
)}">
|
||||
Saisie différée</a>
|
||||
</div>
|
||||
<div>
|
||||
<a class="stdlink" href="{
|
||||
url_for("assiduites.bilan_dept",
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
formsemestre_id=formsemestre.id,
|
||||
group_ids=group.id,
|
||||
)}">
|
||||
Justificatifs en attente</a>
|
||||
</div>
|
||||
"""
|
||||
)}" title="Page en cours de fusion et sera prochainement supprimée. Veuillez utiliser la page `Saisir l'assiduité`">
|
||||
(Saisie différée)</a>
|
||||
</div>
|
||||
"""
|
||||
)
|
||||
|
||||
H.append("</div>") # /sem-groups-assi
|
||||
|
@ -110,6 +110,7 @@ get_base_preferences(formsemestre_id)
|
||||
Return base preferences for current scodoc_dept (instance BasePreferences)
|
||||
|
||||
"""
|
||||
|
||||
import flask
|
||||
from flask import current_app, flash, g, request, url_for
|
||||
|
||||
@ -622,18 +623,6 @@ class BasePreferences:
|
||||
"explanation": "Désactive la saisie et l'affichage des présences",
|
||||
},
|
||||
),
|
||||
(
|
||||
"periode_defaut",
|
||||
{
|
||||
"initvalue": 2.0,
|
||||
"size": 10,
|
||||
"title": "Durée par défaut d'un créneau",
|
||||
"type": "float",
|
||||
"category": "assi",
|
||||
"only_global": True,
|
||||
"explanation": "Durée d'un créneau en heure. Utilisé dans les pages de saisie",
|
||||
},
|
||||
),
|
||||
(
|
||||
"nb_heures_par_jour",
|
||||
{
|
||||
@ -2302,9 +2291,7 @@ class BasePreferences:
|
||||
if "explanation" in descr:
|
||||
del descr["explanation"]
|
||||
if formsemestre_id:
|
||||
descr[
|
||||
"explanation"
|
||||
] = f"""ou <span class="spanlink"
|
||||
descr["explanation"] = f"""ou <span class="spanlink"
|
||||
onclick="set_global_pref(this, '{pref_name}');"
|
||||
>utiliser paramètre global</span>"""
|
||||
if formsemestre_id and self.is_global(formsemestre_id, pref_name):
|
||||
|
@ -302,7 +302,6 @@
|
||||
.rbtn {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@ -327,9 +326,12 @@
|
||||
background-image: url(../icons/absent.svg);
|
||||
}
|
||||
|
||||
.rbtn.aucun::before {
|
||||
background-image: url(../icons/aucun.svg);
|
||||
background-color: var(--color-defaut-dark);
|
||||
.rbtn.aucun {
|
||||
background-image: url("../icons/delete.svg");
|
||||
background-size: calc(100% - 8px) calc(100% - 8px);
|
||||
/* Adjust size to create "margin" */
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.rbtn.retard::before {
|
||||
|
1
app/static/icons/delete.svg
Normal file
1
app/static/icons/delete.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg id="Layer_1" height="512" viewBox="0 0 512 512" width="512" xmlns="http://www.w3.org/2000/svg" data-name="Layer 1"><path d="m170.8 14.221a14.21 14.21 0 0 1 14.2-14.207l141.991-.008a14.233 14.233 0 0 1 14.2 14.223v35.117h-170.391zm233.461 477.443a21.75 21.75 0 0 1 -21.856 20.33h-254.451a21.968 21.968 0 0 1 -21.854-20.416l-21.774-318.518h343.174l-23.234 318.6zm56.568-347.452h-409.658v-33a33.035 33.035 0 0 1 33.005-33.012l343.644-.011a33.051 33.051 0 0 1 33 33.02v33zm-270.79 291.851a14.422 14.422 0 1 0 28.844 0v-202.247a14.42 14.42 0 0 0 -28.839-.01v202.257zm102.9 0a14.424 14.424 0 1 0 28.848 0v-202.247a14.422 14.422 0 0 0 -28.843-.01z" fill="#fc3333" fill-rule="evenodd"/></svg>
|
After Width: | Height: | Size: 689 B |
@ -53,7 +53,7 @@ async function async_get(path, success, errors) {
|
||||
* @param {CallableFunction} errors fonction à effectuer en cas d'échec
|
||||
*/
|
||||
async function async_post(path, data, success, errors) {
|
||||
console.log("async_post " + path);
|
||||
// console.log("async_post " + path);
|
||||
let response;
|
||||
try {
|
||||
response = await fetch(path, {
|
||||
@ -401,7 +401,7 @@ async function creerTousLesEtudiants(etuds) {
|
||||
* @returns {String}
|
||||
*/
|
||||
async function getModuleImpl(assiduite) {
|
||||
if (assiduite == null) return "Pas de module";
|
||||
if (assiduite == null) return "Module non spécifié";
|
||||
const id = assiduite.moduleimpl_id;
|
||||
|
||||
if (id == null || id == undefined) {
|
||||
@ -414,7 +414,7 @@ async function getModuleImpl(assiduite) {
|
||||
? "Autre module (pas dans la liste)"
|
||||
: assiduite.external_data.module;
|
||||
} else {
|
||||
return "Pas de module";
|
||||
return "Module non spécifié";
|
||||
}
|
||||
}
|
||||
|
||||
@ -643,6 +643,9 @@ function mettreToutLeMonde(etat, el = null) {
|
||||
|
||||
// Suppression des assiduités
|
||||
if (etat == "vide") {
|
||||
if (!confirm("Effacer tout les évènements correspondant à cette plage ?")) {
|
||||
return; // annulation
|
||||
}
|
||||
const assiduites_id = lignesEtuds
|
||||
.filter((e) => e.getAttribute("type") == "edition")
|
||||
.map((e) => Number(e.getAttribute("assiduite_id")));
|
||||
@ -759,6 +762,7 @@ function envoiToastEtudiant(etat, etud) {
|
||||
pushToast(generateToast(span, getToastColorFromEtat(etat.toUpperCase()), 5));
|
||||
}
|
||||
|
||||
// TODO commenter toutes les fonctions js
|
||||
function envoiToastTous(etat, count) {
|
||||
const span = document.createElement("span");
|
||||
let etatAffiche = etat;
|
||||
@ -798,13 +802,16 @@ function estJourTravail(jour, nonWorkdays) {
|
||||
return !nonWorkdays.includes(d);
|
||||
}
|
||||
|
||||
function retourJourTravail(date) {
|
||||
function retourJourTravail(date, anti = true) {
|
||||
const jourMiliSecondes = 86400000; // 24 * 3600 * 1000 | H * s * ms
|
||||
let jour = date;
|
||||
let compte = 0;
|
||||
|
||||
while (!estJourTravail(jour, nonWorkDays) && compte++ < 7) {
|
||||
jour = new Date(jour - jourMiliSecondes);
|
||||
let temps = anti
|
||||
? jour - jourMiliSecondes
|
||||
: jour.valueOf() + jourMiliSecondes;
|
||||
jour = new Date(temps);
|
||||
}
|
||||
return jour;
|
||||
}
|
||||
@ -814,9 +821,12 @@ function dateCouranteEstTravaillee() {
|
||||
if (!estJourTravail(date, nonWorkDays)) {
|
||||
const nouvelleDate = retourJourTravail(date);
|
||||
$("#date").datepicker("setDate", nouvelleDate);
|
||||
|
||||
let msg = "Le jour sélectionné";
|
||||
if ((new Date()).format("YYYY-MM-DD") == date.format("YYYY-MM-DD")) {
|
||||
msg = "Aujourd'hui";
|
||||
}
|
||||
const att = document.createTextNode(
|
||||
`Le jour sélectionné (${Date.toFRA(
|
||||
`${msg} (${Date.toFRA(
|
||||
date.format("YYYY-MM-DD")
|
||||
)}) n'est pas un jour travaillé.`
|
||||
);
|
||||
@ -837,6 +847,17 @@ function dateCouranteEstTravaillee() {
|
||||
return true;
|
||||
}
|
||||
|
||||
function jourSuivant(anti = false) {
|
||||
let date = $("#date").datepicker("getDate");
|
||||
|
||||
date = anti ? date.add(-1, "days") : date.add(1, "days");
|
||||
|
||||
const nouvelleDate = retourJourTravail(date, anti);
|
||||
|
||||
$("#date").datepicker("setDate", nouvelleDate);
|
||||
creerTousLesEtudiants(etuds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajout de la visualisation des assiduités de la mini timeline
|
||||
* @param {HTMLElement} el l'élément survollé
|
||||
@ -876,6 +897,11 @@ function setupAssiduiteBubble(el, assiduite) {
|
||||
actionsDiv.appendChild(infos);
|
||||
bubble.appendChild(actionsDiv);
|
||||
|
||||
const stateDiv = document.createElement("div");
|
||||
stateDiv.className = "assiduite-state";
|
||||
stateDiv.textContent = `État: ${assiduite.etat.capitalize()}`;
|
||||
bubble.appendChild(stateDiv);
|
||||
|
||||
const idDiv = document.createElement("div");
|
||||
idDiv.className = "assiduite-id";
|
||||
getModuleImpl(assiduite).then((modImpl) => {
|
||||
@ -883,26 +909,32 @@ function setupAssiduiteBubble(el, assiduite) {
|
||||
});
|
||||
bubble.appendChild(idDiv);
|
||||
|
||||
const periodDivDeb = document.createElement("div");
|
||||
periodDivDeb.className = "assiduite-period";
|
||||
periodDivDeb.textContent = `${formatDateModal(assiduite.date_debut)}`;
|
||||
bubble.appendChild(periodDivDeb);
|
||||
const periodDivFin = document.createElement("div");
|
||||
periodDivFin.className = "assiduite-period";
|
||||
periodDivFin.textContent = `${formatDateModal(assiduite.date_fin)}`;
|
||||
bubble.appendChild(periodDivFin);
|
||||
// Affichage des dates
|
||||
// si les jours sont les mêmes, on affiche "jour hh:mm - hh:mm"
|
||||
// sinon on affiche "jour hh:mm - jour hh:mm"
|
||||
const periodDiv = document.createElement("div");
|
||||
periodDiv.className = "assiduite-period";
|
||||
const dateDeb = new Date(Date.removeUTC(assiduite.date_debut));
|
||||
const dateFin = new Date(Date.removeUTC(assiduite.date_fin));
|
||||
if (dateDeb.isSame(dateFin, "day")) {
|
||||
const jour = dateDeb.format("DD/MM/YYYY");
|
||||
const deb = dateDeb.format("HH:mm");
|
||||
const fin = dateFin.format("HH:mm");
|
||||
periodDiv.textContent = `${jour} de ${deb} à ${fin}`;
|
||||
} else {
|
||||
const jourDeb = dateDeb.format("DD/MM/YYYY");
|
||||
const jourFin = dateFin.format("DD/MM/YYYY");
|
||||
periodDiv.textContent = `du ${jourDeb} au ${jourFin}`;
|
||||
}
|
||||
|
||||
const stateDiv = document.createElement("div");
|
||||
stateDiv.className = "assiduite-state";
|
||||
stateDiv.textContent = `État: ${assiduite.etat.capitalize()}`;
|
||||
bubble.appendChild(stateDiv);
|
||||
bubble.appendChild(periodDiv);
|
||||
|
||||
const motifDiv = document.createElement("div");
|
||||
stateDiv.className = "assiduite-why";
|
||||
motifDiv.className = "assiduite-why";
|
||||
const motif = ["", null, undefined].includes(assiduite.desc)
|
||||
? "Pas de motif"
|
||||
? "Non spécifié"
|
||||
: assiduite.desc.capitalize();
|
||||
stateDiv.textContent = `Motif: ${motif}`;
|
||||
motifDiv.textContent = `Motif: ${motif}`;
|
||||
bubble.appendChild(motifDiv);
|
||||
|
||||
const userIdDiv = document.createElement("div");
|
||||
|
@ -11,8 +11,8 @@ h.id="btc";
|
||||
h.setAttribute("id","btc");
|
||||
h.style.position="absolute";
|
||||
document.getElementsByTagName("body")[0].appendChild(h);
|
||||
if(id==null) links=document.getElementsByTagName("a");
|
||||
else links=document.getElementById(id).getElementsByTagName("a");
|
||||
if(id==null) links=document.querySelectorAll("a, [data-tooltip]"); // was document.getElementsByTagName("a")
|
||||
else links=document.getElementById(id).querySelectorAll("a, [data-tooltip]");// was document.getElementById(id).getElementsByTagName("a")
|
||||
for(i=0;i<links.length;i++){
|
||||
Prepare(links[i]);
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
<h1>Traitement de l'assiduité</h1>
|
||||
<p class="help">
|
||||
Pour saisir l'assiduité ou consulter les états, il est recommandé de passer par
|
||||
Pour saisir l'assiduité ou consulter les états, passer par
|
||||
le semestre concerné (saisie par jour ou saisie différée).
|
||||
</p>
|
||||
|
||||
|
@ -86,9 +86,6 @@ Bilan assiduité de {{sco.etud.nomprenom}}
|
||||
|
||||
<div class="scobox">
|
||||
<section class="nonvalide">
|
||||
<div class="help">Le tableau n'affiche que les assiduités non justifiées
|
||||
et les justificatifs soumis / modifiés
|
||||
</div>
|
||||
{{tableau | safe }}
|
||||
</section>
|
||||
</div>
|
||||
@ -99,6 +96,9 @@ Bilan assiduité de {{sco.etud.nomprenom}}
|
||||
département)</p>
|
||||
<p>Les statistiques sont calculées entre les deux dates sélectionnées. Après modification des dates,
|
||||
appuyer sur le bouton "Actualiser"</p>
|
||||
|
||||
{% include "assiduites/explication_etats_justifs.j2" %}
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
@ -1,27 +0,0 @@
|
||||
{% extends "sco_page.j2" %}
|
||||
|
||||
{% block title %}
|
||||
Assiduité de {{etud.nomprenom}}
|
||||
{% endblock title %}
|
||||
|
||||
{% block styles %}
|
||||
{{ super() }}
|
||||
<link rel="stylesheet" href="{{scu.STATIC_DIR}}/css/assiduites.css">
|
||||
{% endblock styles %}
|
||||
|
||||
{% block scripts %}
|
||||
{{ super() }}
|
||||
<script src="{{scu.STATIC_DIR}}/js/date_utils.js"></script>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block app_content %}
|
||||
<div class="pageContent">
|
||||
|
||||
<h2>Liste de l'assiduité et des justificatifs de {{sco.etud.html_link_fiche()|safe}}</h2>
|
||||
{{tableau | safe }}
|
||||
</div>
|
||||
|
||||
{% include "assiduites/explication_etats_justifs.j2" %}
|
||||
|
||||
{% endblock app_content %}
|
@ -570,6 +570,13 @@ window.addEventListener("load", main);
|
||||
|
||||
<h2>Signalement différé de l'assiduité {{gr |safe}}</h2>
|
||||
|
||||
<div class="ue_warning">
|
||||
Attention, cette page est en cours de fusion avec la page de Saisie journalière.
|
||||
<br>
|
||||
Vous pouvez dès à présent cliquer sur <a href="{{url_for('assiduites.signal_assiduites_group', scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id, group_ids=group_ids)}}" target="_blank">ce lien</a> pour accéder à la nouvelle version.
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div id="fix">
|
||||
<!-- Nouvelle Plage
|
||||
|
@ -105,6 +105,24 @@
|
||||
<link rel="stylesheet" href="{{scu.STATIC_DIR}}/libjs/bootstrap-multiselect-1.1.2/bootstrap-multiselect.min.css">
|
||||
<link rel="stylesheet" href="{{scu.STATIC_DIR}}/css/assiduites.css">
|
||||
<link rel="stylesheet" href="{{scu.STATIC_DIR}}/css/minitimeline.css">
|
||||
|
||||
<style>
|
||||
#retour-haut{
|
||||
position: fixed;
|
||||
bottom: 10px;
|
||||
right: 10px;
|
||||
font-size: 3em;
|
||||
padding: 5px;
|
||||
border-radius: 5px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
html{
|
||||
scroll-behavior: smooth !important;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
{% endblock styles %}
|
||||
|
||||
|
||||
@ -113,6 +131,10 @@
|
||||
{{ minitimeline|safe }}
|
||||
<section id="content">
|
||||
|
||||
<a id="retour-haut" href="#gtrcontent">
|
||||
⬆️
|
||||
</a>
|
||||
|
||||
<div class="no-display">
|
||||
<span class="formsemestre_id">{{formsemestre_id}}</span>
|
||||
<span id="formsemestre_date_debut">{{formsemestre_date_debut}}</span>
|
||||
@ -131,12 +153,22 @@
|
||||
<div class="infos">
|
||||
<div class="infos-button">Groupes : {{grp|safe}}</div>
|
||||
<div>
|
||||
<button class="btn_date" onclick="jourSuivant(true)">
|
||||
⇤
|
||||
</button>
|
||||
<input type="text" name="date" id="date" class="datepicker" value="{{date}}">
|
||||
</div>
|
||||
<button class="btn_date" onclick="jourSuivant(false)">
|
||||
⇥
|
||||
</button>
|
||||
</div>
|
||||
</fieldset>
|
||||
<div style="display: {{'none' if readonly == 'true' else 'block'}};">
|
||||
{{timeline|safe}}
|
||||
<div>
|
||||
<button onclick="setPeriodValues(t_start, t_mid)">Matin</button>
|
||||
<button onclick="setPeriodValues(t_mid, t_end)">Après-Midi</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if readonly == "false" %}
|
||||
@ -162,14 +194,14 @@
|
||||
<fieldset class="btns_field mass">
|
||||
{% if not non_present %}
|
||||
<input type="checkbox" value="present" name="mass_btn_assiduites" id="mass_rbtn_present"
|
||||
class="rbtn present" onclick="mettreToutLeMonde('present', this)" title="Present">
|
||||
class="rbtn present" onclick="mettreToutLeMonde('present', this)" title="Indique l'état Présent pour tous les étudiants" data-tooltip>
|
||||
{% endif %}
|
||||
<input type="checkbox" value="retard" name="mass_btn_assiduites" id="mass_rbtn_retard"
|
||||
class="rbtn retard" onclick="mettreToutLeMonde('retard', this)" title="Retard">
|
||||
class="rbtn retard" onclick="mettreToutLeMonde('retard', this)" title="Indique l'état Retard pour tous les étudiants" data-tooltip>
|
||||
<input type="checkbox" value="absent" name="mass_btn_assiduites" id="mass_rbtn_absent"
|
||||
class="rbtn absent" onclick="mettreToutLeMonde('absent', this)" title="Absent">
|
||||
class="rbtn absent" onclick="mettreToutLeMonde('absent', this)" title="Indique l'état Absent pour tous les étudiants" data-tooltip>
|
||||
<input type="checkbox" value="remove" name="mass_btn_assiduites" id="mass_rbtn_aucun"
|
||||
class="rbtn aucun" onclick="mettreToutLeMonde('vide', this)" title="Supprimer">
|
||||
class="rbtn aucun" onclick="mettreToutLeMonde('vide', this)" title="Retire l'état pour tous les étudiants" data-tooltip>
|
||||
</fieldset>
|
||||
<em>Les saisies ci-dessous sont enregistrées au fur et à mesure.</em>
|
||||
</div>
|
||||
|
@ -1,8 +1,7 @@
|
||||
<div class="assiduite-bubble {{etat}}">
|
||||
<div class="assiduite-id">{{moduleimpl}}</div>
|
||||
<div class="assiduite-period">{{date_debut}}</div>
|
||||
<div class="assiduite-period">{{date_fin}}</div>
|
||||
<div class="assiduite-state">État: {{etat}}</div>
|
||||
<div class="assiduite-id">{{moduleimpl}}</div>
|
||||
<div class="assiduite-period">{{date}}</div>
|
||||
<div class="assiduite-why">Motif: {{motif}}</div>
|
||||
<div class="assiduite-user_id">{{saisie}}</div>
|
||||
</div>
|
@ -17,12 +17,13 @@
|
||||
const timelineContainer = document.querySelector(".timeline-container");
|
||||
const periodTimeLine = document.querySelector(".period");
|
||||
const t_start = {{ t_start }};
|
||||
const t_mid = {{ t_mid }};
|
||||
const t_end = {{ t_end }};
|
||||
|
||||
const tick_time = 60 / {{ tick_time }};
|
||||
const tick_delay = 1 / tick_time;
|
||||
|
||||
const period_default = {{ periode_defaut }};
|
||||
const period_default = 2;
|
||||
|
||||
let handleMoving = false;
|
||||
|
||||
@ -133,6 +134,7 @@
|
||||
timelineContainer.removeEventListener("mousemove", onMouseMove);
|
||||
handleMoving = false;
|
||||
func_call();
|
||||
savePeriodInLocalStorage();
|
||||
|
||||
}
|
||||
timelineContainer.addEventListener("mousemove", onMouseMove);
|
||||
@ -166,6 +168,7 @@
|
||||
snapHandlesToQuarters();
|
||||
timelineContainer.removeEventListener("mousemove", onMouseMove);
|
||||
func_call();
|
||||
savePeriodInLocalStorage();
|
||||
}
|
||||
timelineContainer.addEventListener("mousemove", onMouseMove);
|
||||
timelineContainer.addEventListener("touchmove", onMouseMove);
|
||||
@ -264,6 +267,7 @@
|
||||
snapHandlesToQuarters();
|
||||
updatePeriodTimeLabel()
|
||||
func_call();
|
||||
savePeriodInLocalStorage();
|
||||
}
|
||||
|
||||
function snapHandlesToQuarters() {
|
||||
@ -309,9 +313,23 @@
|
||||
}
|
||||
}
|
||||
|
||||
function savePeriodInLocalStorage(){
|
||||
const dates = getPeriodValues();
|
||||
localStorage.setItem("sco-timeline-values", JSON.stringify(dates));
|
||||
}
|
||||
|
||||
function loadPeriodFromLocalStorage(){
|
||||
const dates = JSON.parse(localStorage.getItem("sco-timeline-values"));
|
||||
if(dates){
|
||||
setPeriodValues(...dates);
|
||||
}else{
|
||||
setPeriodValues(t_start, t_start + period_default);
|
||||
}
|
||||
}
|
||||
|
||||
createTicks();
|
||||
|
||||
setPeriodValues(t_start, t_start + period_default);
|
||||
loadPeriodFromLocalStorage();
|
||||
|
||||
{% if heures %}
|
||||
let [heure_deb, heure_fin] = [{{ heures | safe }}]
|
||||
|
@ -49,7 +49,7 @@
|
||||
<script src="{{scu.STATIC_DIR}}/js/scodoc.js"></script>
|
||||
<script src="{{scu.STATIC_DIR}}/DataTables/datatables.min.js"></script>
|
||||
<script>
|
||||
window.onload = function () { enableTooltips("gtrcontent") };
|
||||
window.onload = function () { enableTooltips("gtrcontent"); enableTooltips("sidebar"); };
|
||||
|
||||
const SCO_URL = "{{ url_for('scolar.index_html', scodoc_dept=g.scodoc_dept) }}";
|
||||
</script>
|
||||
|
@ -1,7 +1,7 @@
|
||||
{# Barre marge gauche ScoDoc #}
|
||||
{# -*- mode: jinja-html -*- #}
|
||||
<!-- sidebar -->
|
||||
<div class="sidebar">
|
||||
<div class="sidebar" id="sidebar">
|
||||
{# sidebar_common #}
|
||||
<a class="scodoc_title" href="{{
|
||||
url_for('scodoc.index', scodoc_dept=g.scodoc_dept) }}">ScoDoc {{ sco.SCOVERSION }}</a>
|
||||
@ -57,7 +57,7 @@
|
||||
<b>Absences</b>
|
||||
{% if sco.etud_cur_sem %}
|
||||
<span title="absences du {{ sco.etud_cur_sem['date_debut'].strftime('%d/%m/%Y') }}
|
||||
au {{ sco.etud_cur_sem['date_fin'].strftime('%d/%m/%Y') }}">({{sco.prefs["assi_metrique"]}})
|
||||
au {{ sco.etud_cur_sem['date_fin'].strftime('%d/%m/%Y') }}" data-tooltip>({{sco.prefs["assi_metrique"]}})
|
||||
<br />{{'%1g'|format(sco.nb_abs_just)}} J., {{'%1g'|format(sco.nb_abs_nj)}} N.J.</span>
|
||||
{% endif %}
|
||||
<ul>
|
||||
@ -73,10 +73,8 @@
|
||||
{% endif %}
|
||||
<li><a href="{{ url_for('assiduites.calendrier_assi_etud', scodoc_dept=g.scodoc_dept,
|
||||
etudid=sco.etud.id) }}">Calendrier</a></li>
|
||||
<li><a href="{{ url_for('assiduites.liste_assiduites_etud', scodoc_dept=g.scodoc_dept,
|
||||
etudid=sco.etud.id) }}">Liste</a></li>
|
||||
<li><a href="{{ url_for('assiduites.bilan_etud', scodoc_dept=g.scodoc_dept,
|
||||
etudid=sco.etud.id) }}">Bilan</a></li>
|
||||
etudid=sco.etud.id) }}" title="Les pages bilan et liste ont été fusionnées">Liste/Bilan</a></li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div> {# /etud-insidebar #}
|
||||
|
@ -511,51 +511,6 @@ def _record_assiduite_etud(
|
||||
return False
|
||||
|
||||
|
||||
@bp.route("/liste_assiduites_etud")
|
||||
@scodoc
|
||||
@permission_required(Permission.ScoView)
|
||||
def liste_assiduites_etud():
|
||||
"""
|
||||
liste_assiduites_etud Affichage de toutes les assiduites et justificatifs d'un etudiant
|
||||
Args:
|
||||
etudid (int): l'identifiant de l'étudiant
|
||||
|
||||
Returns:
|
||||
str: l'html généré
|
||||
"""
|
||||
|
||||
# Récupération de l'étudiant concerné
|
||||
etudid = request.args.get("etudid", -1)
|
||||
etud: Identite = Identite.query.get_or_404(etudid)
|
||||
if etud.dept_id != g.scodoc_dept_id:
|
||||
abort(404, "étudiant inexistant dans ce département")
|
||||
|
||||
# Gestion d'une assiduité unique (redirigé depuis le calendrier) TODO-Assiduites
|
||||
assiduite_id: int = request.args.get("assiduite_id", -1)
|
||||
|
||||
# Préparation de la page
|
||||
tableau = _prepare_tableau(
|
||||
liste_assi.AssiJustifData.from_etudiants(
|
||||
etud,
|
||||
),
|
||||
filename=f"assiduites-justificatifs-{etud.id}",
|
||||
afficher_etu=False,
|
||||
filtre=liste_assi.AssiFiltre(type_obj=0),
|
||||
options=liste_assi.AssiDisplayOptions(show_module=True),
|
||||
cache_key=f"tableau-etud-{etud.id}",
|
||||
)
|
||||
if not tableau[0]:
|
||||
return tableau[1]
|
||||
# Page HTML:
|
||||
return render_template(
|
||||
"assiduites/pages/liste_assiduites.j2",
|
||||
assi_id=assiduite_id,
|
||||
etud=etud,
|
||||
tableau=tableau[1],
|
||||
sco=ScoData(etud),
|
||||
)
|
||||
|
||||
|
||||
@bp.route("/bilan_etud")
|
||||
@scodoc
|
||||
@permission_required(Permission.ScoView)
|
||||
@ -583,28 +538,19 @@ def bilan_etud():
|
||||
sco_preferences.get_preference("assi_metrique", dept_id=g.scodoc_dept_id),
|
||||
)
|
||||
|
||||
# Récupération des assiduités et justificatifs de l'étudiant
|
||||
data = liste_assi.AssiJustifData(
|
||||
etud.assiduites.filter(
|
||||
Assiduite.etat != scu.EtatAssiduite.PRESENT, Assiduite.est_just == False
|
||||
# Préparation de la page
|
||||
tableau = _prepare_tableau(
|
||||
liste_assi.AssiJustifData.from_etudiants(
|
||||
etud,
|
||||
),
|
||||
etud.justificatifs.filter(
|
||||
Justificatif.etat.in_(
|
||||
[scu.EtatJustificatif.ATTENTE, scu.EtatJustificatif.MODIFIE]
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
table = _prepare_tableau(
|
||||
data,
|
||||
filename=f"assiduites-justificatifs-{etud.id}",
|
||||
afficher_etu=False,
|
||||
filename=f"Bilan assiduité {etud.nomprenom}",
|
||||
titre="Bilan de l'assiduité de l'étudiant",
|
||||
cache_key=f"tableau-etud-{etud.id}-bilan",
|
||||
filtre=liste_assi.AssiFiltre(type_obj=0),
|
||||
options=liste_assi.AssiDisplayOptions(show_module=True),
|
||||
cache_key=f"tableau-etud-{etud.id}",
|
||||
)
|
||||
|
||||
if not table[0]:
|
||||
return table[1]
|
||||
if not tableau[0]:
|
||||
return tableau[1]
|
||||
|
||||
# Génération de la page HTML
|
||||
return render_template(
|
||||
@ -614,7 +560,7 @@ def bilan_etud():
|
||||
date_debut=date_debut,
|
||||
date_fin=date_fin,
|
||||
sco=ScoData(etud),
|
||||
tableau=table[1],
|
||||
tableau=tableau[1],
|
||||
)
|
||||
|
||||
|
||||
@ -654,7 +600,7 @@ def edit_justificatif_etud(justif_id: int):
|
||||
back_url = request.args.get("back_url", None)
|
||||
|
||||
redirect_url = back_url or url_for(
|
||||
"assiduites.liste_assiduites_etud",
|
||||
"assiduites.bilan_etud",
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
etudid=justif.etudiant.id,
|
||||
)
|
||||
@ -958,8 +904,6 @@ def choix_date() -> str:
|
||||
Route utilisée uniquement si la date courante n'est pas dans le semestre
|
||||
concerné par la requête vers une des pages suivantes :
|
||||
- saisie_assiduites_group
|
||||
- visu_assiduites_group
|
||||
|
||||
"""
|
||||
formsemestre_id = request.args.get("formsemestre_id")
|
||||
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
||||
@ -989,11 +933,7 @@ def choix_date() -> str:
|
||||
if ok:
|
||||
return redirect(
|
||||
url_for(
|
||||
(
|
||||
"assiduites.signal_assiduites_group"
|
||||
if request.args.get("readonly") is None
|
||||
else "assiduites.visu_assiduites_group"
|
||||
),
|
||||
"assiduites.signal_assiduites_group",
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
formsemestre_id=formsemestre_id,
|
||||
group_ids=group_ids,
|
||||
@ -1065,7 +1005,7 @@ def signal_assiduites_group():
|
||||
)
|
||||
if not groups_infos.members:
|
||||
return (
|
||||
html_sco_header.sco_header(page_title="Saisie journalière de l'assiduité")
|
||||
html_sco_header.sco_header(page_title="Saisie de l'assiduité")
|
||||
+ "<h3>Aucun étudiant ! </h3>"
|
||||
+ html_sco_header.sco_footer()
|
||||
)
|
||||
@ -1156,137 +1096,7 @@ def signal_assiduites_group():
|
||||
sco=ScoData(formsemestre=formsemestre),
|
||||
sem=sem["titre_num"],
|
||||
timeline=_timeline(heures=",".join([f"'{s}'" for s in heures])),
|
||||
title="Saisie journalière des assiduités",
|
||||
)
|
||||
|
||||
|
||||
@bp.route("/visu_assiduites_group")
|
||||
@scodoc
|
||||
@permission_required(Permission.ScoView)
|
||||
def visu_assiduites_group():
|
||||
"""
|
||||
Visualisation des assiduités des groupes pour le jour donné
|
||||
dans le formsemestre_id et le moduleimpl_id
|
||||
Returns:
|
||||
str: l'html généré
|
||||
"""
|
||||
|
||||
# Récupération des paramètres de la requête
|
||||
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)
|
||||
if group_ids is None:
|
||||
group_ids = []
|
||||
else:
|
||||
group_ids = group_ids.split(",")
|
||||
map(str, group_ids)
|
||||
|
||||
# Vérification du moduleimpl_id
|
||||
if moduleimpl_id is not None:
|
||||
try:
|
||||
moduleimpl_id = int(moduleimpl_id)
|
||||
except (TypeError, ValueError) as exc:
|
||||
raise ScoValueError("identifiant de moduleimpl invalide") from exc
|
||||
# Vérification du formsemestre_id
|
||||
if formsemestre_id is not None:
|
||||
try:
|
||||
formsemestre_id = int(formsemestre_id)
|
||||
except (TypeError, ValueError) as exc:
|
||||
raise ScoValueError("identifiant de formsemestre invalide") from exc
|
||||
|
||||
# Récupérations des/du groupe(s)
|
||||
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 de l'assiduité")
|
||||
+ "<h3>Aucun étudiant ! </h3>"
|
||||
+ html_sco_header.sco_footer()
|
||||
)
|
||||
|
||||
# --- 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")
|
||||
|
||||
# Récupération des étudiants du/des groupe(s)
|
||||
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 or real_date > formsemestre.date_fin:
|
||||
# Si le jour est hors semestre, renvoyer vers choix date
|
||||
return redirect(
|
||||
url_for(
|
||||
"assiduites.choix_date",
|
||||
formsemestre_id=formsemestre_id,
|
||||
group_ids=group_ids,
|
||||
moduleimpl_id=moduleimpl_id,
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
readonly="true",
|
||||
)
|
||||
)
|
||||
|
||||
# --- 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 du HTML ---
|
||||
|
||||
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>"
|
||||
)
|
||||
|
||||
# Récupération du semestre en dictionnaire
|
||||
sem = formsemestre.to_dict()
|
||||
|
||||
return render_template(
|
||||
"assiduites/pages/signal_assiduites_group.j2",
|
||||
date=_dateiso_to_datefr(date),
|
||||
defdem=_get_etuds_dem_def(formsemestre),
|
||||
forcer_module=sco_preferences.get_preference(
|
||||
"forcer_module",
|
||||
formsemestre_id=formsemestre_id,
|
||||
dept_id=g.scodoc_dept_id,
|
||||
),
|
||||
formsemestre_date_debut=str(formsemestre.date_debut),
|
||||
formsemestre_date_fin=str(formsemestre.date_fin),
|
||||
formsemestre_id=formsemestre_id,
|
||||
gr_tit=gr_tit,
|
||||
grp=sco_groups_view.menu_groups_choice(groups_infos),
|
||||
minitimeline=_mini_timeline(),
|
||||
moduleimpl_select=_module_selector(formsemestre, moduleimpl_id),
|
||||
nonworkdays=_non_work_days(),
|
||||
sem=sem["titre_num"],
|
||||
timeline=_timeline(),
|
||||
readonly="true",
|
||||
sco=ScoData(formsemestre=formsemestre),
|
||||
title="Saisie journalière de l'assiduité",
|
||||
title="Saisie de l'assiduité",
|
||||
)
|
||||
|
||||
|
||||
@ -2028,6 +1838,8 @@ def signal_assiduites_diff():
|
||||
dept_id=g.scodoc_dept_id,
|
||||
),
|
||||
nouv_plage=nouv_plage,
|
||||
formsemestre_id=formsemestre_id,
|
||||
group_ids=group_ids,
|
||||
)
|
||||
|
||||
|
||||
@ -2298,89 +2110,6 @@ def _get_date_str(deb: datetime.datetime, fin: datetime.datetime) -> str:
|
||||
return f'du {deb.strftime("%d/%m/%Y %H:%M")} au {fin.strftime("%d/%m/%Y %H:%M")}'
|
||||
|
||||
|
||||
def _get_days_between_dates(deb: str, fin: str) -> str:
|
||||
"""
|
||||
_get_days_between_dates récupère tous les jours entre deux dates
|
||||
|
||||
Args:
|
||||
deb (str): date de début
|
||||
fin (str): date de fin
|
||||
|
||||
Returns:
|
||||
str: une chaine json représentant une liste des jours
|
||||
['date_iso','date_iso2', ...]
|
||||
"""
|
||||
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: list[dict],
|
||||
moduleimpl_select: str,
|
||||
date: str = None,
|
||||
periode: dict[str, str] = None,
|
||||
formsemestre_id: int = None,
|
||||
) -> str:
|
||||
"""
|
||||
_differee Génère un tableau de saisie différé
|
||||
|
||||
Args:
|
||||
etudiants (list[dict]): la liste des étudiants (représentés par des dictionnaires)
|
||||
moduleimpl_select (str): l'html représentant le selecteur de module
|
||||
date (str, optional): la première date à afficher. Defaults to None.
|
||||
periode (dict[str, str], optional):La période par défaut de la première colonne.
|
||||
formsemestre_id (int, optional): l'id du semestre pour le selecteur de module.
|
||||
|
||||
Returns:
|
||||
str: le widget (html/css/js)
|
||||
"""
|
||||
if date is None:
|
||||
date = datetime.date.today().isoformat()
|
||||
|
||||
forcer_module = sco_preferences.get_preference(
|
||||
"forcer_module",
|
||||
formsemestre_id=formsemestre_id,
|
||||
dept_id=g.scodoc_dept_id,
|
||||
)
|
||||
|
||||
assi_etat_defaut = sco_preferences.get_preference(
|
||||
"assi_etat_defaut",
|
||||
formsemestre_id=formsemestre_id,
|
||||
dept_id=g.scodoc_dept_id,
|
||||
)
|
||||
|
||||
periode_defaut = sco_preferences.get_preference(
|
||||
"periode_defaut",
|
||||
formsemestre_id=formsemestre_id,
|
||||
dept_id=g.scodoc_dept_id,
|
||||
)
|
||||
|
||||
return render_template(
|
||||
"assiduites/widgets/differee.j2",
|
||||
etudiants=etudiants,
|
||||
assi_etat_defaut=assi_etat_defaut,
|
||||
periode_defaut=periode_defaut,
|
||||
forcer_module=forcer_module,
|
||||
moduleimpl_select=moduleimpl_select,
|
||||
date=date,
|
||||
periode=periode,
|
||||
)
|
||||
|
||||
|
||||
def _module_selector(formsemestre: FormSemestre, moduleimpl_id: int = None) -> str:
|
||||
"""
|
||||
_module_selector Génère un HTMLSelectElement à partir des moduleimpl du formsemestre
|
||||
@ -2450,7 +2179,7 @@ def _module_selector_multiple(
|
||||
)
|
||||
|
||||
|
||||
def _timeline(formsemestre_id: int = None, heures=None) -> str:
|
||||
def _timeline(heures=None) -> str:
|
||||
"""
|
||||
_timeline retourne l'html de la timeline
|
||||
|
||||
@ -2465,11 +2194,9 @@ def _timeline(formsemestre_id: int = None, heures=None) -> str:
|
||||
return render_template(
|
||||
"assiduites/widgets/timeline.j2",
|
||||
t_start=ScoDocSiteConfig.assi_get_rounded_time("assi_morning_time", "08:00:00"),
|
||||
t_mid=ScoDocSiteConfig.assi_get_rounded_time("assi_lunch_time", "13:00:00"),
|
||||
t_end=ScoDocSiteConfig.assi_get_rounded_time("assi_afternoon_time", "18:00:00"),
|
||||
tick_time=ScoDocSiteConfig.get("assi_tick_time", 15),
|
||||
periode_defaut=sco_preferences.get_preference(
|
||||
"periode_defaut", formsemestre_id
|
||||
),
|
||||
heures=heures,
|
||||
)
|
||||
|
||||
@ -2854,14 +2581,26 @@ def _generate_assiduite_bubble(assiduite: Assiduite) -> str:
|
||||
# Récupérer informations saisie
|
||||
saisie: str = assiduite.get_saisie()
|
||||
|
||||
motif: str = assiduite.description if assiduite.description else ""
|
||||
motif: str = assiduite.description or "Non spécifié"
|
||||
|
||||
# Récupérer date
|
||||
|
||||
if assiduite.date_debut.date() == assiduite.date_fin.date():
|
||||
jour = assiduite.date_debut.strftime("%d/%m/%Y")
|
||||
heure_deb: str = assiduite.date_debut.strftime("%H:%M")
|
||||
heure_fin: str = assiduite.date_fin.strftime("%H:%M")
|
||||
date: str = f"{jour} de {heure_deb} à {heure_fin}"
|
||||
else:
|
||||
date: str = (
|
||||
f"du {assiduite.date_debut.strftime('%d/%m/%Y')} "
|
||||
+ f"au {assiduite.date_fin.strftime('%d/%m/%Y')}"
|
||||
)
|
||||
|
||||
return render_template(
|
||||
"assiduites/widgets/assiduite_bubble.j2",
|
||||
moduleimpl=moduleimpl_infos,
|
||||
etat=scu.EtatAssiduite(assiduite.etat).name.lower(),
|
||||
date_debut=assiduite.date_debut.strftime("%d/%m/%Y %H:%M"),
|
||||
date_fin=assiduite.date_fin.strftime("%d/%m/%Y %H:%M"),
|
||||
date=date,
|
||||
saisie=saisie,
|
||||
motif=motif,
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user