1
0
forked from ScoDoc/ScoDoc

TYraitement erreur saisie assiduité + cosmetic

This commit is contained in:
Emmanuel Viennet 2024-09-02 10:35:24 +02:00
parent 04a8177d12
commit 2de4f6e0b3
12 changed files with 44 additions and 206 deletions

View File

@ -29,16 +29,10 @@
Génération de la "sidebar" (marge gauche des pages HTML) Génération de la "sidebar" (marge gauche des pages HTML)
""" """
from flask import render_template, url_for from flask import request
from flask import g, request
from flask_login import current_user
from app import db from app import db
from app.models import Evaluation, GroupDescr, Identite, ModuleImpl, Partition from app.models import Evaluation, GroupDescr, ModuleImpl, Partition
import app.scodoc.sco_utils as scu
from app.scodoc import sco_preferences
from app.scodoc.sco_permissions import Permission
from sco_version import SCOVERSION
def retreive_formsemestre_from_request() -> int: def retreive_formsemestre_from_request() -> int:
@ -93,173 +87,3 @@ def retreive_formsemestre_from_request() -> int:
return int(formsemestre_id) return int(formsemestre_id)
except ValueError: except ValueError:
return None # no current formsemestre return None # no current formsemestre
def sidebar_common():
"partie commune à toutes les sidebar"
home_link = url_for("scodoc.index", scodoc_dept=g.scodoc_dept)
H = [
f"""<a class="scodoc_title" href="{home_link}">ScoDoc {SCOVERSION}</a><br>
<a href="{home_link}" class="sidebar">Accueil</a> <br>
<div id="authuser"><a id="authuserlink" href="{
url_for("users.user_info_page",
scodoc_dept=g.scodoc_dept, user_name=current_user.user_name)
}">{current_user.user_name}</a>
<br><a id="deconnectlink" href="{url_for("auth.logout")}">déconnexion</a>
</div>
{sidebar_dept()}
<h2 class="insidebar">Scolarité</h2>
<a href="{
url_for("scolar.index_html", scodoc_dept=g.scodoc_dept)
}" class="sidebar">Semestres</a> <br>
<a href="{
url_for("notes.index_html", scodoc_dept=g.scodoc_dept)
}" class="sidebar">Formations</a> <br>
"""
]
if current_user.has_permission(Permission.AbsChange):
H.append(
f""" <a href="{
url_for("assiduites.bilan_dept", scodoc_dept=g.scodoc_dept)
}" class="sidebar">Assiduité</a> <br> """
)
if current_user.has_permission(
Permission.UsersAdmin
) or current_user.has_permission(Permission.UsersView):
H.append(
f"""<a href="{
url_for("users.index_html", scodoc_dept=g.scodoc_dept)
}" class="sidebar">Utilisateurs</a> <br>"""
)
if current_user.has_permission(Permission.EditPreferences):
H.append(
f"""<a href="{url_for("scolar.edit_preferences", scodoc_dept=g.scodoc_dept)}"
class="sidebar">Paramétrage</a> <br>"""
)
return "".join(H)
def sidebar(etudid: int = None):
"Main HTML page sidebar"
# rewritten from legacy DTML code
from app.scodoc import sco_assiduites
from app.scodoc import sco_etud
params = {}
H = [
f"""
<!-- sidebar py -->
<div class="sidebar" id="sidebar">
{ sidebar_common() }
<div class="box-chercheetud">Chercher étudiant:<br>
<form method="get" id="form-chercheetud"
action="{url_for('scolar.search_etud_in_dept', scodoc_dept=g.scodoc_dept) }">
<div><input type="text" size="12" class="in-expnom" name="expnom" spellcheck="false"></input></div>
</form></div>
<div class="etud-insidebar">
"""
]
# ---- Il y-a-t-il un etudiant selectionné ?
etudid = etudid if etudid is not None else g.get("etudid", None)
if etudid is None:
if request.method == "GET":
etudid = request.args.get("etudid", None)
elif request.method == "POST":
etudid = request.form.get("etudid", None)
if etudid is not None:
etud = Identite.get_etud(etudid)
# compte les absences du semestre en cours
H.append(
f"""<h2 id="insidebar-etud"><a href="{
url_for(
"scolar.fiche_etud", scodoc_dept=g.scodoc_dept, etudid=etudid
)
}" class="sidebar">
<font color="#FF0000">{etud.civilite_str} {etud.nom_disp()}</font></a>
</h2>
<b>Absences</b>"""
)
inscription = etud.inscription_courante()
if inscription:
formsemestre = inscription.formsemestre
nbabsnj, nbabsjust, _ = sco_assiduites.formsemestre_get_assiduites_count(
etudid, formsemestre
)
H.append(
f"""<span title="absences du {
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>"""
)
H.append("<ul>")
if current_user.has_permission(Permission.AbsChange):
# essaie de conserver le semestre actuellement en vue
cur_formsemestre_id = retreive_formsemestre_from_request()
H.append(
f"""
<li><a href="{
url_for('assiduites.ajout_assiduite_etud',
scodoc_dept=g.scodoc_dept, etudid=etudid)
}">Ajouter</a></li>
<li><a href="{
url_for('assiduites.ajout_justificatif_etud',
scodoc_dept=g.scodoc_dept, etudid=etudid,
formsemestre_id=cur_formsemestre_id,
)
}">Justifier</a></li>
"""
)
if sco_preferences.get_preference("handle_billets_abs"):
H.append(
f"""<li><a href="{
url_for('absences.billets_etud',
scodoc_dept=g.scodoc_dept, etudid=etudid)
}">Billets</a></li>"""
)
H.append(
f"""
<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.bilan_etud',
scodoc_dept=g.scodoc_dept, etudid=etudid)
}" title="Les pages bilan et liste ont été fusionnées">Liste/Bilan</a></li>
</ul>
"""
)
else:
pass # H.append("(pas d'étudiant en cours)")
# ---------
H.append("</div>") # /etud-insidebar
# Logo
H.append(
f"""<div class="logo-insidebar">
<div class="sidebar-bottom"><a href="{
url_for( 'scodoc.about', scodoc_dept=g.scodoc_dept )
}" class="sidebar">À propos</a><br>
<a href="{ scu.SCO_USER_MANUAL }" target="_blank" rel="noopener" class="sidebar">Aide</a>
</div></div>
<div class="logo-logo">
<a href="{ url_for( 'scodoc.about', scodoc_dept=g.scodoc_dept ) }">
{ scu.icontag("scologo_img", no_size=True) }</a>
</div>
</div>
<!-- end of sidebar -->
"""
)
return "".join(H)
def sidebar_dept():
"""Partie supérieure de la marge de gauche"""
return render_template(
"sidebar_dept.j2",
prefs=sco_preferences.SemPreferences(),
)

