diff --git a/app/api/formsemestres.py b/app/api/formsemestres.py index 6c2479021..4fd8b0c51 100644 --- a/app/api/formsemestres.py +++ b/app/api/formsemestres.py @@ -569,10 +569,14 @@ def formsemestre_edt(formsemestre_id: int): Si ok, une liste d'évènements. Sinon, une chaine indiquant un message d'erreur. group_ids permet de filtrer sur les groupes ScoDoc. + show_modules_titles affiche le titre complet du module (défaut), sinon juste le code. """ query = FormSemestre.query.filter_by(id=formsemestre_id) if g.scodoc_dept: query = query.filter_by(dept_id=g.scodoc_dept_id) formsemestre: FormSemestre = query.first_or_404(formsemestre_id) group_ids = request.args.getlist("group_ids", int) - return sco_edt_cal.formsemestre_edt_dict(formsemestre, group_ids=group_ids) + show_modules_titles = scu.to_bool(request.args.get("show_modules_titles", False)) + return sco_edt_cal.formsemestre_edt_dict( + formsemestre, group_ids=group_ids, show_modules_titles=show_modules_titles + ) diff --git a/app/scodoc/sco_edt_cal.py b/app/scodoc/sco_edt_cal.py index eaa172a0f..cf3904382 100644 --- a/app/scodoc/sco_edt_cal.py +++ b/app/scodoc/sco_edt_cal.py @@ -115,7 +115,9 @@ _EVENT_DEFAULT_COLOR = "rgb(214, 233, 248)" def formsemestre_edt_dict( - formsemestre: FormSemestre, group_ids: list[int] = None + formsemestre: FormSemestre, + group_ids: list[int] = None, + show_modules_titles=True, ) -> list[dict]: """EDT complet du semestre, comme une liste de dict serialisable en json. Fonction appelée par l'API /formsemestre//edt @@ -126,10 +128,12 @@ def formsemestre_edt_dict( """ group_ids_set = set(group_ids) if group_ids else set() try: - events_scodoc = _load_and_convert_ics(formsemestre) + events_scodoc, _ = load_and_convert_ics(formsemestre) except ScoValueError as exc: return exc.args[0] # Génération des événements pour le calendrier html + promo_icon = f"""promotion""" events_cal = [] for event in events_scodoc: group: GroupDescr | bool = event["group"] @@ -140,7 +144,7 @@ def formsemestre_edt_dict( """ else: group_disp = ( - f"""
{group.get_nom_with_part(default="promo")}
""" + f"""
{group.get_nom_with_part(default=promo_icon)}
""" if group else f"""
{event['edt_group']} @@ -173,13 +177,14 @@ def formsemestre_edt_dict( scu.EMO_WARNING} {event['edt_module']}""" bubble = "code module non trouvé dans ScoDoc. Vérifier configuration." case _: # module EDT bien retrouvé dans ScoDoc - mod_disp = f"""{ - modimpl.module.code}""" - bubble = f"{modimpl.module.abbrev or ''} ({event['edt_module']})" - - title = f"""
- {mod_disp} {event['title']} + bubble = f"{modimpl.module.abbrev or modimpl.module.titre or ''} ({event['edt_module']})" + mod_disp = ( + f"""{modimpl.module.code}""" + ) + # {event['title_edt']} + span_title = f" {event['title']}" if show_modules_titles else "" + title = f""" """ @@ -208,8 +213,15 @@ def formsemestre_edt_dict( return events_cal -def _load_and_convert_ics(formsemestre: FormSemestre) -> list[dict]: - "chargement fichier, filtrage et extraction des identifiants." +def load_and_convert_ics(formsemestre: FormSemestre) -> tuple[list[dict], list[str]]: + """Chargement fichier ics, filtrage et extraction des identifiants. + Renvoie une liste d'évènements, et la liste des identifiants de groupes + trouvés (utilisée pour l'aide). + + Groupes: + - False si extraction regexp non configuré + - "tous" (promo) si pas de correspondance trouvée. + """ # Chargement du calendier ics _, calendar = formsemestre_load_calendar(formsemestre) if not calendar: @@ -251,6 +263,7 @@ def _load_and_convert_ics(formsemestre: FormSemestre) -> list[dict]: group_name: _COLOR_PALETTE[i % (len(_COLOR_PALETTE) - 1) + 1] for i, group_name in enumerate(edt2group) } + edt_groups_ids = set() # les ids de groupes tels que dans l'ics default_group = formsemestre.get_default_group() edt2modimpl = formsemestre_retreive_modimpls_from_edt_id(formsemestre) # --- @@ -271,6 +284,7 @@ def _load_and_convert_ics(formsemestre: FormSemestre) -> list[dict]: edt_group = extract_event_data( event, edt_ics_group_field, edt_ics_group_pattern ) + edt_groups_ids.add(edt_group) # si pas de groupe dans l'event, ou si groupe non reconnu, # prend toute la promo ("tous") group: GroupDescr = ( @@ -324,7 +338,7 @@ def _load_and_convert_ics(formsemestre: FormSemestre) -> list[dict]: "end": event.decoded("dtend").isoformat(), } ) - return events_sco + return events_sco, sorted(edt_groups_ids) def extract_event_data( diff --git a/app/static/css/edt.css b/app/static/css/edt.css index e60408299..1564596d1 100644 --- a/app/static/css/edt.css +++ b/app/static/css/edt.css @@ -1,3 +1,8 @@ +#show_modules_titles_form { + display: inline-block; + margin-left: 16px; +} + .toastui-calendar-template-time { padding: 4px; word-break: break-all; diff --git a/app/static/icons/promo.svg b/app/static/icons/promo.svg new file mode 100644 index 000000000..499919618 --- /dev/null +++ b/app/static/icons/promo.svg @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/templates/assiduites/pages/config_assiduites.j2 b/app/templates/assiduites/pages/config_assiduites.j2 index d29c19015..7d2ae0a52 100644 --- a/app/templates/assiduites/pages/config_assiduites.j2 +++ b/app/templates/assiduites/pages/config_assiduites.j2 @@ -81,7 +81,10 @@ affectent notamment les comptages d'absences de tous les bulletins des

