sco_gen_cal : calendrier_choix_date + implementation dans Assiduité closes #914

This commit is contained in:
Iziram 2024-05-30 10:51:24 +02:00
parent 2aafbad9e2
commit 7575959bd4
8 changed files with 150 additions and 74 deletions

View File

@ -30,6 +30,7 @@
Lecture et conversion des ics.
"""
from datetime import timezone
import glob
import os
@ -229,7 +230,7 @@ def translate_calendar(
heure_deb=event["heure_deb"],
heure_fin=event["heure_fin"],
moduleimpl_id=modimpl.id,
jour=event["jour"],
day=event["jour"],
)
if modimpl and group
else None

View File

@ -832,7 +832,7 @@ def _make_listes_sem(formsemestre: FormSemestre) -> str:
<a class="stdlink" href="{
url_for("assiduites.signal_assiduites_group",
scodoc_dept=g.scodoc_dept,
jour=datetime.date.today().isoformat(),
day=datetime.date.today().isoformat(),
formsemestre_id=formsemestre.id,
group_ids=group.id,
)}">

View File

@ -54,11 +54,11 @@ class Jour:
"""
return self.date.isocalendar()[0:2] == datetime.date.today().isocalendar()[0:2]
def get_date(self) -> str:
def get_date(self, fmt=scu.DATE_FMT) -> str:
"""
Renvoie la date du jour au format "dd/mm/yyyy"
Renvoie la date du jour au format fmt ou "dd/mm/yyyy" par défaut
"""
return self.date.strftime(scu.DATE_FMT)
return self.date.strftime(fmt)
def get_html(self):
"""
@ -165,3 +165,50 @@ class Calendrier:
return render_template(
"calendrier.j2", calendrier=self.jours, highlight=self.highlight
)
class JourChoix(Jour):
"""
Représente un jour dans le calendrier pour choisir une date
"""
def get_html(self):
return ""
class CalendrierChoix(Calendrier):
"""
Représente un calendrier pour choisir une date
"""
def instanciate_jour(self, date: datetime.date) -> Jour:
return JourChoix(date)
def calendrier_choix_date(
date_debut: datetime.date,
date_fin: datetime.date,
url: str,
mode: str = "jour",
titre: str = "Choisir une date",
):
"""
Permet d'afficher un calendrier pour choisir une date et renvoyer sur une url.
mode : str
- "jour" -> ajoutera "&day=yyyy-mm-dd" à l'url (ex: 2024-05-30)
- "semaine" -> ajoutera "&week=yyyy-Www" à l'url (ex : 2024-W22)
titre : str
- texte à afficher au dessus du calendrier
"""
calendrier: CalendrierChoix = CalendrierChoix(date_debut, date_fin, highlight=mode)
return render_template(
"choix_date.j2",
calendrier=calendrier.get_html(),
url=url,
titre=titre,
mode=mode,
)

View File

@ -983,7 +983,7 @@ def form_choix_jour_saisie_hebdo(groups_infos, moduleimpl_id=None):
"assiduites.signal_assiduites_group",
scodoc_dept=g.scodoc_dept,
group_ids=",".join(map(str,groups_infos.group_ids)),
jour=datetime.date.today().isoformat(),
day=datetime.date.today().isoformat(),
formsemestre_id=groups_infos.formsemestre_id,
moduleimpl_id="" if moduleimpl_id is None else moduleimpl_id
)

View File

@ -346,7 +346,7 @@ def moduleimpl_status(moduleimpl_id=None, partition_id=None):
f"""
<span class="moduleimpl_abs_link"><a class="stdlink" href="{
url_for("assiduites.signal_assiduites_group", scodoc_dept=g.scodoc_dept)
}?group_ids={group_id}&jour={
}?group_ids={group_id}&day={
datetime.date.today().isoformat()
}&formsemestre_id={formsemestre.id}
&moduleimpl_id={moduleimpl_id}

View File

@ -5,7 +5,7 @@
{% for semaine in semaines %}
<div class="jours {{'highlight' if highlight=='semaine'}}" week_index="{{semaine}}">
{% for jour in semaines[semaine] %}
<div class="jour {{jour.get_class()}} {{'highlight' if highlight=='jour'}}" date="{{jour.get_date()}}">
<div class="jour {{jour.get_class()}} {{'highlight' if highlight=='jour'}}" date="{{jour.get_date('%Y-%m-%d')}}">
<span class="nom">{{jour.get_nom()}}</span>
<div class="contenu">
{{jour.get_html() | safe}}

View File

