EDT: filtrage par groupe scodoc

This commit is contained in:
Emmanuel Viennet 2023-11-16 23:34:47 +01:00
parent b0daccb32e
commit 1f319dfeba
7 changed files with 251 additions and 143 deletions

View File

@ -565,11 +565,14 @@ def save_groups_auto_assignment(formsemestre_id: int):
@permission_required(Permission.ScoView) @permission_required(Permission.ScoView)
@as_json @as_json
def formsemestre_edt(formsemestre_id: int): def formsemestre_edt(formsemestre_id: int):
"""l'emploi du temps du semestre """l'emploi du temps du semestre.
Si ok, une liste d'évènements. Sinon, une chaine indiquant un message d'erreur. Si ok, une liste d'évènements. Sinon, une chaine indiquant un message d'erreur.
group_ids permet de filtrer sur les groupes ScoDoc.
""" """
query = FormSemestre.query.filter_by(id=formsemestre_id) query = FormSemestre.query.filter_by(id=formsemestre_id)
if g.scodoc_dept: if g.scodoc_dept:
query = query.filter_by(dept_id=g.scodoc_dept_id) query = query.filter_by(dept_id=g.scodoc_dept_id)
formsemestre: FormSemestre = query.first_or_404(formsemestre_id) formsemestre: FormSemestre = query.first_or_404(formsemestre_id)
return sco_edt_cal.formsemestre_edt_dict(formsemestre) group_ids = request.args.getlist("group_ids", int)
return sco_edt_cal.formsemestre_edt_dict(formsemestre, group_ids=group_ids)

View File

@ -111,11 +111,17 @@ _COLOR_PALETTE = [
_EVENT_DEFAULT_COLOR = "rgb(214, 233, 248)" _EVENT_DEFAULT_COLOR = "rgb(214, 233, 248)"
def formsemestre_edt_dict(formsemestre: FormSemestre) -> list[dict]: def formsemestre_edt_dict(
formsemestre: FormSemestre, group_ids: list[int] = None
) -> list[dict]:
"""EDT complet du semestre, comme une liste de dict serialisable en json. """EDT complet du semestre, comme une liste de dict serialisable en json.
Fonction appellée par l'API /formsemestre/<int:formsemestre_id>/edt Fonction appelée par l'API /formsemestre/<int:formsemestre_id>/edt
group_ids indiquer les groupes ScoDoc à afficher (les autres sont filtrés).
Les évènements pour lesquels le groupe ScoDoc n'est pas reconnu sont
toujours présents.
TODO: spécifier intervalle de dates start et end TODO: spécifier intervalle de dates start et end
""" """
group_ids_set = set(group_ids) if group_ids else set()
try: try:
events_scodoc = _load_and_convert_ics(formsemestre) events_scodoc = _load_and_convert_ics(formsemestre)
except ScoValueError as exc: except ScoValueError as exc:
@ -138,9 +144,12 @@ def formsemestre_edt_dict(formsemestre: FormSemestre) -> list[dict]:
{scu.EMO_WARNING} non reconnu</span> {scu.EMO_WARNING} non reconnu</span>
</div>""" </div>"""
) )
if group and group_ids_set and group.id not in group_ids_set:
continue # ignore cet évènement
modimpl: ModuleImpl | bool = event["modimpl"] modimpl: ModuleImpl | bool = event["modimpl"]
if modimpl is False: if modimpl is False:
mod_disp = f"""<div class="module-edt" title="extraction emploi du temps non configurée"> mod_disp = f"""<div class="module-edt"
title="extraction emploi du temps non configurée">
{scu.EMO_WARNING} non configuré {scu.EMO_WARNING} non configuré
</div>""" </div>"""
else: else:

View File

@ -290,8 +290,9 @@ def get_group_members(group_id, etat=None):
return r return r
def get_group_infos(group_id, etat=None): # was _getlisteetud def get_group_infos(group_id, etat: str | None = None): # was _getlisteetud
"""legacy code: used by group_list and trombino""" """legacy code: used by group_list and trombino.
etat: état de l'inscription."""
from app.scodoc import sco_formsemestre from app.scodoc import sco_formsemestre
cnx = ndb.GetDBConnexion() cnx = ndb.GetDBConnexion()

