diff --git a/app/models/etudiants.py b/app/models/etudiants.py
index 30e42d25b..87ce6163e 100644
--- a/app/models/etudiants.py
+++ b/app/models/etudiants.py
@@ -405,6 +405,18 @@ class Identite(models.ScoDocModel):
modimpls_by_formsemestre[formsemestre.id] = modimpls_sem
return modimpls_by_formsemestre
+ def get_modimpls_from_formsemestre(
+ self, formsemestre: "FormSemestre"
+ ) -> list["ModuleImpl"]:
+ """
+ Liste des ModuleImpl auxquels l'étudiant est inscrit dans le formsemestre.
+ """
+ modimpls = ModuleImpl.query.join(ModuleImplInscription).filter(
+ ModuleImplInscription.etudid == self.id,
+ ModuleImpl.formsemestre_id == formsemestre.id,
+ )
+ return modimpls.all()
+
@classmethod
def convert_dict_fields(cls, args: dict) -> dict:
"""Convert fields in the given dict. No other side effect.
diff --git a/app/static/css/assiduites.css b/app/static/css/assiduites.css
index 8ccd607c4..ff04a8019 100644
--- a/app/static/css/assiduites.css
+++ b/app/static/css/assiduites.css
@@ -754,4 +754,86 @@ tr.row-justificatif.non_valide td.assi-type {
#gtrcontent[data-pdp="true"] .pdp {
display: block;
+}
+
+.sco-drop {
+ border: 1px solid #e1e1e1;
+ /* Couleur de bordure plus douce */
+ border-radius: 8px;
+ /* Coins plus arrondis */
+ background-color: #fafafa;
+ /* Couleur de fond légère */
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+ /* Ombre douce pour de la profondeur */
+ width: 100%;
+ /* Adaptation à la largeur de son conteneur */
+ max-width: 600px;
+ /* Largeur maximale pour une meilleure apparence sur grands écrans */
+ margin: 10px auto;
+ /* Centrage avec une marge */
+ position: relative;
+ z-index: 1;
+}
+
+.sco-drop[open] {
+ z-index: 2;
+ /* Empilement au-dessus des autres détails */
+}
+
+.sco-drop summary {
+ font-weight: 600;
+ /* Texte plus épais */
+ color: #333;
+ /* Couleur de texte plus foncée pour le contraste */
+ padding: 7px 10px;
+ /* Plus de padding pour une meilleure ergonomie */
+ cursor: pointer;
+ list-style: none;
+ /* Enlève les puces */
+ outline: none;
+ /* Supprime la bordure de focus par défaut pour un look plus net */
+ user-select: none;
+ /* Empêche la sélection du texte */
+ text-align: center;
+}
+
+.sco-drop summary::-webkit-details-marker {
+ display: none;
+ /* Cache le triangle par défaut sur Chrome/Safari */
+}
+
+.sco-drop summary:focus {
+ outline: none;
+ /* Plus propre sans contour lors du focus */
+}
+
+.sco-drop ul {
+ list-style: none;
+ /* Enlève les puces */
+ margin: 5px 0;
+ padding: 0;
+ background-color: #fff;
+ /* Arrière-plan blanc pour le contenu */
+ position: absolute;
+ border-radius: 8px;
+ z-index: 1000;
+ border: 1px solid #e1e1e1;
+ /* Bordure plus douce */
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
+ /* Ombre douce pour de la profondeur */
+ overflow-y: scroll;
+ max-height: 150px;
+ /* Hauteur maximale pour une meilleure apparence sur grands écrans */
+}
+
+.sco-drop li {
+ padding: 10px 20px;
+ /* Espacement intérieur pour les éléments de liste */
+ border-top: 1px solid #e1e1e1;
+ /* Séparateur subtil entre les éléments */
+}
+
+.sco-drop li:first-child {
+ border-top: none;
+ /* Pas de bordure en haut du premier élément */
}
\ No newline at end of file
diff --git a/app/templates/assiduites/pages/signal_assiduites_hebdo.j2 b/app/templates/assiduites/pages/signal_assiduites_hebdo.j2
index ed5e4983e..36985a8de 100644
--- a/app/templates/assiduites/pages/signal_assiduites_hebdo.j2
+++ b/app/templates/assiduites/pages/signal_assiduites_hebdo.j2
@@ -335,17 +335,36 @@
);
}
+ function generateConflitDetails(assiduites){
+ let html = 'Assiduités en conflit
'
+
+ assiduites.forEach((a)=>{
+ const deb = new Date(a.date_debut);
+ const fin = new Date(a.date_fin);
+ let date = "";
+ if (deb.isSame(fin, "day")){
+ date = `le ${deb.format("DD/MM/YYYY")} de ${deb.format("HH:mm")} à ${fin.format("HH:mm")}`;
+ }else{
+ date = `du ${deb.format("DD/MM/YYYY")} au ${fin.format("DD/MM/YYYY")}`;
+ }
+
+ html += `-
+
+ ${a.etat} ${date}
+
+
`
+
+ })
+
+ return html + "
"
+ }
+
function updateTable(assiduites) {
-
- const img_conflit = `
- 📅`
-
// Suppression existant
document.querySelectorAll("td.btns").forEach((el) => {
el.remove();
@@ -454,8 +473,7 @@
tdMatin.setAttribute("data-tooltip", "");
} else {
- tdMatin.innerHTML = img_conflit;
- tdMatin.querySelector(".conflit_calendar").href = `calendrier_assi_etud?etudid=${etudid}`;
+ tdMatin.innerHTML = generateConflitDetails(etudAssiMorning);
tdMatin.classList.add("conflit");
}
}
@@ -485,8 +503,7 @@
tdApresmidi.setAttribute("title", text);
tdApresmidi.setAttribute("data-tooltip", "");
} else {
- tdApresmidi.innerHTML = img_conflit;
- tdApresmidi.querySelector(".conflit_calendar").href = `calendrier_assi_etud?etudid=${etudid}`;
+ tdApresmidi.innerHTML = generateConflitDetails(etudAssiAfternoon);
tdApresmidi.classList.add("conflit");
}
}
@@ -560,7 +577,6 @@
// coche tous les boutons de la colonne
function allPresent(day, time) {
// Version naive : coche tous les boutons de la colonne
- // TODO - Optimiser avec une seule requête API
let tds = document.querySelectorAll(`td[day="${day}"][time="${time}"]`);
const real_time = time == "am" ? "matin" : "apresmidi";
const assi = {
diff --git a/app/templates/assiduites/pages/traitement_justificatifs.j2 b/app/templates/assiduites/pages/traitement_justificatifs.j2
index ea2ae094c..5833a7f2b 100644
--- a/app/templates/assiduites/pages/traitement_justificatifs.j2
+++ b/app/templates/assiduites/pages/traitement_justificatifs.j2
@@ -86,87 +86,7 @@
}
- .sco-drop {
- border: 1px solid #e1e1e1;
- /* Couleur de bordure plus douce */
- border-radius: 8px;
- /* Coins plus arrondis */
- background-color: #fafafa;
- /* Couleur de fond légère */
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
- /* Ombre douce pour de la profondeur */
- width: 100%;
- /* Adaptation à la largeur de son conteneur */
- max-width: 600px;
- /* Largeur maximale pour une meilleure apparence sur grands écrans */
- margin: 10px auto;
- /* Centrage avec une marge */
- position: relative;
- z-index: 1;
- }
-
- .sco-drop[open] {
- z-index: 2;
- /* Empilement au-dessus des autres détails */
- }
-
- .sco-drop summary {
- font-weight: 600;
- /* Texte plus épais */
- color: #333;
- /* Couleur de texte plus foncée pour le contraste */
- padding: 7px 10px;
- /* Plus de padding pour une meilleure ergonomie */
- cursor: pointer;
- list-style: none;
- /* Enlève les puces */
- outline: none;
- /* Supprime la bordure de focus par défaut pour un look plus net */
- user-select: none;
- /* Empêche la sélection du texte */
- text-align: center;
- }
-
- .sco-drop summary::-webkit-details-marker {
- display: none;
- /* Cache le triangle par défaut sur Chrome/Safari */
- }
-
- .sco-drop summary:focus {
- outline: none;
- /* Plus propre sans contour lors du focus */
- }
-
- .sco-drop ul {
- list-style: none;
- /* Enlève les puces */
- margin: 5px 0;
- padding: 0;
- background-color: #fff;
- /* Arrière-plan blanc pour le contenu */
- position: absolute;
- border-radius: 8px;
- z-index: 1000;
- border: 1px solid #e1e1e1;
- /* Bordure plus douce */
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
- /* Ombre douce pour de la profondeur */
- overflow-y: scroll;
- max-height: 150px;
- /* Hauteur maximale pour une meilleure apparence sur grands écrans */
- }
-
- .sco-drop li {
- padding: 10px 20px;
- /* Espacement intérieur pour les éléments de liste */
- border-top: 1px solid #e1e1e1;
- /* Séparateur subtil entre les éléments */
- }
-
- .sco-drop li:first-child {
- border-top: none;
- /* Pas de bordure en haut du premier élément */
- }
+
{% endblock styles %}
diff --git a/app/views/assiduites.py b/app/views/assiduites.py
index 21f39f8c3..f053a5f5b 100644
--- a/app/views/assiduites.py
+++ b/app/views/assiduites.py
@@ -2168,17 +2168,19 @@ def edit_assiduite_etud(assiduite_id: int):
form.disable_all()
# peuplement moduleimpl_select
- modimpls_by_formsemestre = etud.get_modimpls_by_formsemestre(scu.annee_scolaire())
choices: OrderedDict = OrderedDict()
choices[""] = [("", "Non spécifié"), ("autre", "Autre module (pas dans la liste)")]
- # indique le nom du semestre dans le menu (optgroup)
- group_name: str = formsemestre.titre_annee()
- choices[group_name] = [
- (m.id, f"{m.module.code} {m.module.abbrev or m.module.titre or ''}")
- for m in modimpls_by_formsemestre[formsemestre.id]
- if m.module.ue.type == UE_STANDARD
- ]
+ # Récupération des modulesimpl du semestre si existant.
+ if formsemestre:
+ # indique le nom du semestre dans le menu (optgroup)
+ modimpls_from_formsemestre = etud.get_modimpls_from_formsemestre(formsemestre)
+ group_name: str = formsemestre.titre_annee()
+ choices[group_name] = [
+ (m.id, f"{m.module.code} {m.module.abbrev or m.module.titre or ''}")
+ for m in modimpls_from_formsemestre
+ if m.module.ue.type == UE_STANDARD
+ ]
choices.move_to_end("", last=False)
form.modimpl.choices = choices