forked from ScoDoc/ScoDoc
Update opolka/ScoDoc from ScoDoc/ScoDoc #2
@ -28,12 +28,14 @@
|
||||
"""
|
||||
Formulaire configuration Module Assiduités
|
||||
"""
|
||||
import datetime
|
||||
|
||||
from flask_wtf import FlaskForm
|
||||
from wtforms import SubmitField, DecimalField
|
||||
from wtforms import DecimalField, SubmitField, ValidationError
|
||||
from wtforms.fields.simple import StringField
|
||||
from wtforms.validators import Optional
|
||||
|
||||
from wtforms.widgets import TimeInput
|
||||
import datetime
|
||||
|
||||
|
||||
class TimeField(StringField):
|
||||
@ -72,9 +74,28 @@ class TimeField(StringField):
|
||||
else:
|
||||
raise ValueError
|
||||
self.data = datetime.time(hour, minutes, seconds)
|
||||
except ValueError:
|
||||
except ValueError as exc:
|
||||
self.data = None
|
||||
raise ValueError(self.gettext("Not a valid time string"))
|
||||
raise ValueError(self.gettext("Not a valid time string")) from exc
|
||||
|
||||
|
||||
def check_tick_time(form, field):
|
||||
"""Le tick_time doit être entre 0 et 60 minutes"""
|
||||
if field.data < 1 or field.data > 59:
|
||||
raise ValidationError("Valeur de granularité invalide (entre 1 et 59)")
|
||||
|
||||
|
||||
def check_ics_path(form, field):
|
||||
"""Vérifie que le chemin est bien un chemin absolu
|
||||
et qu'il contient edt_id
|
||||
"""
|
||||
data = field.data.strip()
|
||||
if not data:
|
||||
return
|
||||
if not data.startswith("/"):
|
||||
raise ValidationError("Le chemin vers les ics doit commencer par /")
|
||||
if not "{edt_id}" in data:
|
||||
raise ValidationError("Le chemin vers les ics doit utiliser {edt_id}")
|
||||
|
||||
|
||||
class ConfigAssiduitesForm(FlaskForm):
|
||||
@ -84,7 +105,20 @@ class ConfigAssiduitesForm(FlaskForm):
|
||||
lunch_time = TimeField("Heure de midi (date pivot entre Matin et Après Midi)")
|
||||
afternoon_time = TimeField("Fin de la journée")
|
||||
|
||||
tick_time = DecimalField("Granularité de la Time Line (temps en minutes)", places=0)
|
||||
tick_time = DecimalField(
|
||||
"Granularité de la timeline (temps en minutes)",
|
||||
places=0,
|
||||
validators=[check_tick_time],
|
||||
)
|
||||
|
||||
edt_ics_path = StringField(
|
||||
label="Chemin vers les ics",
|
||||
description="""Chemin absolu unix sur le serveur vers le fichier ics donnant l'emploi
|
||||
du temps d'un semestre. La balise <tt>{edt_id}</tt> sera remplacée par l'edt_id du
|
||||
semestre (par défaut, son code étape Apogée).
|
||||
Si ce champ n'est pas renseigné, les emplois du temps ne seront pas utilisés.""",
|
||||
validators=[Optional(), check_ics_path],
|
||||
)
|
||||
|
||||
submit = SubmitField("Valider")
|
||||
cancel = SubmitField("Annuler", render_kw={"formnovalidate": True})
|
||||
|
@ -42,11 +42,13 @@ def check_cas_uid_from_mail_regexp(form, field):
|
||||
if not ScoDocSiteConfig.cas_uid_from_mail_regexp_is_valid(field.data):
|
||||
raise ValidationError("expression régulière invalide")
|
||||
|
||||
|
||||
def check_cas_edt_id_from_xml_regexp(form, field):
|
||||
"Vérifie la regexp fournie pour l'extraction du CAS id"
|
||||
if not ScoDocSiteConfig.cas_edt_id_from_xml_regexp_is_valid(field.data):
|
||||
raise ValidationError("expression régulière pour edt_id invalide")
|
||||
|
||||
|
||||
class ConfigCASForm(FlaskForm):
|
||||
"Formulaire paramétrage CAS"
|
||||
cas_enable = BooleanField("Activer le CAS")
|
||||
|
@ -29,7 +29,7 @@ def PersonalizedLinksForm() -> _PersonalizedLinksForm:
|
||||
F,
|
||||
f"link_{idx}",
|
||||
StringField(
|
||||
f"Titre",
|
||||
"Titre",
|
||||
validators=[
|
||||
validators.Optional(),
|
||||
validators.Length(min=1, max=80),
|
||||
@ -42,7 +42,7 @@ def PersonalizedLinksForm() -> _PersonalizedLinksForm:
|
||||
F,
|
||||
f"link_url_{idx}",
|
||||
StringField(
|
||||
f"URL",
|
||||
"URL",
|
||||
description="adresse, incluant le http.",
|
||||
validators=[
|
||||
validators.Optional(),
|
||||
@ -56,7 +56,7 @@ def PersonalizedLinksForm() -> _PersonalizedLinksForm:
|
||||
F,
|
||||
f"link_with_args_{idx}",
|
||||
BooleanField(
|
||||
f"ajouter arguments",
|
||||
"ajouter arguments",
|
||||
description="query string avec ids",
|
||||
),
|
||||
)
|
||||
|
@ -42,9 +42,6 @@ class ModuleImpl(db.Model):
|
||||
viewonly=True,
|
||||
)
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super(ModuleImpl, self).__init__(**kwargs)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<{self.__class__.__name__} {self.id} module={repr(self.module)}>"
|
||||
|
||||
|
@ -74,7 +74,8 @@ _moduleEditor = ndb.EditableTable(
|
||||
"semestre_id",
|
||||
"numero",
|
||||
"code_apogee",
|
||||
"module_type"
|
||||
"module_type",
|
||||
"edt_id",
|
||||
#'ects'
|
||||
),
|
||||
sortkey="numero, code, titre",
|
||||
|
@ -68,6 +68,7 @@ _formsemestreEditor = ndb.EditableTable(
|
||||
"ens_can_edit_eval",
|
||||
"elt_sem_apo",
|
||||
"elt_annee_apo",
|
||||
"edt_id",
|
||||
),
|
||||
filter_dept=True,
|
||||
sortkey="date_debut",
|
||||
|
@ -40,6 +40,7 @@ from app.models import (
|
||||
ModuleImpl,
|
||||
Evaluation,
|
||||
UniteEns,
|
||||
ScoDocSiteConfig,
|
||||
ScolarFormSemestreValidation,
|
||||
ScolarAutorisationInscription,
|
||||
ApcValidationAnnee,
|
||||
@ -445,6 +446,18 @@ def do_formsemestre_createwithmodules(edit=False, formsemestre: FormSemestre = N
|
||||
},
|
||||
)
|
||||
)
|
||||
if ScoDocSiteConfig.get("edt_ics_path"):
|
||||
modform.append(
|
||||
(
|
||||
"edt_id",
|
||||
{
|
||||
"size": 32,
|
||||
"title": "Identifiant EDT",
|
||||
"explanation": "optionnel, identifiant sur le logiciel emploi du temps (par défaut, utilise la première étape Apogée).",
|
||||
"allow_null": True,
|
||||
},
|
||||
)
|
||||
)
|
||||
if edit:
|
||||
formtit = f"""
|
||||
<p><a class="stdlink" href="{url_for("notes.formsemestre_edit_uecoefs",
|
||||
|
@ -79,7 +79,9 @@ partitionEditor = ndb.EditableTable(
|
||||
)
|
||||
|
||||
groupEditor = ndb.EditableTable(
|
||||
"group_descr", "group_id", ("group_id", "partition_id", "group_name", "numero")
|
||||
"group_descr",
|
||||
"group_id",
|
||||
("group_id", "partition_id", "group_name", "numero", "edt_id"),
|
||||
)
|
||||
|
||||
group_list = groupEditor.list
|
||||
|
@ -13,10 +13,9 @@ affectent notamment les comptages d'absences de tous les bulletins des
|
||||
|
||||
</div>
|
||||
|
||||
<form class="form form-horizontal" method="post" enctype="multipart/form-data" role="form">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
|
||||
<form class="form form-horizontal" method="post" enctype="multipart/form-data" role="form">
|
||||
{{ form.hidden_tag() }}
|
||||
{{ wtf.form_errors(form, hiddens="only") }}
|
||||
|
||||
@ -24,13 +23,24 @@ affectent notamment les comptages d'absences de tous les bulletins des
|
||||
{{ wtf.form_field(form.lunch_time) }}
|
||||
{{ wtf.form_field(form.afternoon_time) }}
|
||||
{{ wtf.form_field(form.tick_time) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<h1>Emplois du temps</h1>
|
||||
<div class="help">ScoDoc peut récupérer les emplois du temps de chaque session.</div>
|
||||
<div class="col-md-8">
|
||||
<div class="config-edt">
|
||||
{{ wtf.form_field(form.edt_ics_path) }}
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
{{ wtf.form_field(form.submit) }}
|
||||
{{ wtf.form_field(form.cancel) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -73,8 +73,8 @@ Heure: <b><tt>{{ time.strftime("%d/%m/%Y %H:%M") }}</tt></b>
|
||||
</p>
|
||||
</section>
|
||||
<section>
|
||||
<h2>Assiduité</h2>
|
||||
<p><a class="stdlink" href="{{url_for('scodoc.config_assiduites')}}">Configuration du suivi de l'assiduité</a>
|
||||
<h2>Assiduité et emplois du temps</h2>
|
||||
<p><a class="stdlink" href="{{url_for('scodoc.config_assiduites')}}">Configuration du suivi de l'assiduité et accès aux emplois du temps</a>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
|
@ -323,6 +323,7 @@ def config_assiduites():
|
||||
form = ConfigAssiduitesForm()
|
||||
if request.method == "POST" and form.cancel.data: # cancel button
|
||||
return redirect(url_for("scodoc.index"))
|
||||
|
||||
if form.validate_on_submit():
|
||||
if ScoDocSiteConfig.set("assi_morning_time", form.data["morning_time"]):
|
||||
flash("Heure du début de la journée enregistrée")
|
||||
@ -330,18 +331,13 @@ def config_assiduites():
|
||||
flash("Heure de midi enregistrée")
|
||||
if ScoDocSiteConfig.set("assi_afternoon_time", form.data["afternoon_time"]):
|
||||
flash("Heure de fin de la journée enregistrée")
|
||||
if (
|
||||
form.data["tick_time"] > 0
|
||||
and form.data["tick_time"] < 60
|
||||
and ScoDocSiteConfig.set("assi_tick_time", float(form.data["tick_time"]))
|
||||
):
|
||||
if ScoDocSiteConfig.set("assi_tick_time", float(form.data["tick_time"])):
|
||||
flash("Granularité de la timeline enregistrée")
|
||||
else:
|
||||
flash("Erreur : Granularité invalide ou identique")
|
||||
|
||||
if ScoDocSiteConfig.set("edt_ics_path", form.data["edt_ics_path"]):
|
||||
flash("Chemin vers les calendriers ics enregistré")
|
||||
return redirect(url_for("scodoc.configuration"))
|
||||
|
||||
elif request.method == "GET":
|
||||
if request.method == "GET":
|
||||
form.morning_time.data = ScoDocSiteConfig.get(
|
||||
"assi_morning_time", datetime.time(8, 0, 0)
|
||||
)
|
||||
@ -356,6 +352,7 @@ def config_assiduites():
|
||||
except ValueError:
|
||||
form.tick_time.data = 15.0
|
||||
ScoDocSiteConfig.set("assi_tick_time", 15.0)
|
||||
form.edt_ics_path.data = ScoDocSiteConfig.get("edt_ics_path")
|
||||
|
||||
return render_template(
|
||||
"assiduites/pages/config_assiduites.j2",
|
||||
|
Loading…
Reference in New Issue
Block a user