forked from ScoDoc/ScoDoc
Templatification des vues (WIP)
This commit is contained in:
parent
dc25ad7ca2
commit
ebd71a3299
@ -51,7 +51,7 @@ from wtforms import (
|
||||
from app.models import Evaluation, ModuleImpl
|
||||
import app.scodoc.sco_utils as scu
|
||||
import app.scodoc.notesdb as ndb
|
||||
from app.scodoc import html_sco_header, sco_preferences
|
||||
from app.scodoc import sco_preferences
|
||||
from app.scodoc import sco_edit_module
|
||||
from app.scodoc import sco_evaluations
|
||||
from app.scodoc import sco_excel
|
||||
@ -204,14 +204,14 @@ def placement_eval_selectetuds(evaluation_id):
|
||||
% runner.__dict__
|
||||
)
|
||||
return runner.exec_placement() # calcul et generation du fichier
|
||||
htmls = [
|
||||
html_sco_header.sco_header(),
|
||||
sco_evaluations.evaluation_describe(evaluation_id=evaluation_id),
|
||||
"<h3>Placement et émargement des étudiants</h3>",
|
||||
render_template("scodoc/forms/placement.j2", form=form),
|
||||
]
|
||||
footer = html_sco_header.sco_footer()
|
||||
return "\n".join(htmls) + "<p>" + footer
|
||||
|
||||
return render_template(
|
||||
"scodoc/forms/placement.j2",
|
||||
evaluations_description=sco_evaluations.evaluation_describe(
|
||||
evaluation_id=evaluation_id
|
||||
),
|
||||
form=form,
|
||||
)
|
||||
|
||||
|
||||
class PlacementRunner:
|
||||
|
@ -37,7 +37,7 @@ import time
|
||||
import datetime
|
||||
from operator import itemgetter
|
||||
|
||||
from flask import url_for, g, request
|
||||
from flask import url_for, g, render_template, request
|
||||
import pydot
|
||||
|
||||
from app import log
|
||||
@ -50,7 +50,6 @@ from app.models.etudiants import Identite
|
||||
|
||||
from app.scodoc import (
|
||||
codes_cursus,
|
||||
html_sco_header,
|
||||
sco_etud,
|
||||
sco_formsemestre,
|
||||
sco_formsemestre_inscriptions,
|
||||
@ -411,11 +410,6 @@ def formsemestre_report_counts(
|
||||
if fmt != "html":
|
||||
return tableau
|
||||
H = [
|
||||
html_sco_header.sco_header(
|
||||
cssstyles=sco_groups_view.CSSSTYLES,
|
||||
javascripts=sco_groups_view.JAVASCRIPTS,
|
||||
page_title=title,
|
||||
),
|
||||
tableau,
|
||||
"\n".join(F),
|
||||
"""<p class="help">Le tableau affiche le nombre d'étudiants de ce semestre dans chacun
|
||||
@ -423,9 +417,14 @@ def formsemestre_report_counts(
|
||||
pour les lignes et les colonnes. Le <tt>codedecision</tt> est le code de la décision
|
||||
du jury.
|
||||
</p>""",
|
||||
html_sco_header.sco_footer(),
|
||||
]
|
||||
return "\n".join(H)
|
||||
return render_template(
|
||||
"sco_page.j2",
|
||||
cssstyles=sco_groups_view.CSSSTYLES,
|
||||
javascripts=sco_groups_view.JAVASCRIPTS,
|
||||
title=title,
|
||||
content="\n".join(H),
|
||||
)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
@ -813,11 +812,6 @@ def formsemestre_suivi_cohorte(
|
||||
href="{burl}&percent=1">Afficher les résultats en pourcentages</a></p>"""
|
||||
|
||||
H = [
|
||||
html_sco_header.sco_header(
|
||||
cssstyles=sco_groups_view.CSSSTYLES,
|
||||
javascripts=sco_groups_view.JAVASCRIPTS,
|
||||
page_title=tab.page_title,
|
||||
),
|
||||
"""<h2 class="formsemestre">Suivi cohorte: devenir des étudiants de ce semestre</h2>""",
|
||||
_gen_form_selectetuds(
|
||||
formsemestre.id,
|
||||
@ -853,9 +847,14 @@ def formsemestre_suivi_cohorte(
|
||||
</p>
|
||||
""",
|
||||
expl,
|
||||
html_sco_header.sco_footer(),
|
||||
]
|
||||
return "\n".join(H)
|
||||
return render_template(
|
||||
"sco_page.j2",
|
||||
cssstyles=sco_groups_view.CSSSTYLES,
|
||||
javascripts=sco_groups_view.JAVASCRIPTS,
|
||||
title=tab.page_title,
|
||||
content="\n".join(H),
|
||||
)
|
||||
|
||||
|
||||
def _gen_form_selectetuds(
|
||||
@ -1365,15 +1364,11 @@ def formsemestre_suivi_cursus(
|
||||
]
|
||||
|
||||
H = [
|
||||
html_sco_header.sco_header(
|
||||
page_title=tab.page_title,
|
||||
),
|
||||
"""<h2 class="formsemestre">Cursus suivis par les étudiants de ce semestre</h2>""",
|
||||
"\n".join(F),
|
||||
t,
|
||||
html_sco_header.sco_footer(),
|
||||
]
|
||||
return "\n".join(H)
|
||||
return render_template("sco_page.j2", title=tab.page_title, content="\n".join(H))
|
||||
|
||||
|
||||
# -------------
|
||||
@ -1742,12 +1737,6 @@ def formsemestre_graph_cursus(
|
||||
)
|
||||
|
||||
H = [
|
||||
html_sco_header.sco_header(
|
||||
cssstyles=sco_groups_view.CSSSTYLES,
|
||||
javascripts=sco_groups_view.JAVASCRIPTS,
|
||||
page_title="Graphe cursus de %(titreannee)s" % sem,
|
||||
no_sidebar=True,
|
||||
),
|
||||
"""<h2 class="formsemestre">Cursus des étudiants de ce semestre</h2>""",
|
||||
doc,
|
||||
f"<p>{len(etuds)} étudiants sélectionnés</p>",
|
||||
@ -1771,11 +1760,12 @@ def formsemestre_graph_cursus(
|
||||
),
|
||||
"""<p>Origine et devenir des étudiants inscrits dans %(titreannee)s"""
|
||||
% sem,
|
||||
"""(<a href="%s">version pdf</a>"""
|
||||
% url_for("notes.formsemestre_graph_cursus", fmt="pdf", **url_kw),
|
||||
""", <a href="%s">image PNG</a>)"""
|
||||
% url_for("notes.formsemestre_graph_cursus", fmt="png", **url_kw),
|
||||
f"""
|
||||
f"""(<a href="{
|
||||
url_for("notes.formsemestre_graph_cursus", fmt="pdf", **url_kw)
|
||||
}">version pdf</a>,
|
||||
<a href="{
|
||||
url_for("notes.formsemestre_graph_cursus", fmt="png", **url_kw)}">image PNG</a>)
|
||||
|
||||
</p>
|
||||
<p class="help">Le graphe permet de suivre les étudiants inscrits dans le semestre
|
||||
sélectionné (dessiné en vert). Chaque rectangle représente un semestre (cliquez dedans
|
||||
@ -1788,8 +1778,14 @@ def formsemestre_graph_cursus(
|
||||
étudiants appartenant aux groupes indiqués <em>dans le semestre d'origine</em>.
|
||||
</p>
|
||||
""",
|
||||
html_sco_header.sco_footer(),
|
||||
]
|
||||
return "\n".join(H)
|
||||
return render_template(
|
||||
"sco_page.j2",
|
||||
cssstyles=sco_groups_view.CSSSTYLES,
|
||||
javascripts=sco_groups_view.JAVASCRIPTS,
|
||||
page_title=f"Graphe cursus de {sem['titreannee']}",
|
||||
no_sidebar=True,
|
||||
content="\n".join(H),
|
||||
)
|
||||
else:
|
||||
raise ValueError(f"invalid format: {fmt}")
|
||||
|
@ -31,21 +31,18 @@
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
from flask import request
|
||||
from flask import render_template, request
|
||||
|
||||
from app import db
|
||||
from app.but import jury_but
|
||||
from app.models import FormSemestre
|
||||
from app.models.formsemestre import FormSemestreInscription
|
||||
|
||||
import app.scodoc.sco_utils as scu
|
||||
from app.scodoc import html_sco_header
|
||||
from app.scodoc import codes_cursus
|
||||
from app.scodoc.sco_exceptions import ScoValueError
|
||||
|
||||
from app.scodoc import sco_preferences
|
||||
import sco_version
|
||||
from app.scodoc.gen_tables import GenTable
|
||||
import sco_version
|
||||
|
||||
|
||||
# Titres, ordonnés
|
||||
@ -107,13 +104,11 @@ def formsemestre_but_indicateurs(formsemestre_id: int, fmt="html"):
|
||||
if fmt != "html":
|
||||
return t
|
||||
H = [
|
||||
html_sco_header.sco_header(page_title=title),
|
||||
t,
|
||||
"""<p class="help">
|
||||
</p>""",
|
||||
html_sco_header.sco_footer(),
|
||||
]
|
||||
return "\n".join(H)
|
||||
return render_template("sco_page.j2", title=title, content="\n".join(H))
|
||||
|
||||
|
||||
def but_indicateurs_by_bac(formsemestre: FormSemestre) -> dict[str:dict]:
|
||||
|
@ -40,17 +40,15 @@ sem_set_list()
|
||||
"""
|
||||
|
||||
import flask
|
||||
from flask import g, url_for
|
||||
from flask import g, render_template, url_for
|
||||
|
||||
from app import db, log
|
||||
from app.comp import res_sem
|
||||
from app.comp.res_compat import NotesTableCompat
|
||||
from app.models import FormSemestre
|
||||
from app.scodoc import html_sco_header
|
||||
from app.scodoc import sco_etape_apogee
|
||||
from app.scodoc import sco_formsemestre
|
||||
from app.scodoc import sco_formsemestre_status
|
||||
from app.scodoc import sco_portal_apogee
|
||||
from app.scodoc import sco_preferences
|
||||
from app.scodoc.gen_tables import GenTable
|
||||
from app.scodoc.sco_etape_bilan import EtapeBilan
|
||||
@ -412,7 +410,7 @@ def do_semset_delete(semset_id, dialog_confirmed=False):
|
||||
s = SemSet(semset_id=semset_id)
|
||||
if not dialog_confirmed:
|
||||
return scu.confirm_dialog(
|
||||
"<h2>Suppression de l'ensemble %(title)s ?</h2>" % s,
|
||||
f"<h2>Suppression de l'ensemble {s['title']} ?</h2>",
|
||||
dest_url="",
|
||||
parameters={"semset_id": semset_id},
|
||||
cancel_url="semset_page",
|
||||
@ -421,14 +419,14 @@ def do_semset_delete(semset_id, dialog_confirmed=False):
|
||||
return flask.redirect("semset_page")
|
||||
|
||||
|
||||
def edit_semset_set_title(id=None, value=None):
|
||||
def edit_semset_set_title(oid=None, value=None):
|
||||
"""Change title of semset"""
|
||||
title = value.strip()
|
||||
if not id:
|
||||
if not oid:
|
||||
raise ScoValueError("empty semset_id")
|
||||
SemSet(semset_id=id)
|
||||
SemSet(semset_id=oid)
|
||||
cnx = ndb.GetDBConnexion()
|
||||
semset_edit(cnx, {"semset_id": id, "title": title})
|
||||
semset_edit(cnx, {"semset_id": oid, "title": title})
|
||||
return title
|
||||
|
||||
|
||||
@ -517,22 +515,18 @@ def semset_page(fmt="html"):
|
||||
|
||||
page_title = "Ensembles de semestres"
|
||||
H = [
|
||||
html_sco_header.sco_header(
|
||||
page_title=page_title,
|
||||
javascripts=["libjs/jinplace-1.2.1.min.js"],
|
||||
),
|
||||
"""<script>$(function() {
|
||||
$('.inplace_edit').jinplace();
|
||||
});
|
||||
</script>""",
|
||||
"<h2>%s</h2>" % page_title,
|
||||
f"<h2>{page_title}</h2>",
|
||||
]
|
||||
H.append(tab.html())
|
||||
|
||||
annee_courante = int(scu.annee_scolaire())
|
||||
menu_annee = "\n".join(
|
||||
[
|
||||
'<option value="%s">%s</option>' % (i, i)
|
||||
f"""<option value="{i}">{i}</option>"""
|
||||
for i in range(2014, annee_courante + 1)
|
||||
]
|
||||
)
|
||||
@ -561,8 +555,8 @@ def semset_page(fmt="html"):
|
||||
|
||||
H.append(
|
||||
"""
|
||||
<div>
|
||||
<h4>Autres opérations:</h4>
|
||||
<div class="scobox space-before-24">
|
||||
<div class="scobox-title">Autres opérations :</div>
|
||||
<ul>
|
||||
<li><a class="stdlink" href="scodoc_table_results">
|
||||
Table des résultats de tous les semestres
|
||||
@ -575,4 +569,9 @@ def semset_page(fmt="html"):
|
||||
"""
|
||||
)
|
||||
|
||||
return "\n".join(H) + html_sco_header.sco_footer()
|
||||
return render_template(
|
||||
"sco_page_dept.j2",
|
||||
title=page_title,
|
||||
javascripts=["libjs/jinplace-1.2.1.min.js"],
|
||||
content="\n".join(H),
|
||||
)
|
||||
|
@ -49,7 +49,6 @@ import app.scodoc.sco_utils as scu
|
||||
from app.scodoc.TrivialFormulator import TrivialFormulator
|
||||
from app.scodoc.sco_exceptions import ScoPDFFormatError, ScoValueError
|
||||
from app.scodoc.sco_pdf import SU
|
||||
from app.scodoc import html_sco_header
|
||||
from app.scodoc import htmlutils
|
||||
from app.scodoc import sco_import_etuds
|
||||
from app.scodoc import sco_excel
|
||||
@ -90,12 +89,7 @@ def trombino(
|
||||
return _listeappel_photos_pdf(groups_infos)
|
||||
elif fmt == "doc":
|
||||
return sco_trombino_doc.trombino_doc(groups_infos)
|
||||
else:
|
||||
raise Exception("invalid format")
|
||||
|
||||
|
||||
def _trombino_html_header():
|
||||
return html_sco_header.sco_header(javascripts=["js/trombino.js"])
|
||||
raise ValueError("invalid format")
|
||||
|
||||
|
||||
def trombino_html(groups_infos):
|
||||
@ -251,14 +245,18 @@ def trombino_copy_photos(group_ids=None, dialog_confirmed=False):
|
||||
back_url = "groups_photos?" + str(groups_infos.groups_query_args)
|
||||
|
||||
portal_url = sco_portal_apogee.get_portal_url()
|
||||
header = html_sco_header.sco_header(page_title="Chargement des photos")
|
||||
footer = html_sco_header.sco_footer()
|
||||
if not portal_url:
|
||||
return f"""{ header }
|
||||
return render_template(
|
||||
"sco_page.j2",
|
||||
content=f"""
|
||||
<p>portail non configuré</p>
|
||||
<p><a href="{back_url}" class="stdlink">Retour au trombinoscope</a></p>
|
||||
{ footer }
|
||||
"""
|
||||
<div>
|
||||
<a class="stdlink" href="{back_url}" class="stdlink">
|
||||
Retour au trombinoscope
|
||||
</a>
|
||||
</div>
|
||||
""",
|
||||
)
|
||||
if not dialog_confirmed:
|
||||
return scu.confirm_dialog(
|
||||
f"""<h2>Copier les photos du portail vers ScoDoc ?</h2>
|
||||
@ -285,14 +283,18 @@ def trombino_copy_photos(group_ids=None, dialog_confirmed=False):
|
||||
|
||||
msg.append(f"<b>{nok} photos correctement chargées</b>")
|
||||
|
||||
return f"""{ header }
|
||||
return render_template(
|
||||
"sco_page.j2",
|
||||
content=f"""
|
||||
<h2>Chargement des photos depuis le portail</h2>
|
||||
<ul><li>
|
||||
{ '</li><li>'.join(msg) }
|
||||
</li></ul>
|
||||
<p><a href="{back_url}">retour au trombinoscope</a>
|
||||
{ footer }
|
||||
"""
|
||||
<div class="space-before-24">
|
||||
<a class="stdlink" href="{back_url}">retour au trombinoscope</a>
|
||||
</div>
|
||||
""",
|
||||
)
|
||||
|
||||
|
||||
def _get_etud_platypus_image(t, image_width=2 * cm):
|
||||
@ -506,7 +508,6 @@ def photos_import_files_form(group_ids=()):
|
||||
back_url = f"groups_photos?{groups_infos.groups_query_args}"
|
||||
|
||||
H = [
|
||||
html_sco_header.sco_header(page_title="Import des photos des étudiants"),
|
||||
f"""<h2 class="formsemestre">Téléchargement des photos des étudiants</h2>
|
||||
<p><b>Vous pouvez aussi charger les photos individuellement via la fiche
|
||||
de chaque étudiant (menu "Étudiant" / "Changer la photo").</b>
|
||||
@ -526,7 +527,6 @@ def photos_import_files_form(group_ids=()):
|
||||
<li style="padding-top: 2em;">
|
||||
""",
|
||||
]
|
||||
F = html_sco_header.sco_footer()
|
||||
vals = scu.get_request_args()
|
||||
vals["group_ids"] = groups_infos.group_ids
|
||||
tf = TrivialFormulator(
|
||||
@ -540,37 +540,40 @@ def photos_import_files_form(group_ids=()):
|
||||
)
|
||||
|
||||
if tf[0] == 0:
|
||||
return "\n".join(H) + tf[1] + "</li></ol>" + F
|
||||
elif tf[0] == -1:
|
||||
return flask.redirect(back_url)
|
||||
else:
|
||||
|
||||
def callback(etud: Identite, data, filename):
|
||||
return sco_photos.store_photo(etud, data, filename)
|
||||
|
||||
(
|
||||
ignored_zipfiles,
|
||||
unmatched_files,
|
||||
stored_etud_filename,
|
||||
) = zip_excel_import_files(
|
||||
xlsfile=tf[2]["xlsfile"],
|
||||
zipfile=tf[2]["zipfile"],
|
||||
callback=callback,
|
||||
filename_title="fichier_photo",
|
||||
back_url=back_url,
|
||||
)
|
||||
return render_template(
|
||||
"scolar/photos_import_files.j2",
|
||||
page_title="Téléchargement des photos des étudiants",
|
||||
ignored_zipfiles=ignored_zipfiles,
|
||||
unmatched_files=unmatched_files,
|
||||
stored_etud_filename=stored_etud_filename,
|
||||
next_page=url_for(
|
||||
"scolar.groups_photos",
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
formsemestre_id=groups_infos.formsemestre_id,
|
||||
),
|
||||
"sco_page.j2",
|
||||
title="Import des photos des étudiants",
|
||||
content="\n".join(H) + tf[1] + "</li></ol>",
|
||||
)
|
||||
if tf[0] == -1:
|
||||
return flask.redirect(back_url)
|
||||
|
||||
def callback(etud: Identite, data, filename):
|
||||
return sco_photos.store_photo(etud, data, filename)
|
||||
|
||||
(
|
||||
ignored_zipfiles,
|
||||
unmatched_files,
|
||||
stored_etud_filename,
|
||||
) = zip_excel_import_files(
|
||||
xlsfile=tf[2]["xlsfile"],
|
||||
zipfile=tf[2]["zipfile"],
|
||||
callback=callback,
|
||||
filename_title="fichier_photo",
|
||||
back_url=back_url,
|
||||
)
|
||||
return render_template(
|
||||
"scolar/photos_import_files.j2",
|
||||
page_title="Téléchargement des photos des étudiants",
|
||||
ignored_zipfiles=ignored_zipfiles,
|
||||
unmatched_files=unmatched_files,
|
||||
stored_etud_filename=stored_etud_filename,
|
||||
next_page=url_for(
|
||||
"scolar.groups_photos",
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
formsemestre_id=groups_infos.formsemestre_id,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def _norm_zip_filename(fn, lowercase=True):
|
||||
|
@ -59,11 +59,11 @@ div.sco-app-content {
|
||||
}
|
||||
|
||||
.space-before-18 {
|
||||
margin-top: 18px;
|
||||
margin-top: 18px !important;
|
||||
}
|
||||
|
||||
.space-before-24 {
|
||||
margin-top: 24px;
|
||||
margin-top: 24px !important;
|
||||
}
|
||||
|
||||
div.scobox.maxwidth {
|
||||
|
@ -1,10 +0,0 @@
|
||||
// Affichage progressif du trombinoscope html
|
||||
|
||||
$().ready(function () {
|
||||
var spans = $(".unloaded_img");
|
||||
for (var i = 0; i < spans.size(); i++) {
|
||||
var sp = spans[i];
|
||||
var etudid = sp.id;
|
||||
$(sp).load(SCO_URL + "etud_photo_html?etudid=" + etudid);
|
||||
}
|
||||
});
|
@ -10,7 +10,7 @@
|
||||
<br />
|
||||
Ces utilisateurs peuvent être réactivés à tout moment.
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="row space-before-24">
|
||||
<div class="col-md-4">
|
||||
{{ wtf.quick_form(form, button_map={'submit':'secondary'}) }}
|
||||
</div>
|
||||
|
@ -1,3 +1,5 @@
|
||||
{% extends 'sco_page.j2' %}
|
||||
|
||||
{% import 'wtf.j2' as wtf %}
|
||||
|
||||
{% macro render_field(field) %}
|
||||
@ -15,6 +17,12 @@
|
||||
</tr>
|
||||
{% endmacro %}
|
||||
|
||||
{% block app_content %}
|
||||
|
||||
{{ evaluations_description|safe}}
|
||||
|
||||
<h3 class="space-before-24">Placement et émargement des étudiants</h3>
|
||||
|
||||
<div class="saisienote_etape1 form_placement">
|
||||
<form method=post>
|
||||
{{ form.evaluation_id }}
|
||||
@ -78,3 +86,4 @@
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endblock %}
|
@ -1,5 +1,5 @@
|
||||
{# -*- mode: jinja-html -*- #}
|
||||
{% extends 'base.j2' %}
|
||||
{% extends 'sco_page.j2' %}
|
||||
|
||||
{% block app_content %}
|
||||
|
||||
|
@ -24,7 +24,8 @@
|
||||
##############################################################################
|
||||
|
||||
"""
|
||||
Module absences: remplacé par assiduité en août 2023, reste ici seulement la gestion des "billets"
|
||||
Module absences: remplacé par assiduité en août 2023,
|
||||
reste ici seulement la gestion des "billets"
|
||||
|
||||
"""
|
||||
|
||||
@ -32,8 +33,7 @@ import dateutil
|
||||
import dateutil.parser
|
||||
|
||||
import flask
|
||||
from flask import g, request
|
||||
from flask import abort, flash, url_for
|
||||
from flask import abort, flash, g, render_template, request, url_for
|
||||
from flask_login import current_user
|
||||
|
||||
from app import db, log
|
||||
@ -54,11 +54,8 @@ from app.scodoc import sco_utils as scu
|
||||
from app.scodoc.sco_permissions import Permission
|
||||
from app.scodoc.sco_exceptions import ScoValueError
|
||||
from app.scodoc.TrivialFormulator import TrivialFormulator
|
||||
from app.scodoc import html_sco_header
|
||||
from app.scodoc import sco_cal
|
||||
from app.scodoc import sco_assiduites as scass
|
||||
from app.scodoc import sco_abs_billets
|
||||
from app.scodoc import sco_etud
|
||||
from app.scodoc import sco_preferences
|
||||
|
||||
|
||||
@ -77,11 +74,7 @@ from app.scodoc import sco_preferences
|
||||
def index_html():
|
||||
"""Gestionnaire absences, page principale"""
|
||||
|
||||
H = [
|
||||
html_sco_header.sco_header(
|
||||
page_title="Billets d'absences",
|
||||
),
|
||||
]
|
||||
H = []
|
||||
if current_user.has_permission(
|
||||
Permission.AbsChange
|
||||
) and sco_preferences.get_preference("handle_billets_abs"):
|
||||
@ -93,8 +86,9 @@ def index_html():
|
||||
</li></ul>
|
||||
"""
|
||||
)
|
||||
H.append(html_sco_header.sco_footer())
|
||||
return "\n".join(H)
|
||||
return render_template(
|
||||
"sco_page_dept.j2", title="Billets d'absences", content="\n".join(H)
|
||||
)
|
||||
|
||||
|
||||
# ----- Gestion des "billets d'absence": signalement par les etudiants eux mêmes (à travers le portail)
|
||||
@ -158,12 +152,8 @@ def add_billets_absence_form(etudid):
|
||||
"""Formulaire ajout billet (pour tests seulement, le vrai
|
||||
formulaire accessible aux etudiants étant sur le portail étudiant).
|
||||
"""
|
||||
etud = sco_etud.get_etud_info(filled=True, etudid=etudid)[0]
|
||||
H = [
|
||||
html_sco_header.sco_header(
|
||||
page_title="Billet d'absence de %s" % etud["nomprenom"]
|
||||
)
|
||||
]
|
||||
_ = Identite.get_etud(etudid) # check
|
||||
H = ["""<h2>Formulaire ajout billet (pour tests)</h2>"""]
|
||||
tf = TrivialFormulator(
|
||||
request.base_url,
|
||||
scu.get_request_args(),
|
||||
@ -179,7 +169,11 @@ def add_billets_absence_form(etudid):
|
||||
),
|
||||
)
|
||||
if tf[0] == 0:
|
||||
return "\n".join(H) + tf[1] + html_sco_header.sco_footer()
|
||||
return render_template(
|
||||
"sco_page_dept.j2",
|
||||
title="""Billet d'absence de {etud["nomprenom"]}""",
|
||||
content="\n".join(H) + tf[1],
|
||||
)
|
||||
elif tf[0] == -1:
|
||||
return flask.redirect(url_for("scolar.index_html", scodoc_dept=g.scodoc_dept))
|
||||
else:
|
||||
@ -242,11 +236,8 @@ def list_billets():
|
||||
et formulaire recherche d'un billet.
|
||||
"""
|
||||
table = sco_abs_billets.table_billets_etud(etat=False)
|
||||
T = table.html()
|
||||
table_html = table.html()
|
||||
H = [
|
||||
html_sco_header.sco_header(
|
||||
page_title="Billet d'absence non traités",
|
||||
),
|
||||
f"<h2>Billets d'absence en attente de traitement ({table.get_nb_rows()})</h2>",
|
||||
]
|
||||
|
||||
@ -257,15 +248,18 @@ def list_billets():
|
||||
submitbutton=False,
|
||||
)
|
||||
if tf[0] == 0:
|
||||
return "\n".join(H) + tf[1] + T + html_sco_header.sco_footer()
|
||||
else:
|
||||
return flask.redirect(
|
||||
url_for(
|
||||
"absences.process_billet_absence_form",
|
||||
billet_id=tf[2]["billet_id"],
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
)
|
||||
return render_template(
|
||||
"sco_page.j2",
|
||||
title="Billet d'absence non traités",
|
||||
content="\n".join(H) + tf[1] + table_html,
|
||||
)
|
||||
return flask.redirect(
|
||||
url_for(
|
||||
"absences.process_billet_absence_form",
|
||||
billet_id=tf[2]["billet_id"],
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@bp.route("/delete_billets_absence", methods=["POST", "GET"])
|
||||
@ -337,7 +331,8 @@ def _ProcessBilletAbsence(
|
||||
def process_billet_absence_form(billet_id: int):
|
||||
"""Formulaire traitement d'un billet"""
|
||||
if not isinstance(billet_id, int):
|
||||
raise abort(404, "billet_id invalide")
|
||||
abort(404, "billet_id invalide")
|
||||
return # safety guard
|
||||
billet: BilletAbsence = (
|
||||
BilletAbsence.query.filter_by(id=billet_id)
|
||||
.join(Identite)
|
||||
@ -352,9 +347,6 @@ def process_billet_absence_form(billet_id: int):
|
||||
etud = billet.etudiant
|
||||
|
||||
H = [
|
||||
html_sco_header.sco_header(
|
||||
page_title=f"Traitement billet d'absence de {etud.nomprenom}",
|
||||
),
|
||||
f"""<h2>Traitement du billet {billet.id} : <a class="discretelink" href="{
|
||||
url_for("scolar.fiche_etud", scodoc_dept=g.scodoc_dept, etudid=etud.id)
|
||||
}">{etud.nomprenom}</a></h2>
|
||||
@ -403,7 +395,11 @@ def process_billet_absence_form(billet_id: int):
|
||||
</p>
|
||||
"""
|
||||
|
||||
return "\n".join(H) + "<br>" + tf[1] + F + html_sco_header.sco_footer()
|
||||
return render_template(
|
||||
"sco_page.j2",
|
||||
title=f"Traitement billet d'absence de {etud.nomprenom}",
|
||||
content="\n".join(H) + "<br>" + tf[1] + F,
|
||||
)
|
||||
elif tf[0] == -1:
|
||||
return flask.redirect(url_for("scolar.index_html", scodoc_dept=g.scodoc_dept))
|
||||
else:
|
||||
@ -414,7 +410,7 @@ def process_billet_absence_form(billet_id: int):
|
||||
j = "non justifiées"
|
||||
H.append('<div class="head_message">')
|
||||
if n > 0:
|
||||
H.append("%d absences (1/2 journées) %s ajoutées" % (n, j))
|
||||
H.append(f"{n} absences (1/2 journées) {j} ajoutées")
|
||||
elif n == 0:
|
||||
H.append("Aucun jour d'absence dans les dates indiquées !")
|
||||
elif n < 0:
|
||||
@ -434,4 +430,8 @@ def process_billet_absence_form(billet_id: int):
|
||||
)
|
||||
tab = sco_abs_billets.table_billets(billets, etud=etud)
|
||||
H.append(tab.html())
|
||||
return "\n".join(H) + html_sco_header.sco_footer()
|
||||
return render_template(
|
||||
"sco_page.j2",
|
||||
title=f"Traitement billet d'absence de {etud.nomprenom}",
|
||||
content="\n".join(H),
|
||||
)
|
||||
|
@ -1073,10 +1073,10 @@ def signal_assiduites_group():
|
||||
select_all_when_unspecified=True,
|
||||
)
|
||||
if not groups_infos.members:
|
||||
return (
|
||||
html_sco_header.sco_header(page_title="Saisie de l'assiduité")
|
||||
+ "<h3>Aucun étudiant ! </h3>"
|
||||
+ html_sco_header.sco_footer()
|
||||
return render_template(
|
||||
"sco_page.j2",
|
||||
title="Saisie de l'assiduité",
|
||||
content="<h3>Aucun étudiant !</h3>",
|
||||
)
|
||||
|
||||
# --- Filtrage par formsemestre ---
|
||||
@ -1952,10 +1952,10 @@ def signal_assiduites_hebdo():
|
||||
group_ids, formsemestre_id=formsemestre.id, select_all_when_unspecified=True
|
||||
)
|
||||
if not groups_infos.members:
|
||||
return (
|
||||
html_sco_header.sco_header(page_title="Assiduité: saisie hebdomadaire")
|
||||
+ "<h3>Aucun étudiant ! </h3>"
|
||||
+ html_sco_header.sco_footer()
|
||||
return render_template(
|
||||
"sco_page.j2",
|
||||
title="Assiduité: feuille saisie hebdomadaire",
|
||||
content="<h3>Aucun étudiant !</h3>",
|
||||
)
|
||||
|
||||
# Récupération des étudiants
|
||||
@ -2305,12 +2305,10 @@ def feuille_abs_hebdo():
|
||||
group_ids, formsemestre_id=formsemestre.id, select_all_when_unspecified=True
|
||||
)
|
||||
if not groups_infos.members:
|
||||
return (
|
||||
html_sco_header.sco_header(
|
||||
page_title="Assiduité: feuille saisie hebdomadaire"
|
||||
)
|
||||
+ "<h3>Aucun étudiant ! </h3>"
|
||||
+ html_sco_header.sco_footer()
|
||||
return render_template(
|
||||
"sco_page.j2",
|
||||
title="Assiduité: feuille saisie hebdomadaire",
|
||||
content="<h3>Aucun étudiant !</h3>",
|
||||
)
|
||||
|
||||
# Gestion des jours
|
||||
|
@ -60,7 +60,6 @@ from app.models import (
|
||||
ScoDocSiteConfig,
|
||||
)
|
||||
from app.scodoc import (
|
||||
html_sco_header,
|
||||
sco_bulletins_json,
|
||||
sco_cache,
|
||||
sco_formsemestre_exterieurs,
|
||||
@ -251,27 +250,23 @@ def formsemestre_validation_but(
|
||||
</div>
|
||||
"""
|
||||
|
||||
H = [
|
||||
html_sco_header.sco_header(
|
||||
page_title=f"Validation BUT S{formsemestre.semestre_id}",
|
||||
formsemestre_id=formsemestre_id,
|
||||
etudid=etudid,
|
||||
H = ["""<div class="jury_but">"""]
|
||||
inscription = formsemestre.etuds_inscriptions.get(etudid)
|
||||
if not inscription:
|
||||
raise ScoValueError("étudiant non inscrit au semestre")
|
||||
if inscription.etat != scu.INSCRIT:
|
||||
return render_template(
|
||||
"sco_page.j2",
|
||||
title=f"Validation BUT S{formsemestre.semestre_id}",
|
||||
sco=ScoData(etud=etud, formsemestre=formsemestre),
|
||||
cssstyles=[
|
||||
"css/jury_but.css",
|
||||
"css/cursus_but.css",
|
||||
],
|
||||
javascripts=("js/jury_but.js",),
|
||||
),
|
||||
"""<div class="jury_but">
|
||||
""",
|
||||
]
|
||||
inscription = formsemestre.etuds_inscriptions.get(etudid)
|
||||
if not inscription:
|
||||
raise ScoValueError("étudiant non inscrit au semestre")
|
||||
if inscription.etat != scu.INSCRIT:
|
||||
return (
|
||||
"\n".join(H)
|
||||
+ f"""
|
||||
content=(
|
||||
"\n".join(H)
|
||||
+ f"""
|
||||
<div>
|
||||
<div class="bull_head">
|
||||
<div>
|
||||
@ -291,7 +286,7 @@ def formsemestre_validation_but(
|
||||
{navigation_div}
|
||||
</div>
|
||||
"""
|
||||
+ html_sco_header.sco_footer()
|
||||
),
|
||||
)
|
||||
|
||||
deca = jury_but.DecisionsProposeesAnnee(etud, formsemestre)
|
||||
@ -341,7 +336,7 @@ def formsemestre_validation_but(
|
||||
êtes-vous certain de vouloir enregistrer une décision de jury ?
|
||||
</div>"""
|
||||
if read_only:
|
||||
warning += f"""<div class="warning">Affichage en lecture seule</div>"""
|
||||
warning += """<div class="warning">Affichage en lecture seule</div>"""
|
||||
|
||||
if deca.formsemestre_impair:
|
||||
inscription = deca.formsemestre_impair.etuds_inscriptions.get(etud.id)
|
||||
@ -507,7 +502,17 @@ def formsemestre_validation_but(
|
||||
</div>
|
||||
"""
|
||||
)
|
||||
return "\n".join(H) + html_sco_header.sco_footer()
|
||||
return render_template(
|
||||
"sco_page.j2",
|
||||
title=f"Validation BUT S{formsemestre.semestre_id}",
|
||||
sco=ScoData(etud=etud, formsemestre=formsemestre),
|
||||
cssstyles=[
|
||||
"css/jury_but.css",
|
||||
"css/cursus_but.css",
|
||||
],
|
||||
javascripts=("js/jury_but.js",),
|
||||
content="\n".join(H),
|
||||
)
|
||||
|
||||
|
||||
@bp.route(
|
||||
|
@ -88,7 +88,6 @@ from app.scodoc.sco_exceptions import (
|
||||
ScoInvalidIdType,
|
||||
)
|
||||
from app.scodoc import (
|
||||
html_sco_header,
|
||||
sco_apogee_compare,
|
||||
sco_archives_formsemestre,
|
||||
sco_assiduites,
|
||||
@ -770,8 +769,10 @@ def formation_import_xml_form():
|
||||
cancelbutton="Annuler",
|
||||
)
|
||||
if tf[0] == 0:
|
||||
return f"""
|
||||
{ html_sco_header.sco_header(page_title="Import d'une formation") }
|
||||
return render_template(
|
||||
"sco_page_dept.j2",
|
||||
title="Import d'une formation",
|
||||
content=f"""
|
||||
<h2>Import d'une formation</h2>
|
||||
<p>Création d'une formation (avec UE, matières, modules)
|
||||
à partir un fichier XML (réservé aux utilisateurs avertis).
|
||||
@ -783,8 +784,8 @@ def formation_import_xml_form():
|
||||
}">page des référentiels</a>).
|
||||
</p>
|
||||
{ tf[1] }
|
||||
{ html_sco_header.sco_footer() }
|
||||
"""
|
||||
""",
|
||||
)
|
||||
elif tf[0] == -1:
|
||||
return flask.redirect(url_for("notes.index_html", scodoc_dept=g.scodoc_dept))
|
||||
else:
|
||||
@ -792,8 +793,10 @@ def formation_import_xml_form():
|
||||
tf[2]["xmlfile"].read()
|
||||
)
|
||||
|
||||
return f"""
|
||||
{ html_sco_header.sco_header(page_title="Import d'une formation") }
|
||||
return render_template(
|
||||
"sco_page_dept.j2",
|
||||
title="Import d'une formation",
|
||||
content=f"""
|
||||
<h2>Import effectué !</h2>
|
||||
<ul>
|
||||
<li><a class="stdlink" href="{
|
||||
@ -806,8 +809,8 @@ def formation_import_xml_form():
|
||||
(en cas d'erreur, par exemple pour charger auparavant le référentiel de compétences)
|
||||
</li>
|
||||
</ul>
|
||||
{ html_sco_header.sco_footer() }
|
||||
"""
|
||||
""",
|
||||
)
|
||||
|
||||
|
||||
sco_publish("/module_move", sco_edit_formation.module_move, Permission.EditFormation)
|
||||
@ -2182,15 +2185,17 @@ def formsemestre_bulletins_mailetuds(
|
||||
if sent:
|
||||
nb_sent += 1
|
||||
#
|
||||
return f"""
|
||||
{html_sco_header.sco_header()}
|
||||
return render_template(
|
||||
"sco_page.j2",
|
||||
title="Mailing bulletins",
|
||||
content=f"""
|
||||
<p>{nb_sent} bulletins sur {len(inscriptions)} envoyés par mail !</p>
|
||||
<p><a class="stdlink" href="{url_for('notes.formsemestre_status',
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
formsemestre_id=formsemestre_id)
|
||||
}">continuer</a></p>
|
||||
{html_sco_header.sco_footer()}
|
||||
"""
|
||||
""",
|
||||
)
|
||||
|
||||
|
||||
sco_publish(
|
||||
@ -2258,10 +2263,8 @@ def appreciation_add_form(
|
||||
else:
|
||||
action = "Ajout"
|
||||
H = [
|
||||
html_sco_header.sco_header(),
|
||||
f"""<h2>{action} d'une appréciation sur {etud.nomprenom}</h2>""",
|
||||
]
|
||||
F = html_sco_header.sco_footer()
|
||||
descr = [
|
||||
("edit", {"input_type": "hidden", "default": edit}),
|
||||
("etudid", {"input_type": "hidden"}),
|
||||
@ -2286,7 +2289,7 @@ def appreciation_add_form(
|
||||
submitlabel="Ajouter appréciation",
|
||||
)
|
||||
if tf[0] == 0:
|
||||
return "\n".join(H) + "\n" + tf[1] + F
|
||||
return render_template("sco_page.j2", content="\n".join(H) + "\n" + tf[1])
|
||||
elif tf[0] == -1:
|
||||
return flask.redirect(bul_url)
|
||||
else:
|
||||
@ -2643,7 +2646,7 @@ def check_form_integrity(formation_id, fix=False):
|
||||
else:
|
||||
txth = "OK"
|
||||
log("ok")
|
||||
return html_sco_header.sco_header() + txth + html_sco_header.sco_footer()
|
||||
return render_template("sco_page.j2", content=txth)
|
||||
|
||||
|
||||
@bp.route("/check_formsemestre_integrity")
|
||||
@ -2681,6 +2684,4 @@ def check_formsemestre_integrity(formsemestre_id):
|
||||
else:
|
||||
diag = ["OK"]
|
||||
log("ok")
|
||||
return (
|
||||
html_sco_header.sco_header() + "<br>".join(diag) + html_sco_header.sco_footer()
|
||||
)
|
||||
return render_template("sco_page.j2", content="<br>".join(diag))
|
||||
|
@ -64,7 +64,7 @@ from app.decorators import (
|
||||
permission_required,
|
||||
)
|
||||
|
||||
from app.scodoc import html_sco_header, sco_import_users, sco_roles_default
|
||||
from app.scodoc import sco_import_users, sco_roles_default
|
||||
from app.scodoc import sco_users
|
||||
from app.scodoc import sco_utils as scu
|
||||
from app.scodoc import sco_xml
|
||||
@ -74,7 +74,6 @@ from app.scodoc.sco_import_users import generate_password
|
||||
from app.scodoc.sco_permissions_check import can_handle_passwd
|
||||
from app.scodoc.TrivialFormulator import TrivialFormulator, tf_error_message
|
||||
from app.views import users_bp as bp
|
||||
from app.views import scodoc_bp
|
||||
|
||||
|
||||
_ = lambda x: x # sans babel
|
||||
@ -92,7 +91,7 @@ class ChangePasswordForm(FlaskForm):
|
||||
validators=[
|
||||
EqualTo(
|
||||
"new_password",
|
||||
message="Les deux saisies sont " "différentes, recommencez",
|
||||
message="Les deux saisies sont différentes, recommencez",
|
||||
),
|
||||
],
|
||||
)
|
||||
@ -106,9 +105,9 @@ class ChangePasswordForm(FlaskForm):
|
||||
submit = SubmitField()
|
||||
cancel = SubmitField("Annuler")
|
||||
|
||||
def validate_email(self, email):
|
||||
"vérifie que le mail est unique"
|
||||
user = User.query.filter_by(email=email.data.strip()).first()
|
||||
def validate_email(self, e_mail):
|
||||
"vérifie que le mail est unique (inline wtf validator)"
|
||||
user = User.query.filter_by(email=e_mail.data.strip()).first()
|
||||
if user is not None and self.user_name.data != user.user_name:
|
||||
raise ValidationError(
|
||||
_("Cette adresse e-mail est déjà attribuée à un autre compte")
|
||||
@ -120,6 +119,7 @@ class ChangePasswordForm(FlaskForm):
|
||||
raise ValidationError("Mot de passe trop simple, recommencez")
|
||||
|
||||
def validate_old_password(self, old_password):
|
||||
"vérifie password actuel"
|
||||
if not current_user.check_password(old_password.data):
|
||||
raise ValidationError("Mot de passe actuel incorrect, ré-essayez")
|
||||
|
||||
@ -855,9 +855,7 @@ def import_users_generate_excel_sample():
|
||||
@scodoc7func
|
||||
def import_users_form():
|
||||
"""Import utilisateurs depuis feuille Excel"""
|
||||
head = html_sco_header.sco_header(page_title="Import utilisateurs")
|
||||
H = [
|
||||
head,
|
||||
"""<h2>Téléchargement d'une liste d'utilisateurs</h2>
|
||||
<p style="color: red">A utiliser pour importer de <b>nouveaux</b>
|
||||
utilisateurs (enseignants ou secrétaires)
|
||||
@ -886,12 +884,10 @@ def import_users_form():
|
||||
<li><b>Étape 1: </b><a class="stdlink" href="{
|
||||
url_for("users.import_users_generate_excel_sample", scodoc_dept=g.scodoc_dept)
|
||||
}">Obtenir la feuille excel vide à remplir</a>
|
||||
ou bien la liste complète des utilisateurs.
|
||||
</li>
|
||||
<li><b> Étape 2:</b>
|
||||
"""
|
||||
)
|
||||
F = html_sco_header.sco_footer()
|
||||
tf = TrivialFormulator(
|
||||
request.base_url,
|
||||
scu.get_request_args(),
|
||||
@ -915,7 +911,11 @@ def import_users_form():
|
||||
submitlabel="Télécharger",
|
||||
)
|
||||
if tf[0] == 0:
|
||||
return "\n".join(H) + tf[1] + "</li></ul>" + help_msg + F
|
||||
return render_template(
|
||||
"sco_page_dept.j2",
|
||||
title="Import utilisateurs",
|
||||
content="\n".join(H) + tf[1] + "</li></ul>" + help_msg,
|
||||
)
|
||||
elif tf[0] == -1:
|
||||
return flask.redirect(url_for("scolar.index_html", docodc_dept=g.scodoc_dept))
|
||||
|
||||
@ -923,8 +923,10 @@ def import_users_form():
|
||||
ok, diags, nb_created = sco_import_users.import_excel_file(
|
||||
tf[2]["xlsfile"], tf[2]["force"]
|
||||
)
|
||||
H = [html_sco_header.sco_header(page_title="Import utilisateurs")]
|
||||
H.append("<ul>")
|
||||
H = [
|
||||
"""<h2>Téléchargement d'une liste d'utilisateurs</h2>
|
||||
<ul>"""
|
||||
]
|
||||
for diag in diags:
|
||||
H.append(f"<li>{diag}</li>")
|
||||
H.append("</ul>")
|
||||
@ -942,7 +944,9 @@ def import_users_form():
|
||||
<p><a class="stdlink" href="{dest_url}">Continuer</a></p>
|
||||
"""
|
||||
)
|
||||
return "\n".join(H) + html_sco_header.sco_footer()
|
||||
return render_template(
|
||||
"sco_page_dept.j2", title="Import utilisateurs", content="\n".join(H)
|
||||
)
|
||||
|
||||
|
||||
@bp.route("/user_info_page")
|
||||
@ -1061,76 +1065,6 @@ def form_change_password(user_name=None):
|
||||
)
|
||||
|
||||
|
||||
@bp.route("/change_password", methods=["POST"])
|
||||
@scodoc
|
||||
@permission_required(Permission.ScoView)
|
||||
@scodoc7func
|
||||
def change_password(user_name, password, password2):
|
||||
"Change the password for user given by user_name"
|
||||
if user_name is not None: # scodoc7func converti en int !
|
||||
user_name = str(user_name)
|
||||
u = User.query.filter_by(user_name=user_name).first()
|
||||
# Check access permission
|
||||
if not can_handle_passwd(u):
|
||||
# access denied
|
||||
log(
|
||||
f"change_password: access denied (authuser={current_user}, user_name={user_name})"
|
||||
)
|
||||
raise AccessDenied("vous n'avez pas la permission de changer ce mot de passe")
|
||||
H = []
|
||||
F = html_sco_header.sco_footer()
|
||||
# check password
|
||||
dest_url = url_for(
|
||||
"users.form_change_password", scodoc_dept=g.scodoc_dept, user_name=user_name
|
||||
)
|
||||
if password != password2:
|
||||
H.append(
|
||||
f"""<p>Les deux mots de passes saisis sont différents !</p>
|
||||
<p><a href="{dest_url}" class="stdlink">Recommencer</a></p>
|
||||
"""
|
||||
)
|
||||
else:
|
||||
if not is_valid_password(password):
|
||||
H.append(
|
||||
f"""<p><b>ce mot de passe n'est pas assez compliqué !</b>
|
||||
<br>(oui, il faut un mot de passe vraiment compliqué !)
|
||||
</p>
|
||||
<p><a href="{dest_url}" class="stdlink">Recommencer</a></p>
|
||||
"""
|
||||
)
|
||||
else:
|
||||
# ok, strong password
|
||||
db.session.add(u)
|
||||
u.set_password(password)
|
||||
db.session.commit()
|
||||
#
|
||||
# ici page simplifiee car on peut ne plus avoir
|
||||
# le droit d'acceder aux feuilles de style
|
||||
return f"""<?xml version="1.0" encoding="{scu.SCO_ENCODING}"?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Mot de passe changé</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset={scu.SCO_ENCODING}" />
|
||||
<body>
|
||||
<h1>Mot de passe changé !</h1>
|
||||
<h2>Changement effectué</h2>
|
||||
<p>Ne notez pas ce mot de passe, mais mémorisez le !</p>
|
||||
<p>Rappel: il est <b>interdit</b> de communiquer son mot de passe à
|
||||
un tiers, même si c'est un collègue de confiance !</p>
|
||||
<p><b>Si vous n'êtes pas administrateur, le système va vous redemander
|
||||
votre login et nouveau mot de passe au prochain accès.</b>
|
||||
</p>
|
||||
<a href="{
|
||||
url_for("scolar.index_html", scodoc_dept=g.scodoc_dept)
|
||||
}" class="stdlink">Continuer</a>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
return html_sco_header.sco_header() + "\n".join(H) + F
|
||||
|
||||
|
||||
@bp.route("/toggle_active_user/<user_name>", methods=["GET", "POST"])
|
||||
@scodoc
|
||||
@permission_required(Permission.UsersAdmin)
|
||||
|
Loading…
Reference in New Issue
Block a user