This commit is contained in:
Emmanuel Viennet 2024-10-21 19:12:33 +02:00
commit 30f2888881
7 changed files with 112 additions and 105 deletions

View File

@ -494,7 +494,7 @@ class GenTable:
caption = self.html_caption or self.caption caption = self.html_caption or self.caption
if caption or self.base_url: if caption or self.base_url:
H.append('<p class="gt_caption">') H.append('<div class="gt_caption">')
if caption: if caption:
H.append(caption) H.append(caption)
if self.base_url: if self.base_url:
@ -512,7 +512,7 @@ class GenTable:
}">{scu.ICON_PDF}</a>""" }">{scu.ICON_PDF}</a>"""
) )
H.append("</span>") H.append("</span>")
H.append("</p>") H.append("</div>")
H.append(self.html_next_section) H.append(self.html_next_section)
return "\n".join(H) return "\n".join(H)

View File

@ -71,19 +71,17 @@ def html_edit_formation_apc(
ues_by_sem = {} ues_by_sem = {}
ects_by_sem = {} ects_by_sem = {}
for semestre_idx in semestre_ids: for s_idx in semestre_ids:
ues_by_sem[semestre_idx] = formation.ues.filter_by( ues_by_sem[s_idx] = (
semestre_idx=semestre_idx formation.ues.filter_by(semestre_idx=s_idx)
).order_by(UniteEns.semestre_idx, UniteEns.numero, UniteEns.acronyme) .order_by(UniteEns.semestre_idx, UniteEns.numero, UniteEns.acronyme)
ects = [ .all()
ue.ects )
for ue in ues_by_sem[semestre_idx] ects = [ue.ects for ue in ues_by_sem[s_idx] if ue.type != codes_cursus.UE_SPORT]
if ue.type != codes_cursus.UE_SPORT
]
if None in ects: if None in ects:
ects_by_sem[semestre_idx] = '<span class="missing_ue_ects">manquant</span>' ects_by_sem[s_idx] = '<span class="missing_ue_ects">manquant</span>'
else: else:
ects_by_sem[semestre_idx] = f"{sum(ects):g}" ects_by_sem[s_idx] = f"{sum(ects):g}"
arrow_up, arrow_down, arrow_none = sco_groups.get_arrow_icons_tags() arrow_up, arrow_down, arrow_none = sco_groups.get_arrow_icons_tags()
@ -124,14 +122,14 @@ def html_edit_formation_apc(
ues_by_sem=ues_by_sem, ues_by_sem=ues_by_sem,
), ),
] ]
for semestre_idx in semestre_ids: for s_idx in semestre_ids:
ressources_in_sem = ressources.filter_by(semestre_id=semestre_idx) ressources_in_sem = ressources.filter_by(semestre_id=s_idx)
saes_in_sem = saes.filter_by(semestre_id=semestre_idx) saes_in_sem = saes.filter_by(semestre_id=s_idx)
other_modules_in_sem = other_modules.filter_by(semestre_id=semestre_idx) other_modules_in_sem = other_modules.filter_by(semestre_id=s_idx)
matiere_parent = Matiere.query.filter( matiere_parent = Matiere.query.filter(
Matiere.ue_id == UniteEns.id, Matiere.ue_id == UniteEns.id,
UniteEns.formation_id == formation.id, UniteEns.formation_id == formation.id,
UniteEns.semestre_idx == semestre_idx, UniteEns.semestre_idx == s_idx,
UniteEns.type != codes_cursus.UE_SPORT, UniteEns.type != codes_cursus.UE_SPORT,
).first() ).first()
H += [ H += [
@ -139,7 +137,7 @@ def html_edit_formation_apc(
render_template( render_template(
"pn/form_mods.j2", "pn/form_mods.j2",
formation=formation, formation=formation,
titre=f"Ressources du S{semestre_idx}", titre=f"Ressources du S{s_idx}",
create_element_msg="créer une nouvelle ressource", create_element_msg="créer une nouvelle ressource",
# matiere_parent=matiere_parent, # matiere_parent=matiere_parent,
modules=ressources_in_sem, modules=ressources_in_sem,
@ -148,16 +146,16 @@ def html_edit_formation_apc(
tag_editable=tag_editable, tag_editable=tag_editable,
icons=icons, icons=icons,
scu=scu, scu=scu,
semestre_id=semestre_idx, semestre_id=s_idx,
) )
if ues_by_sem[semestre_idx].count() > 0 if len(ues_by_sem[s_idx]) > 0
else "" else ""
), ),
( (
render_template( render_template(
"pn/form_mods.j2", "pn/form_mods.j2",
formation=formation, formation=formation,
titre=f"Situations d'Apprentissage et d'Évaluation (SAÉs) S{semestre_idx}", titre=f"Situations d'Apprentissage et d'Évaluation (SAÉs) S{s_idx}",
create_element_msg="créer une nouvelle SAÉ", create_element_msg="créer une nouvelle SAÉ",
# matiere_parent=matiere_parent, # matiere_parent=matiere_parent,
modules=saes_in_sem, modules=saes_in_sem,
@ -166,16 +164,16 @@ def html_edit_formation_apc(
tag_editable=tag_editable, tag_editable=tag_editable,
icons=icons, icons=icons,
scu=scu, scu=scu,
semestre_id=semestre_idx, semestre_id=s_idx,
) )
if ues_by_sem[semestre_idx].count() > 0 if len(ues_by_sem[s_idx]) > 0
else "" else ""
), ),
( (
render_template( render_template(
"pn/form_mods.j2", "pn/form_mods.j2",
formation=formation, formation=formation,
titre=f"Autres modules (non BUT) du S{semestre_idx}", titre=f"Autres modules (non BUT) du S{s_idx}",
create_element_msg="créer un nouveau module", create_element_msg="créer un nouveau module",
modules=other_modules_in_sem, modules=other_modules_in_sem,
module_type=ModuleType.STANDARD, module_type=ModuleType.STANDARD,
@ -183,10 +181,11 @@ def html_edit_formation_apc(
tag_editable=tag_editable, tag_editable=tag_editable,
icons=icons, icons=icons,
scu=scu, scu=scu,
semestre_id=semestre_idx, semestre_id=s_idx,
) )
if ues_by_sem[semestre_idx].count() > 0 if len(ues_by_sem[s_idx]) > 0
else """<span class="fontred">créer une UE pour pouvoir ajouter des modules</span>""" else """<span class="warning">créer une UE pour pouvoir ajouter des
modules</span>"""
), ),
] ]

View File

@ -56,34 +56,34 @@ from app.scodoc import sco_formsemestre_validation
from app.scodoc.codes_cursus import UE_SPORT from app.scodoc.codes_cursus import UE_SPORT
def formsemestre_ext_create(etudid, sem_params): def formsemestre_ext_create(etud: Identite | None, sem_params: dict) -> FormSemestre:
"""Crée un formsemestre exterieur et y inscrit l'étudiant. """Crée un formsemestre exterieur et y inscrit l'étudiant.
sem_params: dict nécessaire à la création du formsemestre sem_params: dict nécessaire à la création du formsemestre
""" """
# Check args # Check args
_ = Formation.query.get_or_404(sem_params["formation_id"]) _ = Formation.query.get_or_404(sem_params["formation_id"])
if etudid:
_ = Identite.get_etud(etudid)
# Create formsemestre # Create formsemestre
sem_params["modalite"] = "EXT" sem_params["modalite"] = "EXT"
sem_params["etapes"] = None sem_params["etapes"] = None
sem_params["responsables"] = [current_user.id] sem_params["responsables"] = [current_user.id]
formsemestre_id = sco_formsemestre.do_formsemestre_create(sem_params, silent=True) formsemestre = FormSemestre.create_formsemestre(sem_params, silent=True)
# nota: le semestre est créé vide: pas de modules # nota: le semestre est créé vide: pas de modules
# Inscription au semestre # Inscription au semestre
sco_formsemestre_inscriptions.do_formsemestre_inscription_with_modules( if etud:
formsemestre_id, sco_formsemestre_inscriptions.do_formsemestre_inscription_with_modules(
etudid, formsemestre.id,
method="formsemestre_ext_create", etud.id,
) method="formsemestre_ext_create",
return formsemestre_id )
return formsemestre
def formsemestre_ext_create_form(etudid, formsemestre_id): def formsemestre_ext_create_form(etudid, formsemestre_id):
"""Formulaire création/inscription à un semestre extérieur""" """Formulaire création/inscription à un semestre extérieur"""
etud = Identite.get_etud(etudid) etud = Identite.get_etud(etudid)
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
H = [ H = [
f"""<h2>Enregistrement d'une inscription antérieure dans un autre f"""<h2>Enregistrement d'une inscription antérieure dans un autre
établissement</h2> établissement</h2>
@ -96,27 +96,26 @@ def formsemestre_ext_create_form(etudid, formsemestre_id):
Notez que si un semestre extérieur similaire a déjà été créé pour un autre Notez que si un semestre extérieur similaire a déjà été créé pour un autre
étudiant, il est préférable d'utiliser la fonction étudiant, il est préférable d'utiliser la fonction
"<a href="{ url_for('notes.formsemestre_inscription_with_modules_form', "<a href="{ url_for('notes.formsemestre_inscription_with_modules_form',
scodoc_dept=g.scodoc_dept, etudid=etudid, only_ext=1) }"> scodoc_dept=g.scodoc_dept, etudid=etud.id, only_ext=1) }">
inscrire à un autre semestre</a>" inscrire à un autre semestre</a>"
</p> </p>
<h3><a href="{ url_for('scolar.fiche_etud', <h3><a href="{ url_for('scolar.fiche_etud',
scodoc_dept=g.scodoc_dept, etudid=etudid) scodoc_dept=g.scodoc_dept, etudid=etud.id)
}" class="stdlink">Étudiant {etud.nomprenom}</a></h3> }" class="stdlink">Étudiant {etud.nomprenom}</a></h3>
""", """,
] ]
orig_sem = sco_formsemestre.get_formsemestre(formsemestre_id)
# Ne propose que des semestres de semestre_id strictement inférieur # Ne propose que des semestres de semestre_id strictement inférieur
# au semestre courant # au semestre courant
# et seulement si pas inscrit au même semestre_id d'un semestre ordinaire ScoDoc. # et seulement si pas inscrit au même semestre_id d'un semestre ordinaire ScoDoc.
# Les autres situations (eg redoublements en changeant d'établissement) # Les autres situations (eg redoublements en changeant d'établissement)
# doivent être gérées par les validations de semestres "antérieurs" # doivent être gérées par les validations de semestres "antérieurs"
insem = sco_formsemestre_inscriptions.do_formsemestre_inscription_list( insem = sco_formsemestre_inscriptions.do_formsemestre_inscription_list(
args={"etudid": etudid, "etat": scu.INSCRIT} args={"etudid": etud.id, "etat": scu.INSCRIT}
) )
semlist = [sco_formsemestre.get_formsemestre(i["formsemestre_id"]) for i in insem] semlist = [sco_formsemestre.get_formsemestre(i["formsemestre_id"]) for i in insem]
existing_semestre_ids = {s["semestre_id"] for s in semlist} existing_semestre_ids = {s["semestre_id"] for s in semlist}
min_semestre_id = 1 min_semestre_id = 1
max_semestre_id = orig_sem["semestre_id"] max_semestre_id = formsemestre.semestre_id
semestre_ids = set(range(min_semestre_id, max_semestre_id)) - existing_semestre_ids semestre_ids = set(range(min_semestre_id, max_semestre_id)) - existing_semestre_ids
H.append( H.append(
f"""<p>L'étudiant est déjà inscrit dans des semestres ScoDoc de rangs: f"""<p>L'étudiant est déjà inscrit dans des semestres ScoDoc de rangs:
@ -203,22 +202,22 @@ def formsemestre_ext_create_form(etudid, formsemestre_id):
</p>""" </p>"""
) )
return render_template("sco_page.j2", content="\n".join(H) + "\n" + tf[1]) return render_template("sco_page.j2", content="\n".join(H) + "\n" + tf[1])
elif tf[0] == -1: if tf[0] == -1:
return flask.redirect( return flask.redirect(
url_for( url_for(
"notes.formsemestre_bulletinetud", "notes.formsemestre_bulletinetud",
scodoc_dept=g.scodoc_dept, scodoc_dept=g.scodoc_dept,
formsemestre_id=formsemestre_id, formsemestre_id=formsemestre_id,
etudid=etudid, etudid=etud.id,
) )
) )
else:
# Le semestre extérieur est créé dans la même formation que le semestre courant # Le semestre extérieur est créé dans la même formation que le semestre courant
tf[2]["formation_id"] = orig_sem["formation_id"] tf[2]["formation_id"] = formsemestre.formation_id
formsemestre_ext_create(etudid, tf[2]) formsemestre_ext_create(etud, tf[2])
return flask.redirect( return flask.redirect(
url_for("scolar.fiche_etud", scodoc_dept=g.scodoc_dept, etudid=etudid) url_for("scolar.fiche_etud", scodoc_dept=g.scodoc_dept, etudid=etud.id)
) )
def formsemestre_ext_edit_ue_validations(formsemestre_id, etudid): def formsemestre_ext_edit_ue_validations(formsemestre_id, etudid):

View File

@ -56,4 +56,9 @@ div.dt-container div.dt-search {
div.dt-container div.dt-search input { div.dt-container div.dt-search input {
margin-left: 0.5em; margin-left: 0.5em;
}
div.gt_caption {
margin-top: 4px;
margin-bottom: 16px;
} }

View File

@ -131,6 +131,11 @@ div.scobox-etud {
background-color: var(--sco-color-background); background-color: var(--sco-color-background);
} }
ul.sco-links li {
margin-bottom: 8px;
}
/* customization of multiselect style */ /* customization of multiselect style */
.multiselect-container.dropdown-menu { .multiselect-container.dropdown-menu {
background-color: #e9e9e9; background-color: #e9e9e9;
@ -4091,26 +4096,6 @@ div.scobox.update_warning>div:nth-child(2) {
padding-left: 8ex; padding-left: 8ex;
} }
/*
Titres des tabs:
.nav-tabs li a {
font-variant: small-caps;
font-size: 13pt;
}
#group-tabs {
clear: both;
}
#group-tabs ul {
display: inline;
}
#group-tabs ul li {
display: inline;
}
*/
/* Page accueil */ /* Page accueil */
#scodoc_attribution p { #scodoc_attribution p {
font-size: 75%; font-size: 75%;

View File

@ -118,7 +118,7 @@
</ul> </ul>
{% if editable %} {% if editable %}
<ul> <ul>
{% if ues_by_sem[semestre_idx] and not ues_by_sem[semestre_idx][0].is_locked()[0] %} {% if not ues_by_sem[semestre_idx] or not ues_by_sem[semestre_idx][0].is_locked()[0] %}
<li class="notes_ue_list notes_ue_list_add"><a class="stdlink" href="{{ <li class="notes_ue_list notes_ue_list_add"><a class="stdlink" href="{{
url_for('notes.ue_create', url_for('notes.ue_create',
scodoc_dept=g.scodoc_dept, scodoc_dept=g.scodoc_dept,

View File

@ -688,39 +688,58 @@ def index_html():
if editable: if editable:
H.append( H.append(
f""" f"""
<p class="help">Une "formation" est un programme pédagogique structuré <div class="scobox">
en UE, matières et modules. Chaque semestre se réfère à une formation. <div class="help">
La modification d'une formation affecte tous les semestres qui s'y <p>Une "formation" est un programme pédagogique structuré
réfèrent.</p> en UE, matières et modules.
Chaque semestre se réfère à une formation.
La modification d'une formation affecte tous les semestres qui s'y
réfèrent.
</p>
</div>
<ul class="sco-links">
<li><a class="stdlink" href="formation_create" id="link-create-formation">Créer une
formation</a>
</li>
<li><a class="stdlink" href="formation_import_xml_form">Importer une formation (xml)</a>
</li>
<li><a class="stdlink" href="{
url_for("notes.export_recap_formations_annee_scolaire",
scodoc_dept=g.scodoc_dept, annee_scolaire=scu.annee_scolaire()-1)
}">exporter les formations de l'année scolaire
{scu.annee_scolaire()-1} - {scu.annee_scolaire()}
</a>
</li>
<li><a class="stdlink" href="{
url_for("notes.export_recap_formations_annee_scolaire",
scodoc_dept=g.scodoc_dept, annee_scolaire=scu.annee_scolaire())
}">exporter les formations de l'année scolaire
{scu.annee_scolaire()} - {scu.annee_scolaire()+1}
</a>
</li>
</ul>
</div>
<ul> <div class="scobox">
<li><a class="stdlink" href="formation_create" id="link-create-formation">Créer une <div class="scobox-title">Référentiels de compétences</div>
formation</a>
</li> <div class="help">
<li><a class="stdlink" href="formation_import_xml_form">Importer une formation (xml)</a> Les formations par compétences de type BUT doivent être associées à un référentiel
</li> de compétences définissant leur structure en blocs de compétences.
<li><a class="stdlink" href="{ Le référentiel doit être chargé avant la définition de la formation s'y référant.
url_for("notes.export_recap_formations_annee_scolaire", </div>
scodoc_dept=g.scodoc_dept, annee_scolaire=scu.annee_scolaire()-1) <ul class="sco-links">
}">exporter les formations de l'année scolaire <li><a class="stdlink" href="{
{scu.annee_scolaire()-1} - {scu.annee_scolaire()} url_for('notes.refcomp_table', scodoc_dept=g.scodoc_dept)
</a> }">Liste des référentiels chargés</a>
</li> </li>
<li><a class="stdlink" href="{ <li>
url_for("notes.export_recap_formations_annee_scolaire", <a class="stdlink" href="{url_for(
scodoc_dept=g.scodoc_dept, annee_scolaire=scu.annee_scolaire()) 'notes.refcomp_load', scodoc_dept=g.scodoc_dept)
}">exporter les formations de l'année scolaire }">Charger un nouveau référentiel de compétences Orébut</a>
{scu.annee_scolaire()} - {scu.annee_scolaire()+1} </li>
</a> </ul>
</li> </div>
</ul>
<h3>Référentiels de compétences</h3>
<ul>
<li><a class="stdlink" href="{
url_for('notes.refcomp_table', scodoc_dept=g.scodoc_dept)
}">Liste des référentiels chargés</a>
</li>
</ul>
""" """
) )