Pages groupes: 3 pages séparées au lieu des tabs

This commit is contained in:
Emmanuel Viennet 2024-08-22 22:02:34 +02:00
parent b448e32f8a
commit 26dcc0db3b
13 changed files with 214 additions and 80 deletions

View File

@ -358,7 +358,7 @@ def etudarchive_import_files(
unmatched_files=unmatched_files, unmatched_files=unmatched_files,
stored_etud_filename=stored_etud_filename, stored_etud_filename=stored_etud_filename,
next_page=url_for( next_page=url_for(
"scolar.groups_view", "scolar.groups_feuilles",
scodoc_dept=g.scodoc_dept, scodoc_dept=g.scodoc_dept,
formsemestre_id=formsemestre_id, formsemestre_id=formsemestre_id,
), ),

View File

@ -335,7 +335,7 @@ def formsemestre_status_menubar(formsemestre: FormSemestre | None) -> str:
}, },
{ {
"title": "Exporter table des étudiants", "title": "Exporter table des étudiants",
"endpoint": "scolar.groups_view", "endpoint": "scolar.groups_lists",
"args": { "args": {
"fmt": "allxls", "fmt": "allxls",
"group_ids": sco_groups.get_default_group( "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() can_change_groups = formsemestre.can_change_groups()
menu_groupes = [ menu_groupes = [
{ {
"title": "Listes, photos, feuilles...", "title": "Listes des groupes",
"endpoint": "scolar.groups_view", "endpoint": "scolar.groups_lists",
"args": {"formsemestre_id": formsemestre_id}, "args": {"formsemestre_id": formsemestre_id},
"enabled": True, "enabled": True,
"helpmsg": "Accès aux listes des groupes d'étudiants", "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", "title": "Modifier groupes et partitions",
"endpoint": "scolar.partition_editor", "endpoint": "scolar.partition_editor",
@ -826,7 +840,7 @@ def _make_listes_sem(formsemestre: FormSemestre) -> str:
<div class="sem-groups-list"> <div class="sem-groups-list">
<div> <div>
<a class="stdlink" href="{ <a class="stdlink" href="{
url_for("scolar.groups_view", url_for("scolar.groups_lists",
group_ids=group.id, group_ids=group.id,
scodoc_dept=g.scodoc_dept, scodoc_dept=g.scodoc_dept,
) )

View File

@ -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) # Re-ecriture en 2014 (re-organisation de l'interface, modernisation du code)
# Modif en 2024 (9.7/revamp, abandon des tabs bootstrap)
import datetime import datetime
from urllib.parse import parse_qs 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 flask_login import current_user
from app import db from app import db
@ -64,8 +65,8 @@ JAVASCRIPTS = html_sco_header.BOOTSTRAP_JS + [
CSSSTYLES = html_sco_header.BOOTSTRAP_CSS CSSSTYLES = html_sco_header.BOOTSTRAP_CSS
# view: # view
def groups_view( def groups_lists(
group_ids=(), group_ids=(),
fmt="html", fmt="html",
with_codes=0, with_codes=0,
@ -87,6 +88,7 @@ def groups_view(
formsemestre_id est utilisé si aucun groupe selectionné pour construire la liste des groupes. 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: # Informations sur les groupes à afficher:
groups_infos = DisplayedGroupsInfos( groups_infos = DisplayedGroupsInfos(
group_ids, group_ids,
@ -112,60 +114,58 @@ def groups_view(
# - charger tous les etudiants au debut, quels que soient les groupes selectionnés # - 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 # - ajouter du JS pour modifier les liens (arguments group_ids) quand le menu change
return f""" return render_template(
{ html_sco_header.sco_header( "formsemestre/groups_lists.j2",
javascripts=JAVASCRIPTS, form_groups_choice=form_groups_choice(groups_infos, submit_on_change=True),
cssstyles=CSSSTYLES groups_table=groups_table(
) groups_infos=groups_infos,
} fmt=fmt,
<style> with_codes=with_codes,
span.warning_unauthorized {{ etat=etat,
color: pink; with_paiement=with_paiement,
font-style: italic; with_archives=with_archives,
margin-left: 12px; with_annotations=with_annotations,
}} with_bourse=with_bourse,
</style> ),
<div id="group-tabs"> groups_titles=groups_infos.groups_titles,
<!-- 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() }
# 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( def form_groups_choice(

View File

@ -254,7 +254,7 @@ def fiche_etud(etudid=None):
grlinks.append( grlinks.append(
f"""<a class="discretelink" href="{ 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']) scodoc_dept=g.scodoc_dept, group_ids=partition['group_id'])
}" title="Liste du groupe {gr_name}">{gr_name}</a> }" title="Liste du groupe {gr_name}">{gr_name}</a>
""" """

View File

@ -208,8 +208,7 @@ def check_local_photos_availability(groups_infos, fmt=""):
>exporter seulement les photos existantes</a>""", >exporter seulement les photos existantes</a>""",
dest_url="trombino", dest_url="trombino",
OK="Exporter seulement les photos existantes", OK="Exporter seulement les photos existantes",
cancel_url="groups_view?curtab=tab-photos&" cancel_url="groups_photos?" + groups_infos.groups_query_args,
+ groups_infos.groups_query_args,
parameters=parameters, 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)" "Copy photos from portal to ScoDoc (overwriting local copy)"
group_ids = [] if group_ids is None else group_ids group_ids = [] if group_ids is None else group_ids
groups_infos = sco_groups_view.DisplayedGroupsInfos(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() portal_url = sco_portal_apogee.get_portal_url()
header = html_sco_header.sco_header(page_title="Chargement des photos") 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: if not group_ids:
raise ScoValueError("paramètre manquant !") raise ScoValueError("paramètre manquant !")
groups_infos = sco_groups_view.DisplayedGroupsInfos(group_ids) 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 = [ H = [
html_sco_header.sco_header(page_title="Import des photos des étudiants"), 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, unmatched_files=unmatched_files,
stored_etud_filename=stored_etud_filename, stored_etud_filename=stored_etud_filename,
next_page=url_for( next_page=url_for(
"scolar.groups_view", "scolar.groups_photos",
scodoc_dept=g.scodoc_dept, scodoc_dept=g.scodoc_dept,
formsemestre_id=groups_infos.formsemestre_id, formsemestre_id=groups_infos.formsemestre_id,
curtab="tab-photos",
), ),
) )

View File

@ -20,11 +20,6 @@ function groups_view_url() {
"formsemestre_id", "formsemestre_id",
$("#group_selector")[0].formsemestre_id.value $("#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"); urlParams.delete("group_ids");
// ajout des groupes selectionnes // ajout des groupes selectionnes
var selected_groups = document.getElementById("group_ids_sel").value; var selected_groups = document.getElementById("group_ids_sel").value;

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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 %}

View File

@ -21,7 +21,7 @@
</span> </span>
<span class="resp"><a <span class="resp"><a
title="{{sco.formsemestre.responsables_str(abbrev_prenom=False)}}">{{sco.formsemestre.responsables_str()}}</a></span> 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> formsemestre_id=sco.formsemestre.id)}}">{{sco.formsemestre.inscriptions|length}} inscrits</a></span>
<span class="lock"> <span class="lock">
{% if not sco.formsemestre.etat %}<a href="{{url_for('notes.formsemestre_flip_lock', scodoc_dept=g.scodoc_dept, {% if not sco.formsemestre.etat %}<a href="{{url_for('notes.formsemestre_flip_lock', scodoc_dept=g.scodoc_dept,

View File

@ -17,7 +17,7 @@
au {{formsemestre.date_fin.strftime('%d/%m/%Y')}} ">{{formsemestre.mois_debut()}} - au {{formsemestre.date_fin.strftime('%d/%m/%Y')}} ">{{formsemestre.mois_debut()}} -
{{formsemestre.mois_fin()}}</a></span><span class="resp"><a {{formsemestre.mois_fin()}}</a></span><span class="resp"><a
title="{{formsemestre.responsables_str(abbrev_prenom=False)}}">{{formsemestre.responsables_str()}}</a></span><span 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) scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre.id)
}}">{{formsemestre.etuds_inscriptions|length}} inscrits</a></span><span class="lock"> }}">{{formsemestre.etuds_inscriptions|length}} inscrits</a></span><span class="lock">
{%-if not formsemestre.etat -%} {%-if not formsemestre.etat -%}

View File

@ -461,11 +461,11 @@ sco_publish(
) )
@bp.route("/groups_view") @bp.route("/groups_lists")
@scodoc @scodoc
@permission_required_compat_scodoc7(Permission.ScoView) @permission_required(Permission.ScoView)
@scodoc7func @scodoc7func
def groups_view( def groups_lists(
group_ids=(), group_ids=(),
fmt="html", fmt="html",
# Options pour listes: # Options pour listes:
@ -477,10 +477,10 @@ def groups_view(
with_bourse=0, with_bourse=0,
formsemestre_id=None, formsemestre_id=None,
): ):
return sco_groups_view.groups_view( "Listes des étudiants des groupes"
return sco_groups_view.groups_lists(
group_ids=group_ids, group_ids=group_ids,
fmt=fmt, fmt=fmt,
# Options pour listes:
with_codes=with_codes, with_codes=with_codes,
etat=etat, etat=etat,
with_paiement=with_paiement, 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( sco_publish(
"/export_groups_as_moodle_csv", "/export_groups_as_moodle_csv",
sco_groups_view.export_groups_as_moodle_csv, sco_groups_view.export_groups_as_moodle_csv,

View File

@ -136,7 +136,9 @@ def test_formsemestre_misc_views(test_client):
ans = sco_formsemestre_inscriptions.formsemestre_inscrits_ailleurs(formsemestre.id) ans = sco_formsemestre_inscriptions.formsemestre_inscrits_ailleurs(formsemestre.id)
# ----- MENU GROUPES # ----- 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 = call_view(scolar.partition_editor, formsemestre.id)
ans = sco_groups.edit_partition_form(formsemestre.id) ans = sco_groups.edit_partition_form(formsemestre.id)