diff --git a/app/scodoc/sco_archives_etud.py b/app/scodoc/sco_archives_etud.py index b7ff7d32b07b18f30253b6bf1bf73a42fe993a0b..0067be0af139303c90f1f89b5860bed9f1bb80aa 100644 --- a/app/scodoc/sco_archives_etud.py +++ b/app/scodoc/sco_archives_etud.py @@ -358,7 +358,7 @@ def etudarchive_import_files( unmatched_files=unmatched_files, stored_etud_filename=stored_etud_filename, next_page=url_for( - "scolar.groups_view", + "scolar.groups_feuilles", scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id, ), diff --git a/app/scodoc/sco_formsemestre_status.py b/app/scodoc/sco_formsemestre_status.py index 6b5d1a3a163c53524bdf8e397c83374eacbc5fb6..5f3d69cebf4d385077209ec5fc1095b738a15a4e 100755 --- a/app/scodoc/sco_formsemestre_status.py +++ b/app/scodoc/sco_formsemestre_status.py @@ -335,7 +335,7 @@ def formsemestre_status_menubar(formsemestre: FormSemestre | None) -> str: }, { "title": "Exporter table des étudiants", - "endpoint": "scolar.groups_view", + "endpoint": "scolar.groups_lists", "args": { "fmt": "allxls", "group_ids": sco_groups.get_default_group( @@ -354,12 +354,26 @@ def formsemestre_status_menubar(formsemestre: FormSemestre | None) -> str: can_change_groups = formsemestre.can_change_groups() menu_groupes = [ { - "title": "Listes, photos, feuilles...", - "endpoint": "scolar.groups_view", + "title": "Listes des groupes", + "endpoint": "scolar.groups_lists", "args": {"formsemestre_id": formsemestre_id}, "enabled": True, "helpmsg": "Accès aux listes des groupes d'étudiants", }, + { + "title": "Trombinoscopes", + "endpoint": "scolar.groups_photos", + "args": {"formsemestre_id": formsemestre_id}, + "enabled": True, + "helpmsg": "Accès aux photos des groupes d'étudiants", + }, + { + "title": "Assiduité, feuilles d'appel, ...", + "endpoint": "scolar.groups_feuilles", + "args": {"formsemestre_id": formsemestre_id}, + "enabled": True, + "helpmsg": "Accès aux feuilles d'appel des groupes d'étudiants", + }, { "title": "Modifier groupes et partitions", "endpoint": "scolar.partition_editor", @@ -826,7 +840,7 @@ def _make_listes_sem(formsemestre: FormSemestre) -> str: <div class="sem-groups-list"> <div> <a class="stdlink" href="{ - url_for("scolar.groups_view", + url_for("scolar.groups_lists", group_ids=group.id, scodoc_dept=g.scodoc_dept, ) diff --git a/app/scodoc/sco_groups_view.py b/app/scodoc/sco_groups_view.py index 2114f20c78a36a53bf657c1840349dc20d8178e6..d4817ee286f1daaee3de7cad810da38f8d75deac 100644 --- a/app/scodoc/sco_groups_view.py +++ b/app/scodoc/sco_groups_view.py @@ -30,12 +30,13 @@ sous forme: de liste html (table exportable), de trombinoscope (exportable en pd """ # Re-ecriture en 2014 (re-organisation de l'interface, modernisation du code) +# Modif en 2024 (9.7/revamp, abandon des tabs bootstrap) import datetime from urllib.parse import parse_qs -from flask import url_for, g, request +from flask import url_for, g, render_template, request from flask_login import current_user from app import db @@ -64,8 +65,8 @@ JAVASCRIPTS = html_sco_header.BOOTSTRAP_JS + [ CSSSTYLES = html_sco_header.BOOTSTRAP_CSS -# view: -def groups_view( +# view +def groups_lists( group_ids=(), fmt="html", with_codes=0, @@ -87,6 +88,7 @@ def groups_view( formsemestre_id est utilisé si aucun groupe selectionné pour construire la liste des groupes. """ + # version sans tabs: juste la liste des étudiants # Informations sur les groupes à afficher: groups_infos = DisplayedGroupsInfos( group_ids, @@ -112,60 +114,58 @@ def groups_view( # - charger tous les etudiants au debut, quels que soient les groupes selectionnés # - ajouter du JS pour modifier les liens (arguments group_ids) quand le menu change - return f""" - { html_sco_header.sco_header( - javascripts=JAVASCRIPTS, - cssstyles=CSSSTYLES - ) - } - <style> - span.warning_unauthorized {{ - color: pink; - font-style: italic; - margin-left: 12px; - }} - </style> - <div id="group-tabs"> - <!-- Menu choix groupe --> - {form_groups_choice(groups_infos, submit_on_change=True)} - <ul class="nav nav-tabs" id="myTab" role="tablist"> - <li class="nav-item" role="presentation"> - <button class="nav-link active" id="tab-listes" data-bs-toggle="tab" data-bs-target="#tab-listes-pane" type="button" role="tab" aria-controls="tab-listes-pane" aria-selected="true">Listes</button> - </li> - <li class="nav-item" role="presentation"> - <button class="nav-link" id="tab-photos" data-bs-toggle="tab" data-bs-target="#tab-photos-pane" type="button" role="tab" aria-controls="tab-photos-pane" aria-selected="true">Photos</button> - </li> - <li class="nav-item" role="presentation"> - <button class="nav-link" id="tab-abs" data-bs-toggle="tab" data-bs-target="#tab-abs-pane" type="button" role="tab" aria-controls="tab-abs-pane" aria-selected="true">Absences et feuilles...</button> - </li> - </ul> - <!-- Tab panes --> - <div class="tab-content" id="myTabContent"> - <div class="tab-pane active show" id="tab-listes-pane" role="tabpanel" aria-labelledby="tab-listes" tabindex="0"> - { - groups_table( - groups_infos=groups_infos, - fmt=fmt, - with_codes=with_codes, - etat=etat, - with_paiement=with_paiement, - with_archives=with_archives, - with_annotations=with_annotations, - with_bourse=with_bourse, - ) - } - </div> - <div class="tab-pane" id="tab-photos-pane" role="tabpanel" aria-labelledby="tab-photos" tabindex="0"> - { tab_photos_html(groups_infos, etat=etat) } - </div> - <div class="tab-pane" id="tab-abs-pane" role="tabpanel" aria-labelledby="tab-abs" tabindex="0"> - { tab_absences_html(groups_infos, etat=etat) } - </div> - </div> - </div> - - { html_sco_header.sco_footer() } + return render_template( + "formsemestre/groups_lists.j2", + form_groups_choice=form_groups_choice(groups_infos, submit_on_change=True), + groups_table=groups_table( + groups_infos=groups_infos, + fmt=fmt, + with_codes=with_codes, + etat=etat, + with_paiement=with_paiement, + with_archives=with_archives, + with_annotations=with_annotations, + with_bourse=with_bourse, + ), + groups_titles=groups_infos.groups_titles, + ) + + +# view +def groups_photos(group_ids=(), etat=None, formsemestre_id=None): + """Affichage des photos des étudiants (trombi) des groupes indiqués + group_ids: liste de group_id + formsemestre_id est utilisé si aucun groupe selectionné pour construire la liste des groupes. + """ + groups_infos = DisplayedGroupsInfos( + group_ids, + formsemestre_id=formsemestre_id, + select_all_when_unspecified=True, + ) + return render_template( + "formsemestre/groups_photos.j2", + form_groups_choice=form_groups_choice(groups_infos, submit_on_change=True), + tab_photos_html=tab_photos_html(groups_infos, etat=etat), + groups_titles=groups_infos.groups_titles, + ) + + +def groups_feuilles(group_ids=(), etat=None, formsemestre_id=None): + """Affichage des feuilles d'appel des groupes indiqués + group_ids: liste de group_id + formsemestre_id est utilisé si aucun groupe selectionné pour construire la liste des groupes. """ + groups_infos = DisplayedGroupsInfos( + group_ids, + formsemestre_id=formsemestre_id, + select_all_when_unspecified=True, + ) + return render_template( + "formsemestre/groups_feuilles.j2", + form_groups_choice=form_groups_choice(groups_infos, submit_on_change=True), + tab_absences_html=tab_absences_html(groups_infos, etat=etat), + groups_titles=groups_infos.groups_titles, + ) def form_groups_choice( diff --git a/app/scodoc/sco_page_etud.py b/app/scodoc/sco_page_etud.py index c2f604c359aa266371654f8ca1e5562ae2156424..5250af778c77138f7ce47569419576fb7328d354 100644 --- a/app/scodoc/sco_page_etud.py +++ b/app/scodoc/sco_page_etud.py @@ -254,7 +254,7 @@ def fiche_etud(etudid=None): grlinks.append( f"""<a class="discretelink" href="{ - url_for('scolar.groups_view', + url_for('scolar.groups_lists', scodoc_dept=g.scodoc_dept, group_ids=partition['group_id']) }" title="Liste du groupe {gr_name}">{gr_name}</a> """ diff --git a/app/scodoc/sco_trombino.py b/app/scodoc/sco_trombino.py index 7431609bc3971a211d5c791a098132fdf0fa91c0..3ed60ec124d04d7faf5478a4d73306167f4771ef 100644 --- a/app/scodoc/sco_trombino.py +++ b/app/scodoc/sco_trombino.py @@ -208,8 +208,7 @@ def check_local_photos_availability(groups_infos, fmt=""): >exporter seulement les photos existantes</a>""", dest_url="trombino", OK="Exporter seulement les photos existantes", - cancel_url="groups_view?curtab=tab-photos&" - + groups_infos.groups_query_args, + cancel_url="groups_photos?" + groups_infos.groups_query_args, parameters=parameters, ), ) @@ -249,7 +248,7 @@ def trombino_copy_photos(group_ids=None, dialog_confirmed=False): "Copy photos from portal to ScoDoc (overwriting local copy)" group_ids = [] if group_ids is None else group_ids groups_infos = sco_groups_view.DisplayedGroupsInfos(group_ids) - back_url = "groups_view?%s&curtab=tab-photos" % groups_infos.groups_query_args + back_url = "groups_photos?" + str(groups_infos.groups_query_args) portal_url = sco_portal_apogee.get_portal_url() header = html_sco_header.sco_header(page_title="Chargement des photos") @@ -504,7 +503,7 @@ def photos_import_files_form(group_ids=()): if not group_ids: raise ScoValueError("paramètre manquant !") groups_infos = sco_groups_view.DisplayedGroupsInfos(group_ids) - back_url = f"groups_view?{groups_infos.groups_query_args}&curtab=tab-photos" + back_url = f"groups_photos?{groups_infos.groups_query_args}" H = [ html_sco_header.sco_header(page_title="Import des photos des étudiants"), @@ -567,10 +566,9 @@ def photos_import_files_form(group_ids=()): unmatched_files=unmatched_files, stored_etud_filename=stored_etud_filename, next_page=url_for( - "scolar.groups_view", + "scolar.groups_photos", scodoc_dept=g.scodoc_dept, formsemestre_id=groups_infos.formsemestre_id, - curtab="tab-photos", ), ) diff --git a/app/static/js/groups_view.js b/app/static/js/groups_view.js index 29517a325d7b57ba8dc6be2ada0b7fdc163e87f9..7f16a580d7f6241decbdb7550e810e267e9fa648 100644 --- a/app/static/js/groups_view.js +++ b/app/static/js/groups_view.js @@ -20,11 +20,6 @@ function groups_view_url() { "formsemestre_id", $("#group_selector")[0].formsemestre_id.value ); - // ajout du tab actif - const tabActif = document.querySelector( - '[role="tab"][aria-selected="true"]' - ).id; - urlParams.set("tab", tabActif); urlParams.delete("group_ids"); // ajout des groupes selectionnes var selected_groups = document.getElementById("group_ids_sel").value; diff --git a/app/templates/formsemestre/groups_feuilles.j2 b/app/templates/formsemestre/groups_feuilles.j2 new file mode 100644 index 0000000000000000000000000000000000000000..2565ca0f53fdba0d3b7e78d5c6f89162eb1d3865 --- /dev/null +++ b/app/templates/formsemestre/groups_feuilles.j2 @@ -0,0 +1,27 @@ +{# Trombinoscope HTML #} + +{% extends "sco_page.j2" %} + + +{% block title %} + Feuilles {{groups_titles}} +{% endblock title %} + + +{% block app_content %} + <div class="pageContent"> + <!-- Menu choix groupe --> + {{form_groups_choice|safe}} + + <div> + {{tab_absences_html|safe}} + </div> + </div> + +{% endblock %} + + +{% block scripts %} + {{ super() }} + <script src="{{scu.STATIC_DIR}}/js/groups_view.js"></script> +{% endblock %} diff --git a/app/templates/formsemestre/groups_lists.j2 b/app/templates/formsemestre/groups_lists.j2 new file mode 100644 index 0000000000000000000000000000000000000000..eeb0fdd156d2f0a09a4af9c8f85ab960999b6c94 --- /dev/null +++ b/app/templates/formsemestre/groups_lists.j2 @@ -0,0 +1,37 @@ +{# Liste des membres d'un ou plusieurs groupes #} + +{% extends "sco_page.j2" %} + +{% block styles %} + {{ super() }} + <style> + span.warning_unauthorized { + color: pink; + font-style: italic; + margin-left: 12px; + } + </style> +{% endblock styles %} + + + +{% block title %} + {{groups_titles}} +{% endblock title %} + +{% block app_content %} + <div class="pageContent"> + <!-- Menu choix groupe --> + {{form_groups_choice|safe}} + + <div> + {{groups_table|safe}} + </div> + </div> +{% endblock %} + + +{% block scripts %} + {{ super() }} + <script src="{{scu.STATIC_DIR}}/js/groups_view.js"></script> +{% endblock %} diff --git a/app/templates/formsemestre/groups_photos.j2 b/app/templates/formsemestre/groups_photos.j2 new file mode 100644 index 0000000000000000000000000000000000000000..68d1516facf3b39372c0558882d30102d2c5caef --- /dev/null +++ b/app/templates/formsemestre/groups_photos.j2 @@ -0,0 +1,27 @@ +{# Trombinoscope HTML #} + +{% extends "sco_page.j2" %} + + +{% block title %} + Photos {{groups_titles}} +{% endblock title %} + + +{% block app_content %} + <div class="pageContent"> + <!-- Menu choix groupe --> + {{form_groups_choice|safe}} + + <div> + {{tab_photos_html|safe}} + </div> + </div> + +{% endblock %} + + +{% block scripts %} + {{ super() }} + <script src="{{scu.STATIC_DIR}}/js/groups_view.js"></script> +{% endblock %} diff --git a/app/templates/formsemestre_header.j2 b/app/templates/formsemestre_header.j2 index d8d7693e474438c4faba66ef20ec164cc9d89357..1e5019a9158b8e4d30f96b4135d5e5dd90e9fb58 100644 --- a/app/templates/formsemestre_header.j2 +++ b/app/templates/formsemestre_header.j2 @@ -21,7 +21,7 @@ </span> <span class="resp"><a title="{{sco.formsemestre.responsables_str(abbrev_prenom=False)}}">{{sco.formsemestre.responsables_str()}}</a></span> - <span class="nbinscrits"><a class="discretelink" href="{{url_for('scolar.groups_view', scodoc_dept=g.scodoc_dept, + <span class="nbinscrits"><a class="discretelink" href="{{url_for('scolar.groups_lists', scodoc_dept=g.scodoc_dept, formsemestre_id=sco.formsemestre.id)}}">{{sco.formsemestre.inscriptions|length}} inscrits</a></span> <span class="lock"> {% if not sco.formsemestre.etat %}<a href="{{url_for('notes.formsemestre_flip_lock', scodoc_dept=g.scodoc_dept, diff --git a/app/templates/formsemestre_page_title.j2 b/app/templates/formsemestre_page_title.j2 index 1d6f4f1f6b15fc93d7e6ec6ae5a49fabd09f37fd..075faf9b13c7f396145b6c5df3fb409cc0c0c50b 100644 --- a/app/templates/formsemestre_page_title.j2 +++ b/app/templates/formsemestre_page_title.j2 @@ -17,7 +17,7 @@ au {{formsemestre.date_fin.strftime('%d/%m/%Y')}} ">{{formsemestre.mois_debut()}} - {{formsemestre.mois_fin()}}</a></span><span class="resp"><a title="{{formsemestre.responsables_str(abbrev_prenom=False)}}">{{formsemestre.responsables_str()}}</a></span><span - class="nbinscrits"><a class="discretelink" href="{{url_for('scolar.groups_view', + class="nbinscrits"><a class="discretelink" href="{{url_for('scolar.groups_lists', scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre.id) }}">{{formsemestre.etuds_inscriptions|length}} inscrits</a></span><span class="lock"> {%-if not formsemestre.etat -%} diff --git a/app/views/scolar.py b/app/views/scolar.py index 60e89d4dd741d252f89da9362164d52c1cdcfb0a..b375b533126ae3c2c3a009855c437f90e3d96a4c 100644 --- a/app/views/scolar.py +++ b/app/views/scolar.py @@ -461,11 +461,11 @@ sco_publish( ) -@bp.route("/groups_view") +@bp.route("/groups_lists") @scodoc -@permission_required_compat_scodoc7(Permission.ScoView) +@permission_required(Permission.ScoView) @scodoc7func -def groups_view( +def groups_lists( group_ids=(), fmt="html", # Options pour listes: @@ -477,10 +477,10 @@ def groups_view( with_bourse=0, formsemestre_id=None, ): - return sco_groups_view.groups_view( + "Listes des étudiants des groupes" + return sco_groups_view.groups_lists( group_ids=group_ids, fmt=fmt, - # Options pour listes: with_codes=with_codes, etat=etat, with_paiement=with_paiement, @@ -491,6 +491,40 @@ def groups_view( ) +@bp.route("/groups_photos") +@scodoc +@permission_required(Permission.ScoView) +@scodoc7func +def groups_photos( + group_ids=(), + etat=None, + formsemestre_id=None, +): + "trombi HTML" + return sco_groups_view.groups_photos( + group_ids=group_ids, + etat=etat, + formsemestre_id=formsemestre_id, + ) + + +@bp.route("/groups_feuilles") +@scodoc +@permission_required(Permission.ScoView) +@scodoc7func +def groups_feuilles( + group_ids=(), + etat=None, + formsemestre_id=None, +): + "Feuilles appel, liens assiduité, etc." + return sco_groups_view.groups_feuilles( + group_ids=group_ids, + etat=etat, + formsemestre_id=formsemestre_id, + ) + + sco_publish( "/export_groups_as_moodle_csv", sco_groups_view.export_groups_as_moodle_csv, diff --git a/tests/unit/test_formsemestre.py b/tests/unit/test_formsemestre.py index e9677c4f8d231c7ed8cc65ec0f955bd2bf22ec92..928aae833c38c8963fadb2dcbbb444debe09daef 100644 --- a/tests/unit/test_formsemestre.py +++ b/tests/unit/test_formsemestre.py @@ -136,7 +136,9 @@ def test_formsemestre_misc_views(test_client): ans = sco_formsemestre_inscriptions.formsemestre_inscrits_ailleurs(formsemestre.id) # ----- MENU GROUPES - ans = call_view(scolar.groups_view, formsemestre.id) + ans = call_view(scolar.groups_lists, formsemestre.id) + ans = call_view(scolar.groups_photos, formsemestre.id) + ans = call_view(scolar.groups_feuilles, formsemestre.id) ans = call_view(scolar.partition_editor, formsemestre.id) ans = sco_groups.edit_partition_form(formsemestre.id)