@ -0,0 +1,62 @@
{% extends "sco_page.j2" %}
{% block styles %}
{{super()}}
<style>
.highlight {
cursor: pointer !important;
}
.highlight * {
cursor: pointer !important;
}
#gtrcontent h2.titre {
text-align: center;
margin-top: 10px;
}
.content{
width: 90%;
max-width: 1600px;
}
</style>
{% endblock %}
{% block app_content %}
<div class="content">
<h2 class="titre">{{titre}}</h2>
{{calendrier | safe}}
</div>
{% endblock app_content %}
{% block scripts %}
{{ super() }}
<script>
const mode = "{{mode}}";
const url = new URL(window.location.origin + "{{url | safe}}");
document.addEventListener("DOMContentLoaded", ()=>{
const highlight = document.querySelectorAll(".highlight");
highlight.forEach((el)=>{
el.addEventListener("click", (e)=>{
if (mode == "jour"){
const date = el.getAttribute("date");
url.searchParams.set("day", date);
}
if (mode == "semaine"){
const date = el.getAttribute("week_index");
url.searchParams.set("week", date);
}
window.location.href = url;
})
})
})
</script>
{% endblock scripts %}

View File

@ -894,63 +894,6 @@ def calendrier_assi_etud():
)
@bp.route("/choix_date", methods=["GET", "POST"])
@scodoc
@permission_required(Permission.AbsChange)
def choix_date() -> str:
"""
choix_date Choix de la date pour la saisie des assiduités
Route utilisée uniquement si la date courante n'est pas dans le semestre
concerné par la requête vers une des pages suivantes :
- saisie_assiduites_group
"""
formsemestre_id = request.args.get("formsemestre_id")
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id)
group_ids = request.args.get("group_ids")
moduleimpl_id = request.args.get("moduleimpl_id")
form = ChoixDateForm(request.form)
if form.validate_on_submit():
if form.cancel.data:
return redirect(url_for("scodoc.index"))
# Vérifier si date dans semestre
ok: bool = False
try:
date: datetime.date = datetime.datetime.strptime(
form.date.data, scu.DATE_FMT
).date()
if date < formsemestre.date_debut or date > formsemestre.date_fin:
form.set_error(
"La date sélectionnée n'est pas dans le semestre.", form.date
)
else:
ok = True
except ValueError:
form.set_error("Date invalide", form.date)
if ok:
return redirect(
url_for(
"assiduites.signal_assiduites_group",
scodoc_dept=g.scodoc_dept,
formsemestre_id=formsemestre_id,
group_ids=group_ids,
moduleimpl_id=moduleimpl_id,
jour=date.isoformat(),
)
)
return render_template(
"assiduites/pages/choix_date.j2",
form=form,
sco=ScoData(formsemestre=formsemestre),
deb=formsemestre.date_debut.strftime(scu.DATE_FMT),
fin=formsemestre.date_fin.strftime(scu.DATE_FMT),
)
@bp.route("/signal_assiduites_group")
@scodoc
@permission_required(Permission.AbsChange)
@ -965,7 +908,7 @@ def signal_assiduites_group():
# formsemestre_id est optionnel si modimpl est indiqué
formsemestre_id: int = request.args.get("formsemestre_id", -1)
moduleimpl_id: int = request.args.get("moduleimpl_id")
date: str = request.args.get("jour", datetime.date.today().isoformat())
date: str = request.args.get("day", datetime.date.today().isoformat())
heures: list[str] = [
request.args.get("heure_deb", ""),
request.args.get("heure_fin", ""),
@ -1028,14 +971,23 @@ def signal_assiduites_group():
if real_date < formsemestre.date_debut or real_date > formsemestre.date_fin:
# Si le jour est hors semestre, renvoyer vers choix date
return redirect(
url_for(
"assiduites.choix_date",
formsemestre_id=formsemestre_id,
group_ids=group_ids,
moduleimpl_id=moduleimpl_id,
flash(
"La date sélectionnée n'est pas dans le semestre. Choisissez une autre date."
)
return sco_gen_cal.calendrier_choix_date(
formsemestre.date_debut,
formsemestre.date_fin,
url=url_for(
"assiduites.signal_assiduites_group",
scodoc_dept=g.scodoc_dept,
)
formsemestre_id=formsemestre_id,
group_ids=",".join(group_ids),
moduleimpl_id=moduleimpl_id,
day="placeholder",
),
mode="jour",
titre="Choix de la date",
)
# --- Restriction en fonction du moduleimpl_id ---
@ -2038,7 +1990,21 @@ def signal_assiduites_hebdo():
# les chaines sont triables par ordre alphanumérique croissant
# et produiront le même ordre que les dates par ordre chronologique croissant
if week < fs_deb_iso8601 or week > fs_fin_iso8601:
raise ScoValueError("Semaine hors du semestre", dest_url=request.referrer)
flash("La semaine n'est pas dans le semestre, Choississez une semaine valide")
return sco_gen_cal.calendrier_choix_date(
date_debut=formsemestre.date_debut,
date_fin=formsemestre.date_fin,
url=url_for(
"assiduites.signal_assiduites_hebdo",
scodoc_dept=g.scodoc_dept,
formsemestre_id=formsemestre_id,
group_ids=group_ids,
moduleimpl_id=moduleimpl_id,
week="placeholder",
),
mode="semaine",
titre="Choix de la semaine",
)
# Vérification des groupes
group_ids = group_ids.split(",") if group_ids != "" else []