diff --git a/app/models/formsemestre.py b/app/models/formsemestre.py index dc6b8cf1..3a9e0015 100644 --- a/app/models/formsemestre.py +++ b/app/models/formsemestre.py @@ -18,7 +18,7 @@ from operator import attrgetter from flask_login import current_user -from flask import flash, g, url_for +from flask import abort, flash, g, url_for from sqlalchemy.sql import text from sqlalchemy import func @@ -185,9 +185,14 @@ class FormSemestre(db.Model): @classmethod def get_formsemestre( - cls, formsemestre_id: int, dept_id: int = None + cls, formsemestre_id: int | str, dept_id: int = None ) -> "FormSemestre": """ "FormSemestre ou 404, cherche uniquement dans le département spécifié ou le courant""" + if not isinstance(formsemestre_id, int): + try: + formsemestre_id = int(formsemestre_id) + except (TypeError, ValueError): + abort(404, "formsemestre_id invalide") if g.scodoc_dept: dept_id = dept_id if dept_id is not None else g.scodoc_dept_id if dept_id is not None: @@ -385,13 +390,18 @@ class FormSemestre(db.Model): return ues @classmethod - def get_user_formsemestres_annee( + def get_user_formsemestres_annee_by_dept( cls, user: User - ) -> tuple[list["FormSemestre"], defaultdict[int, list[ModuleImpl]]]: + ) -> tuple[ + defaultdict[int, list["FormSemestre"]], defaultdict[int, list[ModuleImpl]] + ]: """Liste des formsemestres de l'année scolaire dans lesquels user intervient (comme resp., resp. de module ou enseignant), ainsi que la liste des modimpls concernés dans chaque formsemestre Attention: les semestres et modimpls peuvent être de différents départements ! + Résultat: + { dept_id : [ formsemestre, ... ] }, + { formsemestre_id : [ modimpl, ... ]} """ debut_annee_scolaire = scu.date_debut_annee_scolaire() fin_annee_scolaire = scu.date_fin_annee_scolaire() @@ -439,9 +449,11 @@ class FormSemestre(db.Model): formsemestres.append(modimpl.formsemestre) ids.add(modimpl.formsemestre_id) modimpls_by_formsemestre[modimpl.formsemestre_id].append(modimpl) - # Tris + # Tris et organisation par département + formsemestres_by_dept = defaultdict(lambda: []) formsemestres.sort(key=lambda x: (x.departement.acronym,) + x.sort_key()) for formsemestre in formsemestres: + formsemestres_by_dept[formsemestre.dept_id].append(formsemestre) modimpls = modimpls_by_formsemestre[formsemestre.id] if formsemestre.formation.is_apc(): key = lambda x: x.module.sort_key_apc() @@ -449,7 +461,7 @@ class FormSemestre(db.Model): key = lambda x: x.module.sort_key() modimpls.sort(key=key) - return formsemestres, modimpls_by_formsemestre + return formsemestres_by_dept, modimpls_by_formsemestre def get_evaluations(self) -> list[Evaluation]: "Liste de toutes les évaluations du semestre, triées par module/numero" diff --git a/app/templates/user_board/user_board.j2 b/app/templates/user_board/user_board.j2 index 1413a15a..78f18283 100644 --- a/app/templates/user_board/user_board.j2 +++ b/app/templates/user_board/user_board.j2 @@ -65,32 +65,44 @@

Votre tableau de bord, {{user.get_nomcomplet()}}

-

Vos modules

-
- {% for formsemestre in formsemestres %} -
-
{{formsemestre.html_link_status()|safe}}
-
- {% for modimpl in modimpls_by_formsemestre[formsemestre.id] %} -
- {{modimpl.module.code}} - - {{modimpl.module.titre_str()}} - + {% for dept_id in formsemestres_by_dept %} +

Modules dans le département {{ dept_names[dept_id] }}

+
+ {% for formsemestre in formsemestres_by_dept[dept_id] %} +
+
{{formsemestre.html_link_status()|safe}}
+
+ {% for modimpl in modimpls_by_formsemestre[formsemestre.id] %} + + {% else %} +
pas de modules
+ {% endfor %}
- {% else %} -
pas de modules
- {% endfor %}
+ {% endfor %}
{% endfor %} -
{% endblock app_content %} diff --git a/app/views/user_board.py b/app/views/user_board.py index 8f2e75ea..9b45ad97 100644 --- a/app/views/user_board.py +++ b/app/views/user_board.py @@ -12,8 +12,9 @@ from app.decorators import ( scodoc, permission_required, ) -from app.models import FormSemestre +from app.models import Departement, FormSemestre from app.scodoc.sco_permissions import Permission +from app.scodoc import sco_preferences from app.scodoc import sco_utils as scu from app.views import scolar_bp as bp from app.views import ScoData @@ -25,13 +26,23 @@ from app.views import ScoData def user_board(user_name: str): """Tableau de bord utilisateur: liens vers ses objets""" user = User.query.filter_by(user_name=user_name).first_or_404() - formsemestres, modimpls_by_formsemestre = FormSemestre.get_user_formsemestres_annee( - user - ) + ( + formsemestres_by_dept, + modimpls_by_formsemestre, + ) = FormSemestre.get_user_formsemestres_annee_by_dept(user) + dept_names = { + dept_id: sco_preferences.get_preference("DeptName", dept_id=dept_id) + for dept_id in formsemestres_by_dept + } + dept_names_sorted = { + dept_id: dept_name + for (dept_id, dept_name) in sorted(dept_names.items(), key=lambda x: x[1]) + } # TODO: le calendrier avec ses enseignements return render_template( "user_board/user_board.j2", - formsemestres=formsemestres, + dept_names=dept_names_sorted, + formsemestres_by_dept=formsemestres_by_dept, modimpls_by_formsemestre=modimpls_by_formsemestre, sco=ScoData(), title=f"{user.get_prenomnom()}: tableau de bord",