Dialogue affection groupe: template jinja2, début d'optimisation de XMLgetGroupsInPartition

This commit is contained in:
Emmanuel Viennet 2021-10-04 22:05:05 +02:00
parent 51bd6ba141
commit 54f0b87d39
12 changed files with 100 additions and 67 deletions

View File

@ -655,7 +655,7 @@ def log_unknown_etud():
def get_etud_info(etudid=False, code_nip=False, filled=False) -> list:
"""infos sur un etudiant (API). If not foud, returns empty list.
"""infos sur un etudiant (API). If not found, returns empty list.
On peut specifier etudid ou code_nip
ou bien cherche dans les argumenst de la requête courante:
etudid, code_nip, code_ine (dans cet ordre).
@ -671,6 +671,19 @@ def get_etud_info(etudid=False, code_nip=False, filled=False) -> list:
return etud
# Optim par cache local, utilité non prouvée mais
# on s'oriente vers un cahce persistent dans Redis ou bien l'utilisation de NT
# def get_etud_info_filled_by_etudid(etudid, cnx=None) -> dict:
# """Infos sur un étudiant, avec cache local à la requête"""
# if etudid in g.stored_etud_info:
# return g.stored_etud_info[etudid]
# cnx = cnx or ndb.GetDBConnexion()
# etud = etudident_list(cnx, args={"etudid": etudid})
# fill_etuds_info(etud)
# g.stored_etud_info[etudid] = etud[0]
# return etud[0]
def create_etud(cnx, args={}):
"""Creation d'un étudiant. génère aussi évenement et "news".

View File

@ -95,6 +95,8 @@ _formsemestreEditor = ndb.EditableTable(
def get_formsemestre(formsemestre_id, raise_soft_exc=False):
"list ONE formsemestre"
if formsemestre_id in g.stored_get_formsemestre:
return g.stored_get_formsemestre[formsemestre_id]
if not isinstance(formsemestre_id, int):
raise ValueError("formsemestre_id must be an integer !")
sems = do_formsemestre_list(args={"formsemestre_id": formsemestre_id})
@ -104,6 +106,7 @@ def get_formsemestre(formsemestre_id, raise_soft_exc=False):
raise ScoValueError(f"semestre {formsemestre_id} inconnu !")
else:
raise ValueError(f"semestre {formsemestre_id} inconnu !")
g.stored_get_formsemestre[formsemestre_id] = sems[0]
return sems[0]

View File

@ -337,7 +337,7 @@ def formsemestre_status_menubar(sem):
submenu.append(
{
"title": "%s" % partition["partition_name"],
"endpoint": "scolar.affectGroups",
"endpoint": "scolar.affect_groups",
"args": {"partition_id": partition["partition_id"]},
"enabled": enabled,
}
@ -507,7 +507,7 @@ def formsemestre_page_title():
h = f"""<div class="formsemestre_page_title">
<div class="infos">
<span class="semtitle"><a class="stdlink" title="%(session_id)s"
<span class="semtitle"><a class="stdlink" title="{sem['session_id']}"
href="{url_for('notes.formsemestre_status',
scodoc_dept=g.scodoc_dept, formsemestre_id=sem['formsemestre_id'])}"
>{sem['titre']}</a><a
@ -857,7 +857,7 @@ def _make_listes_sem(sem, with_absences=True):
H.append('<p class="help indent">Aucun groupe dans cette partition')
if sco_groups.sco_permissions_check.can_change_groups(formsemestre_id):
H.append(
f""" (<a href="{url_for("scolar.affectGroups",
f""" (<a href="{url_for("scolar.affect_groups",
scodoc_dept=g.scodoc_dept,
partition_id=partition["partition_id"])
}" class="stdlink">créer</a>)"""

View File