View File

@ -153,63 +153,79 @@ def groups_view(
return "\n".join(H) return "\n".join(H)
def form_groups_choice(groups_infos, with_selectall_butt=False, submit_on_change=False): def form_groups_choice(
groups_infos,
with_selectall_butt=False,
with_deselect_butt=False,
submit_on_change=False,
default_deselect_others=True,
):
"""form pour selection groupes """form pour selection groupes
group_ids est la liste des groupes actuellement sélectionnés group_ids est la liste des groupes actuellement sélectionnés
et doit comporter au moins un élément, sauf si formsemestre_id est spécifié. et doit comporter au moins un élément, sauf si formsemestre_id est spécifié.
(utilisé pour retrouver le semestre et proposer la liste des autres groupes) (utilisé pour retrouver le semestre et proposer la liste des autres groupes)
Si submit_on_change, ajoute une classe "submit_on_change" qui est utilisee en JS Si submit_on_change, soumet (recharge la page) à chaque modif.
Si default_deselect_others, désélectionne le groupe "Tous" quand on sélectionne un autre groupe.
Ces deux options ajoutent des classes utilisées en JS pour la gestion du formulaire.
""" """
default_group_id = sco_groups.get_default_group(groups_infos.formsemestre_id) default_group_id = sco_groups.get_default_group(groups_infos.formsemestre_id)
H = [ H = [
"""<form id="group_selector" method="get"> f"""
<input type="hidden" name="formsemestre_id" id="formsemestre_id" value="%s"/> <form id="group_selector" method="get">
<input type="hidden" name="default_group_id" id="default_group_id" value="%s"/> <input type="hidden" name="formsemestre_id" id="formsemestre_id"
value="{groups_infos.formsemestre_id}"/>
<input type="hidden" name="default_group_id" id="default_group_id"
value="{default_group_id}"/>
Groupes: Groupes:
{
menu_groups_choice(
groups_infos,
submit_on_change=submit_on_change,
default_deselect_others=default_deselect_others,
)
}
""" """
% (groups_infos.formsemestre_id, default_group_id)
] ]
H.append(menu_groups_choice(groups_infos, submit_on_change=submit_on_change))
if with_selectall_butt: if with_selectall_butt:
H.append( H.append(
"""<input type="button" value="sélectionner tous" onmousedown="select_tous();"/>""" """<input type="button" value="sélectionner tous" onmousedown="select_groupe_tous();"/>"""
)
if with_deselect_butt:
H.append(
"""<input type="button" value="ne pas filtrer" onmousedown="remove_group_filter();"/>"""
) )
H.append("</form>") H.append("</form>")
return "\n".join(H) return "\n".join(H)
def menu_groups_choice(groups_infos, submit_on_change=False): def menu_groups_choice(
groups_infos, submit_on_change=False, default_deselect_others=True
):
"""menu pour selection groupes """menu pour selection groupes
group_ids est la liste des groupes actuellement sélectionnés group_ids est la liste des groupes actuellement sélectionnés
et doit comporter au moins un élément, sauf si formsemestre_id est spécifié. et doit comporter au moins un élément, sauf si formsemestre_id est spécifié.
(utilisé pour retrouver le semestre et proposer la liste des autres groupes) (utilisé pour retrouver le semestre et proposer la liste des autres groupes)
""" """
default_group_id = sco_groups.get_default_group(groups_infos.formsemestre_id) default_group_id = sco_groups.get_default_group(groups_infos.formsemestre_id)
if submit_on_change:
klass = "submit_on_change"
else:
klass = ""
H = [
"""<select name="group_ids" id="group_ids_sel" class="multiselect %s" multiple="multiple">
"""
% (klass,)
]
n_members = len(sco_groups.get_group_members(default_group_id)) n_members = len(sco_groups.get_group_members(default_group_id))
if default_group_id in groups_infos.group_ids:
selected = "selected" H = [
else: f"""<select name="group_ids" id="group_ids_sel"
selected = "" class="multiselect
H.append( {'submit_on_change' if submit_on_change else ''}
'<option class="default_group" value="%s" %s>%s (%s)</option>' {'default_deselect_others' if default_deselect_others else ''}
% (default_group_id, selected, "Tous", n_members) "
) multiple="multiple">
<option class="default_group"
value="{default_group_id}"
{'selected' if default_group_id in groups_infos.group_ids else ''}
>Tous ({n_members})</option>
"""
]
for partition in groups_infos.partitions: for partition in groups_infos.partitions:
H.append('<optgroup label="%s">' % partition["partition_name"]) H.append('<optgroup label="%s">' % partition["partition_name"])
@ -289,14 +305,19 @@ class DisplayedGroupsInfos:
.formsemestre_id : semestre "principal" (en fait celui du 1er groupe de la liste) .formsemestre_id : semestre "principal" (en fait celui du 1er groupe de la liste)
.members .members
.groups_titles .groups_titles
etat: filtrage selon l'état de l'inscription
select_all_when_unspecified : sélectionne le groupe "tous" si aucun groupe n'est indiqué.
empty_list_select_all: si vrai (défaut) on sélectionne le groupe tous si aucun groupe indiqué.
""" """
def __init__( def __init__(
self, self,
group_ids=(), # groupes specifies dans l'URL, ou un seul int group_ids=(), # groupes specifies dans l'URL, ou un seul int
formsemestre_id=None, formsemestre_id: int | None = None,
etat=None, etat: str | None = None,
select_all_when_unspecified=False, select_all_when_unspecified=False,
empty_list_select_all=True,
moduleimpl_id=None, # used to find formsemestre when unspecified moduleimpl_id=None, # used to find formsemestre when unspecified
): ):
if isinstance(group_ids, int): if isinstance(group_ids, int):
@ -317,21 +338,26 @@ class DisplayedGroupsInfos:
if not group_ids: # appel sans groupe (eg page accueil) if not group_ids: # appel sans groupe (eg page accueil)
if not formsemestre_id: if not formsemestre_id:
raise Exception("missing parameter formsemestre_id or group_ids") raise ValueError("missing parameter formsemestre_id or group_ids")
if select_all_when_unspecified: if empty_list_select_all:
group_ids = [ if select_all_when_unspecified:
sco_groups.get_default_group(formsemestre_id, fix_if_missing=True) group_ids = [
] sco_groups.get_default_group(
else: formsemestre_id, fix_if_missing=True
# selectionne le premier groupe trouvé, s'il y en a un )
partition = sco_groups.get_partitions_list( ]
formsemestre_id, with_default=True
)[0]
groups = sco_groups.get_partition_groups(partition)
if groups:
group_ids = [groups[0]["group_id"]]
else: else:
group_ids = [sco_groups.get_default_group(formsemestre_id)] # selectionne le premier groupe trouvé, s'il y en a un
partition = sco_groups.get_partitions_list(
formsemestre_id, with_default=True
)[0]
groups = sco_groups.get_partition_groups(partition)
if groups:
group_ids = [groups[0]["group_id"]]
else:
group_ids = [sco_groups.get_default_group(formsemestre_id)]
else:
group_ids = []
gq = [] gq = []
for group_id in group_ids: for group_id in group_ids:
@ -375,7 +401,8 @@ class DisplayedGroupsInfos:
if not self.formsemestre: # aucun groupe selectionne if not self.formsemestre: # aucun groupe selectionne
self.formsemestre = sco_formsemestre.get_formsemestre(formsemestre_id) self.formsemestre = sco_formsemestre.get_formsemestre(formsemestre_id)
if formsemestre_id not in self.sems:
self.sems[formsemestre_id] = self.formsemestre
self.sortuniq() self.sortuniq()
if len(self.sems) > 1: if len(self.sems) > 1:

View File

@ -5,46 +5,54 @@ $().ready(function () {
for (var i = 0; i < spans.length; i++) { for (var i = 0; i < spans.length; i++) {
var sp = spans[i]; var sp = spans[i];
var etudid = sp.id; var etudid = sp.id;
$(sp).load(SCO_URL + '/etud_photo_html?etudid=' + etudid); $(sp).load(SCO_URL + "/etud_photo_html?etudid=" + etudid);
} }
}); });
// L'URL pour recharger l'état courant de la page (groupes et tab selectionnes) // L'URL pour recharger l'état courant de la page (groupes et tab selectionnes)
// (ne fonctionne que pour les requetes GET: manipule la query string) // (ne fonctionne que pour les requetes GET: manipule la query string)
function groups_view_url() { function groups_view_url() {
var url = $.url(); var url = $.url();
delete url.param()['group_ids']; // retire anciens groupes de l'URL delete url.param()["group_ids"]; // retire anciens groupes de l'URL
delete url.param()['curtab']; // retire ancien tab actif delete url.param()["curtab"]; // retire ancien tab actif
if (CURRENT_TAB_HASH) { if (CURRENT_TAB_HASH) {
url.param()['curtab'] = CURRENT_TAB_HASH; url.param()["curtab"] = CURRENT_TAB_HASH;
} }
delete url.param()['formsemestre_id']; delete url.param()["formsemestre_id"];
url.param()['formsemestre_id'] = $("#group_selector")[0].formsemestre_id.value; url.param()["formsemestre_id"] =
$("#group_selector")[0].formsemestre_id.value;
var selected_groups = $("#group_selector select").val(); var selected_groups = $("#group_selector select").val();
url.param()['group_ids'] = selected_groups; // remplace par groupes selectionnes url.param()["group_ids"] = selected_groups; // remplace par groupes selectionnes
return url; return url;
} }
// Selectionne tous les etudiants et recharge la page: // Sélectionne le groupe "tous" et recharge la page:
function select_tous() { function select_groupe_tous() {
var url = groups_view_url(); var url = groups_view_url();
var default_group_id = $("#group_selector")[0].default_group_id.value; var default_group_id = $("#group_selector")[0].default_group_id.value;
delete url.param()['group_ids']; delete url.param()["group_ids"];
url.param()['group_ids'] = [default_group_id]; url.param()["group_ids"] = [default_group_id];
var query_string = $.param(url.param(), traditional = true); var query_string = $.param(url.param(), (traditional = true));
window.location = url.attr('base') + url.attr('path') + '?' + query_string; window.location = url.attr("base") + url.attr("path") + "?" + query_string;
}
// Recharge la page sans arguments group_ids
function remove_group_filter() {
var url = groups_view_url();
delete url.param()["group_ids"];
var query_string = $.param(url.param(), (traditional = true));
window.location = url.attr("base") + url.attr("path") + "?" + query_string;
} }
// L'URL pour l'état courant de la page: // L'URL pour l'état courant de la page:
function get_current_url() { function get_current_url() {
var url = groups_view_url(); var url = groups_view_url();
var query_string = $.param(url.param(), traditional = true); var query_string = $.param(url.param(), (traditional = true));
return url.attr('base') + url.attr('path') + '?' + query_string; return url.attr("base") + url.attr("path") + "?" + query_string;
} }
// Recharge la page en changeant les groupes selectionnés et en conservant le tab actif: // Recharge la page en changeant les groupes selectionnés et en conservant le tab actif:
@ -53,13 +61,15 @@ function submit_group_selector() {
} }
function show_current_tab() { function show_current_tab() {
$('.nav-tabs [href="#' + CURRENT_TAB_HASH + '"]').tab('show'); if (document.getElementsByClassName("nav-tabs").length < 0) {
$('.nav-tabs [href="#' + CURRENT_TAB_HASH + '"]').tab("show");
}
} }
var CURRENT_TAB_HASH = $.url().param()['curtab']; var CURRENT_TAB_HASH = $.url().param()["curtab"];
$().ready(function () { $().ready(function () {
$('.nav-tabs a').on('shown.bs.tab', function (e) { $(".nav-tabs a").on("shown.bs.tab", function (e) {
CURRENT_TAB_HASH = e.target.hash.slice(1); // sans le # CURRENT_TAB_HASH = e.target.hash.slice(1); // sans le #
}); });
@ -69,7 +79,13 @@ $().ready(function () {
function change_list_options() { function change_list_options() {
var url = groups_view_url(); var url = groups_view_url();
var selected_options = $("#group_list_options").val(); var selected_options = $("#group_list_options").val();
var options = ["with_paiement", "with_archives", "with_annotations", "with_codes", "with_bourse"]; var options = [
"with_paiement",
"with_archives",
"with_annotations",
"with_codes",
"with_bourse",
];
for (var i = 0; i < options.length; i++) { for (var i = 0; i < options.length; i++) {
var option = options[i]; var option = options[i];
delete url.param()[option]; delete url.param()[option];
@ -77,8 +93,8 @@ function change_list_options() {
url.param()[option] = 1; url.param()[option] = 1;
} }
} }
var query_string = $.param(url.param(), traditional = true); var query_string = $.param(url.param(), (traditional = true));
window.location = url.attr('base') + url.attr('path') + '?' + query_string; window.location = url.attr("base") + url.attr("path") + "?" + query_string;
} }
// Menu choix groupe: // Menu choix groupe:
@ -95,64 +111,87 @@ function toggle_visible_etuds() {
var input_eval = $("#formnotes_evaluation_id"); var input_eval = $("#formnotes_evaluation_id");
if (input_eval.length > 0) { if (input_eval.length > 0) {
var evaluation_id = input_eval[0].value; var evaluation_id = input_eval[0].value;
$("#menu_saisie_tableur a").attr("href", "saisie_notes_tableur?evaluation_id=" + evaluation_id + qargs); $("#menu_saisie_tableur a").attr(
"href",
"saisie_notes_tableur?evaluation_id=" + evaluation_id + qargs
);
// lien feuille excel: // lien feuille excel:
$("#lnk_feuille_saisie").attr("href", "feuille_saisie_notes?evaluation_id=" + evaluation_id + qargs); $("#lnk_feuille_saisie").attr(
"href",
"feuille_saisie_notes?evaluation_id=" + evaluation_id + qargs
);
} }
// Update champs form group_ids_str // Update champs form group_ids_str
let group_ids_str = Array.from( let group_ids_str = Array.from(
document.querySelectorAll("#group_ids_sel option:checked") document.querySelectorAll("#group_ids_sel option:checked")
).map( )
function (elem) { return elem.value; } .map(function (elem) {
).join(); return elem.value;
document.querySelectorAll("input.group_ids_str").forEach(elem => elem.value = group_ids_str); })
.join();
document
.querySelectorAll("input.group_ids_str")
.forEach((elem) => (elem.value = group_ids_str));
} }
$().ready(function () { $().ready(function () {
$('#group_ids_sel').multiselect( $("#group_ids_sel").multiselect({
{ includeSelectAllOption: false,
includeSelectAllOption: false, nonSelectedText: "choisir...",
nonSelectedText: 'choisir...', // buttonContainer: '<div id="group_ids_sel_container"/>',
// buttonContainer: '<div id="group_ids_sel_container"/>', onChange: function (element, checked) {
onChange: function (element, checked) { // Gestion du groupe "tous"
if (checked == true) { if (
var default_group_id = $(".default_group")[0].value; checked == true &&
$("#group_ids_sel").hasClass("default_deselect_others")
) {
var default_group_id = $(".default_group")[0].value;
if (element.hasClass("default_group")) { if (element.hasClass("default_group")) {
// click sur groupe "tous" // click sur groupe "tous"
// deselectionne les autres // deselectionne les autres
$("#group_ids_sel option:selected").each(function (index, opt) { $("#group_ids_sel option:selected").each(function (
if (opt.value != default_group_id) { index,
$("#group_ids_sel").multiselect('deselect', opt.value); opt
} ) {
}); if (opt.value != default_group_id) {
$("#group_ids_sel").multiselect(
} else { "deselect",
// click sur un autre item opt.value
// si le groupe "tous" est selectionne et que l'on coche un autre, le deselectionner );
var default_is_selected = false;
$("#group_ids_sel option:selected").each(function (index, opt) {
if (opt.value == default_group_id) {
default_is_selected = true;
return false;
}
});
if (default_is_selected) {
$("#group_ids_sel").multiselect('deselect', default_group_id);
} }
});
} else {
// click sur un autre item
// si le groupe "tous" est selectionne et que l'on coche un autre, le deselectionner
var default_is_selected = false;
$("#group_ids_sel option:selected").each(function (
index,
opt
) {
if (opt.value == default_group_id) {
default_is_selected = true;
return false;
}
});
if (default_is_selected) {
$("#group_ids_sel").multiselect(
"deselect",
default_group_id
);
} }
} }
toggle_visible_etuds();
// referme le menu apres chaque choix:
$("#group_selector .btn-group").removeClass('open');
if ($("#group_ids_sel").hasClass("submit_on_change")) {
submit_group_selector();
}
} }
}
); toggle_visible_etuds();
// referme le menu apres chaque choix:
$("#group_selector .btn-group").removeClass("open");
if ($("#group_ids_sel").hasClass("submit_on_change")) {
submit_group_selector();
}
},
});
// initial setup // initial setup
toggle_visible_etuds(); toggle_visible_etuds();
@ -160,27 +199,27 @@ $().ready(function () {
// Trombinoscope // Trombinoscope
$().ready(function () { $().ready(function () {
var elems = $(".trombi-photo"); var elems = $(".trombi-photo");
for (var i = 0; i < elems.length; i++) { for (var i = 0; i < elems.length; i++) {
$(elems[i]).qtip( $(elems[i]).qtip({
{ content: {
content: { ajax: {
ajax: { url:
url: SCO_URL + "/etud_info_html?with_photo=0&etudid=" + get_etudid_from_elem(elems[i]) SCO_URL +
}, "/etud_info_html?with_photo=0&etudid=" +
text: "Loading..." get_etudid_from_elem(elems[i]),
}, },
position: { text: "Loading...",
at: "right", },
my: "left top" position: {
}, at: "right",
style: { my: "left top",
classes: 'qtip-etud' },
}, style: {
// utile pour debugguer le css: classes: "qtip-etud",
// hide: { event: 'unfocus' } },
} // utile pour debugguer le css:
); // hide: { event: 'unfocus' }
});
} }
}); });

View File

@ -3,8 +3,9 @@
{% block styles %} {% block styles %}
{{super()}} {{super()}}
<link href="{{scu.STATIC_DIR}}/libjs/tui.calendar/toastui-calendar.min.css" rel="stylesheet" type="text/css" /> <link rel="stylesheet" href="{{scu.STATIC_DIR}}/libjs/tui.calendar/toastui-calendar.min.css"/>
<link rel="stylesheet" href="{{ scu.STATIC_DIR }}/css/edt.css" type="text/css"> <link rel="stylesheet" href="{{scu.STATIC_DIR}}/libjs/bootstrap-multiselect-1.1.2/bootstrap-multiselect.min.css"/>
<link rel="stylesheet" href="{{scu.STATIC_DIR}}/css/edt.css">
{% endblock %} {% endblock %}
@ -13,6 +14,8 @@
<div class="tab-content"> <div class="tab-content">
<h2>Expérimental: emploi du temps</h2> <h2>Expérimental: emploi du temps</h2>
{{ form_groups_choice|safe }}
<div> <div>
<span id="menu-navi"> <span id="menu-navi">
<button type="button" class="btn btn-default btn-sm move-today" <button type="button" class="btn btn-default btn-sm move-today"
@ -28,12 +31,24 @@
</div> </div>
<div id="calendar" style="height: calc(100vh - 180px);"></div> <div id="calendar" style="height: calc(100vh - 180px);"></div>
<div class="help">
<ul>
<li>Les heures sont toujours affichées dans le fuseau horaire du serveur,
qui est en principe celui des étudiants.
</li>
<li>Si vous filtrez par groupe, les évènements dont le groupe n'est pas reconnu seront affichés.
</li>
</ul>
</div>
</div> </div>
{% endblock app_content %} {% endblock app_content %}
{% block scripts %} {% block scripts %}
{{ super() }} {{ super() }}
<script src="{{scu.STATIC_DIR}}/libjs/bootstrap-multiselect-1.1.2/bootstrap-multiselect.min.js"></script>
<script src="{{scu.STATIC_DIR}}/libjs/purl.js"></script>
<script src="{{scu.STATIC_DIR}}/libjs/tui.calendar/toastui-calendar.min.js"></script> <script src="{{scu.STATIC_DIR}}/libjs/tui.calendar/toastui-calendar.min.js"></script>
<script src="{{scu.STATIC_DIR}}/js/groups_view.js"></script>
<script> <script>
let hm_formatter = new Intl.DateTimeFormat('default', { let hm_formatter = new Intl.DateTimeFormat('default', {
hour: '2-digit', hour: '2-digit',
@ -92,7 +107,7 @@ document.addEventListener('DOMContentLoaded', function() {
const calendar = new Calendar(container, options); const calendar = new Calendar(container, options);
fetch(`${SCO_URL}/../api/formsemestre/{{formsemestre.id}}/edt`) fetch(`${SCO_URL}/../api/formsemestre/{{formsemestre.id}}/edt?{{groups_query_args|safe}}`)
.then(r=>{return r.json()}) .then(r=>{return r.json()})
.then(events=>{ .then(events=>{
if (typeof events == 'string') { if (typeof events == 'string') {

View File

@ -40,6 +40,7 @@ from app.decorators import (
from app.forms.formsemestre import change_formation, edit_modimpls_codes_apo from app.forms.formsemestre import change_formation, edit_modimpls_codes_apo
from app.models import Formation, FormSemestre, ScoDocSiteConfig from app.models import Formation, FormSemestre, ScoDocSiteConfig
from app.scodoc import sco_formations, sco_formation_versions from app.scodoc import sco_formations, sco_formation_versions
from app.scodoc import sco_groups_view
from app.scodoc.sco_permissions import Permission from app.scodoc.sco_permissions import Permission
from app.views import notes_bp as bp from app.views import notes_bp as bp
from app.views import ScoData from app.views import ScoData
@ -162,10 +163,23 @@ def formsemestre_edt(formsemestre_id: int):
hour_start = cfg.value.split(":")[0].lstrip(" 0") if cfg else "7" hour_start = cfg.value.split(":")[0].lstrip(" 0") if cfg else "7"
cfg = ScoDocSiteConfig.query.filter_by(name="assi_afternoon_time").first() cfg = ScoDocSiteConfig.query.filter_by(name="assi_afternoon_time").first()
hour_end = cfg.value.split(":")[0].lstrip(" 0") if cfg else "18" hour_end = cfg.value.split(":")[0].lstrip(" 0") if cfg else "18"
group_ids = request.args.getlist("group_ids", int)
groups_infos = sco_groups_view.DisplayedGroupsInfos(
group_ids=group_ids,
formsemestre_id=formsemestre_id,
empty_list_select_all=False,
)
return render_template( return render_template(
"formsemestre/edt.j2", "formsemestre/edt.j2",
formsemestre=formsemestre, formsemestre=formsemestre,
hour_start=hour_start, hour_start=hour_start,
hour_end=hour_end, hour_end=hour_end,
form_groups_choice=sco_groups_view.form_groups_choice(
groups_infos,
submit_on_change=True,
default_deselect_others=False,
with_deselect_butt=True,
),
groups_query_args=groups_infos.groups_query_args,
sco=ScoData(formsemestre=formsemestre), sco=ScoData(formsemestre=formsemestre),
) )