Emplois du temps

-
ScoDoc peut récupérer les emplois du temps de chaque session.
+
ScoDoc peut récupérer les emplois du temps de chaque session. + Voir la documentation. +
{{ wtf.form_field(form.edt_ics_path) }} diff --git a/app/templates/formsemestre/edt.j2 b/app/templates/formsemestre/edt.j2 index a4c91c38b..55dba3222 100644 --- a/app/templates/formsemestre/edt.j2 +++ b/app/templates/formsemestre/edt.j2 @@ -16,6 +16,12 @@ {{ form_groups_choice|safe }} +
+ noms complets des modules +
+
+ {% endblock app_content %} {% block scripts %} @@ -107,7 +120,7 @@ document.addEventListener('DOMContentLoaded', function() { const calendar = new Calendar(container, options); - fetch(`${SCO_URL}/../api/formsemestre/{{formsemestre.id}}/edt?{{groups_query_args|safe}}`) + fetch(`${SCO_URL}/../api/formsemestre/{{formsemestre.id}}/edt?{{groups_query_args|safe}}&show_modules_titles={{show_modules_titles}}`) .then(r=>{return r.json()}) .then(events=>{ if (typeof events == 'string') { diff --git a/app/templates/formsemestre/edt_help_config.j2 b/app/templates/formsemestre/edt_help_config.j2 new file mode 100644 index 000000000..529bda262 --- /dev/null +++ b/app/templates/formsemestre/edt_help_config.j2 @@ -0,0 +1,87 @@ +{% extends "sco_page.j2" %} + +{% block app_content %} + + +
+

Aide à la configuration de l'emploi du temps

+ +
    +
  • Nombre d'évènements dans le calendrier ics de ce semestre: {{events_sco|length}}
  • +
+

Identifiants de groupes trouvés dans ce calendrier

+
+ si vous voyez ici de nombreuses lignes, il est possible que l'expression régulière + d'extraction soit incorrecte (voir configuration globale) ou bien que votre logiciel d'emploi du temps génère de nombreux évènements non associés à un groupe donné. +
+
Voici ce qui a été extrait de l'emploi du temps par l'expression régulière configurée: +
+
    + {% for gr in edt_groups_ids %} +
  • {{ gr }}
  • + {% endfor %} +
+ +

Table de correspondance entre groupes EDT et groupes ScoDoc

+
+ Si votre logiciel d'emploi du temps utilise des identifiants de groupes différents de ceux de ScoDoc, il faut l'indiquer + {% if formsemestre.can_change_groups(current_user) %} + dans l'éditeur de partitions + {% else %} + dans l'éditeur de partitions (vous n'avez pas l'autorisation de le faire vous même). + {% endif %} +
+ + + + + + {% for edt_gr in edt2group %} + + + + + {% endfor %} + +
Groupe EDTGroupe ScoDocgroup_id
{{edt_gr or "*"}}{{edt2group[edt_gr].group_name or "tous"}}{{edt2group[edt_gr].id}}
+ +
+ +{% endblock app_content %} diff --git a/app/views/notes_formsemestre.py b/app/views/notes_formsemestre.py index 589e20aa1..bc74ebf2d 100644 --- a/app/views/notes_formsemestre.py +++ b/app/views/notes_formsemestre.py @@ -39,9 +39,14 @@ from app.decorators import ( ) from app.forms.formsemestre import change_formation, edit_modimpls_codes_apo from app.models import Formation, FormSemestre, ScoDocSiteConfig -from app.scodoc import sco_formations, sco_formation_versions -from app.scodoc import sco_groups_view +from app.scodoc import ( + sco_edt_cal, + sco_formations, + sco_formation_versions, + sco_groups_view, +) from app.scodoc.sco_permissions import Permission +from app.scodoc import sco_utils as scu from app.views import notes_bp as bp from app.views import ScoData @@ -158,6 +163,7 @@ def formsemestre_edit_modimpls_codes(formsemestre_id: int): @permission_required(Permission.ScoView) def formsemestre_edt(formsemestre_id: int): """Expérimental: affiche emploi du temps du semestre""" + show_modules_titles = scu.to_bool(request.args.get("show_modules_titles", False)) formsemestre = FormSemestre.get_formsemestre(formsemestre_id) cfg = ScoDocSiteConfig.query.filter_by(name="assi_morning_time").first() hour_start = cfg.value.split(":")[0].lstrip(" 0") if cfg else "7" @@ -182,4 +188,25 @@ def formsemestre_edt(formsemestre_id: int): ), groups_query_args=groups_infos.groups_query_args, sco=ScoData(formsemestre=formsemestre), + show_modules_titles=show_modules_titles, + ) + + +@bp.route("/formsemestre/edt_help_config/") +@scodoc +@permission_required(Permission.ScoView) +def formsemestre_edt_help_config(formsemestre_id: int): + """Page d'aide à la configuration de l'extraction emplois du temps + Affiche les identifiants extraits de l'ics et ceux de ScoDoc. + """ + formsemestre = FormSemestre.get_formsemestre(formsemestre_id) + edt2group = sco_edt_cal.formsemestre_retreive_groups_from_edt_id(formsemestre) + events_sco, edt_groups_ids = sco_edt_cal.load_and_convert_ics(formsemestre) + return render_template( + "formsemestre/edt_help_config.j2", + formsemestre=formsemestre, + edt2group=edt2group, + edt_groups_ids=edt_groups_ids, + events_sco=events_sco, + sco=ScoData(formsemestre=formsemestre), )