forked from ScoDoc/ScoDoc
Merge branch 'iziram-sco_gen_cal'
This commit is contained in:
commit
e18c1d8fd0
@ -30,6 +30,7 @@
|
|||||||
Lecture et conversion des ics.
|
Lecture et conversion des ics.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from datetime import timezone
|
from datetime import timezone
|
||||||
import glob
|
import glob
|
||||||
import os
|
import os
|
||||||
@ -229,7 +230,7 @@ def translate_calendar(
|
|||||||
heure_deb=event["heure_deb"],
|
heure_deb=event["heure_deb"],
|
||||||
heure_fin=event["heure_fin"],
|
heure_fin=event["heure_fin"],
|
||||||
moduleimpl_id=modimpl.id,
|
moduleimpl_id=modimpl.id,
|
||||||
jour=event["jour"],
|
day=event["jour"],
|
||||||
)
|
)
|
||||||
if modimpl and group
|
if modimpl and group
|
||||||
else None
|
else None
|
||||||
|
@ -832,7 +832,7 @@ def _make_listes_sem(formsemestre: FormSemestre) -> str:
|
|||||||
<a class="stdlink" href="{
|
<a class="stdlink" href="{
|
||||||
url_for("assiduites.signal_assiduites_group",
|
url_for("assiduites.signal_assiduites_group",
|
||||||
scodoc_dept=g.scodoc_dept,
|
scodoc_dept=g.scodoc_dept,
|
||||||
jour=datetime.date.today().isoformat(),
|
day=datetime.date.today().isoformat(),
|
||||||
formsemestre_id=formsemestre.id,
|
formsemestre_id=formsemestre.id,
|
||||||
group_ids=group.id,
|
group_ids=group.id,
|
||||||
)}">
|
)}">
|
||||||
|
@ -54,11 +54,11 @@ class Jour:
|
|||||||
"""
|
"""
|
||||||
return self.date.isocalendar()[0:2] == datetime.date.today().isocalendar()[0:2]
|
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):
|
def get_html(self):
|
||||||
"""
|
"""
|
||||||
@ -93,12 +93,22 @@ class Calendrier:
|
|||||||
Représente un calendrier
|
Représente un calendrier
|
||||||
Permet d'obtenir les informations sur les jours
|
Permet d'obtenir les informations sur les jours
|
||||||
et générer une représentation html
|
et générer une représentation html
|
||||||
|
|
||||||
|
highlight: str
|
||||||
|
-> ["jour", "semaine", "mois"]
|
||||||
|
permet de mettre en valeur lors du passage de la souris
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, date_debut: datetime.date, date_fin: datetime.date):
|
def __init__(
|
||||||
|
self,
|
||||||
|
date_debut: datetime.date,
|
||||||
|
date_fin: datetime.date,
|
||||||
|
highlight: str = None,
|
||||||
|
):
|
||||||
self.date_debut = date_debut
|
self.date_debut = date_debut
|
||||||
self.date_fin = date_fin
|
self.date_fin = date_fin
|
||||||
self.jours: dict[str, list[Jour]] = {}
|
self.jours: dict[str, list[Jour]] = {}
|
||||||
|
self.highlight: str = highlight
|
||||||
|
|
||||||
def _get_dates_between(self) -> list[datetime.date]:
|
def _get_dates_between(self) -> list[datetime.date]:
|
||||||
"""
|
"""
|
||||||
@ -130,11 +140,13 @@ class Calendrier:
|
|||||||
month = scu.MONTH_NAMES_ABBREV[date.month - 1]
|
month = scu.MONTH_NAMES_ABBREV[date.month - 1]
|
||||||
# Ajouter le jour à la liste correspondante au mois
|
# Ajouter le jour à la liste correspondante au mois
|
||||||
if month not in organized:
|
if month not in organized:
|
||||||
organized[month] = []
|
organized[month] = {} # semaine {22: []}
|
||||||
|
|
||||||
jour: Jour = self.instanciate_jour(date)
|
jour: Jour = self.instanciate_jour(date)
|
||||||
|
semaine = date.strftime("%G-W%V")
|
||||||
organized[month].append(jour)
|
if semaine not in organized[month]:
|
||||||
|
organized[month][semaine] = []
|
||||||
|
organized[month][semaine].append(jour)
|
||||||
|
|
||||||
self.jours = organized
|
self.jours = organized
|
||||||
|
|
||||||
@ -150,4 +162,53 @@ class Calendrier:
|
|||||||
get_html Renvoie le code html du calendrier
|
get_html Renvoie le code html du calendrier
|
||||||
"""
|
"""
|
||||||
self.organize_by_month()
|
self.organize_by_month()
|
||||||
return render_template("calendrier.j2", calendrier=self.jours)
|
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,
|
||||||
|
)
|
||||||
|
@ -983,7 +983,7 @@ def form_choix_jour_saisie_hebdo(groups_infos, moduleimpl_id=None):
|
|||||||
"assiduites.signal_assiduites_group",
|
"assiduites.signal_assiduites_group",
|
||||||
scodoc_dept=g.scodoc_dept,
|
scodoc_dept=g.scodoc_dept,
|
||||||
group_ids=",".join(map(str,groups_infos.group_ids)),
|
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,
|
formsemestre_id=groups_infos.formsemestre_id,
|
||||||
moduleimpl_id="" if moduleimpl_id is None else moduleimpl_id
|
moduleimpl_id="" if moduleimpl_id is None else moduleimpl_id
|
||||||
)
|
)
|
||||||
|
@ -346,7 +346,7 @@ def moduleimpl_status(moduleimpl_id=None, partition_id=None):
|
|||||||
f"""
|
f"""
|
||||||
<span class="moduleimpl_abs_link"><a class="stdlink" href="{
|
<span class="moduleimpl_abs_link"><a class="stdlink" href="{
|
||||||
url_for("assiduites.signal_assiduites_group", scodoc_dept=g.scodoc_dept)
|
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()
|
datetime.date.today().isoformat()
|
||||||
}&formsemestre_id={formsemestre.id}
|
}&formsemestre_id={formsemestre.id}
|
||||||
&moduleimpl_id={moduleimpl_id}
|
&moduleimpl_id={moduleimpl_id}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
<div class="calendrier">
|
<div class="calendrier">
|
||||||
{% for mois,jours in calendrier.items() %}
|
{% for mois,semaines in calendrier.items() %}
|
||||||
<div class="mois">
|
<div class="mois {{'highlight' if highlight=='mois'}}">
|
||||||
<h3>{{mois}}</h3>
|
<h3>{{mois}}</h3>
|
||||||
<div class="jours">
|
{% for semaine in semaines %}
|
||||||
{% for jour in jours %}
|
<div class="jours {{'highlight' if highlight=='semaine'}}" week_index="{{semaine}}">
|
||||||
<div class="jour {{jour.get_class()}}">
|
{% for jour in semaines[semaine] %}
|
||||||
|
<div class="jour {{jour.get_class()}} {{'highlight' if highlight=='jour'}}" date="{{jour.get_date('%Y-%m-%d')}}">
|
||||||
<span class="nom">{{jour.get_nom()}}</span>
|
<span class="nom">{{jour.get_nom()}}</span>
|
||||||
<div class="contenu">
|
<div class="contenu">
|
||||||
{{jour.get_html() | safe}}
|
{{jour.get_html() | safe}}
|
||||||
@ -12,6 +13,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
@ -84,5 +86,8 @@
|
|||||||
border-left: solid 3px var(--couleur);
|
border-left: solid 3px var(--couleur);
|
||||||
border-right: solid 3px var(--couleur);
|
border-right: solid 3px var(--couleur);
|
||||||
}
|
}
|
||||||
|
.highlight:hover{
|
||||||
|
border: solid 3px yellow;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
62
app/templates/choix_date.j2
Normal file
62
app/templates/choix_date.j2
Normal 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 %}
|
@ -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")
|
@bp.route("/signal_assiduites_group")
|
||||||
@scodoc
|
@scodoc
|
||||||
@permission_required(Permission.AbsChange)
|
@permission_required(Permission.AbsChange)
|
||||||
@ -965,7 +908,7 @@ def signal_assiduites_group():
|
|||||||
# formsemestre_id est optionnel si modimpl est indiqué
|
# formsemestre_id est optionnel si modimpl est indiqué
|
||||||
formsemestre_id: int = request.args.get("formsemestre_id", -1)
|
formsemestre_id: int = request.args.get("formsemestre_id", -1)
|
||||||
moduleimpl_id: int = request.args.get("moduleimpl_id")
|
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] = [
|
heures: list[str] = [
|
||||||
request.args.get("heure_deb", ""),
|
request.args.get("heure_deb", ""),
|
||||||
request.args.get("heure_fin", ""),
|
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:
|
if real_date < formsemestre.date_debut or real_date > formsemestre.date_fin:
|
||||||
# Si le jour est hors semestre, renvoyer vers choix date
|
# Si le jour est hors semestre, renvoyer vers choix date
|
||||||
return redirect(
|
flash(
|
||||||
url_for(
|
"La date sélectionnée n'est pas dans le semestre. Choisissez une autre date."
|
||||||
"assiduites.choix_date",
|
|
||||||
formsemestre_id=formsemestre_id,
|
|
||||||
group_ids=group_ids,
|
|
||||||
moduleimpl_id=moduleimpl_id,
|
|
||||||
scodoc_dept=g.scodoc_dept,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
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 ---
|
# --- Restriction en fonction du moduleimpl_id ---
|
||||||
@ -2038,7 +1990,23 @@ def signal_assiduites_hebdo():
|
|||||||
# les chaines sont triables par ordre alphanumérique croissant
|
# les chaines sont triables par ordre alphanumérique croissant
|
||||||
# et produiront le même ordre que les dates par ordre chronologique croissant
|
# et produiront le même ordre que les dates par ordre chronologique croissant
|
||||||
if week < fs_deb_iso8601 or week > fs_fin_iso8601:
|
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, choisissez la semaine sur laquelle saisir l'assiduité"
|
||||||
|
)
|
||||||
|
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
|
# Vérification des groupes
|
||||||
group_ids = group_ids.split(",") if group_ids != "" else []
|
group_ids = group_ids.split(",") if group_ids != "" else []
|
||||||
|
Loading…
Reference in New Issue
Block a user