Update opolka/ScoDoc from ScoDoc/ScoDoc #2

Merged
opolka merged 1272 commits from ScoDoc/ScoDoc:master into master 2024-05-27 09:11:04 +02:00
14 changed files with 160 additions and 129 deletions
Showing only changes of commit a200be586a - Show all commits

View File

@ -256,7 +256,7 @@ def _gen_but_niveau_ue(
return f"""<div class="but_niveau_ue {ue_class} return f"""<div class="but_niveau_ue {ue_class}
{'annee_prec' if annee_prec else ''} {'annee_prec' if annee_prec else ''}
"> ">
<div title="{ue.titre}">{ue.acronyme}</div> <div title="{ue.titre or ''}">{ue.acronyme}</div>
<div class="but_note with_scoplement"> <div class="but_note with_scoplement">
<div>{moy_ue_str}</div> <div>{moy_ue_str}</div>
{scoplement} {scoplement}

View File

@ -487,7 +487,6 @@ def arret_de_formation(etud: Identite, cosemestres: list[FormSemestre]) -> bool:
TODO:: A reprendre pour le cas des étudiants à l'étranger TODO:: A reprendre pour le cas des étudiants à l'étranger
TODO:: A reprendre si BUT avec semestres décalés TODO:: A reprendre si BUT avec semestres décalés
""" """
# Les semestres APC de l'étudiant # Les semestres APC de l'étudiant
semestres = get_semestres_apc(etud) semestres = get_semestres_apc(etud)
semestres_apc = {sem.semestre_id: sem for sem in semestres} semestres_apc = {sem.semestre_id: sem for sem in semestres}

View File

@ -126,53 +126,59 @@ def html_edit_formation_apc(
UniteEns.type != codes_cursus.UE_SPORT, UniteEns.type != codes_cursus.UE_SPORT,
).first() ).first()
H += [ H += [
render_template( (
"pn/form_mods.j2", render_template(
formation=formation, "pn/form_mods.j2",
titre=f"Ressources du S{semestre_idx}", formation=formation,
create_element_msg="créer une nouvelle ressource", titre=f"Ressources du S{semestre_idx}",
# matiere_parent=matiere_parent, create_element_msg="créer une nouvelle ressource",
modules=ressources_in_sem, # matiere_parent=matiere_parent,
module_type=ModuleType.RESSOURCE, modules=ressources_in_sem,
editable=editable, module_type=ModuleType.RESSOURCE,
tag_editable=tag_editable, editable=editable,
icons=icons, tag_editable=tag_editable,
scu=scu, icons=icons,
semestre_id=semestre_idx, scu=scu,
) semestre_id=semestre_idx,
if ues_by_sem[semestre_idx].count() > 0 )
else "", if ues_by_sem[semestre_idx].count() > 0
render_template( else ""
"pn/form_mods.j2", ),
formation=formation, (
titre=f"Situations d'Apprentissage et d'Évaluation (SAÉs) S{semestre_idx}", render_template(
create_element_msg="créer une nouvelle SAÉ", "pn/form_mods.j2",
# matiere_parent=matiere_parent, formation=formation,
modules=saes_in_sem, titre=f"Situations d'Apprentissage et d'Évaluation (SAÉs) S{semestre_idx}",
module_type=ModuleType.SAE, create_element_msg="créer une nouvelle SAÉ",
editable=editable, # matiere_parent=matiere_parent,
tag_editable=tag_editable, modules=saes_in_sem,
icons=icons, module_type=ModuleType.SAE,
scu=scu, editable=editable,
semestre_id=semestre_idx, tag_editable=tag_editable,
) icons=icons,
if ues_by_sem[semestre_idx].count() > 0 scu=scu,
else "", semestre_id=semestre_idx,
render_template( )
"pn/form_mods.j2", if ues_by_sem[semestre_idx].count() > 0
formation=formation, else ""
titre=f"Autres modules (non BUT) du S{semestre_idx}", ),
create_element_msg="créer un nouveau module", (
modules=other_modules_in_sem, render_template(
module_type=ModuleType.STANDARD, "pn/form_mods.j2",
editable=editable, formation=formation,
tag_editable=tag_editable, titre=f"Autres modules (non BUT) du S{semestre_idx}",
icons=icons, create_element_msg="créer un nouveau module",
scu=scu, modules=other_modules_in_sem,
semestre_id=semestre_idx, module_type=ModuleType.STANDARD,
) editable=editable,
if ues_by_sem[semestre_idx].count() > 0 tag_editable=tag_editable,
else """<span class="fontred">créer une UE pour pouvoir ajouter des modules</span>""", icons=icons,
scu=scu,
semestre_id=semestre_idx,
)
if ues_by_sem[semestre_idx].count() > 0
else """<span class="fontred">créer une UE pour pouvoir ajouter des modules</span>"""
),
] ]
return "\n".join(H) return "\n".join(H)
@ -202,7 +208,7 @@ def html_ue_infos(ue):
) )
return render_template( return render_template(
"pn/ue_infos.j2", "pn/ue_infos.j2",
titre=f"UE {ue.acronyme} {ue.titre}", titre=f"UE {ue.acronyme} {ue.titre or ''}",
ue=ue, ue=ue,
formsemestres=formsemestres, formsemestres=formsemestres,
nb_etuds_valid_ue=nb_etuds_valid_ue, nb_etuds_valid_ue=nb_etuds_valid_ue,

View File

@ -104,7 +104,7 @@ def matiere_create(ue_id=None):
default_numero = max([mat.numero for mat in ue.matieres] or [9]) + 1 default_numero = max([mat.numero for mat in ue.matieres] or [9]) + 1
H = [ H = [
html_sco_header.sco_header(page_title="Création d'une matière"), html_sco_header.sco_header(page_title="Création d'une matière"),
f"""<h2>Création d'une matière dans l'UE {ue.titre} ({ue.acronyme})</h2> f"""<h2>Création d'une matière dans l'UE {ue.titre or ''} ({ue.acronyme})</h2>
<p class="help">Les matières sont des groupes de modules dans une UE <p class="help">Les matières sont des groupes de modules dans une UE
d'une formation donnée. Les matières servent surtout pour la d'une formation donnée. Les matières servent surtout pour la
présentation (bulletins, etc) mais <em>n'ont pas de rôle dans le calcul présentation (bulletins, etc) mais <em>n'ont pas de rôle dans le calcul

View File

@ -85,7 +85,7 @@ _moduleEditor = ndb.EditableTable(
"heures_tp": ndb.float_null_is_zero, "heures_tp": ndb.float_null_is_zero,
"numero": ndb.int_null_is_zero, "numero": ndb.int_null_is_zero,
"coefficient": ndb.float_null_is_zero, "coefficient": ndb.float_null_is_zero,
"module_type": ndb.int_null_is_zero "module_type": ndb.int_null_is_zero,
#'ects' : ndb.float_null_is_null #'ects' : ndb.float_null_is_null
}, },
) )
@ -387,14 +387,16 @@ def module_edit(
"scodoc/help/modules.j2", "scodoc/help/modules.j2",
is_apc=is_apc, is_apc=is_apc,
semestre_id=semestre_id, semestre_id=semestre_id,
formsemestres=FormSemestre.query.filter( formsemestres=(
ModuleImpl.formsemestre_id == FormSemestre.id, FormSemestre.query.filter(
ModuleImpl.module_id == module_id, ModuleImpl.formsemestre_id == FormSemestre.id,
) ModuleImpl.module_id == module_id,
.order_by(FormSemestre.date_debut) )
.all() .order_by(FormSemestre.date_debut)
if not create .all()
else None, if not create
else None
),
create=create, create=create,
), ),
] ]
@ -413,9 +415,11 @@ def module_edit(
} }
if module: if module:
module_types |= { module_types |= {
scu.ModuleType(module.module_type) (
if module.module_type scu.ModuleType(module.module_type)
else scu.ModuleType.STANDARD if module.module_type
else scu.ModuleType.STANDARD
)
} }
# Numéro du module # Numéro du module
# cherche le numero adéquat (pour placer le module en fin de liste) # cherche le numero adéquat (pour placer le module en fin de liste)
@ -571,15 +575,17 @@ def module_edit(
"input_type": "menu", "input_type": "menu",
"title": "Rattachement :" if is_apc else "Matière :", "title": "Rattachement :" if is_apc else "Matière :",
"explanation": ( "explanation": (
"UE de rattachement, utilisée notamment pour les malus" (
+ ( "UE de rattachement, utilisée notamment pour les malus"
" (module utilisé, ne peut pas être changé de semestre)" + (
if in_use " (module utilisé, ne peut pas être changé de semestre)"
else "" if in_use
else ""
)
) )
) if is_apc
if is_apc else "un module appartient à une seule matière."
else "un module appartient à une seule matière.", ),
"labels": mat_names, "labels": mat_names,
"allowed_values": ue_mat_ids, "allowed_values": ue_mat_ids,
"enabled": unlocked, "enabled": unlocked,
@ -733,7 +739,7 @@ def module_edit(
"title": f"""<span class="fontred">{scu.EMO_WARNING } "title": f"""<span class="fontred">{scu.EMO_WARNING }
L'UE <a class="stdlink" href="{ L'UE <a class="stdlink" href="{
url_for("notes.ue_edit", scodoc_dept=g.scodoc_dept, ue_id=ue.id) url_for("notes.ue_edit", scodoc_dept=g.scodoc_dept, ue_id=ue.id)
}">{ue.acronyme} {ue.titre}</a> }">{ue.acronyme} {ue.titre or ''}</a>
n'est pas associée à un niveau de compétences n'est pas associée à un niveau de compétences
</span>""", </span>""",
}, },
@ -766,12 +772,14 @@ def module_edit(
request.base_url, request.base_url,
scu.get_request_args(), scu.get_request_args(),
descr, descr,
html_foot_markup=f"""<div class="sco_tag_module_edit"><span html_foot_markup=(
f"""<div class="sco_tag_module_edit"><span
class="sco_tag_edit"><textarea data-module_id="{module_id}" class="module_tag_editor" class="sco_tag_edit"><textarea data-module_id="{module_id}" class="module_tag_editor"
>{','.join(sco_tag_module.module_tag_list(module_id))}</textarea></span></div> >{','.join(sco_tag_module.module_tag_list(module_id))}</textarea></span></div>
""" """
if not create if not create
else "", else ""
),
initvalues=module_dict if module else {}, initvalues=module_dict if module else {},
submitlabel="Modifier ce module" if module else "Créer ce module", submitlabel="Modifier ce module" if module else "Créer ce module",
cancelbutton="Annuler", cancelbutton="Annuler",
@ -814,7 +822,7 @@ def module_edit(
tf[2]["matiere_id"] = matiere.id tf[2]["matiere_id"] = matiere.id
else: else:
matiere_id = sco_edit_matiere.do_matiere_create( matiere_id = sco_edit_matiere.do_matiere_create(
{"ue_id": ue.id, "titre": ue.titre, "numero": 1}, {"ue_id": ue.id, "titre": ue.titre or "", "numero": 1},
) )
tf[2]["matiere_id"] = matiere_id tf[2]["matiere_id"] = matiere_id

View File

@ -167,7 +167,7 @@ def do_ue_delete(ue: UniteEns, delete_validations=False, force=False):
if not ue.can_be_deleted(): if not ue.can_be_deleted():
raise ScoNonEmptyFormationObject( raise ScoNonEmptyFormationObject(
f"UE (id={ue.id}, dud)", f"UE (id={ue.id}, dud)",
msg=ue.titre, msg=f"{ue.titre or ''} ({ue.acronyme})",
dest_url=url_for( dest_url=url_for(
"notes.ue_table", "notes.ue_table",
scodoc_dept=g.scodoc_dept, scodoc_dept=g.scodoc_dept,
@ -639,8 +639,8 @@ def ue_delete(ue_id=None, delete_validations=False, dialog_confirmed=False):
) )
if not ue.can_be_deleted(): if not ue.can_be_deleted():
raise ScoNonEmptyFormationObject( raise ScoNonEmptyFormationObject(
f"UE", "UE",
msg=ue.titre, msg=f"{ue.titre or ''} ({ue.acronyme})",
dest_url=url_for( dest_url=url_for(
"notes.ue_table", "notes.ue_table",
scodoc_dept=g.scodoc_dept, scodoc_dept=g.scodoc_dept,
@ -651,7 +651,7 @@ def ue_delete(ue_id=None, delete_validations=False, dialog_confirmed=False):
if not dialog_confirmed: if not dialog_confirmed:
return scu.confirm_dialog( return scu.confirm_dialog(
f"<h2>Suppression de l'UE {ue.titre} ({ue.acronyme})</h2>", f"<h2>Suppression de l'UE {ue.titre or ''} ({ue.acronyme})</h2>",
dest_url="", dest_url="",
parameters={"ue_id": ue.id}, parameters={"ue_id": ue.id},
cancel_url=url_for( cancel_url=url_for(
@ -1452,7 +1452,7 @@ def ue_sharing_code(ue_code: str = "", ue_id: int = None, hide_ue_id: int = None
H.append("<ul>") H.append("<ul>")
for ue in ues: for ue in ues:
H.append( H.append(
f"""<li>{ue.acronyme} ({ue.titre}) dans f"""<li>{ue.acronyme} ({ue.titre or ''}) dans
<a class="stdlink" href="{ <a class="stdlink" href="{
url_for("notes.ue_table", url_for("notes.ue_table",
scodoc_dept=g.scodoc_dept, formation_id=ue.formation.id)}" scodoc_dept=g.scodoc_dept, formation_id=ue.formation.id)}"

View File

@ -283,7 +283,7 @@ def evaluation_create_form(
"coef. mod.:" +str(coef_ue) if coef_ue "coef. mod.:" +str(coef_ue) if coef_ue
else "ce module n'a pas de coef. dans cette UE" else "ce module n'a pas de coef. dans cette UE"
})</span> })</span>
<span class="eval_coef_ue_titre">{ue.titre}</span> <span class="eval_coef_ue_titre">{ue.titre or ''}</span>
""", """,
"allow_null": False, "allow_null": False,
# ok si poids nul ou coef vers l'UE nul: # ok si poids nul ou coef vers l'UE nul:

View File

@ -258,13 +258,17 @@ def formsemestre_ext_edit_ue_validations(formsemestre_id, etudid):
submitlabel="Enregistrer ces validations", submitlabel="Enregistrer ces validations",
cancelbutton="Annuler", cancelbutton="Annuler",
initvalues=initvalues, initvalues=initvalues,
cssclass="tf_ext_edit_ue_validations ext_apc" cssclass=(
if formsemestre.formation.is_apc() "tf_ext_edit_ue_validations ext_apc"
else "tf_ext_edit_ue_validations", if formsemestre.formation.is_apc()
else "tf_ext_edit_ue_validations"
),
# En APC, stocke les coefficients pour l'affichage de la moyenne en direct # En APC, stocke les coefficients pour l'affichage de la moyenne en direct
form_attrs=f"""data-ue_coefs='[{', '.join(str(ue.ects or 0) for ue in ues)}]'""" form_attrs=(
if formsemestre.formation.is_apc() f"""data-ue_coefs='[{', '.join(str(ue.ects or 0) for ue in ues)}]'"""
else "", if formsemestre.formation.is_apc()
else ""
),
) )
if tf[0] == -1: if tf[0] == -1:
return "<h4>annulation</h4>" return "<h4>annulation</h4>"
@ -421,12 +425,18 @@ def _ue_form_description(
"input_type": "text", "input_type": "text",
"size": 4, "size": 4,
"template": itemtemplate, "template": itemtemplate,
"title": "<tt>" "title": (
+ (f"S{ue.semestre_idx} " if ue.semestre_idx is not None else "") "<tt>"
+ f"<b>{ue.acronyme}</b></tt> {ue.titre}" + (
+ f" ({ue.ects} ECTS)" f"S{ue.semestre_idx} "
if ue.ects is not None if ue.semestre_idx is not None
else "", else ""
)
+ f"<b>{ue.acronyme}</b></tt> {ue.titre or ''}"
+ f" ({ue.ects} ECTS)"
if ue.ects is not None
else ""
),
"attributes": [coef_disabled], "attributes": [coef_disabled],
}, },
) )

View File

@ -281,9 +281,11 @@ def formsemestre_status_menubar(formsemestre: FormSemestre) -> str:
menu_inscriptions = [ menu_inscriptions = [
{ {
"title": "Gérer les inscriptions aux UE et modules" "title": (
if formsemestre.formation.is_apc() "Gérer les inscriptions aux UE et modules"
else "Gérer les inscriptions aux modules", if formsemestre.formation.is_apc()
else "Gérer les inscriptions aux modules"
),
"endpoint": "notes.moduleimpl_inscriptions_stats", "endpoint": "notes.moduleimpl_inscriptions_stats",
"args": {"formsemestre_id": formsemestre_id}, "args": {"formsemestre_id": formsemestre_id},
} }
@ -619,9 +621,9 @@ def formsemestre_description_table(
if ue.color: if ue.color:
for k in list(ue_info.keys()): for k in list(ue_info.keys()):
if not k.startswith("_"): if not k.startswith("_"):
ue_info[ ue_info[f"_{k}_td_attrs"] = (
f"_{k}_td_attrs" f'style="background-color: {ue.color} !important;"'
] = f'style="background-color: {ue.color} !important;"' )
if not is_apc: if not is_apc:
# n'affiche la ligne UE qu'en formation classique # n'affiche la ligne UE qu'en formation classique
# car l'UE de rattachement n'a pas d'intérêt en BUT # car l'UE de rattachement n'a pas d'intérêt en BUT
@ -1050,9 +1052,11 @@ def formsemestre_status(formsemestre_id=None, check_parcours=True):
formsemestre_id=formsemestre_id, page_title="Tableau de bord" formsemestre_id=formsemestre_id, page_title="Tableau de bord"
), ),
formsemestre_warning_apc_setup(formsemestre, nt), formsemestre_warning_apc_setup(formsemestre, nt),
formsemestre_warning_etuds_sans_note(formsemestre, nt) (
if can_change_all_notes formsemestre_warning_etuds_sans_note(formsemestre, nt)
else "", if can_change_all_notes
else ""
),
"""<p style="font-size: 130%"><b>Tableau de bord&nbsp;: </b>""", """<p style="font-size: 130%"><b>Tableau de bord&nbsp;: </b>""",
] ]
if formsemestre.est_courant(): if formsemestre.est_courant():
@ -1226,7 +1230,7 @@ def formsemestre_tableau_modules(
ue = modimpl.module.ue ue = modimpl.module.ue
if show_ues and (prev_ue_id != ue.id): if show_ues and (prev_ue_id != ue.id):
prev_ue_id = ue.id prev_ue_id = ue.id
titre = ue.titre titre = ue.titre or ""
if use_ue_coefs: if use_ue_coefs:
titre += f""" <b>(coef. {ue.coefficient or 0.0})</b>""" titre += f""" <b>(coef. {ue.coefficient or 0.0})</b>"""
H.append( H.append(

View File

@ -728,7 +728,9 @@ def formsemestre_recap_parcours_table(
) )
# Dispense BUT ? # Dispense BUT ?
if (etudid, ue.id) in nt.dispense_ues: if (etudid, ue.id) in nt.dispense_ues:
moy_ue_txt = "" if (ue_status and ue_status["is_capitalized"]) else "" moy_ue_txt = (
"" if (ue_status and ue_status["is_capitalized"]) else ""
)
explanation_ue.append("non inscrit (dispense)") explanation_ue.append("non inscrit (dispense)")
else: else:
moy_ue_txt = scu.fmt_note(moy_ue) moy_ue_txt = scu.fmt_note(moy_ue)
@ -1098,7 +1100,7 @@ def formsemestre_validate_previous_ue(formsemestre: FormSemestre, etud: Identite
ue_names = ["Choisir..."] + [ ue_names = ["Choisir..."] + [
f"""{('S'+str(ue.semestre_idx)+' : ') if ue.semestre_idx is not None else '' f"""{('S'+str(ue.semestre_idx)+' : ') if ue.semestre_idx is not None else ''
}{ue.acronyme} {ue.titre} ({ue.ue_code or ""})""" }{ue.acronyme} {ue.titre or ''} ({ue.ue_code or ""})"""
for ue in ues for ue in ues
] ]
ue_ids = [""] + [ue.id for ue in ues] ue_ids = [""] + [ue.id for ue in ues]

View File

@ -682,9 +682,9 @@ class RowRecap(tb.Row):
self.add_ue_modimpls_cols(ue, ue_status["is_capitalized"]) self.add_ue_modimpls_cols(ue, ue_status["is_capitalized"])
self.nb_ues_etud_parcours = len(res.etud_parcours_ues_ids(etud.id)) self.nb_ues_etud_parcours = len(res.etud_parcours_ues_ids(etud.id))
ue_valid_txt = ( ue_valid_txt = ue_valid_txt_html = (
ue_valid_txt_html f"{self.nb_ues_validables}/{self.nb_ues_etud_parcours}"
) = f"{self.nb_ues_validables}/{self.nb_ues_etud_parcours}" )
if self.nb_ues_warning: if self.nb_ues_warning:
ue_valid_txt_html += " " + scu.EMO_WARNING ue_valid_txt_html += " " + scu.EMO_WARNING
cell_class = "" cell_class = ""
@ -708,9 +708,9 @@ class RowRecap(tb.Row):
# sous-classé par JuryRow pour ajouter les codes # sous-classé par JuryRow pour ajouter les codes
table: TableRecap = self.table table: TableRecap = self.table
formsemestre: FormSemestre = table.res.formsemestre formsemestre: FormSemestre = table.res.formsemestre
table.group_titles[ table.group_titles["col_ue"] = (
"col_ue" f"UEs du S{formsemestre.semestre_id} {formsemestre.annee_scolaire()}"
] = f"UEs du S{formsemestre.semestre_id} {formsemestre.annee_scolaire()}" )
col_id = f"moy_ue_{ue.id}" col_id = f"moy_ue_{ue.id}"
val = ( val = (
ue_status["moy"] ue_status["moy"]
@ -740,7 +740,7 @@ class RowRecap(tb.Row):
) )
table.foot_title_row.cells[col_id].target_attrs[ table.foot_title_row.cells[col_id].target_attrs[
"title" "title"
] = f"""{ue.titre} S{ue.semestre_idx or '?'}""" ] = f"""{ue.titre or ue.acronyme} S{ue.semestre_idx or '?'}"""
def add_ue_modimpls_cols(self, ue: UniteEns, is_capitalized: bool): def add_ue_modimpls_cols(self, ue: UniteEns, is_capitalized: bool):
"""Ajoute à row les moyennes des modules (ou ressources et SAÉs) dans l'UE""" """Ajoute à row les moyennes des modules (ou ressources et SAÉs) dans l'UE"""

View File

@ -39,7 +39,7 @@
else 'compétence ' + ue.niveau_competence.annee + ' ' + ue.niveau_competence.competence.titre_long) else 'compétence ' + ue.niveau_competence.annee + ' ' + ue.niveau_competence.competence.titre_long)
if ue.type == 0 if ue.type == 0
else '' else ''
}}">{{ue.titre}}</a> }}">{{ue.titre or ue.acronyme}}</a>
</b> </b>
{% set virg = joiner(", ") %} {% set virg = joiner(", ") %}
<span class="ue_code">( <span class="ue_code">(

View File

@ -4,7 +4,7 @@
{% block app_content %} {% block app_content %}
<!-- begin ue_infos --> <!-- begin ue_infos -->
<h2>Unité d'Enseignement {{ue.acronyme|e}} {{ue.titre}}</h2> <h2>Unité d'Enseignement {{ue.acronyme|e}} {{(ue.titre or '')|e}}</h2>
<div class="ue_infos"> <div class="ue_infos">

View File

@ -113,7 +113,7 @@ def table_modules_ue_coefs(formation_id, semestre_idx=None, parcours_id: int = N
"y": 1, # 1ere ligne "y": 1, # 1ere ligne
"style": "title_ue", "style": "title_ue",
"data": ue.acronyme, "data": ue.acronyme,
"title": ue.titre, "title": ue.titre or ue.acronymexs,
} }
for (col, ue) in enumerate(ues, start=2) for (col, ue) in enumerate(ues, start=2)
] ]
@ -214,11 +214,13 @@ def edit_modules_ue_coefs():
{lockicon} {lockicon}
</h2> </h2>
""", """,
"""<span class="warning">Formation verrouilée car un ou plusieurs (
"""<span class="warning">Formation verrouilée car un ou plusieurs
semestres verrouillés l'utilisent. semestres verrouillés l'utilisent.
</span>""" </span>"""
if locked if locked
else "", else ""
),
render_template( render_template(
"pn/form_modules_ue_coefs.j2", "pn/form_modules_ue_coefs.j2",
formation=formation, formation=formation,