View File

@ -171,7 +171,6 @@ def fiche_etud(etudid=None):
log(f"fiche_etud: etudid={etudid!r} request.args={request.args!r}") log(f"fiche_etud: etudid={etudid!r} request.args={request.args!r}")
raise ScoValueError("Étudiant inexistant !") from exc raise ScoValueError("Étudiant inexistant !") from exc
# la sidebar est differente s'il y a ou pas un etudid # la sidebar est differente s'il y a ou pas un etudid
# voir html_sidebar.sidebar()
g.etudid = etudid g.etudid = etudid
info = etud.to_dict_scodoc7(restrict=restrict_etud_data) info = etud.to_dict_scodoc7(restrict=restrict_etud_data)
if etud.prenom_etat_civil: if etud.prenom_etat_civil:

View File

@ -267,6 +267,14 @@ class EtatAssiduite(int, BiDirectionalEnum):
EtatAssiduite.RETARD: "Retard", EtatAssiduite.RETARD: "Retard",
}.get(self, "") }.get(self, "")
def e(self) -> str:
"""e si la version libile est féminine"""
return {
EtatAssiduite.PRESENT: "e",
EtatAssiduite.ABSENT: "e",
EtatAssiduite.RETARD: "",
}.get(self, "")
class EtatJustificatif(int, BiDirectionalEnum): class EtatJustificatif(int, BiDirectionalEnum):
"""Code des états des justificatifs""" """Code des états des justificatifs"""