@ -492,6 +492,8 @@ def XMLgetGroupsInPartition(partition_id): # was XMLgetGroupesTD
"""
from app.scodoc import sco_formsemestre
cnx = ndb.GetDBConnexion()
t0 = time.time()
partition = get_partition(partition_id)
formsemestre_id = partition["formsemestre_id"]
@ -500,6 +502,7 @@ def XMLgetGroupsInPartition(partition_id): # was XMLgetGroupesTD
nt = sco_cache.NotesTableCache.get(formsemestre_id) # > inscrdict
etuds_set = set(nt.inscrdict)
# Build XML:
t1 = time.time()
doc = Element("ajax-response")
x_response = Element("response", type="object", id="MyUpdater")
doc.append(x_response)
@ -513,7 +516,8 @@ def XMLgetGroupsInPartition(partition_id): # was XMLgetGroupesTD
)
x_response.append(x_group)
for e in get_group_members(group["group_id"]):
etud = sco_etud.get_etud_info(etudid=e["etudid"], filled=1)[0]
etud = sco_etud.get_etud_info(etudid=e["etudid"], filled=True)[0]
# etud = sco_etud.get_etud_info_filled_by_etudid(e["etudid"], cnx)
x_group.append(
Element(
"etud",
@ -540,6 +544,7 @@ def XMLgetGroupsInPartition(partition_id): # was XMLgetGroupesTD
doc.append(x_group)
for etudid in etuds_set:
etud = sco_etud.get_etud_info(etudid=etudid, filled=True)[0]
# etud = sco_etud.get_etud_info_filled_by_etudid(etudid, cnx)
x_group.append(
Element(
"etud",
@ -550,7 +555,8 @@ def XMLgetGroupsInPartition(partition_id): # was XMLgetGroupesTD
origin=comp_origin(etud, sem),
)
)
log("XMLgetGroupsInPartition: %s seconds" % (time.time() - t0))
t2 = time.time()
log(f"XMLgetGroupsInPartition: {t2-t0} seconds ({t1-t0}+{t2-t1})")
# XML response:
data = sco_xml.XML_HEADER + ElementTree.tostring(doc).decode(scu.SCO_ENCODING)
response = make_response(data)
@ -911,7 +917,7 @@ def editPartitionForm(formsemestre_id=None):
H.append(", ".join(lg))
H.append(
f"""</td><td><a class="stdlink" href="{
url_for("scolar.affectGroups",
url_for("scolar.affect_groups",
scodoc_dept=g.scodoc_dept,
partition_id=p["partition_id"])
}">répartir</a></td>
@ -1173,7 +1179,7 @@ def group_set_name(group_id, group_name, redirect=1):
if redirect:
return flask.redirect(
url_for(
"scolar.affectGroups",
"scolar.affect_groups",
scodoc_dept=g.scodoc_dept,
partition_id=group["partition_id"],
)
@ -1216,7 +1222,7 @@ def group_rename(group_id):
elif tf[0] == -1:
return flask.redirect(
url_for(
"scolar.affectGroups",
"scolar.affect_groups",
scodoc_dept=g.scodoc_dept,
partition_id=group["partition_id"],
)
@ -1236,7 +1242,7 @@ def groups_auto_repartition(partition_id=None):
formsemestre_id = partition["formsemestre_id"]
# renvoie sur page édition groupes
dest_url = url_for(
"scolar.affectGroups", scodoc_dept=g.scodoc_dept, partition_id=partition_id
"scolar.affect_groups", scodoc_dept=g.scodoc_dept, partition_id=partition_id
)
if not sco_permissions_check.can_change_groups(formsemestre_id):
raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !")

View File

@ -27,70 +27,33 @@
"""Formulaires gestion des groupes
"""
from flask import render_template
from app.scodoc import html_sco_header
from app.scodoc import sco_groups
from app.scodoc.sco_exceptions import AccessDenied
def affectGroups(partition_id):
def affect_groups(partition_id):
"""Formulaire affectation des etudiants aux groupes de la partition.
Permet aussi la creation et la suppression de groupes.
"""
# Ported from DTML and adapted to new group management (nov 2009)
# réécrit pour 9.0.47 avec un template
partition = sco_groups.get_partition(partition_id)
formsemestre_id = partition["formsemestre_id"]
if not sco_groups.sco_permissions_check.can_change_groups(formsemestre_id):
raise AccessDenied("vous n'avez pas la permission d'effectuer cette opération")
H = [
html_sco_header.sco_header(
return render_template(
"scolar/affect_groups.html",
sco_header=html_sco_header.sco_header(
page_title="Affectation aux groupes",
javascripts=["js/groupmgr.js"],
cssstyles=["css/groups.css"],
),
"""<h2 class="formsemestre">Affectation aux groupes de %s</h2><form id="sp">"""
% partition["partition_name"],
]
H += [
"""</select></form>""",
"""<p>Faites glisser les étudiants d'un groupe à l'autre. Les modifications ne sont enregistrées que lorsque vous cliquez sur le bouton "<em>Enregistrer ces groupes</em>". Vous pouvez créer de nouveaux groupes. Pour <em>supprimer</em> un groupe, utiliser le lien "suppr." en haut à droite de sa boite. Vous pouvez aussi <a class="stdlink" href="groups_auto_repartition?partition_id=%(partition_id)s">répartir automatiquement les groupes</a>.
</p>"""
% partition,
"""<div id="gmsg" class="head_message"></div>""",
"""<div id="ginfo"></div>""",
"""<div id="savedinfo"></div>""",
"""<form name="formGroup" id="formGroup" onSubmit="return false;">""",
"""<input type="hidden" name="partition_id" value="%s"/>""" % partition_id,
"""<input name="groupName" size="6"/>
<input type="button" onClick="createGroup();" value="Créer groupe"/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<input type="button" onClick="submitGroups( target='gmsg' );" value="Enregistrer ces groupes" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<input type="button" onClick="document.location = 'formsemestre_status?formsemestre_id=%s'" value="Annuler" />&nbsp;&nbsp;&nbsp;&nbsp;
Editer groupes de
<select name="other_partition_id" onchange="GotoAnother();">"""
% formsemestre_id,
]
for p in sco_groups.get_partitions_list(formsemestre_id, with_default=False):
H.append('<option value="%s"' % p["partition_id"])
if p["partition_id"] == partition_id:
H.append(" selected")
H.append(">%s</option>" % p["partition_name"])
H += [
"""</select>
</form>
<div id="groups">
</div>
<div style="clear: left; margin-top: 15px;">
<p class="help"></p>
</div>
</div>
""",
html_sco_header.sco_footer(),
]
return "\n".join(H)
sco_footer=html_sco_header.sco_footer(),
partition=partition,
partitions_list=sco_groups.get_partitions_list(
formsemestre_id, with_default=False
),
formsemestre_id=formsemestre_id,
)

View File

@ -390,7 +390,7 @@ def formsemestre_inscr_passage(
): # il y a au moins une vraie partition
H.append(
f"""<li><a class="stdlink" href="{
url_for("scolar.affectGroups",
url_for("scolar.affect_groups",
scodoc_dept=g.scodoc_dept, partition_id=partition["partition_id"])
}">Répartir les groupes de {partition["partition_name"]}</a></li>
"""

View File

@ -315,7 +315,7 @@ def _make_table_notes(
rows.append(
{
"code": code,
"code": str(code), # INE, NIP ou etudid
"_code_td_attrs": 'style="padding-left: 1em; padding-right: 2em;"',
"etudid": etudid,
"nom": etud["nom"].upper(),
@ -376,7 +376,9 @@ def _make_table_notes(
if anonymous_listing:
rows.sort(key=lambda x: x["code"])
else:
rows.sort(key=lambda x: (x["nom"], x["prenom"])) # sort by nom, prenom
rows.sort(
key=lambda x: (x["nom"] or "", x["prenom"] or "")
) # sort by nom, prenom
# Si module, ajoute moyenne du module:
if len(evals) > 1:

View File

@ -271,7 +271,7 @@ def formsemestre_synchro_etuds(
if partitions: # il y a au moins une vraie partition
H.append(
f"""<li><a class="stdlink" href="{
url_for("scolar.affectGroups",
url_for("scolar.affect_groups",
scodoc_dept=g.scodoc_dept,
partition_id=partitions[0]["partition_id"]
)}">Répartir les groupes de {partitions[0]["partition_name"]}</a></li>

View File

@ -402,7 +402,7 @@ function GotoAnother() {
if (groups_unsaved) {
alert("Enregistrez ou annulez vos changement avant !");
} else
document.location = SCO_URL + '/affectGroups?partition_id=' + document.formGroup.other_partition_id.value;
document.location = SCO_URL + '/affect_groups?partition_id=' + document.formGroup.other_partition_id.value;
}

View File

@ -0,0 +1,43 @@
{{ sco_header|safe }}
<h2 class="formsemestre">Affectation aux groupes de {{ partition["partition_name"] }}</h2>
<p>Faites glisser les étudiants d'un groupe à l'autre. Les modifications ne
sont enregistrées que lorsque vous cliquez sur le bouton "<em>Enregistrer ces groupes</em>".
Vous pouvez créer de nouveaux groupes. Pour <em>supprimer</em> un groupe, utiliser le lien
"suppr." en haut à droite de sa boite.
Vous pouvez aussi <a class="stdlink"
href="{{ url_for('scolar.groups_auto_repartition', scodoc_dept=g.scodoc_dept, partition_id=partition['partition_id']) }}"
>répartir automatiquement les groupes</a>.
</p>
<div id="gmsg" class="head_message"></div>
<div id="ginfo"></div>
<div id="savedinfo"></div>
<form name="formGroup" id="formGroup" onSubmit="return false;">
<input type="hidden" name="partition_id" value="{{ partition['partition_id'] }}"/>
<input name="groupName" size="6"/>
<input type="button" onClick="createGroup();" value="Créer groupe"/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<input type="button" onClick="submitGroups( target='gmsg' );" value="Enregistrer ces groupes" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<input type="button"
onClick="document.location = '{{ url_for( 'notes.formsemestre_status', scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id) }}'"
value="Annuler" />&nbsp;&nbsp;&nbsp;&nbsp;Éditer groupes de
<select name="other_partition_id" onchange="GotoAnother();">
{% for p in partitions_list %}
<option value="{{ p['id'] }}" {{"selected" if p["partition_id"] == partition_id }}>{{p["partition_name"]}}</option>
{% endfor %}
</select>
</form>
<div id="groups">
</div>
<div style="clear: left; margin-top: 15px;">
<p class="help"></p>
</div>
</div>
{{ sco_footer|safe }}

View File

@ -30,6 +30,9 @@ def start_scodoc_request():
if current_user.is_authenticated:
current_user.last_seen = datetime.datetime.utcnow()
db.session.commit()
# caches locaux (durée de vie=la requête en cours)
g.stored_get_formsemestre = {}
# g.stored_etud_info = {} optim en cours, voir si utile
@scodoc_bp.teardown_app_request

View File

@ -651,8 +651,8 @@ def formChangeCoordonnees(etudid):
# --- Gestion des groupes:
sco_publish(
"/affectGroups",
sco_groups_edit.affectGroups,
"/affect_groups",
sco_groups_edit.affect_groups,
Permission.ScoView,
methods=["GET", "POST"],
)