Formulaire feuille d'appel

This commit is contained in:
Iziram 2024-07-12 16:40:46 +02:00
parent 75665497fa
commit 57f0066556
6 changed files with 225 additions and 15 deletions

View File

@ -0,0 +1,56 @@
"""
Formulaire FlaskWTF pour les groupes
"""
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, validators
class FeuilleAppelPreForm(FlaskForm):
"""
Formulaire utiliser dans le téléchargement des feuilles d'émargement
"""
def __init__(self, *args, **kwargs):
"Init form, adding a filed for our error messages"
super().__init__(*args, **kwargs)
self.ok = True
self.error_messages: list[str] = []
def set_error(self, err_msg, field=None):
"Set error message both in form and field"
self.ok = False
self.error_messages.append(err_msg)
if field:
field.errors.append(err_msg)
discipline = StringField(
"Discipline",
)
ens = StringField(
"Enseignant",
)
date = StringField(
"Date de la séance",
validators=[validators.Length(max=10)],
render_kw={
"class": "datepicker",
"size": 10,
"id": "date",
},
)
heure = StringField(
"Heure de début de la séance",
default="",
validators=[validators.Length(max=5)],
render_kw={
"class": "timepicker",
"size": 5,
"id": "heure",
},
)
submit = SubmitField("Télécharger la liste d'émargement")

View File

@ -26,8 +26,8 @@
##############################################################################
""" Excel file handling
"""
"""Excel file handling"""
import datetime
import io
import time
@ -724,10 +724,7 @@ def excel_feuille_listeappel(
# ligne 3
cell_2 = ws.make_cell("Enseignant :", style2)
cell_6 = ws.make_cell(f"Groupe {groupname}", style3)
ws.append_row(
[None, cell_2, ws.make_cell(edt_params.get("ens", ""), style3), cell_6]
)
ws.append_row([None, cell_2, ws.make_cell(edt_params.get("ens", ""), style3)])
# ligne 4: Avertissement pour ne pas confondre avec listes notes + Date
cell_1 = ws.make_cell("Date :", style2)
@ -745,10 +742,13 @@ def excel_feuille_listeappel(
]
)
# ligne 6: groupe
ws.append_row([None, ws.make_cell(f"Groupe {groupname}", style3)])
ws.append_blank_row()
ws.append_row([None, cell_2])
# ligne 8: Entête (contruction dans une liste cells)
# ligne 9: Entête (contruction dans une liste cells)
cell_2 = ws.make_cell("Nom", style3)
cells = [None, cell_2]
letter_int += 1

View File

