forked from ScoDoc/ScoDoc
Compare commits
8 Commits
aa9d85f4bd
...
0509f1c923
Author | SHA1 | Date | |
---|---|---|---|
0509f1c923 | |||
659c790af2 | |||
88d9356209 | |||
84580a8a6f | |||
bf53dfa93a | |||
c1d8a34e34 | |||
dc53fe8395 | |||
464d678299 |
@ -685,6 +685,7 @@ class GenTable:
|
|||||||
javascripts=(),
|
javascripts=(),
|
||||||
with_html_headers=True,
|
with_html_headers=True,
|
||||||
publish=True,
|
publish=True,
|
||||||
|
template="sco_page.j2",
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Build page at given format
|
Build page at given format
|
||||||
@ -703,7 +704,7 @@ class GenTable:
|
|||||||
H.append(self.html())
|
H.append(self.html())
|
||||||
if with_html_headers:
|
if with_html_headers:
|
||||||
return render_template(
|
return render_template(
|
||||||
"sco_page.j2",
|
template,
|
||||||
content="\n".join(H),
|
content="\n".join(H),
|
||||||
title=page_title,
|
title=page_title,
|
||||||
javascripts=javascripts,
|
javascripts=javascripts,
|
||||||
|
@ -36,7 +36,6 @@ from app.comp.res_compat import NotesTableCompat
|
|||||||
from app.models import FormSemestre
|
from app.models import FormSemestre
|
||||||
from app.scodoc.TrivialFormulator import TrivialFormulator
|
from app.scodoc.TrivialFormulator import TrivialFormulator
|
||||||
from app.scodoc.sco_exceptions import ScoPermissionDenied
|
from app.scodoc.sco_exceptions import ScoPermissionDenied
|
||||||
from app.scodoc import html_sco_header
|
|
||||||
from app.scodoc import sco_bulletins_pdf
|
from app.scodoc import sco_bulletins_pdf
|
||||||
from app.scodoc import sco_groups
|
from app.scodoc import sco_groups
|
||||||
from app.scodoc import sco_groups_view
|
from app.scodoc import sco_groups_view
|
||||||
@ -123,18 +122,18 @@ def do_formsemestre_archive(
|
|||||||
)
|
)
|
||||||
if table_html:
|
if table_html:
|
||||||
flash(f"Moyennes archivées le {date}", category="info")
|
flash(f"Moyennes archivées le {date}", category="info")
|
||||||
data = "\n".join(
|
data = render_template(
|
||||||
[
|
"sco_page.j2",
|
||||||
html_sco_header.sco_header(
|
|
||||||
page_title=f"Moyennes archivées le {date}",
|
|
||||||
no_sidebar=True,
|
no_sidebar=True,
|
||||||
),
|
title=f"Moyennes archivées le {date}",
|
||||||
|
content="\n".join(
|
||||||
|
[
|
||||||
f'<h2 class="fontorange">Valeurs archivées le {date}</h2>',
|
f'<h2 class="fontorange">Valeurs archivées le {date}</h2>',
|
||||||
"""<style type="text/css">table.notes_recapcomplet tr { color: rgb(185,70,0); }
|
"""<style type="text/css">table.notes_recapcomplet tr { color: rgb(185,70,0); }
|
||||||
</style>""",
|
</style>""",
|
||||||
table_html,
|
table_html,
|
||||||
html_sco_header.sco_footer(),
|
|
||||||
]
|
]
|
||||||
|
),
|
||||||
)
|
)
|
||||||
PV_ARCHIVER.store(
|
PV_ARCHIVER.store(
|
||||||
archive_id, "Tableau_moyennes.html", data, dept_id=formsemestre.dept_id
|
archive_id, "Tableau_moyennes.html", data, dept_id=formsemestre.dept_id
|
||||||
@ -254,7 +253,6 @@ enregistrés et non modifiables, on peut les retrouver ultérieurement.
|
|||||||
}">Paramétrage</a>"
|
}">Paramétrage</a>"
|
||||||
(accessible à l'administrateur du département).</em>
|
(accessible à l'administrateur du département).</em>
|
||||||
</p>""",
|
</p>""",
|
||||||
html_sco_header.sco_footer(),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
descr = [
|
descr = [
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
Rapport (table) avec dernier semestre fréquenté et débouché de chaque étudiant
|
Rapport (table) avec dernier semestre fréquenté et débouché de chaque étudiant
|
||||||
"""
|
"""
|
||||||
import http
|
import http
|
||||||
from flask import url_for, g, request
|
from flask import g, render_template, request, url_for
|
||||||
|
|
||||||
from app import log
|
from app import log
|
||||||
from app.comp import res_sem
|
from app.comp import res_sem
|
||||||
@ -40,7 +40,6 @@ import app.scodoc.notesdb as ndb
|
|||||||
from app.scodoc.sco_exceptions import AccessDenied, ScoValueError
|
from app.scodoc.sco_exceptions import AccessDenied, ScoValueError
|
||||||
from app.scodoc.gen_tables import GenTable
|
from app.scodoc.gen_tables import GenTable
|
||||||
from app.scodoc import safehtml
|
from app.scodoc import safehtml
|
||||||
from app.scodoc import html_sco_header
|
|
||||||
from app.scodoc import sco_permissions_check
|
from app.scodoc import sco_permissions_check
|
||||||
from app.scodoc import sco_preferences
|
from app.scodoc import sco_preferences
|
||||||
from app.scodoc import sco_tag_module
|
from app.scodoc import sco_tag_module
|
||||||
@ -78,6 +77,7 @@ def report_debouche_date(start_year=None, fmt="html"):
|
|||||||
title="""<h2 class="formsemestre">Débouchés étudiants </h2>""",
|
title="""<h2 class="formsemestre">Débouchés étudiants </h2>""",
|
||||||
fmt=fmt,
|
fmt=fmt,
|
||||||
with_html_headers=True,
|
with_html_headers=True,
|
||||||
|
template="sco_page_dept.j2",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -226,14 +226,16 @@ def table_debouche_etudids(etudids, keep_numeric=True):
|
|||||||
|
|
||||||
def report_debouche_ask_date(msg: str) -> str:
|
def report_debouche_ask_date(msg: str) -> str:
|
||||||
"""Formulaire demande date départ"""
|
"""Formulaire demande date départ"""
|
||||||
return f"""{html_sco_header.sco_header()}
|
return render_template(
|
||||||
|
"sco_page_dept.j2",
|
||||||
|
content=f"""
|
||||||
<h2>Table des débouchés des étudiants</h2>
|
<h2>Table des débouchés des étudiants</h2>
|
||||||
<form method="GET">
|
<form method="GET">
|
||||||
{msg}
|
{msg}
|
||||||
<input type="text" name="start_year" value="" size=10/>
|
<input type="text" name="start_year" value="" size=10/>
|
||||||
</form>
|
</form>
|
||||||
{html_sco_header.sco_footer()}
|
""",
|
||||||
"""
|
)
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
@ -323,11 +325,11 @@ def itemsuivi_set_date(itemsuivi_id, item_date):
|
|||||||
return ("", 204)
|
return ("", 204)
|
||||||
|
|
||||||
|
|
||||||
def itemsuivi_set_situation(object, value):
|
def itemsuivi_set_situation(obj, value):
|
||||||
"""set situation"""
|
"""set situation"""
|
||||||
if not sco_permissions_check.can_edit_suivi():
|
if not sco_permissions_check.can_edit_suivi():
|
||||||
raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !")
|
raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !")
|
||||||
itemsuivi_id = object
|
itemsuivi_id = obj
|
||||||
situation = value.strip("-_ \t")
|
situation = value.strip("-_ \t")
|
||||||
# log('itemsuivi_set_situation %s : %s' % (itemsuivi_id, situation))
|
# log('itemsuivi_set_situation %s : %s' % (itemsuivi_id, situation))
|
||||||
cnx = ndb.GetDBConnexion()
|
cnx = ndb.GetDBConnexion()
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
(portage from DTML)
|
(portage from DTML)
|
||||||
"""
|
"""
|
||||||
import flask
|
import flask
|
||||||
from flask import flash, g, url_for, request
|
from flask import flash, g, url_for, render_template, request
|
||||||
import sqlalchemy
|
import sqlalchemy
|
||||||
|
|
||||||
from app import db
|
from app import db
|
||||||
@ -54,7 +54,6 @@ def formation_delete(formation_id=None, dialog_confirmed=False):
|
|||||||
formation: Formation = Formation.query.get_or_404(formation_id)
|
formation: Formation = Formation.query.get_or_404(formation_id)
|
||||||
|
|
||||||
H = [
|
H = [
|
||||||
html_sco_header.sco_header(page_title="Suppression d'une formation"),
|
|
||||||
f"""<h2>Suppression de la formation {formation.titre} ({formation.acronyme})</h2>""",
|
f"""<h2>Suppression de la formation {formation.titre} ({formation.acronyme})</h2>""",
|
||||||
]
|
]
|
||||||
formsemestres = formation.formsemestres.all()
|
formsemestres = formation.formsemestres.all()
|
||||||
@ -85,6 +84,7 @@ def formation_delete(formation_id=None, dialog_confirmed=False):
|
|||||||
OK="Supprimer cette formation",
|
OK="Supprimer cette formation",
|
||||||
cancel_url=url_for("notes.index_html", scodoc_dept=g.scodoc_dept),
|
cancel_url=url_for("notes.index_html", scodoc_dept=g.scodoc_dept),
|
||||||
parameters={"formation_id": formation_id},
|
parameters={"formation_id": formation_id},
|
||||||
|
template="sco_page_dept.j2",
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
do_formation_delete(formation_id)
|
do_formation_delete(formation_id)
|
||||||
@ -95,8 +95,9 @@ def formation_delete(formation_id=None, dialog_confirmed=False):
|
|||||||
}">continuer</a></p>"""
|
}">continuer</a></p>"""
|
||||||
)
|
)
|
||||||
|
|
||||||
H.append(html_sco_header.sco_footer())
|
return render_template(
|
||||||
return "\n".join(H)
|
"sco_page-dept.j2", content="\n".join(H), title="Suppression d'une formation"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def do_formation_delete(formation_id):
|
def do_formation_delete(formation_id):
|
||||||
|
@ -51,7 +51,6 @@ from app.scodoc.sco_exceptions import (
|
|||||||
ScoGenError,
|
ScoGenError,
|
||||||
ScoNonEmptyFormationObject,
|
ScoNonEmptyFormationObject,
|
||||||
)
|
)
|
||||||
from app.scodoc import html_sco_header
|
|
||||||
from app.scodoc import codes_cursus
|
from app.scodoc import codes_cursus
|
||||||
from app.scodoc import sco_edit_matiere
|
from app.scodoc import sco_edit_matiere
|
||||||
from app.scodoc import sco_moduleimpl
|
from app.scodoc import sco_moduleimpl
|
||||||
@ -208,8 +207,8 @@ def module_delete(module_id=None):
|
|||||||
)
|
)
|
||||||
|
|
||||||
H = [
|
H = [
|
||||||
html_sco_header.sco_header(page_title="Suppression d'un module"),
|
f"""<h2>Suppression du module {module.titre or "<em>sans titre</em>"}
|
||||||
f"""<h2>Suppression du module {module.titre or "<em>sans titre</em>"} ({module.code})</h2>""",
|
({module.code})</h2>""",
|
||||||
]
|
]
|
||||||
|
|
||||||
dest_url = url_for(
|
dest_url = url_for(
|
||||||
@ -227,7 +226,11 @@ def module_delete(module_id=None):
|
|||||||
cancelbutton="Annuler",
|
cancelbutton="Annuler",
|
||||||
)
|
)
|
||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
return "\n".join(H) + tf[1] + html_sco_header.sco_footer()
|
return render_template(
|
||||||
|
"sco_page_dept.j2",
|
||||||
|
title="Suppression d'un module",
|
||||||
|
content="\n".join(H) + tf[1],
|
||||||
|
)
|
||||||
elif tf[0] == -1:
|
elif tf[0] == -1:
|
||||||
return flask.redirect(dest_url)
|
return flask.redirect(dest_url)
|
||||||
else:
|
else:
|
||||||
@ -372,16 +375,6 @@ def module_edit(
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
H = [
|
H = [
|
||||||
html_sco_header.sco_header(
|
|
||||||
page_title=page_title,
|
|
||||||
cssstyles=["libjs/jQuery-tagEditor/jquery.tag-editor.css"],
|
|
||||||
javascripts=[
|
|
||||||
"libjs/jQuery-tagEditor/jquery.tag-editor.min.js",
|
|
||||||
"libjs/jQuery-tagEditor/jquery.caret.min.js",
|
|
||||||
"js/module_tag_editor.js",
|
|
||||||
"js/module_edit.js",
|
|
||||||
],
|
|
||||||
),
|
|
||||||
f"""<h2>{title}</h2>""",
|
f"""<h2>{title}</h2>""",
|
||||||
render_template(
|
render_template(
|
||||||
"scodoc/help/modules.j2",
|
"scodoc/help/modules.j2",
|
||||||
@ -780,7 +773,7 @@ def module_edit(
|
|||||||
scu.get_request_args(),
|
scu.get_request_args(),
|
||||||
descr,
|
descr,
|
||||||
html_foot_markup=(
|
html_foot_markup=(
|
||||||
f"""<div class="sco_tag_module_edit"><span
|
f"""<div class="scobox 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>
|
||||||
"""
|
"""
|
||||||
@ -793,8 +786,17 @@ def module_edit(
|
|||||||
)
|
)
|
||||||
#
|
#
|
||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
return (
|
return render_template(
|
||||||
"\n".join(H)
|
"sco_page_dept.j2",
|
||||||
|
title=page_title,
|
||||||
|
cssstyles=["libjs/jQuery-tagEditor/jquery.tag-editor.css"],
|
||||||
|
javascripts=[
|
||||||
|
"libjs/jQuery-tagEditor/jquery.tag-editor.min.js",
|
||||||
|
"libjs/jQuery-tagEditor/jquery.caret.min.js",
|
||||||
|
"js/module_tag_editor.js",
|
||||||
|
"js/module_edit.js",
|
||||||
|
],
|
||||||
|
content="\n".join(H)
|
||||||
+ tf[1]
|
+ tf[1]
|
||||||
+ (
|
+ (
|
||||||
f"""
|
f"""
|
||||||
@ -805,8 +807,7 @@ def module_edit(
|
|||||||
"""
|
"""
|
||||||
if not create
|
if not create
|
||||||
else ""
|
else ""
|
||||||
)
|
),
|
||||||
+ html_sco_header.sco_footer()
|
|
||||||
)
|
)
|
||||||
elif tf[0] == -1:
|
elif tf[0] == -1:
|
||||||
return flask.redirect(
|
return flask.redirect(
|
||||||
@ -904,9 +905,6 @@ def module_table(formation_id):
|
|||||||
raise ScoValueError("invalid formation !")
|
raise ScoValueError("invalid formation !")
|
||||||
formation: Formation = Formation.query.get_or_404(formation_id)
|
formation: Formation = Formation.query.get_or_404(formation_id)
|
||||||
H = [
|
H = [
|
||||||
html_sco_header.sco_header(
|
|
||||||
page_title=f"Liste des modules de {formation.titre}"
|
|
||||||
),
|
|
||||||
f"""<h2>Listes des modules dans la formation {formation.titre} ({formation.acronyme}</h2>
|
f"""<h2>Listes des modules dans la formation {formation.titre} ({formation.acronyme}</h2>
|
||||||
<ul class="notes_module_list">
|
<ul class="notes_module_list">
|
||||||
""",
|
""",
|
||||||
@ -926,8 +924,11 @@ def module_table(formation_id):
|
|||||||
)
|
)
|
||||||
H.append("</li>")
|
H.append("</li>")
|
||||||
H.append("</ul>")
|
H.append("</ul>")
|
||||||
H.append(html_sco_header.sco_footer())
|
return render_template(
|
||||||
return "\n".join(H)
|
"sco_page_dept.j2",
|
||||||
|
title=f"Liste des modules de {formation.titre}",
|
||||||
|
content="\n".join(H),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def module_is_locked(module_id):
|
def module_is_locked(module_id):
|
||||||
|
@ -505,8 +505,11 @@ def ue_edit(ue_id=None, create=False, formation_id=None, default_semestre_idx=No
|
|||||||
else:
|
else:
|
||||||
clone_form = ""
|
clone_form = ""
|
||||||
|
|
||||||
return f"""
|
return render_template(
|
||||||
{html_sco_header.sco_header(page_title=title, javascripts=["js/edit_ue.js"])}
|
"sco_page_dept.j2",
|
||||||
|
title=title,
|
||||||
|
javascripts=["js/edit_ue.js"],
|
||||||
|
content=f"""
|
||||||
<h2>{title}, (formation {formation.acronyme}, version {formation.version})</h2>
|
<h2>{title}, (formation {formation.acronyme}, version {formation.version})</h2>
|
||||||
<p class="help">Les UEs sont des groupes de modules dans une formation donnée,
|
<p class="help">Les UEs sont des groupes de modules dans une formation donnée,
|
||||||
utilisés pour la validation (on calcule des moyennes par UE et applique des
|
utilisés pour la validation (on calcule des moyennes par UE et applique des
|
||||||
@ -529,9 +532,8 @@ def ue_edit(ue_id=None, create=False, formation_id=None, default_semestre_idx=No
|
|||||||
|
|
||||||
<div id="bonus_description" class="scobox"></div>
|
<div id="bonus_description" class="scobox"></div>
|
||||||
<div id="ue_list_code" class="sco_box sco_green_bg"></div>
|
<div id="ue_list_code" class="sco_box sco_green_bg"></div>
|
||||||
|
""",
|
||||||
{html_sco_header.sco_footer()}
|
)
|
||||||
"""
|
|
||||||
elif tf[0] == 1:
|
elif tf[0] == 1:
|
||||||
if create:
|
if create:
|
||||||
if not tf[2]["ue_code"]:
|
if not tf[2]["ue_code"]:
|
||||||
|
@ -486,7 +486,8 @@ def formsemestre_evaluations_cal(formsemestre_id):
|
|||||||
<div class="cal_evaluations">
|
<div class="cal_evaluations">
|
||||||
{ cal_html }
|
{ cal_html }
|
||||||
</div>
|
</div>
|
||||||
<p>soit {nb_evals} évaluations planifiées;
|
<div class="scobox maxwidth">
|
||||||
|
<p>soit {nb_evals} évaluations planifiées :
|
||||||
</p>
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>en <span style=
|
<li>en <span style=
|
||||||
@ -508,6 +509,7 @@ def formsemestre_evaluations_cal(formsemestre_id):
|
|||||||
)
|
)
|
||||||
}" class="stdlink">voir les délais de correction</a>
|
}" class="stdlink">voir les délais de correction</a>
|
||||||
</p>
|
</p>
|
||||||
|
</div>
|
||||||
""",
|
""",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -825,7 +825,7 @@ def excel_feuille_listeappel(
|
|||||||
ws.append_blank_row()
|
ws.append_blank_row()
|
||||||
|
|
||||||
# bas de page (date, serveur)
|
# bas de page (date, serveur)
|
||||||
dt = time.strftime("%d/%m/%Y à %Hh%M")
|
dt = time.strftime(scu.DATEATIME_FMT)
|
||||||
if server_name:
|
if server_name:
|
||||||
dt += " sur " + server_name
|
dt += " sur " + server_name
|
||||||
cell_2 = ws.make_cell(("Liste éditée le " + dt), style1i)
|
cell_2 = ws.make_cell(("Liste éditée le " + dt), style1i)
|
||||||
|
@ -174,7 +174,9 @@ def formation_table_recap(formation: Formation, fmt="html") -> Response:
|
|||||||
preferences=sco_preferences.SemPreferences(),
|
preferences=sco_preferences.SemPreferences(),
|
||||||
table_id="formation_table_recap",
|
table_id="formation_table_recap",
|
||||||
)
|
)
|
||||||
return tab.make_page(fmt=fmt, javascripts=["js/formation_recap.js"])
|
return tab.make_page(
|
||||||
|
fmt=fmt, javascripts=["js/formation_recap.js"], template="sco_page_dept.j2"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def export_recap_formations_annee_scolaire(annee_scolaire):
|
def export_recap_formations_annee_scolaire(annee_scolaire):
|
||||||
|
@ -149,6 +149,7 @@ def formsemestre_associate_new_version(
|
|||||||
"formation_id": formation_id,
|
"formation_id": formation_id,
|
||||||
"formsemestre_id": formsemestre_id,
|
"formsemestre_id": formsemestre_id,
|
||||||
},
|
},
|
||||||
|
template="sco_page_dept.j2",
|
||||||
)
|
)
|
||||||
elif request.method == "POST":
|
elif request.method == "POST":
|
||||||
if formsemestre_id is not None: # pas dans le form car checkbox disabled
|
if formsemestre_id is not None: # pas dans le form car checkbox disabled
|
||||||
|
@ -60,7 +60,6 @@ from app.scodoc.TrivialFormulator import TrivialFormulator
|
|||||||
from app.scodoc.sco_exceptions import AccessDenied, ScoValueError
|
from app.scodoc.sco_exceptions import AccessDenied, ScoValueError
|
||||||
from app.scodoc.sco_permissions import Permission
|
from app.scodoc.sco_permissions import Permission
|
||||||
from app.scodoc.sco_vdi import ApoEtapeVDI
|
from app.scodoc.sco_vdi import ApoEtapeVDI
|
||||||
from app.scodoc import html_sco_header
|
|
||||||
from app.scodoc import codes_cursus
|
from app.scodoc import codes_cursus
|
||||||
from app.scodoc import sco_edit_module
|
from app.scodoc import sco_edit_module
|
||||||
from app.scodoc import sco_formsemestre
|
from app.scodoc import sco_formsemestre
|
||||||
@ -80,20 +79,20 @@ def _default_sem_title(formation):
|
|||||||
|
|
||||||
def formsemestre_createwithmodules():
|
def formsemestre_createwithmodules():
|
||||||
"""Page création d'un semestre"""
|
"""Page création d'un semestre"""
|
||||||
H = [
|
H = ["""<h2>Mise en place d'un semestre de formation</h2>"""]
|
||||||
html_sco_header.sco_header(
|
r = do_formsemestre_createwithmodules()
|
||||||
page_title="Création d'un semestre",
|
if not isinstance(r, str):
|
||||||
|
return r # response redirect
|
||||||
|
|
||||||
|
H.append(r)
|
||||||
|
|
||||||
|
return render_template(
|
||||||
|
"sco_page_dept.j2",
|
||||||
|
title="Création d'un semestre",
|
||||||
|
content="\n".join(H),
|
||||||
javascripts=["libjs/AutoSuggest.js", "js/formsemestre_edit.js"],
|
javascripts=["libjs/AutoSuggest.js", "js/formsemestre_edit.js"],
|
||||||
cssstyles=["css/autosuggest_inquisitor.css"],
|
cssstyles=["css/autosuggest_inquisitor.css"],
|
||||||
),
|
)
|
||||||
"""<h2>Mise en place d'un semestre de formation</h2>""",
|
|
||||||
]
|
|
||||||
r = do_formsemestre_createwithmodules()
|
|
||||||
if isinstance(r, str):
|
|
||||||
H.append(r)
|
|
||||||
else:
|
|
||||||
return r # response redirect
|
|
||||||
return "\n".join(H) + html_sco_header.sco_footer()
|
|
||||||
|
|
||||||
|
|
||||||
def formsemestre_editwithmodules(formsemestre_id: int):
|
def formsemestre_editwithmodules(formsemestre_id: int):
|
||||||
@ -1398,6 +1397,7 @@ def do_formsemestre_clone(
|
|||||||
formsemestre.parcours = formsemestre_orig.parcours
|
formsemestre.parcours = formsemestre_orig.parcours
|
||||||
|
|
||||||
# 6- Copy description
|
# 6- Copy description
|
||||||
|
if formsemestre_orig.description:
|
||||||
formsemestre.description = formsemestre_orig.description.clone()
|
formsemestre.description = formsemestre_orig.description.clone()
|
||||||
|
|
||||||
db.session.add(formsemestre)
|
db.session.add(formsemestre)
|
||||||
|
@ -802,7 +802,7 @@ def _make_listes_sem(formsemestre: FormSemestre) -> str:
|
|||||||
})</span></h3>"""
|
})</span></h3>"""
|
||||||
)
|
)
|
||||||
#
|
#
|
||||||
H.append('<div class="sem-groups-abs">')
|
H.append('<div class="sem-groups-abs space-before-18">')
|
||||||
|
|
||||||
disable_abs: str | bool = scass.has_assiduites_disable_pref(formsemestre)
|
disable_abs: str | bool = scass.has_assiduites_disable_pref(formsemestre)
|
||||||
show_abs: str = "hidden" if disable_abs else ""
|
show_abs: str = "hidden" if disable_abs else ""
|
||||||
@ -812,6 +812,8 @@ def _make_listes_sem(formsemestre: FormSemestre) -> str:
|
|||||||
groups = partition.groups.all()
|
groups = partition.groups.all()
|
||||||
effectifs = {g.id: g.get_nb_inscrits() for g in groups}
|
effectifs = {g.id: g.get_nb_inscrits() for g in groups}
|
||||||
partition_is_empty = sum(effectifs.values()) == 0
|
partition_is_empty = sum(effectifs.values()) == 0
|
||||||
|
if partition_is_empty and (partition.is_default() or partition.is_parcours()):
|
||||||
|
continue # inutile de montrer des partitions vides non éditables
|
||||||
H.append(
|
H.append(
|
||||||
f"""
|
f"""
|
||||||
<div class="sem-groups-partition">
|
<div class="sem-groups-partition">
|
||||||
@ -909,7 +911,9 @@ def _make_listes_sem(formsemestre: FormSemestre) -> str:
|
|||||||
)
|
)
|
||||||
|
|
||||||
H.append("</div>") # /sem-groups-assi
|
H.append("</div>") # /sem-groups-assi
|
||||||
if partition_is_empty and not partition.is_default():
|
if partition_is_empty and not (
|
||||||
|
partition.is_default() or partition.is_parcours()
|
||||||
|
):
|
||||||
H.append(
|
H.append(
|
||||||
'<div class="help sem-groups-none">Aucun groupe peuplé dans cette partition'
|
'<div class="help sem-groups-none">Aucun groupe peuplé dans cette partition'
|
||||||
)
|
)
|
||||||
@ -924,41 +928,72 @@ def _make_listes_sem(formsemestre: FormSemestre) -> str:
|
|||||||
H.append("</div>")
|
H.append("</div>")
|
||||||
H.append("</div>") # /sem-groups-partition
|
H.append("</div>") # /sem-groups-partition
|
||||||
|
|
||||||
|
# Boite avec liens divers
|
||||||
|
autres_liens = []
|
||||||
if formsemestre.can_change_groups():
|
if formsemestre.can_change_groups():
|
||||||
H.append(
|
autres_liens.append(
|
||||||
f"""<h4><a class="stdlink"
|
f"""<a class="stdlink"
|
||||||
|
title="une partition est un ensemble de groupes: TD, TP, ..."
|
||||||
href="{url_for("scolar.partition_editor",
|
href="{url_for("scolar.partition_editor",
|
||||||
scodoc_dept=g.scodoc_dept,
|
scodoc_dept=g.scodoc_dept,
|
||||||
formsemestre_id=formsemestre.id,
|
formsemestre_id=formsemestre.id,
|
||||||
edit_partition=1)
|
edit_partition=1)
|
||||||
}">Ajouter une partition</a></h4>"""
|
}">Ajouter une partition</a>"""
|
||||||
)
|
)
|
||||||
|
|
||||||
# --- Formulaire importation Assiduité excel (si autorisé)
|
# --- Formulaire importation Assiduité excel (si autorisé)
|
||||||
if current_user.has_permission(Permission.AbsChange) and not disable_abs:
|
if current_user.has_permission(Permission.AbsChange) and not disable_abs:
|
||||||
H.append(
|
autres_liens.append(
|
||||||
f"""<p>
|
f"""
|
||||||
<a class="stdlink" href="{url_for('assiduites.feuille_abs_formsemestre',
|
<a class="stdlink" href="{url_for('assiduites.feuille_abs_formsemestre',
|
||||||
scodoc_dept=g.scodoc_dept,
|
scodoc_dept=g.scodoc_dept,
|
||||||
formsemestre_id=formsemestre.id)}">
|
formsemestre_id=formsemestre.id)}">
|
||||||
Importation de l'assiduité depuis un fichier excel</a>
|
Importation de l'assiduité depuis un fichier excel</a>
|
||||||
</p>"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
# --- Lien Traitement Justificatifs:
|
# --- Lien Traitement Justificatifs:
|
||||||
|
|
||||||
if (
|
if (
|
||||||
current_user.has_permission(Permission.AbsJustifView)
|
current_user.has_permission(Permission.AbsJustifView)
|
||||||
and current_user.has_permission(Permission.JustifValidate)
|
and current_user.has_permission(Permission.JustifValidate)
|
||||||
and not disable_abs
|
and not disable_abs
|
||||||
):
|
):
|
||||||
H.append(
|
autres_liens.append(
|
||||||
f"""<p>
|
f"""
|
||||||
<a class="stdlink" href="{url_for('assiduites.traitement_justificatifs',
|
<a class="stdlink" href="{url_for('assiduites.traitement_justificatifs',
|
||||||
scodoc_dept=g.scodoc_dept,
|
scodoc_dept=g.scodoc_dept,
|
||||||
formsemestre_id=formsemestre.id)}">
|
formsemestre_id=formsemestre.id)}">
|
||||||
Traitement des justificatifs d'absence</a>
|
Traitement des justificatifs d'absence</a>
|
||||||
</p>"""
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
# --- Lien pour mail aux enseignants
|
||||||
|
# Construit la liste de tous les enseignants de ce semestre:
|
||||||
|
mails_enseignants = set(u.email for u in formsemestre.responsables)
|
||||||
|
for modimpl in formsemestre.modimpls_sorted:
|
||||||
|
mails_enseignants.add(sco_users.user_info(modimpl.responsable_id)["email"])
|
||||||
|
mails_enseignants |= {u.email for u in modimpl.enseignants if u.email}
|
||||||
|
adrlist = list(mails_enseignants - {None, ""})
|
||||||
|
if adrlist:
|
||||||
|
autres_liens.append(
|
||||||
|
f"""
|
||||||
|
<a class="stdlink" href="mailto:?cc={','.join(adrlist)}">Courrier aux {
|
||||||
|
len(adrlist)} enseignants du semestre</a>
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
# Met le tout en boite
|
||||||
|
if autres_liens:
|
||||||
|
H.append(
|
||||||
|
f"""
|
||||||
|
<div class="sem-groups-partition sem-groups-autres-liens">
|
||||||
|
<div class="sem-groups-none">
|
||||||
|
<ul>
|
||||||
|
<li>{'</li><li>'.join(autres_liens)}</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
H.append("</div>")
|
H.append("</div>")
|
||||||
@ -1033,8 +1068,9 @@ def formsemestre_status_head(formsemestre_id: int = None, page_title: str = None
|
|||||||
)
|
)
|
||||||
if evals["last_modif"]:
|
if evals["last_modif"]:
|
||||||
H.append(
|
H.append(
|
||||||
" <em>(dernière note saisie le %s)</em>"
|
f""" <em>(dernière note saisie le {
|
||||||
% evals["last_modif"].strftime("%d/%m/%Y à %Hh%M")
|
evals["last_modif"].strftime(scu.DATEATIME_FMT)
|
||||||
|
})</em>"""
|
||||||
)
|
)
|
||||||
H.append("</td></tr>")
|
H.append("</td></tr>")
|
||||||
H.append("</table>")
|
H.append("</table>")
|
||||||
@ -1073,12 +1109,6 @@ def formsemestre_status(formsemestre_id=None, check_parcours=True):
|
|||||||
modimpls = formsemestre.modimpls_sorted
|
modimpls = formsemestre.modimpls_sorted
|
||||||
nt = res_sem.load_formsemestre_results(formsemestre)
|
nt = res_sem.load_formsemestre_results(formsemestre)
|
||||||
|
|
||||||
# Construit la liste de tous les enseignants de ce semestre:
|
|
||||||
mails_enseignants = set(u.email for u in formsemestre.responsables)
|
|
||||||
for modimpl in modimpls:
|
|
||||||
mails_enseignants.add(sco_users.user_info(modimpl.responsable_id)["email"])
|
|
||||||
mails_enseignants |= {u.email for u in modimpl.enseignants if u.email}
|
|
||||||
|
|
||||||
can_edit = formsemestre.can_be_edited_by(current_user)
|
can_edit = formsemestre.can_be_edited_by(current_user)
|
||||||
can_change_all_notes = current_user.has_permission(Permission.EditAllNotes) or (
|
can_change_all_notes = current_user.has_permission(Permission.EditAllNotes) or (
|
||||||
current_user.id in [resp.id for resp in formsemestre.responsables]
|
current_user.id in [resp.id for resp in formsemestre.responsables]
|
||||||
@ -1206,20 +1236,11 @@ def formsemestre_status(formsemestre_id=None, check_parcours=True):
|
|||||||
)
|
)
|
||||||
# --- LISTE DES ETUDIANTS
|
# --- LISTE DES ETUDIANTS
|
||||||
H += [
|
H += [
|
||||||
'<div class="formsemestre-groupes">',
|
'<div class="formsemestre-groupes space-before-24">',
|
||||||
_make_listes_sem(formsemestre),
|
_make_listes_sem(formsemestre),
|
||||||
"</div>",
|
"</div>",
|
||||||
]
|
]
|
||||||
|
|
||||||
# --- Lien mail enseignants:
|
|
||||||
adrlist = list(mails_enseignants - {None, ""})
|
|
||||||
if adrlist:
|
|
||||||
H.append(
|
|
||||||
f"""<p>
|
|
||||||
<a class="stdlink" href="mailto:?cc={','.join(adrlist)}">Courrier aux {
|
|
||||||
len(adrlist)} enseignants du semestre</a>
|
|
||||||
</p>"""
|
|
||||||
)
|
|
||||||
return render_template(
|
return render_template(
|
||||||
"sco_page.j2",
|
"sco_page.j2",
|
||||||
content="".join(H),
|
content="".join(H),
|
||||||
|
@ -583,6 +583,11 @@ def formsemestre_recap_parcours_table(
|
|||||||
)
|
)
|
||||||
is_cur = situation_etud_cursus.formsemestre_id == formsemestre.id
|
is_cur = situation_etud_cursus.formsemestre_id == formsemestre.id
|
||||||
num_sem += 1
|
num_sem += 1
|
||||||
|
url_status = url_for(
|
||||||
|
"notes.formsemestre_status",
|
||||||
|
scodoc_dept=g.scodoc_dept,
|
||||||
|
formsemestre_id=formsemestre.id,
|
||||||
|
)
|
||||||
|
|
||||||
dpv = sco_pv_dict.dict_pvjury(formsemestre.id, etudids=[etudid])
|
dpv = sco_pv_dict.dict_pvjury(formsemestre.id, etudids=[etudid])
|
||||||
pv = dpv["decisions"][0]
|
pv = dpv["decisions"][0]
|
||||||
@ -642,7 +647,7 @@ def formsemestre_recap_parcours_table(
|
|||||||
H.append(
|
H.append(
|
||||||
f"""
|
f"""
|
||||||
<td class="rcp_type_sem" style="background-color:{bgcolor};">{num_sem}{pm}</td>
|
<td class="rcp_type_sem" style="background-color:{bgcolor};">{num_sem}{pm}</td>
|
||||||
<td class="datedebut">{formsemestre.mois_debut()}</td>
|
<td class="datedebut"><a href="{url_status}">{formsemestre.mois_debut()}</a></td>
|
||||||
<td class="rcp_titre_sem"><a class="formsemestre_status_link"
|
<td class="rcp_titre_sem"><a class="formsemestre_status_link"
|
||||||
href="{
|
href="{
|
||||||
url_for("notes.formsemestre_bulletinetud", scodoc_dept=g.scodoc_dept,
|
url_for("notes.formsemestre_bulletinetud", scodoc_dept=g.scodoc_dept,
|
||||||
@ -724,8 +729,9 @@ def formsemestre_recap_parcours_table(
|
|||||||
f"""Autre formation: {formsemestre.formation.formation_code}"""
|
f"""Autre formation: {formsemestre.formation.formation_code}"""
|
||||||
)
|
)
|
||||||
H.append(
|
H.append(
|
||||||
'<td class="datefin">%s</td><td class="sem_info">%s</td>'
|
f"""<td class="datefin"><a href="{url_status}">{formsemestre.mois_fin()}</a></td>
|
||||||
% (formsemestre.mois_fin(), sem_info.get(formsemestre.id, default_sem_info))
|
<td class="sem_info">{sem_info.get(formsemestre.id, default_sem_info)}</td>
|
||||||
|
"""
|
||||||
)
|
)
|
||||||
# Moy Gen (sous le code decision)
|
# Moy Gen (sous le code decision)
|
||||||
H.append(
|
H.append(
|
||||||
|
@ -65,7 +65,7 @@ def groups_export_annotations(group_ids, formsemestre_id=None, fmt="html"):
|
|||||||
)
|
)
|
||||||
annotations = groups_list_annotation(groups_infos.group_ids)
|
annotations = groups_list_annotation(groups_infos.group_ids)
|
||||||
for annotation in annotations:
|
for annotation in annotations:
|
||||||
annotation["date_str"] = annotation["date"].strftime("%d/%m/%Y à %Hh%M")
|
annotation["date_str"] = annotation["date"].strftime(scu.DATEATIME_FMT)
|
||||||
if fmt == "xls":
|
if fmt == "xls":
|
||||||
columns_ids = ("etudid", "nom", "prenom", "date", "comment")
|
columns_ids = ("etudid", "nom", "prenom", "date", "comment")
|
||||||
else:
|
else:
|
||||||
|
@ -783,12 +783,17 @@ def groups_table(
|
|||||||
tab.html(),
|
tab.html(),
|
||||||
f"""
|
f"""
|
||||||
<ul>
|
<ul>
|
||||||
<li><a class="stdlink" href="{tab.base_url}&fmt=xls">Table Excel</a>
|
<li><a class="stdlink" href="{tab.base_url}&fmt=xls">Table Excel
|
||||||
|
groupe(s) {groups_infos.groups_titles}</a>
|
||||||
</li>
|
</li>
|
||||||
<li><a class="stdlink" href="{tab.base_url}&fmt=moodlecsv">Fichier CSV pour Moodle (groupe sélectionné)</a>
|
<li><a class="stdlink" href="{tab.base_url}&fmt=moodlecsv">Fichier CSV pour
|
||||||
|
Moodle groupe(s) {groups_infos.groups_titles}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a class="stdlink" href="export_groups_as_moodle_csv?formsemestre_id={groups_infos.formsemestre_id}">
|
<a class="stdlink" href="{{
|
||||||
|
url_for('notes.export_groups_as_moodle_csv',
|
||||||
|
scodoc_dept=g.scodoc_dept, formsemestre_id=groups_infos.formsemestre_id)
|
||||||
|
}}">
|
||||||
Fichier CSV pour Moodle (tous les groupes)</a>
|
Fichier CSV pour Moodle (tous les groupes)</a>
|
||||||
<em>(voir le paramétrage pour modifier le format des fichiers Moodle exportés)</em>
|
<em>(voir le paramétrage pour modifier le format des fichiers Moodle exportés)</em>
|
||||||
</li>""",
|
</li>""",
|
||||||
|
@ -656,7 +656,7 @@ def _ligne_evaluation(
|
|||||||
if etat["last_modif"]:
|
if etat["last_modif"]:
|
||||||
H.append(
|
H.append(
|
||||||
f"""<span class="mievr_lastmodif">(dernière modif le {
|
f"""<span class="mievr_lastmodif">(dernière modif le {
|
||||||
etat["last_modif"].strftime("%d/%m/%Y à %Hh%M")})</span>"""
|
etat["last_modif"].strftime(scu.DATEATIME_FMT)})</span>"""
|
||||||
)
|
)
|
||||||
#
|
#
|
||||||
H.append(
|
H.append(
|
||||||
|
@ -51,7 +51,7 @@ from wtforms import (
|
|||||||
from app.models import Evaluation, ModuleImpl
|
from app.models import Evaluation, ModuleImpl
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
import app.scodoc.notesdb as ndb
|
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_edit_module
|
||||||
from app.scodoc import sco_evaluations
|
from app.scodoc import sco_evaluations
|
||||||
from app.scodoc import sco_excel
|
from app.scodoc import sco_excel
|
||||||
@ -204,14 +204,14 @@ def placement_eval_selectetuds(evaluation_id):
|
|||||||
% runner.__dict__
|
% runner.__dict__
|
||||||
)
|
)
|
||||||
return runner.exec_placement() # calcul et generation du fichier
|
return runner.exec_placement() # calcul et generation du fichier
|
||||||
htmls = [
|
|
||||||
html_sco_header.sco_header(),
|
return render_template(
|
||||||
sco_evaluations.evaluation_describe(evaluation_id=evaluation_id),
|
"scodoc/forms/placement.j2",
|
||||||
"<h3>Placement et émargement des étudiants</h3>",
|
evaluations_description=sco_evaluations.evaluation_describe(
|
||||||
render_template("scodoc/forms/placement.j2", form=form),
|
evaluation_id=evaluation_id
|
||||||
]
|
),
|
||||||
footer = html_sco_header.sco_footer()
|
form=form,
|
||||||
return "\n".join(htmls) + "<p>" + footer
|
)
|
||||||
|
|
||||||
|
|
||||||
class PlacementRunner:
|
class PlacementRunner:
|
||||||
|
@ -350,7 +350,7 @@ def formsemestre_pvjury_pdf(formsemestre_id, group_ids: list[int] = None, etudid
|
|||||||
etud = Identite.get_etud(etudid)
|
etud = Identite.get_etud(etudid)
|
||||||
etudids = [etudid]
|
etudids = [etudid]
|
||||||
else:
|
else:
|
||||||
etuddescr = ""
|
etud = None
|
||||||
if not group_ids:
|
if not group_ids:
|
||||||
# tous les inscrits du semestre
|
# tous les inscrits du semestre
|
||||||
group_ids = [sco_groups.get_default_group(formsemestre_id)]
|
group_ids = [sco_groups.get_default_group(formsemestre_id)]
|
||||||
@ -399,7 +399,7 @@ def formsemestre_pvjury_pdf(formsemestre_id, group_ids: list[int] = None, etudid
|
|||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
return render_template(
|
return render_template(
|
||||||
"sco_page.j2",
|
"sco_page.j2",
|
||||||
title=f"Édition du PV de jury de {etud.nom_prenom()}",
|
title=f"Édition du PV de jury {('de ' + etud.nom_prenom()) if etud else ''}",
|
||||||
content=f"""<h2 class="formsemestre">Édition du PV de jury
|
content=f"""<h2 class="formsemestre">Édition du PV de jury
|
||||||
de <a class="discretelink" href="{
|
de <a class="discretelink" href="{
|
||||||
url_for("scolar.fiche_etud", scodoc_dept=g.scodoc_dept, etudid=etudid)
|
url_for("scolar.fiche_etud", scodoc_dept=g.scodoc_dept, etudid=etudid)
|
||||||
|
@ -37,7 +37,7 @@ import time
|
|||||||
import datetime
|
import datetime
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
|
|
||||||
from flask import url_for, g, request
|
from flask import url_for, g, render_template, request
|
||||||
import pydot
|
import pydot
|
||||||
|
|
||||||
from app import log
|
from app import log
|
||||||
@ -50,7 +50,6 @@ from app.models.etudiants import Identite
|
|||||||
|
|
||||||
from app.scodoc import (
|
from app.scodoc import (
|
||||||
codes_cursus,
|
codes_cursus,
|
||||||
html_sco_header,
|
|
||||||
sco_etud,
|
sco_etud,
|
||||||
sco_formsemestre,
|
sco_formsemestre,
|
||||||
sco_formsemestre_inscriptions,
|
sco_formsemestre_inscriptions,
|
||||||
@ -411,11 +410,6 @@ def formsemestre_report_counts(
|
|||||||
if fmt != "html":
|
if fmt != "html":
|
||||||
return tableau
|
return tableau
|
||||||
H = [
|
H = [
|
||||||
html_sco_header.sco_header(
|
|
||||||
cssstyles=sco_groups_view.CSSSTYLES,
|
|
||||||
javascripts=sco_groups_view.JAVASCRIPTS,
|
|
||||||
page_title=title,
|
|
||||||
),
|
|
||||||
tableau,
|
tableau,
|
||||||
"\n".join(F),
|
"\n".join(F),
|
||||||
"""<p class="help">Le tableau affiche le nombre d'étudiants de ce semestre dans chacun
|
"""<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
|
pour les lignes et les colonnes. Le <tt>codedecision</tt> est le code de la décision
|
||||||
du jury.
|
du jury.
|
||||||
</p>""",
|
</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>"""
|
href="{burl}&percent=1">Afficher les résultats en pourcentages</a></p>"""
|
||||||
|
|
||||||
H = [
|
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>""",
|
"""<h2 class="formsemestre">Suivi cohorte: devenir des étudiants de ce semestre</h2>""",
|
||||||
_gen_form_selectetuds(
|
_gen_form_selectetuds(
|
||||||
formsemestre.id,
|
formsemestre.id,
|
||||||
@ -853,9 +847,14 @@ def formsemestre_suivi_cohorte(
|
|||||||
</p>
|
</p>
|
||||||
""",
|
""",
|
||||||
expl,
|
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(
|
def _gen_form_selectetuds(
|
||||||
@ -1365,15 +1364,11 @@ def formsemestre_suivi_cursus(
|
|||||||
]
|
]
|
||||||
|
|
||||||
H = [
|
H = [
|
||||||
html_sco_header.sco_header(
|
|
||||||
page_title=tab.page_title,
|
|
||||||
),
|
|
||||||
"""<h2 class="formsemestre">Cursus suivis par les étudiants de ce semestre</h2>""",
|
"""<h2 class="formsemestre">Cursus suivis par les étudiants de ce semestre</h2>""",
|
||||||
"\n".join(F),
|
"\n".join(F),
|
||||||
t,
|
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 = [
|
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>""",
|
"""<h2 class="formsemestre">Cursus des étudiants de ce semestre</h2>""",
|
||||||
doc,
|
doc,
|
||||||
f"<p>{len(etuds)} étudiants sélectionnés</p>",
|
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"""
|
"""<p>Origine et devenir des étudiants inscrits dans %(titreannee)s"""
|
||||||
% sem,
|
% sem,
|
||||||
"""(<a href="%s">version pdf</a>"""
|
f"""(<a href="{
|
||||||
% url_for("notes.formsemestre_graph_cursus", fmt="pdf", **url_kw),
|
url_for("notes.formsemestre_graph_cursus", fmt="pdf", **url_kw)
|
||||||
""", <a href="%s">image PNG</a>)"""
|
}">version pdf</a>,
|
||||||
% url_for("notes.formsemestre_graph_cursus", fmt="png", **url_kw),
|
<a href="{
|
||||||
f"""
|
url_for("notes.formsemestre_graph_cursus", fmt="png", **url_kw)}">image PNG</a>)
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
<p class="help">Le graphe permet de suivre les étudiants inscrits dans le semestre
|
<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
|
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>.
|
étudiants appartenant aux groupes indiqués <em>dans le semestre d'origine</em>.
|
||||||
</p>
|
</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:
|
else:
|
||||||
raise ValueError(f"invalid format: {fmt}")
|
raise ValueError(f"invalid format: {fmt}")
|
||||||
|
@ -31,21 +31,18 @@
|
|||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
|
|
||||||
from flask import request
|
from flask import render_template, request
|
||||||
|
|
||||||
from app import db
|
from app import db
|
||||||
from app.but import jury_but
|
from app.but import jury_but
|
||||||
from app.models import FormSemestre
|
from app.models import FormSemestre
|
||||||
from app.models.formsemestre import FormSemestreInscription
|
from app.models.formsemestre import FormSemestreInscription
|
||||||
|
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
from app.scodoc import html_sco_header
|
|
||||||
from app.scodoc import codes_cursus
|
from app.scodoc import codes_cursus
|
||||||
from app.scodoc.sco_exceptions import ScoValueError
|
from app.scodoc.sco_exceptions import ScoValueError
|
||||||
|
|
||||||
from app.scodoc import sco_preferences
|
from app.scodoc import sco_preferences
|
||||||
import sco_version
|
|
||||||
from app.scodoc.gen_tables import GenTable
|
from app.scodoc.gen_tables import GenTable
|
||||||
|
import sco_version
|
||||||
|
|
||||||
|
|
||||||
# Titres, ordonnés
|
# Titres, ordonnés
|
||||||
@ -107,13 +104,11 @@ def formsemestre_but_indicateurs(formsemestre_id: int, fmt="html"):
|
|||||||
if fmt != "html":
|
if fmt != "html":
|
||||||
return t
|
return t
|
||||||
H = [
|
H = [
|
||||||
html_sco_header.sco_header(page_title=title),
|
|
||||||
t,
|
t,
|
||||||
"""<p class="help">
|
"""<p class="help">
|
||||||
</p>""",
|
</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]:
|
def but_indicateurs_by_bac(formsemestre: FormSemestre) -> dict[str:dict]:
|
||||||
|
@ -40,17 +40,15 @@ sem_set_list()
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import flask
|
import flask
|
||||||
from flask import g, url_for
|
from flask import g, render_template, url_for
|
||||||
|
|
||||||
from app import db, log
|
from app import db, log
|
||||||
from app.comp import res_sem
|
from app.comp import res_sem
|
||||||
from app.comp.res_compat import NotesTableCompat
|
from app.comp.res_compat import NotesTableCompat
|
||||||
from app.models import FormSemestre
|
from app.models import FormSemestre
|
||||||
from app.scodoc import html_sco_header
|
|
||||||
from app.scodoc import sco_etape_apogee
|
from app.scodoc import sco_etape_apogee
|
||||||
from app.scodoc import sco_formsemestre
|
from app.scodoc import sco_formsemestre
|
||||||
from app.scodoc import sco_formsemestre_status
|
from app.scodoc import sco_formsemestre_status
|
||||||
from app.scodoc import sco_portal_apogee
|
|
||||||
from app.scodoc import sco_preferences
|
from app.scodoc import sco_preferences
|
||||||
from app.scodoc.gen_tables import GenTable
|
from app.scodoc.gen_tables import GenTable
|
||||||
from app.scodoc.sco_etape_bilan import EtapeBilan
|
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)
|
s = SemSet(semset_id=semset_id)
|
||||||
if not dialog_confirmed:
|
if not dialog_confirmed:
|
||||||
return scu.confirm_dialog(
|
return scu.confirm_dialog(
|
||||||
"<h2>Suppression de l'ensemble %(title)s ?</h2>" % s,
|
f"<h2>Suppression de l'ensemble {s['title']} ?</h2>",
|
||||||
dest_url="",
|
dest_url="",
|
||||||
parameters={"semset_id": semset_id},
|
parameters={"semset_id": semset_id},
|
||||||
cancel_url="semset_page",
|
cancel_url="semset_page",
|
||||||
@ -421,14 +419,14 @@ def do_semset_delete(semset_id, dialog_confirmed=False):
|
|||||||
return flask.redirect("semset_page")
|
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"""
|
"""Change title of semset"""
|
||||||
title = value.strip()
|
title = value.strip()
|
||||||
if not id:
|
if not oid:
|
||||||
raise ScoValueError("empty semset_id")
|
raise ScoValueError("empty semset_id")
|
||||||
SemSet(semset_id=id)
|
SemSet(semset_id=oid)
|
||||||
cnx = ndb.GetDBConnexion()
|
cnx = ndb.GetDBConnexion()
|
||||||
semset_edit(cnx, {"semset_id": id, "title": title})
|
semset_edit(cnx, {"semset_id": oid, "title": title})
|
||||||
return title
|
return title
|
||||||
|
|
||||||
|
|
||||||
@ -517,22 +515,18 @@ def semset_page(fmt="html"):
|
|||||||
|
|
||||||
page_title = "Ensembles de semestres"
|
page_title = "Ensembles de semestres"
|
||||||
H = [
|
H = [
|
||||||
html_sco_header.sco_header(
|
|
||||||
page_title=page_title,
|
|
||||||
javascripts=["libjs/jinplace-1.2.1.min.js"],
|
|
||||||
),
|
|
||||||
"""<script>$(function() {
|
"""<script>$(function() {
|
||||||
$('.inplace_edit').jinplace();
|
$('.inplace_edit').jinplace();
|
||||||
});
|
});
|
||||||
</script>""",
|
</script>""",
|
||||||
"<h2>%s</h2>" % page_title,
|
f"<h2>{page_title}</h2>",
|
||||||
]
|
]
|
||||||
H.append(tab.html())
|
H.append(tab.html())
|
||||||
|
|
||||||
annee_courante = int(scu.annee_scolaire())
|
annee_courante = int(scu.annee_scolaire())
|
||||||
menu_annee = "\n".join(
|
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)
|
for i in range(2014, annee_courante + 1)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
@ -561,8 +555,8 @@ def semset_page(fmt="html"):
|
|||||||
|
|
||||||
H.append(
|
H.append(
|
||||||
"""
|
"""
|
||||||
<div>
|
<div class="scobox space-before-24">
|
||||||
<h4>Autres opérations:</h4>
|
<div class="scobox-title">Autres opérations :</div>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a class="stdlink" href="scodoc_table_results">
|
<li><a class="stdlink" href="scodoc_table_results">
|
||||||
Table des résultats de tous les semestres
|
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.TrivialFormulator import TrivialFormulator
|
||||||
from app.scodoc.sco_exceptions import ScoPDFFormatError, ScoValueError
|
from app.scodoc.sco_exceptions import ScoPDFFormatError, ScoValueError
|
||||||
from app.scodoc.sco_pdf import SU
|
from app.scodoc.sco_pdf import SU
|
||||||
from app.scodoc import html_sco_header
|
|
||||||
from app.scodoc import htmlutils
|
from app.scodoc import htmlutils
|
||||||
from app.scodoc import sco_import_etuds
|
from app.scodoc import sco_import_etuds
|
||||||
from app.scodoc import sco_excel
|
from app.scodoc import sco_excel
|
||||||
@ -90,12 +89,7 @@ def trombino(
|
|||||||
return _listeappel_photos_pdf(groups_infos)
|
return _listeappel_photos_pdf(groups_infos)
|
||||||
elif fmt == "doc":
|
elif fmt == "doc":
|
||||||
return sco_trombino_doc.trombino_doc(groups_infos)
|
return sco_trombino_doc.trombino_doc(groups_infos)
|
||||||
else:
|
raise ValueError("invalid format")
|
||||||
raise Exception("invalid format")
|
|
||||||
|
|
||||||
|
|
||||||
def _trombino_html_header():
|
|
||||||
return html_sco_header.sco_header(javascripts=["js/trombino.js"])
|
|
||||||
|
|
||||||
|
|
||||||
def trombino_html(groups_infos):
|
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)
|
back_url = "groups_photos?" + str(groups_infos.groups_query_args)
|
||||||
|
|
||||||
portal_url = sco_portal_apogee.get_portal_url()
|
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:
|
if not portal_url:
|
||||||
return f"""{ header }
|
return render_template(
|
||||||
|
"sco_page.j2",
|
||||||
|
content=f"""
|
||||||
<p>portail non configuré</p>
|
<p>portail non configuré</p>
|
||||||
<p><a href="{back_url}" class="stdlink">Retour au trombinoscope</a></p>
|
<div>
|
||||||
{ footer }
|
<a class="stdlink" href="{back_url}" class="stdlink">
|
||||||
"""
|
Retour au trombinoscope
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
""",
|
||||||
|
)
|
||||||
if not dialog_confirmed:
|
if not dialog_confirmed:
|
||||||
return scu.confirm_dialog(
|
return scu.confirm_dialog(
|
||||||
f"""<h2>Copier les photos du portail vers ScoDoc ?</h2>
|
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>")
|
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>
|
<h2>Chargement des photos depuis le portail</h2>
|
||||||
<ul><li>
|
<ul><li>
|
||||||
{ '</li><li>'.join(msg) }
|
{ '</li><li>'.join(msg) }
|
||||||
</li></ul>
|
</li></ul>
|
||||||
<p><a href="{back_url}">retour au trombinoscope</a>
|
<div class="space-before-24">
|
||||||
{ footer }
|
<a class="stdlink" href="{back_url}">retour au trombinoscope</a>
|
||||||
"""
|
</div>
|
||||||
|
""",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _get_etud_platypus_image(t, image_width=2 * cm):
|
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}"
|
back_url = f"groups_photos?{groups_infos.groups_query_args}"
|
||||||
|
|
||||||
H = [
|
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>
|
f"""<h2 class="formsemestre">Téléchargement des photos des étudiants</h2>
|
||||||
<p><b>Vous pouvez aussi charger les photos individuellement via la fiche
|
<p><b>Vous pouvez aussi charger les photos individuellement via la fiche
|
||||||
de chaque étudiant (menu "Étudiant" / "Changer la photo").</b>
|
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;">
|
<li style="padding-top: 2em;">
|
||||||
""",
|
""",
|
||||||
]
|
]
|
||||||
F = html_sco_header.sco_footer()
|
|
||||||
vals = scu.get_request_args()
|
vals = scu.get_request_args()
|
||||||
vals["group_ids"] = groups_infos.group_ids
|
vals["group_ids"] = groups_infos.group_ids
|
||||||
tf = TrivialFormulator(
|
tf = TrivialFormulator(
|
||||||
@ -540,10 +540,13 @@ def photos_import_files_form(group_ids=()):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
return "\n".join(H) + tf[1] + "</li></ol>" + F
|
return render_template(
|
||||||
elif tf[0] == -1:
|
"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)
|
return flask.redirect(back_url)
|
||||||
else:
|
|
||||||
|
|
||||||
def callback(etud: Identite, data, filename):
|
def callback(etud: Identite, data, filename):
|
||||||
return sco_photos.store_photo(etud, data, filename)
|
return sco_photos.store_photo(etud, data, filename)
|
||||||
|
@ -556,7 +556,7 @@ MONTH_NAMES = (
|
|||||||
)
|
)
|
||||||
DAY_NAMES = ("lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi", "dimanche")
|
DAY_NAMES = ("lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi", "dimanche")
|
||||||
|
|
||||||
TIME_FMT = "%H:%M" # affichage des heures
|
TIME_FMT = "%Hh%M" # affichage des heures
|
||||||
DATE_FMT = "%d/%m/%Y" # affichage des dates
|
DATE_FMT = "%d/%m/%Y" # affichage des dates
|
||||||
DATEATIME_FMT = DATE_FMT + " à " + TIME_FMT
|
DATEATIME_FMT = DATE_FMT + " à " + TIME_FMT
|
||||||
DATETIME_FMT = DATE_FMT + " " + TIME_FMT
|
DATETIME_FMT = DATE_FMT + " " + TIME_FMT
|
||||||
@ -1339,7 +1339,7 @@ def format_telephone(n: str | None) -> str:
|
|||||||
#
|
#
|
||||||
def timedate_human_repr():
|
def timedate_human_repr():
|
||||||
"representation du temps courant pour utilisateur"
|
"representation du temps courant pour utilisateur"
|
||||||
return time.strftime("%d/%m/%Y à %Hh%M")
|
return time.strftime(DATEATIME_FMT)
|
||||||
|
|
||||||
|
|
||||||
def annee_scolaire_repr(year, month):
|
def annee_scolaire_repr(year, month):
|
||||||
@ -1525,6 +1525,7 @@ def confirm_dialog(
|
|||||||
help_msg=None,
|
help_msg=None,
|
||||||
parameters: dict = None,
|
parameters: dict = None,
|
||||||
target_variable="dialog_confirmed",
|
target_variable="dialog_confirmed",
|
||||||
|
template="sco_page.j2",
|
||||||
):
|
):
|
||||||
"""HTML confirmation dialog: submit (POST) to same page or dest_url if given."""
|
"""HTML confirmation dialog: submit (POST) to same page or dest_url if given."""
|
||||||
parameters = parameters or {}
|
parameters = parameters or {}
|
||||||
@ -1565,7 +1566,7 @@ def confirm_dialog(
|
|||||||
if help_msg:
|
if help_msg:
|
||||||
H.append('<p class="help">' + help_msg + "</p>")
|
H.append('<p class="help">' + help_msg + "</p>")
|
||||||
if add_headers:
|
if add_headers:
|
||||||
return render_template("sco_page.j2", content="\n".join(H))
|
return render_template(template, content="\n".join(H))
|
||||||
else:
|
else:
|
||||||
return "\n".join(H)
|
return "\n".join(H)
|
||||||
|
|
||||||
|
@ -55,11 +55,19 @@ div.container {
|
|||||||
div.sco-app-content {
|
div.sco-app-content {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
margin-right: 8px;
|
margin-right: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.space-before-18 {
|
.space-before-18 {
|
||||||
margin-top: 18px;
|
margin-top: 18px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.space-before-24 {
|
||||||
|
margin-top: 24px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.scobox.maxwidth {
|
||||||
|
max-width: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.scobox {
|
div.scobox {
|
||||||
@ -748,14 +756,14 @@ div.fiche_etud {
|
|||||||
/* rgb(255,240,128); */
|
/* rgb(255,240,128); */
|
||||||
border: 1px solid gray;
|
border: 1px solid gray;
|
||||||
width: 910px;
|
width: 910px;
|
||||||
padding: 10px;
|
padding: 24px 10px 10px 10px;
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.menus_etud {
|
div.menus_etud {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
margin-left: 1px;
|
margin-left: 10px;
|
||||||
margin-top: 1px;
|
margin-top: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.fiche_etud h2 {
|
div.fiche_etud h2 {
|
||||||
@ -2059,6 +2067,10 @@ ul.ue_inscr_list li.etud {
|
|||||||
text-underline-offset: 3px;
|
text-underline-offset: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sem-groups-autres-liens {
|
||||||
|
background-color: var(--sco-color-box-bg);
|
||||||
|
}
|
||||||
|
|
||||||
.sem-groups-list .stdlink,
|
.sem-groups-list .stdlink,
|
||||||
.sem-groups-list .stdlink:visited {
|
.sem-groups-list .stdlink:visited {
|
||||||
color: rgb(0, 0, 192);
|
color: rgb(0, 0, 192);
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
});
|
|
@ -45,7 +45,7 @@
|
|||||||
<h2 style="color: crimson;">{{titre_form}}</h2>
|
<h2 style="color: crimson;">{{titre_form}}</h2>
|
||||||
<div class="scobox">
|
<div class="scobox">
|
||||||
<div id="excel-content">
|
<div id="excel-content">
|
||||||
<p class="hint">Avertissement : le fichier doit respecter le format suivant</p>
|
<p class="hint">Le fichier importé doit respecter le format suivant</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
@ -53,12 +53,12 @@
|
|||||||
</li>
|
</li>
|
||||||
<li class="star">colonne B : Date de début</li>
|
<li class="star">colonne B : Date de début</li>
|
||||||
<li class="star">colonne C : Date de fin</li>
|
<li class="star">colonne C : Date de fin</li>
|
||||||
<li class="opt">colonne D : État (ABS,RET,PRE, ABS si vide)</li>
|
<li class="opt">colonne D : État (ABS, RET, PRE), considéré ABSent si vide</li>
|
||||||
<li class="opt">colonne E : code du module</li>
|
<li class="opt">colonne E : code du module</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p class="hint"><span class="opt"></span> : Colonne optionnelle, les cases peuvent être vides</p>
|
<p class="hint"><span class="opt"></span> : Colonne optionnelle, les cases peuvent être vides</p>
|
||||||
<p class="hint"><span class="star"></span> : Formats autorisés :
|
<p class="hint"><span class="star"></span> : Formats de dates autorisés :
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<pre>aaaa-mm-jjThh:mm:ss</pre>
|
<pre>aaaa-mm-jjThh:mm:ss</pre>
|
||||||
@ -73,21 +73,23 @@
|
|||||||
|
|
||||||
|
|
||||||
<form action="" method="post" enctype="multipart/form-data">
|
<form action="" method="post" enctype="multipart/form-data">
|
||||||
<label for="type_identifiant">Type d'identifiant d'étudiant (etudid, ine, nip)</label>
|
<label for="type_identifiant">Type d'identifiant d'étudiant (etudid, INE, NIP)</label>
|
||||||
<select name="type_identifiant" id="type_identifiant">
|
<select name="type_identifiant" id="type_identifiant">
|
||||||
<option value="etudid">ETUDID</option>
|
<option value="etudid">etudid</option>
|
||||||
<option value="ine">INE</option>
|
<option value="ine">INE</option>
|
||||||
<option value="nip">NIP</option>
|
<option value="nip">NIP</option>
|
||||||
</select>
|
</select>
|
||||||
<br>
|
<div class="space-before-18">
|
||||||
<label for="file">
|
<label for="file">
|
||||||
Sélectionnez un fichier:
|
Sélectionnez un fichier:
|
||||||
|
|
||||||
</label>
|
</label>
|
||||||
<input id="file" type="file" name="file"
|
<input id="file" type="file" name="file"
|
||||||
accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel" />
|
accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel" />
|
||||||
<br>
|
</div>
|
||||||
|
<div class="space-before-18">
|
||||||
<button type="submit">Importer</button>
|
<button type="submit">Importer</button>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
<br />
|
<br />
|
||||||
Ces utilisateurs peuvent être réactivés à tout moment.
|
Ces utilisateurs peuvent être réactivés à tout moment.
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row space-before-24">
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
{{ wtf.quick_form(form, button_map={'submit':'secondary'}) }}
|
{{ wtf.quick_form(form, button_map={'submit':'secondary'}) }}
|
||||||
</div>
|
</div>
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<em>établi le {{time.strftime("%d/%m/%Y à %Hh%M")}} (notes sur 20)</em>
|
<em>établi le {{time.strftime(scu.DATEATIME_FMT)}} (notes sur 20)</em>
|
||||||
<span class="rightjust">
|
<span class="rightjust">
|
||||||
<select name="version" onchange="self.location.href='{{
|
<select name="version" onchange="self.location.href='{{
|
||||||
url_for('notes.formsemestre_bulletinetud',
|
url_for('notes.formsemestre_bulletinetud',
|
||||||
|
@ -158,7 +158,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="footer">
|
<div id="footer">
|
||||||
Bulletin généré par ScoDoc le {{time.strftime("%d/%m/%Y à %Hh%M")}}. Explication des codes sur
|
Bulletin généré par ScoDoc le {{time.strftime(scu.DATEATIME_FMT)}}. Explication des codes sur
|
||||||
<a href="https://scodoc.org/BUTCodesJury">https://scodoc.org/BUTCodesJury</a>
|
<a href="https://scodoc.org/BUTCodesJury">https://scodoc.org/BUTCodesJury</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{% extends "sco_page.j2" %}
|
{% extends "sco_page_dept.j2" %}
|
||||||
|
|
||||||
{% block styles %}
|
{% block styles %}
|
||||||
{{super()}}
|
{{super()}}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
{# -*- mode: jinja-html -*- #}
|
||||||
{% extends "base.j2" %}
|
{% extends "sco_page_dept.j2" %}
|
||||||
{% import 'wtf.j2' as wtf %}
|
{% import 'wtf.j2' as wtf %}
|
||||||
|
|
||||||
{% block app_content %}
|
{% block app_content %}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
{# -*- mode: jinja-html -*- #}
|
||||||
{% extends "sco_page.j2" %}
|
{% extends "sco_page_dept.j2" %}
|
||||||
{% block styles %}
|
{% block styles %}
|
||||||
{{super()}}
|
{{super()}}
|
||||||
<link href="{{scu.STATIC_DIR}}/css/refcomp_parcours_niveaux.css" rel="stylesheet" type="text/css" />
|
<link href="{{scu.STATIC_DIR}}/css/refcomp_parcours_niveaux.css" rel="stylesheet" type="text/css" />
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
{# -*- mode: jinja-html -*- #}
|
||||||
{% extends "sco_page.j2" %}
|
{% extends "sco_page_dept.j2" %}
|
||||||
{% import 'wtf.j2' as wtf %}
|
{% import 'wtf.j2' as wtf %}
|
||||||
|
|
||||||
{% block app_content %}
|
{% block app_content %}
|
||||||
|
@ -51,7 +51,7 @@ une formation utilisant une autre version de référentiel, pensez à revalider
|
|||||||
pour l'étudiant{{etud.ne}} {{etud.html_link_fiche()|safe}}
|
pour l'étudiant{{etud.ne}} {{etud.html_link_fiche()|safe}}
|
||||||
<ul>
|
<ul>
|
||||||
<li>DUT 120 spécialité {{formsemestre.formation.referentiel_competence.specialite_long}}
|
<li>DUT 120 spécialité {{formsemestre.formation.referentiel_competence.specialite_long}}
|
||||||
enregistré le {{time.strftime("%d/%m/%Y à %Hh%M")}}
|
enregistré le {{time.strftime(scu.DATEATIME_FMT)}}
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{# Association d'ECTS à une UE par parcours #}
|
{# Association d'ECTS à une UE par parcours #}
|
||||||
{% extends "sco_page.j2" %}
|
{% extends "sco_page_dept.j2" %}
|
||||||
{% import 'wtf.j2' as wtf %}
|
{% import 'wtf.j2' as wtf %}
|
||||||
|
|
||||||
{% block styles %}
|
{% block styles %}
|
||||||
@ -23,7 +23,7 @@
|
|||||||
<form method="POST">
|
<form method="POST">
|
||||||
{% for field in form %}
|
{% for field in form %}
|
||||||
{% if field.name != 'csrf_token' %}
|
{% if field.name != 'csrf_token' %}
|
||||||
<div>
|
<div class="space-before-18">
|
||||||
<label for="{{ field.id }}">{{ field.label }}</label>
|
<label for="{{ field.id }}">{{ field.label }}</label>
|
||||||
{{ field }}
|
{{ field }}
|
||||||
{% for error in field.errors %}
|
{% for error in field.errors %}
|
||||||
@ -33,8 +33,10 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{{ form.csrf_token }}
|
{{ form.csrf_token }}
|
||||||
|
<div class="space-before-24">
|
||||||
<input type="submit" name="submit" value="Enregistrer">
|
<input type="submit" name="submit" value="Enregistrer">
|
||||||
<input type="submit" name="cancel" value="Annuler">
|
<input type="submit" name="cancel" value="Annuler">
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
<h2>{{ title }}</h2>
|
<h2>{{ title }}</h2>
|
||||||
|
|
||||||
|
<div class="scobox">
|
||||||
<p class="help">
|
<p class="help">
|
||||||
{{ explanation|safe }}
|
{{ explanation|safe }}
|
||||||
</p>
|
</p>
|
||||||
@ -47,4 +48,5 @@
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -1,4 +1,26 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
{# -*- mode: jinja-html -*- #}
|
||||||
|
{% extends "sco_page_dept.j2" %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block styles %}
|
||||||
|
{{super()}}
|
||||||
|
<link rel="stylesheet" href="{{scu.STATIC_DIR}}/css/table_editor.css">
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block app_content %}
|
||||||
|
<h2>Formation {{formation.titre}} ({{formation.acronyme}})
|
||||||
|
[version {{formation.version}}] code {{formation.formation_code}}
|
||||||
|
{% if read_only %}
|
||||||
|
{{scu.icontag("lock32_img", title="verrouillé")|safe}}
|
||||||
|
{% endif %}
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
{% if read_only %}
|
||||||
|
<span class="warning">
|
||||||
|
Formation verrouilée car un ou plusieurs semestres verrouillés l'utilisent.
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<h2>{% if not read_only %}Édition des c{% else %}C{%endif%}oefficients des modules vers les UEs</h2>
|
<h2>{% if not read_only %}Édition des c{% else %}C{%endif%}oefficients des modules vers les UEs</h2>
|
||||||
<div class="help">
|
<div class="help">
|
||||||
{% if not read_only %}
|
{% if not read_only %}
|
||||||
@ -59,8 +81,11 @@
|
|||||||
<div class="champs_coef_hors_parcours champs_legende"></div>
|
<div class="champs_coef_hors_parcours champs_legende"></div>
|
||||||
<div class="help">module non associé au parcours de cette UE, le coef devrait être nul.</div>
|
<div class="help">module non associé au parcours de cette UE, le coef devrait être nul.</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block scripts %}
|
||||||
|
{{super()}}
|
||||||
|
<script src="{{scu.STATIC_DIR}}/js/table_editor.js"></script>
|
||||||
<script>
|
<script>
|
||||||
var read_only = {{ "true" if read_only else "false"}};
|
var read_only = {{ "true" if read_only else "false"}};
|
||||||
$(function () {
|
$(function () {
|
||||||
@ -113,3 +138,4 @@
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
{% endblock %}
|
@ -1,3 +1,5 @@
|
|||||||
|
{% extends 'sco_page.j2' %}
|
||||||
|
|
||||||
{% import 'wtf.j2' as wtf %}
|
{% import 'wtf.j2' as wtf %}
|
||||||
|
|
||||||
{% macro render_field(field) %}
|
{% macro render_field(field) %}
|
||||||
@ -15,6 +17,12 @@
|
|||||||
</tr>
|
</tr>
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% block app_content %}
|
||||||
|
|
||||||
|
{{ evaluations_description|safe}}
|
||||||
|
|
||||||
|
<h3 class="space-before-24">Placement et émargement des étudiants</h3>
|
||||||
|
|
||||||
<div class="saisienote_etape1 form_placement">
|
<div class="saisienote_etape1 form_placement">
|
||||||
<form method=post>
|
<form method=post>
|
||||||
{{ form.evaluation_id }}
|
{{ form.evaluation_id }}
|
||||||
@ -78,3 +86,4 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
{% endblock %}
|
@ -1,5 +1,5 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
{# -*- mode: jinja-html -*- #}
|
||||||
{% extends 'base.j2' %}
|
{% extends 'sco_page.j2' %}
|
||||||
|
|
||||||
{% block app_content %}
|
{% 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 dateutil.parser
|
||||||
|
|
||||||
import flask
|
import flask
|
||||||
from flask import g, request
|
from flask import abort, flash, g, render_template, request, url_for
|
||||||
from flask import abort, flash, url_for
|
|
||||||
from flask_login import current_user
|
from flask_login import current_user
|
||||||
|
|
||||||
from app import db, log
|
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_permissions import Permission
|
||||||
from app.scodoc.sco_exceptions import ScoValueError
|
from app.scodoc.sco_exceptions import ScoValueError
|
||||||
from app.scodoc.TrivialFormulator import TrivialFormulator
|
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_assiduites as scass
|
||||||
from app.scodoc import sco_abs_billets
|
from app.scodoc import sco_abs_billets
|
||||||
from app.scodoc import sco_etud
|
|
||||||
from app.scodoc import sco_preferences
|
from app.scodoc import sco_preferences
|
||||||
|
|
||||||
|
|
||||||
@ -77,11 +74,7 @@ from app.scodoc import sco_preferences
|
|||||||
def index_html():
|
def index_html():
|
||||||
"""Gestionnaire absences, page principale"""
|
"""Gestionnaire absences, page principale"""
|
||||||
|
|
||||||
H = [
|
H = []
|
||||||
html_sco_header.sco_header(
|
|
||||||
page_title="Billets d'absences",
|
|
||||||
),
|
|
||||||
]
|
|
||||||
if current_user.has_permission(
|
if current_user.has_permission(
|
||||||
Permission.AbsChange
|
Permission.AbsChange
|
||||||
) and sco_preferences.get_preference("handle_billets_abs"):
|
) and sco_preferences.get_preference("handle_billets_abs"):
|
||||||
@ -93,8 +86,9 @@ def index_html():
|
|||||||
</li></ul>
|
</li></ul>
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
H.append(html_sco_header.sco_footer())
|
return render_template(
|
||||||
return "\n".join(H)
|
"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)
|
# ----- 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 ajout billet (pour tests seulement, le vrai
|
||||||
formulaire accessible aux etudiants étant sur le portail étudiant).
|
formulaire accessible aux etudiants étant sur le portail étudiant).
|
||||||
"""
|
"""
|
||||||
etud = sco_etud.get_etud_info(filled=True, etudid=etudid)[0]
|
_ = Identite.get_etud(etudid) # check
|
||||||
H = [
|
H = ["""<h2>Formulaire ajout billet (pour tests)</h2>"""]
|
||||||
html_sco_header.sco_header(
|
|
||||||
page_title="Billet d'absence de %s" % etud["nomprenom"]
|
|
||||||
)
|
|
||||||
]
|
|
||||||
tf = TrivialFormulator(
|
tf = TrivialFormulator(
|
||||||
request.base_url,
|
request.base_url,
|
||||||
scu.get_request_args(),
|
scu.get_request_args(),
|
||||||
@ -179,7 +169,11 @@ def add_billets_absence_form(etudid):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
if tf[0] == 0:
|
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:
|
elif tf[0] == -1:
|
||||||
return flask.redirect(url_for("scolar.index_html", scodoc_dept=g.scodoc_dept))
|
return flask.redirect(url_for("scolar.index_html", scodoc_dept=g.scodoc_dept))
|
||||||
else:
|
else:
|
||||||
@ -242,11 +236,8 @@ def list_billets():
|
|||||||
et formulaire recherche d'un billet.
|
et formulaire recherche d'un billet.
|
||||||
"""
|
"""
|
||||||
table = sco_abs_billets.table_billets_etud(etat=False)
|
table = sco_abs_billets.table_billets_etud(etat=False)
|
||||||
T = table.html()
|
table_html = table.html()
|
||||||
H = [
|
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>",
|
f"<h2>Billets d'absence en attente de traitement ({table.get_nb_rows()})</h2>",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -257,8 +248,11 @@ def list_billets():
|
|||||||
submitbutton=False,
|
submitbutton=False,
|
||||||
)
|
)
|
||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
return "\n".join(H) + tf[1] + T + html_sco_header.sco_footer()
|
return render_template(
|
||||||
else:
|
"sco_page.j2",
|
||||||
|
title="Billet d'absence non traités",
|
||||||
|
content="\n".join(H) + tf[1] + table_html,
|
||||||
|
)
|
||||||
return flask.redirect(
|
return flask.redirect(
|
||||||
url_for(
|
url_for(
|
||||||
"absences.process_billet_absence_form",
|
"absences.process_billet_absence_form",
|
||||||
@ -337,7 +331,8 @@ def _ProcessBilletAbsence(
|
|||||||
def process_billet_absence_form(billet_id: int):
|
def process_billet_absence_form(billet_id: int):
|
||||||
"""Formulaire traitement d'un billet"""
|
"""Formulaire traitement d'un billet"""
|
||||||
if not isinstance(billet_id, int):
|
if not isinstance(billet_id, int):
|
||||||
raise abort(404, "billet_id invalide")
|
abort(404, "billet_id invalide")
|
||||||
|
return # safety guard
|
||||||
billet: BilletAbsence = (
|
billet: BilletAbsence = (
|
||||||
BilletAbsence.query.filter_by(id=billet_id)
|
BilletAbsence.query.filter_by(id=billet_id)
|
||||||
.join(Identite)
|
.join(Identite)
|
||||||
@ -352,9 +347,6 @@ def process_billet_absence_form(billet_id: int):
|
|||||||
etud = billet.etudiant
|
etud = billet.etudiant
|
||||||
|
|
||||||
H = [
|
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="{
|
f"""<h2>Traitement du billet {billet.id} : <a class="discretelink" href="{
|
||||||
url_for("scolar.fiche_etud", scodoc_dept=g.scodoc_dept, etudid=etud.id)
|
url_for("scolar.fiche_etud", scodoc_dept=g.scodoc_dept, etudid=etud.id)
|
||||||
}">{etud.nomprenom}</a></h2>
|
}">{etud.nomprenom}</a></h2>
|
||||||
@ -403,7 +395,11 @@ def process_billet_absence_form(billet_id: int):
|
|||||||
</p>
|
</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:
|
elif tf[0] == -1:
|
||||||
return flask.redirect(url_for("scolar.index_html", scodoc_dept=g.scodoc_dept))
|
return flask.redirect(url_for("scolar.index_html", scodoc_dept=g.scodoc_dept))
|
||||||
else:
|
else:
|
||||||
@ -414,7 +410,7 @@ def process_billet_absence_form(billet_id: int):
|
|||||||
j = "non justifiées"
|
j = "non justifiées"
|
||||||
H.append('<div class="head_message">')
|
H.append('<div class="head_message">')
|
||||||
if n > 0:
|
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:
|
elif n == 0:
|
||||||
H.append("Aucun jour d'absence dans les dates indiquées !")
|
H.append("Aucun jour d'absence dans les dates indiquées !")
|
||||||
elif n < 0:
|
elif n < 0:
|
||||||
@ -434,4 +430,8 @@ def process_billet_absence_form(billet_id: int):
|
|||||||
)
|
)
|
||||||
tab = sco_abs_billets.table_billets(billets, etud=etud)
|
tab = sco_abs_billets.table_billets(billets, etud=etud)
|
||||||
H.append(tab.html())
|
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,
|
select_all_when_unspecified=True,
|
||||||
)
|
)
|
||||||
if not groups_infos.members:
|
if not groups_infos.members:
|
||||||
return (
|
return render_template(
|
||||||
html_sco_header.sco_header(page_title="Saisie de l'assiduité")
|
"sco_page.j2",
|
||||||
+ "<h3>Aucun étudiant ! </h3>"
|
title="Saisie de l'assiduité",
|
||||||
+ html_sco_header.sco_footer()
|
content="<h3>Aucun étudiant !</h3>",
|
||||||
)
|
)
|
||||||
|
|
||||||
# --- Filtrage par formsemestre ---
|
# --- Filtrage par formsemestre ---
|
||||||
@ -1952,10 +1952,10 @@ def signal_assiduites_hebdo():
|
|||||||
group_ids, formsemestre_id=formsemestre.id, select_all_when_unspecified=True
|
group_ids, formsemestre_id=formsemestre.id, select_all_when_unspecified=True
|
||||||
)
|
)
|
||||||
if not groups_infos.members:
|
if not groups_infos.members:
|
||||||
return (
|
return render_template(
|
||||||
html_sco_header.sco_header(page_title="Assiduité: saisie hebdomadaire")
|
"sco_page.j2",
|
||||||
+ "<h3>Aucun étudiant ! </h3>"
|
title="Assiduité: feuille saisie hebdomadaire",
|
||||||
+ html_sco_header.sco_footer()
|
content="<h3>Aucun étudiant !</h3>",
|
||||||
)
|
)
|
||||||
|
|
||||||
# Récupération des étudiants
|
# Récupération des étudiants
|
||||||
@ -2305,12 +2305,10 @@ def feuille_abs_hebdo():
|
|||||||
group_ids, formsemestre_id=formsemestre.id, select_all_when_unspecified=True
|
group_ids, formsemestre_id=formsemestre.id, select_all_when_unspecified=True
|
||||||
)
|
)
|
||||||
if not groups_infos.members:
|
if not groups_infos.members:
|
||||||
return (
|
return render_template(
|
||||||
html_sco_header.sco_header(
|
"sco_page.j2",
|
||||||
page_title="Assiduité: feuille saisie hebdomadaire"
|
title="Assiduité: feuille saisie hebdomadaire",
|
||||||
)
|
content="<h3>Aucun étudiant !</h3>",
|
||||||
+ "<h3>Aucun étudiant ! </h3>"
|
|
||||||
+ html_sco_header.sco_footer()
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Gestion des jours
|
# Gestion des jours
|
||||||
|
@ -60,7 +60,6 @@ from app.models import (
|
|||||||
ScoDocSiteConfig,
|
ScoDocSiteConfig,
|
||||||
)
|
)
|
||||||
from app.scodoc import (
|
from app.scodoc import (
|
||||||
html_sco_header,
|
|
||||||
sco_bulletins_json,
|
sco_bulletins_json,
|
||||||
sco_cache,
|
sco_cache,
|
||||||
sco_formsemestre_exterieurs,
|
sco_formsemestre_exterieurs,
|
||||||
@ -251,25 +250,21 @@ def formsemestre_validation_but(
|
|||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
H = [
|
H = ["""<div class="jury_but">"""]
|
||||||
html_sco_header.sco_header(
|
inscription = formsemestre.etuds_inscriptions.get(etudid)
|
||||||
page_title=f"Validation BUT S{formsemestre.semestre_id}",
|
if not inscription:
|
||||||
formsemestre_id=formsemestre_id,
|
raise ScoValueError("étudiant non inscrit au semestre")
|
||||||
etudid=etudid,
|
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=[
|
cssstyles=[
|
||||||
"css/jury_but.css",
|
"css/jury_but.css",
|
||||||
"css/cursus_but.css",
|
"css/cursus_but.css",
|
||||||
],
|
],
|
||||||
javascripts=("js/jury_but.js",),
|
javascripts=("js/jury_but.js",),
|
||||||
),
|
content=(
|
||||||
"""<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)
|
"\n".join(H)
|
||||||
+ f"""
|
+ f"""
|
||||||
<div>
|
<div>
|
||||||
@ -291,7 +286,7 @@ def formsemestre_validation_but(
|
|||||||
{navigation_div}
|
{navigation_div}
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
+ html_sco_header.sco_footer()
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
deca = jury_but.DecisionsProposeesAnnee(etud, formsemestre)
|
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 ?
|
êtes-vous certain de vouloir enregistrer une décision de jury ?
|
||||||
</div>"""
|
</div>"""
|
||||||
if read_only:
|
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:
|
if deca.formsemestre_impair:
|
||||||
inscription = deca.formsemestre_impair.etuds_inscriptions.get(etud.id)
|
inscription = deca.formsemestre_impair.etuds_inscriptions.get(etud.id)
|
||||||
@ -507,7 +502,17 @@ def formsemestre_validation_but(
|
|||||||
</div>
|
</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(
|
@bp.route(
|
||||||
|
@ -88,7 +88,6 @@ from app.scodoc.sco_exceptions import (
|
|||||||
ScoInvalidIdType,
|
ScoInvalidIdType,
|
||||||
)
|
)
|
||||||
from app.scodoc import (
|
from app.scodoc import (
|
||||||
html_sco_header,
|
|
||||||
sco_apogee_compare,
|
sco_apogee_compare,
|
||||||
sco_archives_formsemestre,
|
sco_archives_formsemestre,
|
||||||
sco_assiduites,
|
sco_assiduites,
|
||||||
@ -770,8 +769,10 @@ def formation_import_xml_form():
|
|||||||
cancelbutton="Annuler",
|
cancelbutton="Annuler",
|
||||||
)
|
)
|
||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
return f"""
|
return render_template(
|
||||||
{ html_sco_header.sco_header(page_title="Import d'une formation") }
|
"sco_page_dept.j2",
|
||||||
|
title="Import d'une formation",
|
||||||
|
content=f"""
|
||||||
<h2>Import d'une formation</h2>
|
<h2>Import d'une formation</h2>
|
||||||
<p>Création d'une formation (avec UE, matières, modules)
|
<p>Création d'une formation (avec UE, matières, modules)
|
||||||
à partir un fichier XML (réservé aux utilisateurs avertis).
|
à partir un fichier XML (réservé aux utilisateurs avertis).
|
||||||
@ -783,8 +784,8 @@ def formation_import_xml_form():
|
|||||||
}">page des référentiels</a>).
|
}">page des référentiels</a>).
|
||||||
</p>
|
</p>
|
||||||
{ tf[1] }
|
{ tf[1] }
|
||||||
{ html_sco_header.sco_footer() }
|
""",
|
||||||
"""
|
)
|
||||||
elif tf[0] == -1:
|
elif tf[0] == -1:
|
||||||
return flask.redirect(url_for("notes.index_html", scodoc_dept=g.scodoc_dept))
|
return flask.redirect(url_for("notes.index_html", scodoc_dept=g.scodoc_dept))
|
||||||
else:
|
else:
|
||||||
@ -792,8 +793,10 @@ def formation_import_xml_form():
|
|||||||
tf[2]["xmlfile"].read()
|
tf[2]["xmlfile"].read()
|
||||||
)
|
)
|
||||||
|
|
||||||
return f"""
|
return render_template(
|
||||||
{ html_sco_header.sco_header(page_title="Import d'une formation") }
|
"sco_page_dept.j2",
|
||||||
|
title="Import d'une formation",
|
||||||
|
content=f"""
|
||||||
<h2>Import effectué !</h2>
|
<h2>Import effectué !</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a class="stdlink" href="{
|
<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)
|
(en cas d'erreur, par exemple pour charger auparavant le référentiel de compétences)
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
{ html_sco_header.sco_footer() }
|
""",
|
||||||
"""
|
)
|
||||||
|
|
||||||
|
|
||||||
sco_publish("/module_move", sco_edit_formation.module_move, Permission.EditFormation)
|
sco_publish("/module_move", sco_edit_formation.module_move, Permission.EditFormation)
|
||||||
@ -2182,15 +2185,17 @@ def formsemestre_bulletins_mailetuds(
|
|||||||
if sent:
|
if sent:
|
||||||
nb_sent += 1
|
nb_sent += 1
|
||||||
#
|
#
|
||||||
return f"""
|
return render_template(
|
||||||
{html_sco_header.sco_header()}
|
"sco_page.j2",
|
||||||
|
title="Mailing bulletins",
|
||||||
|
content=f"""
|
||||||
<p>{nb_sent} bulletins sur {len(inscriptions)} envoyés par mail !</p>
|
<p>{nb_sent} bulletins sur {len(inscriptions)} envoyés par mail !</p>
|
||||||
<p><a class="stdlink" href="{url_for('notes.formsemestre_status',
|
<p><a class="stdlink" href="{url_for('notes.formsemestre_status',
|
||||||
scodoc_dept=g.scodoc_dept,
|
scodoc_dept=g.scodoc_dept,
|
||||||
formsemestre_id=formsemestre_id)
|
formsemestre_id=formsemestre_id)
|
||||||
}">continuer</a></p>
|
}">continuer</a></p>
|
||||||
{html_sco_header.sco_footer()}
|
""",
|
||||||
"""
|
)
|
||||||
|
|
||||||
|
|
||||||
sco_publish(
|
sco_publish(
|
||||||
@ -2258,10 +2263,8 @@ def appreciation_add_form(
|
|||||||
else:
|
else:
|
||||||
action = "Ajout"
|
action = "Ajout"
|
||||||
H = [
|
H = [
|
||||||
html_sco_header.sco_header(),
|
|
||||||
f"""<h2>{action} d'une appréciation sur {etud.nomprenom}</h2>""",
|
f"""<h2>{action} d'une appréciation sur {etud.nomprenom}</h2>""",
|
||||||
]
|
]
|
||||||
F = html_sco_header.sco_footer()
|
|
||||||
descr = [
|
descr = [
|
||||||
("edit", {"input_type": "hidden", "default": edit}),
|
("edit", {"input_type": "hidden", "default": edit}),
|
||||||
("etudid", {"input_type": "hidden"}),
|
("etudid", {"input_type": "hidden"}),
|
||||||
@ -2286,7 +2289,7 @@ def appreciation_add_form(
|
|||||||
submitlabel="Ajouter appréciation",
|
submitlabel="Ajouter appréciation",
|
||||||
)
|
)
|
||||||
if tf[0] == 0:
|
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:
|
elif tf[0] == -1:
|
||||||
return flask.redirect(bul_url)
|
return flask.redirect(bul_url)
|
||||||
else:
|
else:
|
||||||
@ -2643,7 +2646,7 @@ def check_form_integrity(formation_id, fix=False):
|
|||||||
else:
|
else:
|
||||||
txth = "OK"
|
txth = "OK"
|
||||||
log("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")
|
@bp.route("/check_formsemestre_integrity")
|
||||||
@ -2681,6 +2684,4 @@ def check_formsemestre_integrity(formsemestre_id):
|
|||||||
else:
|
else:
|
||||||
diag = ["OK"]
|
diag = ["OK"]
|
||||||
log("ok")
|
log("ok")
|
||||||
return (
|
return render_template("sco_page.j2", content="<br>".join(diag))
|
||||||
html_sco_header.sco_header() + "<br>".join(diag) + html_sco_header.sco_footer()
|
|
||||||
)
|
|
||||||
|
@ -31,24 +31,18 @@ PN / Edition des coefs
|
|||||||
Emmanuel Viennet, 2021
|
Emmanuel Viennet, 2021
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from flask import url_for
|
from flask import g, render_template, request, url_for
|
||||||
from flask import g, request
|
|
||||||
from flask_json import as_json
|
from flask_json import as_json
|
||||||
from flask_login import current_user
|
from flask_login import current_user
|
||||||
from flask.templating import render_template
|
|
||||||
from app.scodoc.codes_cursus import UE_SPORT
|
|
||||||
|
|
||||||
|
|
||||||
from app import db, models
|
from app import db, models
|
||||||
|
|
||||||
from app.comp import moy_ue
|
from app.comp import moy_ue
|
||||||
from app.decorators import scodoc, permission_required
|
from app.decorators import scodoc, permission_required
|
||||||
from app.models import ApcParcours, Formation, Module
|
from app.models import ApcParcours, Formation, Module
|
||||||
from app.views import notes_bp as bp
|
from app.scodoc.codes_cursus import UE_SPORT
|
||||||
|
|
||||||
from app.scodoc import html_sco_header
|
|
||||||
from app.scodoc import sco_utils as scu
|
from app.scodoc import sco_utils as scu
|
||||||
from app.scodoc.sco_permissions import Permission
|
from app.scodoc.sco_permissions import Permission
|
||||||
|
from app.views import notes_bp as bp
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/table_modules_ue_coefs/<int:formation_id>")
|
@bp.route("/table_modules_ue_coefs/<int:formation_id>")
|
||||||
@ -197,31 +191,7 @@ def edit_modules_ue_coefs():
|
|||||||
formation_id=formation_id
|
formation_id=formation_id
|
||||||
).first_or_404()
|
).first_or_404()
|
||||||
locked = formation.has_locked_sems(semestre_idx)
|
locked = formation.has_locked_sems(semestre_idx)
|
||||||
if locked:
|
return render_template(
|
||||||
lockicon = scu.icontag("lock32_img", title="verrouillé")
|
|
||||||
else:
|
|
||||||
lockicon = ""
|
|
||||||
H = [
|
|
||||||
html_sco_header.sco_header(
|
|
||||||
cssstyles=["css/table_editor.css"],
|
|
||||||
javascripts=[
|
|
||||||
"js/table_editor.js",
|
|
||||||
],
|
|
||||||
page_title=f"Coefs programme {formation.acronyme}",
|
|
||||||
),
|
|
||||||
f"""<h2>Formation {formation.titre} ({formation.acronyme})
|
|
||||||
[version {formation.version}] code {formation.formation_code}
|
|
||||||
{lockicon}
|
|
||||||
</h2>
|
|
||||||
""",
|
|
||||||
(
|
|
||||||
"""<span class="warning">Formation verrouilée car un ou plusieurs
|
|
||||||
semestres verrouillés l'utilisent.
|
|
||||||
</span>"""
|
|
||||||
if locked
|
|
||||||
else ""
|
|
||||||
),
|
|
||||||
render_template(
|
|
||||||
"pn/form_modules_ue_coefs.j2",
|
"pn/form_modules_ue_coefs.j2",
|
||||||
formation=formation,
|
formation=formation,
|
||||||
data_source=url_for(
|
data_source=url_for(
|
||||||
@ -235,13 +205,9 @@ def edit_modules_ue_coefs():
|
|||||||
"notes.set_module_ue_coef",
|
"notes.set_module_ue_coef",
|
||||||
scodoc_dept=g.scodoc_dept,
|
scodoc_dept=g.scodoc_dept,
|
||||||
),
|
),
|
||||||
read_only=locked
|
read_only=locked or not current_user.has_permission(Permission.EditFormation),
|
||||||
or not current_user.has_permission(Permission.EditFormation),
|
|
||||||
semestre_idx=semestre_idx,
|
semestre_idx=semestre_idx,
|
||||||
semestre_ids=range(1, formation.get_cursus().NB_SEM + 1),
|
semestre_ids=range(1, formation.get_cursus().NB_SEM + 1),
|
||||||
parcours_id=parcours_id,
|
parcours_id=parcours_id,
|
||||||
),
|
title=f"Coefs programme {formation.acronyme}",
|
||||||
html_sco_header.sco_footer(),
|
)
|
||||||
]
|
|
||||||
|
|
||||||
return "\n".join(H)
|
|
||||||
|
@ -64,7 +64,7 @@ from app.decorators import (
|
|||||||
permission_required,
|
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_users
|
||||||
from app.scodoc import sco_utils as scu
|
from app.scodoc import sco_utils as scu
|
||||||
from app.scodoc import sco_xml
|
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.sco_permissions_check import can_handle_passwd
|
||||||
from app.scodoc.TrivialFormulator import TrivialFormulator, tf_error_message
|
from app.scodoc.TrivialFormulator import TrivialFormulator, tf_error_message
|
||||||
from app.views import users_bp as bp
|
from app.views import users_bp as bp
|
||||||
from app.views import scodoc_bp
|
|
||||||
|
|
||||||
|
|
||||||
_ = lambda x: x # sans babel
|
_ = lambda x: x # sans babel
|
||||||
@ -92,7 +91,7 @@ class ChangePasswordForm(FlaskForm):
|
|||||||
validators=[
|
validators=[
|
||||||
EqualTo(
|
EqualTo(
|
||||||
"new_password",
|
"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()
|
submit = SubmitField()
|
||||||
cancel = SubmitField("Annuler")
|
cancel = SubmitField("Annuler")
|
||||||
|
|
||||||
def validate_email(self, email):
|
def validate_email(self, e_mail):
|
||||||
"vérifie que le mail est unique"
|
"vérifie que le mail est unique (inline wtf validator)"
|
||||||
user = User.query.filter_by(email=email.data.strip()).first()
|
user = User.query.filter_by(email=e_mail.data.strip()).first()
|
||||||
if user is not None and self.user_name.data != user.user_name:
|
if user is not None and self.user_name.data != user.user_name:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
_("Cette adresse e-mail est déjà attribuée à un autre compte")
|
_("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")
|
raise ValidationError("Mot de passe trop simple, recommencez")
|
||||||
|
|
||||||
def validate_old_password(self, old_password):
|
def validate_old_password(self, old_password):
|
||||||
|
"vérifie password actuel"
|
||||||
if not current_user.check_password(old_password.data):
|
if not current_user.check_password(old_password.data):
|
||||||
raise ValidationError("Mot de passe actuel incorrect, ré-essayez")
|
raise ValidationError("Mot de passe actuel incorrect, ré-essayez")
|
||||||
|
|
||||||
@ -855,9 +855,7 @@ def import_users_generate_excel_sample():
|
|||||||
@scodoc7func
|
@scodoc7func
|
||||||
def import_users_form():
|
def import_users_form():
|
||||||
"""Import utilisateurs depuis feuille Excel"""
|
"""Import utilisateurs depuis feuille Excel"""
|
||||||
head = html_sco_header.sco_header(page_title="Import utilisateurs")
|
|
||||||
H = [
|
H = [
|
||||||
head,
|
|
||||||
"""<h2>Téléchargement d'une liste d'utilisateurs</h2>
|
"""<h2>Téléchargement d'une liste d'utilisateurs</h2>
|
||||||
<p style="color: red">A utiliser pour importer de <b>nouveaux</b>
|
<p style="color: red">A utiliser pour importer de <b>nouveaux</b>
|
||||||
utilisateurs (enseignants ou secrétaires)
|
utilisateurs (enseignants ou secrétaires)
|
||||||
@ -886,12 +884,10 @@ def import_users_form():
|
|||||||
<li><b>Étape 1: </b><a class="stdlink" href="{
|
<li><b>Étape 1: </b><a class="stdlink" href="{
|
||||||
url_for("users.import_users_generate_excel_sample", scodoc_dept=g.scodoc_dept)
|
url_for("users.import_users_generate_excel_sample", scodoc_dept=g.scodoc_dept)
|
||||||
}">Obtenir la feuille excel vide à remplir</a>
|
}">Obtenir la feuille excel vide à remplir</a>
|
||||||
ou bien la liste complète des utilisateurs.
|
|
||||||
</li>
|
</li>
|
||||||
<li><b> Étape 2:</b>
|
<li><b> Étape 2:</b>
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
F = html_sco_header.sco_footer()
|
|
||||||
tf = TrivialFormulator(
|
tf = TrivialFormulator(
|
||||||
request.base_url,
|
request.base_url,
|
||||||
scu.get_request_args(),
|
scu.get_request_args(),
|
||||||
@ -915,7 +911,11 @@ def import_users_form():
|
|||||||
submitlabel="Télécharger",
|
submitlabel="Télécharger",
|
||||||
)
|
)
|
||||||
if tf[0] == 0:
|
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:
|
elif tf[0] == -1:
|
||||||
return flask.redirect(url_for("scolar.index_html", docodc_dept=g.scodoc_dept))
|
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(
|
ok, diags, nb_created = sco_import_users.import_excel_file(
|
||||||
tf[2]["xlsfile"], tf[2]["force"]
|
tf[2]["xlsfile"], tf[2]["force"]
|
||||||
)
|
)
|
||||||
H = [html_sco_header.sco_header(page_title="Import utilisateurs")]
|
H = [
|
||||||
H.append("<ul>")
|
"""<h2>Téléchargement d'une liste d'utilisateurs</h2>
|
||||||
|
<ul>"""
|
||||||
|
]
|
||||||
for diag in diags:
|
for diag in diags:
|
||||||
H.append(f"<li>{diag}</li>")
|
H.append(f"<li>{diag}</li>")
|
||||||
H.append("</ul>")
|
H.append("</ul>")
|
||||||
@ -942,7 +944,9 @@ def import_users_form():
|
|||||||
<p><a class="stdlink" href="{dest_url}">Continuer</a></p>
|
<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")
|
@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"])
|
@bp.route("/toggle_active_user/<user_name>", methods=["GET", "POST"])
|
||||||
@scodoc
|
@scodoc
|
||||||
@permission_required(Permission.UsersAdmin)
|
@permission_required(Permission.UsersAdmin)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# -*- mode: python -*-
|
# -*- mode: python -*-
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
SCOVERSION = "9.7.6"
|
SCOVERSION = "9.7.9"
|
||||||
|
|
||||||
SCONAME = "ScoDoc"
|
SCONAME = "ScoDoc"
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ umask 0022
|
|||||||
|
|
||||||
export SCODOC_DIR=/opt/scodoc
|
export SCODOC_DIR=/opt/scodoc
|
||||||
export SCODOC_VAR_DIR=/opt/scodoc-data
|
export SCODOC_VAR_DIR=/opt/scodoc-data
|
||||||
|
export SCODOC_INSTALL_STATUS_FILE="${SCODOC_VAR_DIR}/.install_status"
|
||||||
export SCODOC_VERSION_DIR="${SCODOC_VAR_DIR}/config/version"
|
export SCODOC_VERSION_DIR="${SCODOC_VAR_DIR}/config/version"
|
||||||
export SCODOC_LOGOS_DIR="${SCODOC_VAR_DIR}/config/logos"
|
export SCODOC_LOGOS_DIR="${SCODOC_VAR_DIR}/config/logos"
|
||||||
|
|
||||||
|
@ -3,11 +3,17 @@
|
|||||||
# Post-installation de scodoc
|
# Post-installation de scodoc
|
||||||
# ici, le répertoire /opt/scodoc vient d'être installé
|
# ici, le répertoire /opt/scodoc vient d'être installé
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
cd /opt/scodoc || (echo "Error chdir to /opt/scodoc"; exit 1)
|
cd /opt/scodoc || (echo "Error chdir to /opt/scodoc"; exit 1)
|
||||||
|
|
||||||
# On peut donc charger la config:
|
# On peut donc charger la config:
|
||||||
source /opt/scodoc/tools/config.sh
|
source /opt/scodoc/tools/config.sh || (echo "Error loading /opt/scodoc/tools/config.sh"; exit 1)
|
||||||
source /opt/scodoc/tools/utils.sh
|
source /opt/scodoc/tools/utils.sh || (echo "Error loading /opt/scodoc/tools/utils.sh"; exit 1)
|
||||||
|
|
||||||
|
# Enleve fichier de statut d'installation s'il existe
|
||||||
|
# (la présence de ce fichier indique que l'install s'est bien passée)
|
||||||
|
remove_install_status
|
||||||
|
|
||||||
# -- Création au besoin de notre utilisateur
|
# -- Création au besoin de notre utilisateur
|
||||||
# adduser --system "${SCODOC_USER}"
|
# adduser --system "${SCODOC_USER}"
|
||||||
@ -134,3 +140,6 @@ systemctl enable scodoc9
|
|||||||
|
|
||||||
# --- RESTART SCODOC
|
# --- RESTART SCODOC
|
||||||
systemctl restart scodoc9
|
systemctl restart scodoc9
|
||||||
|
|
||||||
|
# On est arrivé au bout du post-install !
|
||||||
|
create_install_status
|
||||||
|
19
tools/debian/prerm
Executable file
19
tools/debian/prerm
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Pre-removal script for scodoc
|
||||||
|
# This script is called by dpkg before removing the package
|
||||||
|
|
||||||
|
cd /opt/scodoc || (echo "Error chdir to /opt/scodoc"; exit 1)
|
||||||
|
|
||||||
|
# On peut donc charger la config:
|
||||||
|
source /opt/scodoc/tools/config.sh || (echo "Error loading /opt/scodoc/tools/config.sh"; exit 1)
|
||||||
|
source /opt/scodoc/tools/utils.sh || (echo "Error loading /opt/scodoc/tools/utils.sh"; exit 1)
|
||||||
|
|
||||||
|
check_uid_root
|
||||||
|
|
||||||
|
remove_install_status
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -6,10 +6,11 @@
|
|||||||
#
|
#
|
||||||
# Upgrade also the Linux system using apt.
|
# Upgrade also the Linux system using apt.
|
||||||
#
|
#
|
||||||
# Script for ScoDoc 9
|
# Script for ScoDoc 9. Lancé automatiquement par scodoc-updater.
|
||||||
#
|
#
|
||||||
# E. Viennet, sep 2013, mar 2017, jun 2019, aug 2020, dec 2020, aug 21
|
# E. Viennet, sep 2013, mar 2017, jun 2019, aug 2020, dec 2020, aug 21
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
# Le répertoire de ce script:
|
# Le répertoire de ce script:
|
||||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
|
||||||
@ -29,7 +30,7 @@ if [ -z "$SCODOC_UPGRADE_RUNNING" ]
|
|||||||
# install spécifiquement scodoc9, utile si les dépendances Debian de scodoc9
|
# install spécifiquement scodoc9, utile si les dépendances Debian de scodoc9
|
||||||
# ont été changées, ce qui peut provoquer un
|
# ont été changées, ce qui peut provoquer un
|
||||||
# "packages have been kept back"
|
# "packages have been kept back"
|
||||||
apt install scodoc9
|
apt install scodoc9 || alarm_admin "apt install scodoc9 failed"
|
||||||
fi
|
fi
|
||||||
systemctl restart redis
|
systemctl restart redis
|
||||||
systemctl restart nginx
|
systemctl restart nginx
|
||||||
|
@ -110,3 +110,26 @@ gen_passwd() {
|
|||||||
done
|
done
|
||||||
echo "$password"
|
echo "$password"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Status file: indique si l'install s'est complètement déroulée
|
||||||
|
create_install_status() {
|
||||||
|
touch "${SCODOC_INSTALL_STATUS_FILE}" || die "can't create ${SCODOC_INSTALL_STATUS_FILE}"
|
||||||
|
}
|
||||||
|
remove_install_status() {
|
||||||
|
if [ -e "${SCODOC_INSTALL_STATUS_FILE}" ]
|
||||||
|
then
|
||||||
|
rm -f "${SCODOC_INSTALL_STATUS_FILE}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
alarm_admin() {
|
||||||
|
echo "Error: alarm_admin $1"
|
||||||
|
echo "Sending email to admin..."
|
||||||
|
echo "Subject: ScoDoc: $1" | mail -s "ScoDoc: $1" root <<EOF
|
||||||
|
|
||||||
|
Erreur lors de la mise à jour de ScoDoc sur $(hostname --fqdn)
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user