forked from ScoDoc/ScoDoc
Update opolka/ScoDoc from ScoDoc/ScoDoc #2
@ -208,7 +208,7 @@ class FormSemestre(models.ScoDocModel):
|
|||||||
return cls.query.filter_by(id=formsemestre_id).first_or_404()
|
return cls.query.filter_by(id=formsemestre_id).first_or_404()
|
||||||
|
|
||||||
def sort_key(self) -> tuple:
|
def sort_key(self) -> tuple:
|
||||||
"""clé pour tris par ordre alphabétique
|
"""clé pour tris par ordre de date_debut, le plus ancien en tête
|
||||||
(pour avoir le plus récent d'abord, sort avec reverse=True)"""
|
(pour avoir le plus récent d'abord, sort avec reverse=True)"""
|
||||||
return (self.date_debut, self.semestre_id)
|
return (self.date_debut, self.semestre_id)
|
||||||
|
|
||||||
|
@ -79,21 +79,30 @@ def index_html(showcodes=0, showsemtable=0, export_table_formsemestres=False):
|
|||||||
else:
|
else:
|
||||||
html_table_formsemestres = None
|
html_table_formsemestres = None
|
||||||
|
|
||||||
|
current_formsemestres_by_modalite, modalites = (
|
||||||
|
sco_modalites.group_formsemestres_by_modalite(current_formsemestres)
|
||||||
|
)
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
"scolar/index.j2",
|
"scolar/index.j2",
|
||||||
current_user=current_user,
|
current_user=current_user,
|
||||||
|
current_formsemestres=current_formsemestres,
|
||||||
|
current_formsemestres_by_modalite=current_formsemestres_by_modalite,
|
||||||
dept_name=sco_preferences.get_preference("DeptName"),
|
dept_name=sco_preferences.get_preference("DeptName"),
|
||||||
formsemestres=formsemestres,
|
emptygroupicon=scu.icontag(
|
||||||
html_current_formsemestres=_show_current_formsemestres(
|
"emptygroupicon_img", title="Pas d'inscrits", border="0"
|
||||||
current_formsemestres, showcodes
|
|
||||||
),
|
),
|
||||||
|
formsemestres=formsemestres,
|
||||||
|
groupicon=scu.icontag("groupicon_img", title="Inscrits", border="0"),
|
||||||
html_table_formsemestres=html_table_formsemestres,
|
html_table_formsemestres=html_table_formsemestres,
|
||||||
locked_formsemestres=locked_formsemestres,
|
locked_formsemestres=locked_formsemestres,
|
||||||
|
modalites=modalites,
|
||||||
nb_locked=locked_formsemestres.count(),
|
nb_locked=locked_formsemestres.count(),
|
||||||
nb_user_accounts=sco_users.get_users_count(dept=g.scodoc_dept),
|
nb_user_accounts=sco_users.get_users_count(dept=g.scodoc_dept),
|
||||||
page_title=f"ScoDoc {g.scodoc_dept}",
|
page_title=f"ScoDoc {g.scodoc_dept}",
|
||||||
Permission=Permission,
|
Permission=Permission,
|
||||||
scolar_news_summary=ScolarNews.scolar_news_summary_html(),
|
scolar_news_summary=ScolarNews.scolar_news_summary_html(),
|
||||||
|
showcodes=showcodes,
|
||||||
showsemtable=showsemtable,
|
showsemtable=showsemtable,
|
||||||
sco=ScoData(),
|
sco=ScoData(),
|
||||||
)
|
)
|
||||||
@ -116,6 +125,7 @@ def _convert_formsemestres_to_dicts(
|
|||||||
lockicon = "X"
|
lockicon = "X"
|
||||||
# génère liste de dict
|
# génère liste de dict
|
||||||
sems = []
|
sems = []
|
||||||
|
formsemestre: FormSemestre
|
||||||
for formsemestre in formsemestres:
|
for formsemestre in formsemestres:
|
||||||
nb_inscrits = len(formsemestre.inscriptions)
|
nb_inscrits = len(formsemestre.inscriptions)
|
||||||
formation = formsemestre.formation
|
formation = formsemestre.formation
|
||||||
@ -151,61 +161,6 @@ def _convert_formsemestres_to_dicts(
|
|||||||
return sems
|
return sems
|
||||||
|
|
||||||
|
|
||||||
def _show_current_formsemestres(formsemestres: Query, showcodes: bool) -> str:
|
|
||||||
"""html div avec les formsemestres courants de la page d'accueil"""
|
|
||||||
|
|
||||||
H = []
|
|
||||||
if formsemestres.count():
|
|
||||||
H.append("""<div class="scobox-title">Sessions en cours</div>""")
|
|
||||||
H.append(_sem_table(_convert_formsemestres_to_dicts(formsemestres, showcodes)))
|
|
||||||
else:
|
|
||||||
# aucun semestre courant: affiche aide
|
|
||||||
H.append(
|
|
||||||
"""
|
|
||||||
<div class="scobox-title">Aucune session en cours !</div>
|
|
||||||
<p>Pour ajouter une session, aller dans <a href="Notes" id="link-programmes">Formations</a>,
|
|
||||||
choisissez une formation, puis suivez le lien "<em>UE, modules, semestres</em>".
|
|
||||||
</p>
|
|
||||||
<p>Là, en bas de page, suivez le lien
|
|
||||||
"<em>Mettre en place un nouveau semestre de formation...</em>"
|
|
||||||
</p>"""
|
|
||||||
)
|
|
||||||
return "\n".join(H)
|
|
||||||
|
|
||||||
|
|
||||||
def _sem_table(sems: list[dict]) -> str:
|
|
||||||
"""Affiche liste des semestres, utilisée pour semestres en cours"""
|
|
||||||
tmpl = f"""<tr class="%(trclass)s">%(tmpcode)s
|
|
||||||
<td class="semicon">%(lockimg)s <a href="{
|
|
||||||
url_for("notes.formsemestre_status", scodoc_dept=g.scodoc_dept)}?formsemestre_id=%(formsemestre_id)s#groupes">%(groupicon)s</a></td>
|
|
||||||
<td class="datesem">%(mois_debut)s <a title="%(session_id)s">-</a> %(mois_fin)s</td>
|
|
||||||
<td class="titresem"><a class="stdlink" href="{url_for("notes.formsemestre_status", scodoc_dept=g.scodoc_dept)}?formsemestre_id=%(formsemestre_id)s">%(titre_num)s</a>
|
|
||||||
<span class="respsem">(%(responsable_name)s)</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Liste des semestres, groupés par modalités
|
|
||||||
sems_by_mod, modalites = sco_modalites.group_sems_by_modalite(sems)
|
|
||||||
|
|
||||||
H = ['<table class="listesems">']
|
|
||||||
for modalite in modalites:
|
|
||||||
if len(modalites) > 1:
|
|
||||||
H.append('<tr><th colspan="3">%s</th></tr>' % modalite["titre"])
|
|
||||||
|
|
||||||
if sems_by_mod[modalite["modalite"]]:
|
|
||||||
cur_idx = sems_by_mod[modalite["modalite"]][0]["semestre_id"]
|
|
||||||
for sem in sems_by_mod[modalite["modalite"]]:
|
|
||||||
if cur_idx != sem["semestre_id"]:
|
|
||||||
sem["trclass"] = "firstsem" # separe les groupes de semestres
|
|
||||||
cur_idx = sem["semestre_id"]
|
|
||||||
else:
|
|
||||||
sem["trclass"] = ""
|
|
||||||
H.append(tmpl % sem)
|
|
||||||
H.append("</table>")
|
|
||||||
return "\n".join(H)
|
|
||||||
|
|
||||||
|
|
||||||
def _sem_table_gt(formsemestres: Query, showcodes=False, fmt="html") -> GenTable:
|
def _sem_table_gt(formsemestres: Query, showcodes=False, fmt="html") -> GenTable:
|
||||||
"""Table des semestres
|
"""Table des semestres
|
||||||
Utilise une datatables.
|
Utilise une datatables.
|
||||||
|
@ -36,37 +36,45 @@ Elle n'est pas utilisée pour les parcours, ni pour rien d'autre
|
|||||||
import collections
|
import collections
|
||||||
import app.scodoc.notesdb as ndb
|
import app.scodoc.notesdb as ndb
|
||||||
from app import log
|
from app import log
|
||||||
|
from app.models import FormSemestre
|
||||||
|
|
||||||
|
|
||||||
def list_formsemestres_modalites(sems):
|
def list_formsemestres_modalites(formsemestres: list[FormSemestre]) -> list[dict]:
|
||||||
"""Liste ordonnée des modalités présentes dans ces formsemestres"""
|
"""Liste ordonnée des modalités présentes dans ces formsemestres"""
|
||||||
modalites = {}
|
modalites = {}
|
||||||
for sem in sems:
|
for formsemestre in formsemestres:
|
||||||
if sem["modalite"] not in modalites:
|
if formsemestre.modalite not in modalites:
|
||||||
m = do_modalite_list(args={"modalite": sem["modalite"]})[0]
|
m = do_modalite_list(args={"modalite": formsemestre.modalite})[0]
|
||||||
modalites[m["modalite"]] = m
|
modalites[m["modalite"]] = m
|
||||||
modalites = list(modalites.values())
|
modalites = list(modalites.values())
|
||||||
modalites.sort(key=lambda x: x["numero"])
|
modalites.sort(key=lambda x: x["numero"])
|
||||||
return modalites
|
return modalites
|
||||||
|
|
||||||
|
|
||||||
def group_sems_by_modalite(sems: list[dict]):
|
def group_formsemestres_by_modalite(
|
||||||
|
formsemestres: list[FormSemestre],
|
||||||
|
) -> dict[str, list[FormSemestre]]:
|
||||||
"""Given the list of formsemestre, group them by modalite,
|
"""Given the list of formsemestre, group them by modalite,
|
||||||
sorted in each one by semestre id and date
|
sorted in each one by semestre id and date
|
||||||
"""
|
"""
|
||||||
sems_by_mod = collections.defaultdict(list)
|
sems_by_mod = collections.defaultdict(list)
|
||||||
modalites = list_formsemestres_modalites(sems)
|
modalites = list_formsemestres_modalites(formsemestres)
|
||||||
for modalite in modalites:
|
sems_by_mod = {
|
||||||
for sem in sems:
|
modalite["modalite"]: [
|
||||||
if sem["semestre_id"] < 0: # formations en un semestre
|
formsemestre
|
||||||
sem["sortkey"] = (-100 * sem["semestre_id"], sem["dateord"])
|
for formsemestre in formsemestres
|
||||||
else:
|
if formsemestre.modalite == modalite["modalite"]
|
||||||
sem["sortkey"] = (sem["semestre_id"], sem["dateord"])
|
]
|
||||||
if sem["modalite"] == modalite["modalite"]:
|
for modalite in modalites
|
||||||
sems_by_mod[modalite["modalite"]].append(sem)
|
}
|
||||||
# tri dans chaque modalité par indice de semestre et date debut
|
# tri dans chaque modalité par indice de semestre et date debut
|
||||||
for modalite in modalites:
|
for modalite in modalites:
|
||||||
sems_by_mod[modalite["modalite"]].sort(key=lambda x: x["sortkey"])
|
sems_by_mod[modalite["modalite"]].sort(
|
||||||
|
key=lambda x: (
|
||||||
|
x.semestre_id if x.semestre_id > 0 else -1000 * x.semestre_id,
|
||||||
|
x.date_debut,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
return sems_by_mod, modalites
|
return sems_by_mod, modalites
|
||||||
|
|
||||||
|
@ -83,6 +83,70 @@ table.semlist tbody tr td.modalite {
|
|||||||
padding-right: 1em;
|
padding-right: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.modalite {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
span.effectif {
|
||||||
|
display: inline-block;
|
||||||
|
min-width: 24px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cur-formsemestres {
|
||||||
|
width: max-content; /* Fits content, but respects max-width */
|
||||||
|
max-width: 1024px; /* Maximum width */
|
||||||
|
margin: 0 auto 0 0; /* Centers divs if they are narrower than 1024px */
|
||||||
|
}
|
||||||
|
.cur-formsemestre {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
border-left: 1px solid #ddd;
|
||||||
|
border-right: 1px solid #ddd;;
|
||||||
|
background-color: rgb(246, 255, 254);
|
||||||
|
padding: 0px 8px 0px 8px;
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cur-formsemestre.new-sem {
|
||||||
|
margin-top: 8px;
|
||||||
|
border-top: 1px solid #ddd;;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-section {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-left: 10px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cur-formsemestre .title {
|
||||||
|
flex-grow: 1;
|
||||||
|
text-align: left;
|
||||||
|
margin: 0 20px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-section {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.responsable {
|
||||||
|
font-weight: bold;
|
||||||
|
color: navy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
{# News #}
|
{# News #}
|
||||||
@ -103,7 +167,43 @@ table.semlist tbody tr td.modalite {
|
|||||||
|
|
||||||
{# Les semestres courants (cad non verrouillés) #}
|
{# Les semestres courants (cad non verrouillés) #}
|
||||||
<div class="scobox">
|
<div class="scobox">
|
||||||
{{html_current_formsemestres|safe}}
|
{% if current_formsemestres.count() == 0 %}
|
||||||
|
<div class="scobox-title">Aucune session en cours !</div>
|
||||||
|
<p>Pour ajouter une session, aller dans <a href="Notes" id="link-programmes">Formations</a>,
|
||||||
|
choisissez une formation, puis suivez le lien "<em>UE, modules, semestres</em>".
|
||||||
|
</p>
|
||||||
|
<p>Là, en bas de page, suivez le lien
|
||||||
|
"<em>Mettre en place un nouveau semestre de formation...</em>"
|
||||||
|
</p>
|
||||||
|
{% else %}
|
||||||
|
<div class="scobox-title">Sessions en cours</div>
|
||||||
|
<div class="cur-formsemestres">
|
||||||
|
{% for modalite in modalites %}
|
||||||
|
{% if modalites|length > 1 %}
|
||||||
|
<div class="modalite">{{modalite.titre}}</div>
|
||||||
|
{% endif %}
|
||||||
|
{% for formsemestre in current_formsemestres_by_modalite[modalite.modalite] %}
|
||||||
|
<div class="cur-formsemestre {{'new-sem' if loop.first or formsemestre.semestre_id != loop.previtem.semestre_id}}">
|
||||||
|
<div class="left-section">
|
||||||
|
{{groupicon|safe if formsemestre.inscriptions|length else emptygroupicon|safe}}
|
||||||
|
<div class="date">
|
||||||
|
<div class="date-begin"><a title="{{formsemestre.session_id()}}">{{formsemestre.mois_debut()}}</a></div>
|
||||||
|
<div class="date-end">{{formsemestre.mois_fin()}}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="title">
|
||||||
|
<a class="stdlink" href="{{ url_for("notes.formsemestre_status",
|
||||||
|
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre.id)}}">{{formsemestre.titre_num()}}</a>
|
||||||
|
</div>
|
||||||
|
<div class="right-section">
|
||||||
|
<div class="responsable">{{formsemestre.responsables_str()}}</div>
|
||||||
|
<div class="effectif">{{formsemestre.inscriptions|length}} étuds</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{# Table de tous les semestres #}
|
{# Table de tous les semestres #}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# -*- mode: python -*-
|
# -*- mode: python -*-
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
SCOVERSION = "9.6.954"
|
SCOVERSION = "9.6.955"
|
||||||
|
|
||||||
SCONAME = "ScoDoc"
|
SCONAME = "ScoDoc"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user