View File

@ -519,7 +519,7 @@
.legende { .legende {
border: 1px dashed #333; border: 1px dashed #333;
width: 75%; max-width: var(--sco-content-max-width);
padding: 20px; padding: 20px;
} }

View File

@ -91,6 +91,7 @@ div.scobox {
div.scobox.explanation { div.scobox.explanation {
background-color: var(--sco-color-background); background-color: var(--sco-color-background);
border: 1px dashed #333;
} }
div.scobox.success div.scobox-title { div.scobox.success div.scobox-title {

View File

@ -1,6 +1,6 @@
{# Explication des états des justificatifs #} {# Explication des états des justificatifs #}
<div class="explication-etats-justifs"> <div class="explication-etats-justifs scobox explanation">
<div class="explication-titre">États des justificatifs</div> <div class="explication-titre">États des justificatifs</div>
<div class="explication-etats"> <div class="explication-etats">
<div class="valide">Justificatif valide</div> <div class="valide">Justificatif valide</div>

View File

@ -1,6 +1,6 @@
{# Formulaire ajout ou modification de justificatif {# Formulaire ajout ou modification de justificatif
Si justif, edit #} Si justif, edit #}
{% extends "sco_page.j2" %} {% extends "sco_page_dept.j2" %}
{% import 'wtf.j2' as wtf %} {% import 'wtf.j2' as wtf %}
{% block styles %} {% block styles %}

View File

@ -1,4 +1,4 @@
{% extends "sco_page.j2" %} {% extends "sco_page_dept.j2" %}
{% block title %} {% block title %}
Bilan assiduité de {{sco.etud.nomprenom}} Bilan assiduité de {{sco.etud.nomprenom}}
@ -60,6 +60,8 @@ Bilan assiduité de {{sco.etud.nomprenom}}
{% endblock styles %} {% endblock styles %}
{% block app_content %} {% block app_content %}
{% include "assiduites/widgets/alert.j2" %}
<div class="pageContent"> <div class="pageContent">
<h2>Bilan de l'assiduité de {{sco.etud.html_link_fiche()|safe}}</span></h2> <h2>Bilan de l'assiduité de {{sco.etud.html_link_fiche()|safe}}</span></h2>
@ -70,7 +72,7 @@ Bilan assiduité de {{sco.etud.nomprenom}}
<div class="scobox"> <div class="scobox">
<!-- Statistiques d'assiduité (nb pres, nb retard, nb absence) + nb justifié --> <!-- Statistiques d'assiduité (nb pres, nb retard, nb absence) + nb justifié -->
<h4>Statistiques d'assiduité</h4> <div class="scobox-title">Statistiques d'assiduité</div>
<div class="stats-inputs"> <div class="stats-inputs">
<label class="stats-label"> Date de début <input type="text" class="datepicker" name="stats_date_debut" <label class="stats-label"> Date de début <input type="text" class="datepicker" name="stats_date_debut"
id="stats_date_debut" value="{{date_debut}}"></label> id="stats_date_debut" value="{{date_debut}}"></label>
@ -91,12 +93,13 @@ Bilan assiduité de {{sco.etud.nomprenom}}
</section> </section>
</div> </div>
<div class="legende"> <div class="help scobox explanation">
<h3>Statistiques</h3> <p>Un message d'alerte apparait si le nombre d'absence dépasse le seuil indiqué dans les préférences du
<p>Un message d'alerte apparait si le nombre d'absence dépasse le seuil (indiqué dans les préférences du département (actuellement {{assi_seuil}}).
département)</p> </p>
<p>Les statistiques sont calculées entre les deux dates sélectionnées. Après modification des dates, <p>Les statistiques sont calculées entre les deux dates sélectionnées. Après modification des dates,
appuyer sur le bouton "Actualiser"</p> appuyer sur le bouton "Actualiser".
</p>
{% include "assiduites/explication_etats_justifs.j2" %} {% include "assiduites/explication_etats_justifs.j2" %}

View File

@ -37,8 +37,7 @@ Calendrier de l'assiduité
<span id="label-nom">Assiduité de {{sco.etud.nomprenom}}</span> <span id="label-nom">Assiduité de {{sco.etud.nomprenom}}</span>
</div> </div>
<div class="help"> <div class="scobox explanation help">
<h3>Calendrier</h3>
{% include "assiduites/widgets/legende_couleur.j2" %} {% include "assiduites/widgets/legende_couleur.j2" %}
</div> </div>
<ul class="couleurs print"> <ul class="couleurs print">

View File

@ -220,7 +220,7 @@
</p> </p>
</div> </div>
<div class="help"> <div class="scobox explanation help">
{% include "assiduites/widgets/legende_couleur.j2" %} {% include "assiduites/widgets/legende_couleur.j2" %}
</div> </div>

View File

@ -91,7 +91,7 @@
<li><a href="{{ url_for('assiduites.calendrier_assi_etud', scodoc_dept=g.scodoc_dept, <li><a href="{{ url_for('assiduites.calendrier_assi_etud', scodoc_dept=g.scodoc_dept,
etudid=sco.etud.id) }}">Calendrier</a></li> etudid=sco.etud.id) }}">Calendrier</a></li>
<li><a href="{{ url_for('assiduites.bilan_etud', scodoc_dept=g.scodoc_dept, <li><a href="{{ url_for('assiduites.bilan_etud', scodoc_dept=g.scodoc_dept,
etudid=sco.etud.id) }}" title="Les pages bilan et liste ont été fusionnées">Liste/Bilan</a></li> etudid=sco.etud.id) }}">Bilan</a></li>
</ul> </ul>
{% endif %} {% endif %}
</div> {# /etud-insidebar #} </div> {# /etud-insidebar #}

View File

@ -1387,16 +1387,18 @@ def visu_assi_group():
def _get_anne_sco_from_request() -> int | None: def _get_anne_sco_from_request() -> int | None:
"""La valeur du paramètreannee_sco de la requête GET, """La valeur du paramètre annee_sco de la requête GET,
ou None si absent""" ou None si absent"""
annee_sco: str | None = request.args.get("annee_sco", None) annee_sco: str | None = request.args.get("annee_sco", None)
if annee_sco is None:
return None
# Vérification de l'année scolaire # Vérification de l'année scolaire
if annee_sco is not None: try:
try: annee_sco_int = int(annee_sco)
return int(annee_sco) except (ValueError, TypeError) as exc:
except (ValueError, TypeError): raise ScoValueError("Année scolaire invalide")
pass
return None return annee_sco_int
def _prepare_tableau( def _prepare_tableau(
@ -1600,9 +1602,11 @@ def tableau_assiduite_actions():
objet: Assiduite | Justificatif objet: Assiduite | Justificatif
objet_name = "" objet_name = ""
e = ""
if obj_type == "assiduite": if obj_type == "assiduite":
objet: Assiduite = Assiduite.query.get_or_404(obj_id) objet: Assiduite = Assiduite.query.get_or_404(obj_id)
objet_name = scu.EtatAssiduite(objet.etat).version_lisible() objet_name = scu.EtatAssiduite(objet.etat).version_lisible()
e = scu.EtatAssiduite(objet.etat).e()
else: else:
objet: Justificatif = Justificatif.query.get_or_404(obj_id) objet: Justificatif = Justificatif.query.get_or_404(obj_id)
objet_name = "Justificatif" objet_name = "Justificatif"
@ -1610,7 +1614,7 @@ def tableau_assiduite_actions():
# Suppression : attention, POST ou GET ! # Suppression : attention, POST ou GET !
if action == "supprimer": if action == "supprimer":
objet.supprime() objet.supprime()
flash(f"{objet_name} supprimé") flash(f"{objet_name} supprimé{e}")
return redirect(request.referrer) return redirect(request.referrer)