@ -586,8 +586,8 @@ def groups_table(
etud_info["_nom_disp_order"] = etud_sort_key(etud_info)
etud_info["_prenom_target"] = fiche_url
etud_info["_nom_disp_td_attrs"] = 'id="%s" class="etudinfo"' % (
etud_info["etudid"]
etud_info["_nom_disp_td_attrs"] = (
'id="%s" class="etudinfo"' % (etud_info["etudid"])
)
etud_info["bourse_str"] = "oui" if etud_info["boursier"] else "non"
if etud_info["etat"] == "D":
@ -748,8 +748,6 @@ def groups_table(
tab.html(),
f"""
<ul>
<li><a class="stdlink" href="{tab.base_url}&fmt=xlsappel">Feuille d'appel Excel</a>
</li>
<li><a class="stdlink" href="{tab.base_url}&fmt=xls">Table Excel</a>
</li>
<li><a class="stdlink" href="{tab.base_url}&fmt=moodlecsv">Fichier CSV pour Moodle (groupe sélectionné)</a>
@ -925,14 +923,21 @@ def tab_absences_html(groups_infos, etat=None):
"""
]
url_feuille_appel: str = url_for(
"scolar.formulaire_feuille_appel",
scodoc_dept=g.scodoc_dept,
formsemestre_id=groups_infos.formsemestre_id,
group_ids=group_ids,
)
H.extend(
[
"<h3>Assiduité</h3>",
*liens_abs,
"<h3>Feuilles</h3>",
'<ul class="ul_feuilles">',
"""<li><a class="stdlink" href="%s&fmt=xlsappel">Feuille d'émargement %s (Excel)</a></li>"""
% (groups_infos.base_url, groups_infos.groups_titles),
"""<li><a class="stdlink" href="%s">Feuille d'émargement %s (Excel)</a></li>"""
% (url_feuille_appel, groups_infos.groups_titles),
"""<li><a class="stdlink" href="trombino?%s&fmt=pdf">Trombinoscope en PDF</a></li>"""
% groups_infos.groups_query_args,
"""<li><a class="stdlink" href="pdf_trombino_tours?%s&fmt=pdf">Trombinoscope en PDF (format "IUT de Tours", beta)</a></li>"""

View File

@ -0,0 +1,55 @@
{% extends "sco_page.j2" %}
{% import 'wtf.j2' as wtf %}
{% block styles %}
{{super()}}
<link rel="stylesheet" href="{{scu.STATIC_DIR}}/libjs/bootstrap/css/bootstrap-theme.min.css">
<link rel="stylesheet" href="{{scu.STATIC_DIR}}/libjs/bootstrap-multiselect-1.1.2/bootstrap-multiselect.min.css">
<style>
div{
margin-bottom: 8px;
}
</style>
{% endblock %}
{% block app_content %}
<h2>Préparation de la feuille d'émargement : <span style="color:crimson">{{group_name}}</span></h2>
<div class="scobox">
<form action="" method="post">
<div class="infos-button">Groupes&nbsp;: {{grp|safe}}</div>
<div class="part">
{{ form.discipline.label }}
{{ form.discipline() }}
</div>
<div class="part">
{{ form.ens.label }}
{{ form.ens() }}
</div>
<div class="part">
{{ form.date.label }}
{{ form.date() }}
</div>
<div class="part">
{{ form.heure.label }}
{{ form.heure() }}
</div>
{{form.submit()}}
</form>
</div>
{% endblock app_content %}
{% block scripts %}
{{super()}}
{% include "sco_timepicker.j2" %}
<script src="{{scu.STATIC_DIR}}/js/groups_view.js"></script>
<script src="{{scu.STATIC_DIR}}/libjs/bootstrap-multiselect-1.1.2/bootstrap-multiselect.min.js"></script>
<script src="{{scu.STATIC_DIR}}/libjs/purl.js"></script>
{% endblock scripts %}

View File

@ -1,6 +1,6 @@
# -*- coding: UTF-8 -*
"""ScoDoc Flask views
"""
"""ScoDoc Flask views"""
import datetime
from functools import cached_property
@ -148,6 +148,7 @@ from app.views import (
absences,
assiduites,
but_formation,
groups,
jury_validations,
notes_formsemestre,
notes,

93
app/views/groups.py Normal file
View File

@ -0,0 +1,93 @@
"""
Nouvelles vues pour les groupes
(aux normes ScoDoc9)
"""
from flask import render_template, request
from app.decorators import (
scodoc,
permission_required,
)
from app.forms.scolar import groups_form
from app.models import (
FormSemestre,
)
from app.scodoc.sco_excel import excel_feuille_listeappel
from app.scodoc.sco_groups_view import DisplayedGroupsInfos, menu_groups_choice
from app.scodoc.sco_permissions import Permission
from app.scodoc import sco_utils as scu
from app.views import ScoData
from app.views import scolar_bp as bp
@bp.route("/formulaire_feuille_appel", methods=["GET", "POST"])
@scodoc
@permission_required(Permission.ScoView)
def formulaire_feuille_appel():
"""Formulaire de feuille d'appel
GET : Affiche le formulaire de remplissage de la feuille d'appel
POST : Retourne la feuille d'appelle correspondante
QUERY
-----
formsemestre_id:<int:formsemestre_id>
group_ids:<list:<int:group_id>>
"""
formsemestre_id: int = request.args.get("formsemestre_id")
try:
formsemestre_id = int(formsemestre_id)
except ValueError:
formsemestre_id = None
formsemestre: FormSemestre = FormSemestre.get_formsemestre(formsemestre_id)
group_ids: list[int] = request.args.get("group_ids", "").split(",")
form: groups_form.FeuilleAppelPreForm = groups_form.FeuilleAppelPreForm(
request.form
)
groups_infos = DisplayedGroupsInfos(
group_ids,
formsemestre_id=formsemestre_id,
select_all_when_unspecified=True,
)
if request.method == "POST":
edt_params: dict = {
"date": form.date.data or "",
"heure": form.heure.data or "",
"discipline": form.discipline.data or "",
"ens": form.ens.data or "",
}
form_group_ids: list[str] = request.form.getlist("group_ids")
if form_group_ids:
groups_infos = DisplayedGroupsInfos(
form_group_ids,
formsemestre_id=formsemestre_id,
select_all_when_unspecified=True,
)
xls = excel_feuille_listeappel(
groups_infos.formsemestre,
groups_infos.groups_titles,
groups_infos.members,
partitions=groups_infos.partitions,
edt_params=edt_params,
)
filename = f"liste_{groups_infos.groups_filename}"
return scu.send_file(xls, filename, scu.XLSX_SUFFIX, scu.XLSX_MIMETYPE)
return render_template(
"scolar/formulaire_feuille_appel.j2",
sco_data=ScoData(formsemestre=formsemestre),
form=form,
group_name=groups_infos.groups_titles,
grp=menu_groups_choice(groups_infos),
)