Merge branch 'master' of https://scodoc.org/git/viennet/ScoDoc into sco96

This commit is contained in:
Emmanuel Viennet 2023-07-21 09:28:45 +02:00
commit a2d9e19122
12 changed files with 531 additions and 473 deletions

View File

@ -204,7 +204,8 @@ CODES_UE_VALIDES = CODES_UE_VALIDES_DE_DROIT | {ADJ, ADJR, ADSUP}
CODES_UE_CAPITALISANTS = {ADM} CODES_UE_CAPITALISANTS = {ADM}
"UE capitalisée" "UE capitalisée"
CODES_JURY_RCUE = CODES_JURY_UE # tous les codes d'UEs sont utilisables pour les RCUEs CODES_JURY_RCUE = {ADM, ADJ, ADSUP, CMP, AJ, ATJ, RAT, DEF, ABAN}
"codes de jury utilisables sur les RCUEs"
CODES_RCUE_VALIDES_DE_DROIT = {ADM, CMP} CODES_RCUE_VALIDES_DE_DROIT = {ADM, CMP}
CODES_RCUE_VALIDES = CODES_RCUE_VALIDES_DE_DROIT | {ADJ, ADSUP} CODES_RCUE_VALIDES = CODES_RCUE_VALIDES_DE_DROIT | {ADJ, ADSUP}
"Niveau RCUE validé" "Niveau RCUE validé"

View File

@ -913,9 +913,10 @@ def _make_listes_sem(formsemestre: FormSemestre, with_absences=True):
H.append('<p class="help indent">Aucun groupe peuplé dans cette partition') H.append('<p class="help indent">Aucun groupe peuplé dans cette partition')
if sco_groups.sco_permissions_check.can_change_groups(formsemestre.id): if sco_groups.sco_permissions_check.can_change_groups(formsemestre.id):
H.append( H.append(
f""" (<a href="{url_for("scolar.affect_groups", f""" (<a href="{url_for("scolar.partition_editor",
scodoc_dept=g.scodoc_dept, scodoc_dept=g.scodoc_dept,
partition_id=partition["partition_id"]) formsemestre_id=formsemestre.id,
edit_partition=1)
}" class="stdlink">créer</a>)""" }" class="stdlink">créer</a>)"""
) )
H.append("</p>") H.append("</p>")

View File

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

View File

@ -55,6 +55,7 @@ EKEY_APO = "nip"
EKEY_SCO = "code_nip" EKEY_SCO = "code_nip"
EKEY_NAME = "code NIP" EKEY_NAME = "code NIP"
# view: # view:
def formsemestre_synchro_etuds( def formsemestre_synchro_etuds(
formsemestre_id, formsemestre_id,
@ -270,11 +271,10 @@ def formsemestre_synchro_etuds(
if partitions: # il y a au moins une vraie partition if partitions: # il y a au moins une vraie partition
H.append( H.append(
f"""<li><a class="stdlink" href="{ f"""<li><a class="stdlink" href="{
url_for("scolar.affect_groups", url_for("scolar.partition_editor",
scodoc_dept=g.scodoc_dept, scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id)
partition_id=partitions[0]["partition_id"] }">Répartir les groupes de {partitions[0]["partition_name"]}</a></li>
)}">Répartir les groupes de {partitions[0]["partition_name"]}</a></li> """
"""
) )
H.append(footer) H.append(footer)
@ -407,6 +407,7 @@ def list_synch(sem, anneeapogee=None):
) )
# #
cnx = ndb.GetDBConnexion() cnx = ndb.GetDBConnexion()
# Tri listes # Tri listes
def set_to_sorted_list(etudset, etud_apo=False, is_inscrit=False): def set_to_sorted_list(etudset, etud_apo=False, is_inscrit=False):
def key2etud(key, etud_apo=False): def key2etud(key, etud_apo=False):

View File

@ -166,6 +166,7 @@ div.ue_validation_code div.code {
margin-left: 12px; margin-left: 12px;
} }
select.validation_rcue { select.validation_rcue {
color: black;
display: inline-block; display: inline-block;
margin-left: 32px; margin-left: 32px;
} }

View File

@ -1,10 +1,9 @@
/* -*- mode: javascript -*- /* -*- mode: javascript -*-
* *
* ScoDoc: Affectation des groupes de TD * ScoDoc: Affectation des groupes de TD
* re-ecriture utilisant jQuery de l'ancien code * OBSOLETE: Page ScoDoc 7 avec jQuery, remplacée par partition_editor
*/ */
/* --- Globals ---- */ /* --- Globals ---- */
var EtudColors = ["#E8EEF7", "#ffffff"]; // [ "#E8EEF7", "#E0ECFF", "#E5E6BE", "#F3EAE2", "#E3EAE1" ]; var EtudColors = ["#E8EEF7", "#ffffff"]; // [ "#E8EEF7", "#E0ECFF", "#E5E6BE", "#F3EAE2", "#E3EAE1" ];
var EtudColorsIdx = 0; var EtudColorsIdx = 0;
@ -16,442 +15,471 @@ var groups_unsaved = false;
var groups = new Object(); // Liste des groupes var groups = new Object(); // Liste des groupes
function loadGroupes() { function loadGroupes() {
$("#gmsg")[0].innerHTML = 'Chargement des groupes en cours...'; $("#gmsg")[0].innerHTML = "Chargement des groupes en cours...";
$("#gmsg")[0].style.display = "block"; $("#gmsg")[0].style.display = "block";
var partition_id = document.formGroup.partition_id.value; var partition_id = document.formGroup.partition_id.value;
$.get(SCO_URL + '/XMLgetGroupsInPartition', { partition_id: partition_id }) $.get(SCO_URL + "/XMLgetGroupsInPartition", {
.done( partition_id: partition_id,
function (data) { }).done(function (data) {
var nodes = data.getElementsByTagName('group'); var nodes = data.getElementsByTagName("group");
if (nodes) { if (nodes) {
var nbgroups = nodes.length; var nbgroups = nodes.length;
// put last group at first (etudiants sans groupes) // put last group at first (etudiants sans groupes)
if (nodes.length > 1 && nodes[nbgroups - 1].attributes.getNamedItem("group_id").value == '_none_') { if (
populateGroup(nodes[nodes.length - 1]); nodes.length > 1 &&
nbgroups -= 1; nodes[nbgroups - 1].attributes.getNamedItem("group_id").value ==
} "_none_"
// then standard groups ) {
for (var i = 0; i < nbgroups; i++) { populateGroup(nodes[nodes.length - 1]);
populateGroup(nodes[i]); nbgroups -= 1;
} }
} // then standard groups
$("#gmsg")[0].innerHTML = ''; for (var i = 0; i < nbgroups; i++) {
$("#gmsg")[0].style.display = "none"; populateGroup(nodes[i]);
updateginfo(); }
} }
) $("#gmsg")[0].innerHTML = "";
$("#gmsg")[0].style.display = "none";
updateginfo();
});
} }
function populateGroup(node) { function populateGroup(node) {
var group_id = node.attributes.getNamedItem("group_id").value; var group_id = node.attributes.getNamedItem("group_id").value;
var group_name = node.attributes.getNamedItem("group_name").value; var group_name = node.attributes.getNamedItem("group_name").value;
var groups_editable = Boolean(parseInt(node.attributes.getNamedItem("groups_editable").value)); var groups_editable = Boolean(
// CREE LA BOITE POUR CE GROUPE parseInt(node.attributes.getNamedItem("groups_editable").value)
if (group_id) { );
var gbox = new CGroupBox(group_id, group_name, groups_editable); // CREE LA BOITE POUR CE GROUPE
var etuds = node.getElementsByTagName('etud'); if (group_id) {
var x = ''; var gbox = new CGroupBox(group_id, group_name, groups_editable);
gbox.sorting = false; // disable to speedup var etuds = node.getElementsByTagName("etud");
EtudColorsIdx = 0; // repart de la premiere couleur var x = "";
for (var j = 0; j < etuds.length; j++) { gbox.sorting = false; // disable to speedup
var nom = etuds[j].attributes.getNamedItem("nom").value; EtudColorsIdx = 0; // repart de la premiere couleur
var prenom = etuds[j].attributes.getNamedItem("prenom").value; for (var j = 0; j < etuds.length; j++) {
var sexe = etuds[j].attributes.getNamedItem("sexe").value; var nom = etuds[j].attributes.getNamedItem("nom").value;
var etudid = etuds[j].attributes.getNamedItem("etudid").value; var prenom = etuds[j].attributes.getNamedItem("prenom").value;
var origin = etuds[j].attributes.getNamedItem("origin").value; var sexe = etuds[j].attributes.getNamedItem("sexe").value;
var etud = new CDraggableEtud(nom, prenom, sexe, origin, etudid); var etudid = etuds[j].attributes.getNamedItem("etudid").value;
gbox.createEtudInGroup(etud, group_id); var origin = etuds[j].attributes.getNamedItem("origin").value;
} var etud = new CDraggableEtud(nom, prenom, sexe, origin, etudid);
gbox.sorting = true; gbox.createEtudInGroup(etud, group_id);
gbox.updateTitle(); // sort
} }
gbox.sorting = true;
gbox.updateTitle(); // sort
}
} }
/* --- Boite pour un groupe --- */ /* --- Boite pour un groupe --- */
var groupBoxes = new Object(); // assoc group_id : groupBox var groupBoxes = new Object(); // assoc group_id : groupBox
var groupsToDelete = new Object(); // list of group_id to be supressed var groupsToDelete = new Object(); // list of group_id to be supressed
var CGroupBox = function (group_id, group_name, groups_editable) { var CGroupBox = function (group_id, group_name, groups_editable) {
group_id = $.trim(group_id); group_id = $.trim(group_id);
var regex = /^\w+$/; var regex = /^\w+$/;
if (!regex.test(group_id)) { if (!regex.test(group_id)) {
alert("Id de groupe invalide"); alert("Id de groupe invalide");
return; return;
} }
if (group_id in groups) { if (group_id in groups) {
alert("Le groupe " + group_id + " existe déjà !"); alert("Le groupe " + group_id + " existe déjà !");
return; return;
} }
groups[group_id] = 1; groups[group_id] = 1;
this.group_id = group_id; this.group_id = group_id;
this.group_name = group_name; this.group_name = group_name;
this.groups_editable = groups_editable; this.groups_editable = groups_editable;
this.etuds = new Object(); this.etuds = new Object();
this.nbetuds = 0; this.nbetuds = 0;
this.isNew = false; // true for newly user-created groups this.isNew = false; // true for newly user-created groups
this.sorting = true; // false to disable sorting this.sorting = true; // false to disable sorting
this.groupBox = document.createElement("div"); this.groupBox = document.createElement("div");
this.groupBox.className = "simpleDropPanel"; this.groupBox.className = "simpleDropPanel";
this.groupBox.id = group_id; this.groupBox.id = group_id;
var titleDiv = document.createElement("div"); var titleDiv = document.createElement("div");
titleDiv.className = "groupTitle0"; titleDiv.className = "groupTitle0";
titleDiv.appendChild(this.groupTitle()); titleDiv.appendChild(this.groupTitle());
this.groupBox.appendChild(titleDiv); this.groupBox.appendChild(titleDiv);
var gdiv = document.getElementById('groups'); var gdiv = document.getElementById("groups");
gdiv.appendChild(this.groupBox); gdiv.appendChild(this.groupBox);
this.updateTitle(); this.updateTitle();
$(this.groupBox).droppable( $(this.groupBox).droppable({
{ accept: ".box",
accept: ".box", activeClass: "activatedPanel",
activeClass: "activatedPanel", drop: function (event, ui) {
drop: function (event, ui) { // alert("drop on " + this.group_name);
// alert("drop on " + this.group_name); var etudid = ui.draggable[0].id;
var etudid = ui.draggable[0].id; var etud = ETUDS[etudid];
var etud = ETUDS[etudid]; var newGroupName = this.id;
var newGroupName = this.id; var oldGroupName = ETUD_GROUP[etudid];
var oldGroupName = ETUD_GROUP[etudid]; $(groupBoxes[newGroupName].groupBox).append(ui.draggable);
$(groupBoxes[newGroupName].groupBox).append(ui.draggable) ui.draggable[0].style.left = ""; // fix style (?)
ui.draggable[0].style.left = ""; // fix style (?) ui.draggable[0].style.top = "";
ui.draggable[0].style.top = ""; etud.changeGroup(oldGroupName, newGroupName);
etud.changeGroup(oldGroupName, newGroupName); etud.htmlElement.style.fontStyle = "italic"; // italic pour les etudiants deplaces
etud.htmlElement.style.fontStyle = 'italic'; // italic pour les etudiants deplaces },
} });
}); /* On peut s'amuser a deplacer tout un groupe (visuellement: pas droppable) */
/* On peut s'amuser a deplacer tout un groupe (visuellement: pas droppable) */ $(this.groupBox).draggable({
$(this.groupBox).draggable({ cursor: "move",
cursor: 'move', containment: "#groups",
containment: '#groups' });
});
groupBoxes[group_id] = this; // register groupBoxes[group_id] = this; // register
updateginfo(); updateginfo();
} };
$.extend(CGroupBox.prototype, { $.extend(CGroupBox.prototype, {
// menu for group title // menu for group title
groupTitle: function () { groupTitle: function () {
let menuSpan = document.createElement("span"); let menuSpan = document.createElement("span");
menuSpan.className = "barrenav"; menuSpan.className = "barrenav";
let h = "<table><tr><td><ul class=\"nav\"><li onmouseover=\"MenuDisplay(this)\" onmouseout=\"MenuHide(this)\"><a href=\"#\" class=\"menu custommenu\"><span id=\"titleSpan" + this.group_id + "\" class=\"groupTitle\">menu</span></a><ul>"; let h =
if (this.groups_editable && (this.group_id != '_none_')) { '<table><tr><td><ul class="nav"><li onmouseover="MenuDisplay(this)" onmouseout="MenuHide(this)"><a href="#" class="menu custommenu"><span id="titleSpan' +
h += "<li><a href=\"#\" onClick=\"suppressGroup('" + this.group_id + "');\">Supprimer</a></li>"; this.group_id +
h += "<li><a href=\"#\" onClick=\"renameGroup('" + this.group_id + "');\">Renommer</a></li>"; '" class="groupTitle">menu</span></a><ul>';
} if (this.groups_editable && this.group_id != "_none_") {
h += "</ul></li></ul></td></tr></table>"; h +=
menuSpan.innerHTML = h; '<li><a href="#" onClick="suppressGroup(\'' +
return menuSpan; this.group_id +
}, "');\">Supprimer</a></li>";
// add etud to group, attach to DOM h +=
createEtudInGroup: function (etud) { '<li><a href="#" onClick="renameGroup(\'' +
this.addEtudToGroup(etud); this.group_id +
this.groupBox.appendChild(etud.htmlElement); "');\">Renommer</a></li>";
},
// add existing etud to group (does not affect DOM)
addEtudToGroup: function (etud) {
etud.group_id = this.group_id;
this.etuds[etud.etudid] = etud;
this.nbetuds++;
ETUD_GROUP[etud.etudid] = this.group_id;
this.updateTitle();
},
// remove etud
removeEtud: function (etud) {
delete this.etuds[etud.etudid];
this.nbetuds--;
this.updateTitle();
},
// Update counter display
updateTitle: function () {
var tclass = '';
if (this.isNew) {
tclass = ' class="newgroup"'
}
var titleSpan = document.getElementById('titleSpan' + this.group_id);
if (this.group_id != '_none_')
titleSpan.innerHTML = '<span' + tclass + '>Groupe ' + this.group_name + ' (' + this.nbetuds + ')</span>';
else
titleSpan.innerHTML = '<span' + tclass + '>Etudiants sans groupe' + ' (' + this.nbetuds + ')</span>';
this.sortList(); // maintient toujours la liste triee
},
// Tri de la boite par nom
sortList: function () {
if (!this.sorting)
return;
var newRows = new Array();
for (var i = 1; i < this.groupBox.childNodes.length; i++) { // 1 car div titre
newRows[i - 1] = this.groupBox.childNodes[i];
}
var sortfn = function (a, b) {
// recupere les noms qui sont dans un span
var nom_a = a.childNodes[1].childNodes[0].nodeValue;
var nom_b = b.childNodes[1].childNodes[0].nodeValue;
// console.log( 'comp( %s, %s )', nom_a, nom_b );
if (nom_a == nom_b)
return 0;
if (nom_a < nom_b)
return -1;
return 1;
};
newRows.sort(sortfn);
for (var i = 0; i < newRows.length; i++) {
this.groupBox.appendChild(newRows[i]);
newRows[i].style.backgroundColor = EtudColors[EtudColorsIdx];
EtudColorsIdx = (EtudColorsIdx + 1) % EtudColors.length;
}
} }
h += "</ul></li></ul></td></tr></table>";
menuSpan.innerHTML = h;
return menuSpan;
},
// add etud to group, attach to DOM
createEtudInGroup: function (etud) {
this.addEtudToGroup(etud);
this.groupBox.appendChild(etud.htmlElement);
},
// add existing etud to group (does not affect DOM)
addEtudToGroup: function (etud) {
etud.group_id = this.group_id;
this.etuds[etud.etudid] = etud;
this.nbetuds++;
ETUD_GROUP[etud.etudid] = this.group_id;
this.updateTitle();
},
// remove etud
removeEtud: function (etud) {
delete this.etuds[etud.etudid];
this.nbetuds--;
this.updateTitle();
},
// Update counter display
updateTitle: function () {
var tclass = "";
if (this.isNew) {
tclass = ' class="newgroup"';
}
var titleSpan = document.getElementById("titleSpan" + this.group_id);
if (this.group_id != "_none_")
titleSpan.innerHTML =
"<span" +
tclass +
">Groupe " +
this.group_name +
" (" +
this.nbetuds +
")</span>";
else
titleSpan.innerHTML =
"<span" +
tclass +
">Etudiants sans groupe" +
" (" +
this.nbetuds +
")</span>";
this.sortList(); // maintient toujours la liste triee
},
// Tri de la boite par nom
sortList: function () {
if (!this.sorting) return;
var newRows = new Array();
for (var i = 1; i < this.groupBox.childNodes.length; i++) {
// 1 car div titre
newRows[i - 1] = this.groupBox.childNodes[i];
}
var sortfn = function (a, b) {
// recupere les noms qui sont dans un span
var nom_a = a.childNodes[1].childNodes[0].nodeValue;
var nom_b = b.childNodes[1].childNodes[0].nodeValue;
// console.log( 'comp( %s, %s )', nom_a, nom_b );
if (nom_a == nom_b) return 0;
if (nom_a < nom_b) return -1;
return 1;
};
newRows.sort(sortfn);
for (var i = 0; i < newRows.length; i++) {
this.groupBox.appendChild(newRows[i]);
newRows[i].style.backgroundColor = EtudColors[EtudColorsIdx];
EtudColorsIdx = (EtudColorsIdx + 1) % EtudColors.length;
}
},
}); });
function suppressGroup(group_id) { function suppressGroup(group_id) {
// 1- associate all members to group _none_ // 1- associate all members to group _none_
if (!groupBoxes['_none_']) { if (!groupBoxes["_none_"]) {
// create group _none_ // create group _none_
var gbox = new CGroupBox('_none_', 'Etudiants sans groupe', true); var gbox = new CGroupBox("_none_", "Etudiants sans groupe", true);
} }
var dst_group_id = groupBoxes['_none_'].group_id; var dst_group_id = groupBoxes["_none_"].group_id;
var src_box_etuds = groupBoxes[group_id].etuds; var src_box_etuds = groupBoxes[group_id].etuds;
for (var etudid in src_box_etuds) { for (var etudid in src_box_etuds) {
var etud = src_box_etuds[etudid]; var etud = src_box_etuds[etudid];
etud.changeGroup(group_id, dst_group_id); etud.changeGroup(group_id, dst_group_id);
groupBoxes['_none_'].groupBox.appendChild(etud.htmlElement); groupBoxes["_none_"].groupBox.appendChild(etud.htmlElement);
} }
groupBoxes['_none_'].updateTitle(); groupBoxes["_none_"].updateTitle();
// 2- add group to list of groups to be removed (unless it's a new group) // 2- add group to list of groups to be removed (unless it's a new group)
if (!groupBoxes[group_id].isNew) if (!groupBoxes[group_id].isNew) groupsToDelete[group_id] = true;
groupsToDelete[group_id] = true; // 3- delete objects and remove from DOM
// 3- delete objects and remove from DOM var div = document.getElementById(group_id);
var div = document.getElementById(group_id); div.remove();
div.remove(); delete groupBoxes[group_id];
delete groupBoxes[group_id]; groups_unsaved = true;
groups_unsaved = true; updateginfo();
updateginfo();
} }
function renameGroup(group_id) { function renameGroup(group_id) {
// 1-- save modifications // 1-- save modifications
if (groups_unsaved) { if (groups_unsaved) {
alert("Enregistrez ou annulez vos changement avant !"); alert("Enregistrez ou annulez vos changement avant !");
} else { } else {
// 2- form rename // 2- form rename
document.location = 'group_rename?group_id=' + group_id; document.location = "group_rename?group_id=" + group_id;
} }
} }
var createdGroupId = 0; var createdGroupId = 0;
function newGroupId() { function newGroupId() {
var gid; var gid;
do { do {
gid = 'NG' + createdGroupId.toString(); gid = "NG" + createdGroupId.toString();
createdGroupId += 1; createdGroupId += 1;
} while (gid in groupBoxes); } while (gid in groupBoxes);
return gid; return gid;
} }
// Creation d'un groupe // Creation d'un groupe
function createGroup() { function createGroup() {
var group_name = document.formGroup.groupName.value.trim(); var group_name = document.formGroup.groupName.value.trim();
if (!group_name) { if (!group_name) {
alert("Nom de groupe vide !"); alert("Nom de groupe vide !");
return false;
}
if (group_name.length >= 32) {
// SHORT_STR_LEN
alert("Nom de groupe trop long !");
return false;
}
// check name:
for (var group_id in groupBoxes) {
if (group_id != "extend") {
if (groupBoxes[group_id].group_name == group_name) {
alert("Nom de groupe déja existant !");
return false; return false;
}
} }
if (group_name.length >= 32) { // SHORT_STR_LEN }
alert("Nom de groupe trop long !"); var group_id = newGroupId();
return false; groups_unsaved = true;
} var gbox = new CGroupBox(group_id, group_name, true);
// check name: gbox.isNew = true;
for (var group_id in groupBoxes) { gbox.updateTitle();
if (group_id != 'extend') { return true;
if (groupBoxes[group_id].group_name == group_name) {
alert("Nom de groupe déja existant !");
return false;
}
}
}
var group_id = newGroupId();
groups_unsaved = true;
var gbox = new CGroupBox(group_id, group_name, true);
gbox.isNew = true;
gbox.updateTitle();
return true;
} }
/* --- Etudiant draggable --- */ /* --- Etudiant draggable --- */
var CDraggableEtud = function (nom, prenom, sexe, origin, etudid) { var CDraggableEtud = function (nom, prenom, sexe, origin, etudid) {
this.type = 'Custom'; this.type = "Custom";
this.name = etudid; this.name = etudid;
this.etudid = etudid; this.etudid = etudid;
this.nom = nom; this.nom = nom;
this.prenom = prenom; this.prenom = prenom;
this.sexe = sexe; this.sexe = sexe;
this.origin = origin; this.origin = origin;
this.createNode(); this.createNode();
ETUDS[etudid] = this; ETUDS[etudid] = this;
NbEtuds++; NbEtuds++;
} };
$.extend(CDraggableEtud.prototype, { $.extend(CDraggableEtud.prototype, {
repr: function () { repr: function () {
return this.sexe + ' ' + this.prenom + ' <span class="nom">' + this.nom + '</span> ' + '<b>' + this.origin + '</b>'; return (
}, this.sexe +
createNode: function () { " " +
// Create DOM element for student this.prenom +
var e = document.createElement("div"); ' <span class="nom">' +
this.htmlElement = e; this.nom +
e.className = "box"; "</span> " +
e.id = this.etudid; "<b>" +
// e.style.backgroundColor = EtudColors[EtudColorsIdx]; this.origin +
// EtudColorsIdx = (EtudColorsIdx + 1) % EtudColors.length; "</b>"
//var txtNode = document.createTextNode( this.repr() ); );
//e.appendChild(txtNode); },
e.innerHTML = this.repr(); createNode: function () {
// declare as draggable // Create DOM element for student
$(e).draggable({ var e = document.createElement("div");
cursor: 'move', this.htmlElement = e;
stack: '#groups div', e.className = "box";
containment: '#groups', e.id = this.etudid;
revert: 'invalid' // e.style.backgroundColor = EtudColors[EtudColorsIdx];
}); // EtudColorsIdx = (EtudColorsIdx + 1) % EtudColors.length;
}, //var txtNode = document.createTextNode( this.repr() );
endDrag: function () { //e.appendChild(txtNode);
var el = this.htmlElement; e.innerHTML = this.repr();
var p = el.parentNode; // declare as draggable
// alert("endDrag: [" + this.name +"] " + p.id ); $(e).draggable({
this.changeGroup(this.group_id, p.id); cursor: "move",
this.htmlElement.style.fontStyle = 'italic'; // italic pour les etudiants deplaces stack: "#groups div",
}, containment: "#groups",
// Move a student from a group to another revert: "invalid",
changeGroup: function (oldGroupName, newGroupName) { });
if (oldGroupName == newGroupName) { },
// drop on original group, just sort endDrag: function () {
groupBoxes[oldGroupName].updateTitle(); var el = this.htmlElement;
return; var p = el.parentNode;
} // alert("endDrag: [" + this.name +"] " + p.id );
var oldGroupBox = null; this.changeGroup(this.group_id, p.id);
if (oldGroupName) { this.htmlElement.style.fontStyle = "italic"; // italic pour les etudiants deplaces
oldGroupBox = groupBoxes[oldGroupName]; },
} // Move a student from a group to another
var newGroupBox = groupBoxes[newGroupName]; changeGroup: function (oldGroupName, newGroupName) {
newGroupBox.addEtudToGroup(this); if (oldGroupName == newGroupName) {
if (oldGroupBox) // drop on original group, just sort
oldGroupBox.removeEtud(this); groupBoxes[oldGroupName].updateTitle();
groups_unsaved = true; return;
updatesavedinfo();
} }
var oldGroupBox = null;
if (oldGroupName) {
oldGroupBox = groupBoxes[oldGroupName];
}
var newGroupBox = groupBoxes[newGroupName];
newGroupBox.addEtudToGroup(this);
if (oldGroupBox) oldGroupBox.removeEtud(this);
groups_unsaved = true;
updatesavedinfo();
},
}); });
/* --- Upload du resultat --- */ /* --- Upload du resultat --- */
function processResponse(value) { function processResponse(value) {
location.reload(); // necessaire pour reinitialiser les id des groupes créés location.reload(); // necessaire pour reinitialiser les id des groupes créés
} }
function handleError(msg) { function handleError(msg) {
alert('Error: ' + msg); alert("Error: " + msg);
console.log('Error: ' + msg); console.log("Error: " + msg);
} }
function submitGroups() { function submitGroups() {
var url = SCO_URL + '/setGroups'; var url = SCO_URL + "/setGroups";
// build post request body: groupname \n etudid; ... // build post request body: groupname \n etudid; ...
var groupsLists = ''; var groupsLists = "";
var groupsToCreate = ''; var groupsToCreate = "";
for (var group_id in groupBoxes) { for (var group_id in groupBoxes) {
if (group_id != 'extend') { // je ne sais pas ce dont il s'agit ??? if (group_id != "extend") {
if (group_id != '_none_') { // ne renvoie pas le groupe des sans-groupes // je ne sais pas ce dont il s'agit ???
groupBox = groupBoxes[group_id]; if (group_id != "_none_") {
if (groupBox.isNew) { // ne renvoie pas le groupe des sans-groupes
groupsToCreate += groupBox.group_name + ';'; groupBox = groupBoxes[group_id];
for (var etudid in groupBox.etuds) { if (groupBox.isNew) {
if (etudid != 'extend') groupsToCreate += groupBox.group_name + ";";
groupsToCreate += etudid + ';'; for (var etudid in groupBox.etuds) {
} if (etudid != "extend") groupsToCreate += etudid + ";";
groupsToCreate += '\n'; }
groupBox.isNew = false; // is no more new ! groupsToCreate += "\n";
} else { groupBox.isNew = false; // is no more new !
groupsLists += group_id + ';'; } else {
for (var etudid in groupBox.etuds) { groupsLists += group_id + ";";
if (etudid != 'extend') for (var etudid in groupBox.etuds) {
groupsLists += etudid + ';'; if (etudid != "extend") groupsLists += etudid + ";";
} }
groupsLists += '\n'; groupsLists += "\n";
}
}
} }
}
} }
var todel = ''; }
for (var group_id in groupsToDelete) { var todel = "";
todel += group_id + ';'; for (var group_id in groupsToDelete) {
} todel += group_id + ";";
groupsToDelete = new Object(); // empty }
var partition_id = document.formGroup.partition_id.value; groupsToDelete = new Object(); // empty
// Send to server var partition_id = document.formGroup.partition_id.value;
$.post(url, { // Send to server
groupsLists: groupsLists, $.post(url, {
partition_id: partition_id, groupsLists: groupsLists,
groupsToDelete: todel, partition_id: partition_id,
groupsToCreate: groupsToCreate groupsToDelete: todel,
groupsToCreate: groupsToCreate,
})
.done(function (data) {
processResponse(data);
}) })
.done(function (data) { .fail(function (xhr, status, error) {
processResponse(data); let msg = "inconnue";
}) if (xhr.responseXML.childNodes.length > 0) {
.fail(function (xhr, status, error) { msg = xhr.responseXML.childNodes[0].innerHTML;
let msg = "inconnue"; }
if (xhr.responseXML.childNodes.length > 0) { handleError("Erreur lors de l'enregistrement de groupes: " + msg);
msg = xhr.responseXML.childNodes[0].innerHTML; });
}
handleError("Erreur lors de l'enregistrement de groupes: " + msg);
});
} }
// Move to another partition (specified by menu) // Move to another partition (specified by menu)
function GotoAnother() { function GotoAnother() {
if (groups_unsaved) { if (groups_unsaved) {
alert("Enregistrez ou annulez vos changement avant !"); alert("Enregistrez ou annulez vos changement avant !");
} else } else
document.location = SCO_URL + '/affect_groups?partition_id=' + document.formGroup.other_partition_id.value; document.location =
SCO_URL +
"/affect_groups?partition_id=" +
document.formGroup.other_partition_id.value;
} }
// Boite information haut de page // Boite information haut de page
function updateginfo() { function updateginfo() {
var g = document.getElementById('ginfo'); var g = document.getElementById("ginfo");
var group_names = new Array(); var group_names = new Array();
for (var group_id in groupBoxes) { for (var group_id in groupBoxes) {
if ((group_id != 'extend') && (groupBoxes[group_id].group_name)) { if (group_id != "extend" && groupBoxes[group_id].group_name) {
group_names.push(groupBoxes[group_id].group_name); group_names.push(groupBoxes[group_id].group_name);
}
} }
g.innerHTML = '<b>Groupes définis: ' + group_names.join(', ') + '<br/>' }
+ "Nombre d'etudiants: " + NbEtuds + '</b>'; g.innerHTML =
"<b>Groupes définis: " +
group_names.join(", ") +
"<br/>" +
"Nombre d'etudiants: " +
NbEtuds +
"</b>";
updatesavedinfo(); updatesavedinfo();
} }
// Boite indiquant si modifications non enregistrees ou non // Boite indiquant si modifications non enregistrees ou non
function updatesavedinfo() { function updatesavedinfo() {
var g = document.getElementById('savedinfo'); var g = document.getElementById("savedinfo");
if (groups_unsaved) { if (groups_unsaved) {
g.innerHTML = 'modifications non enregistrées'; g.innerHTML = "modifications non enregistrées";
g.style.visibility = 'visible'; g.style.visibility = "visible";
} else { } else {
g.innerHTML = ''; g.innerHTML = "";
g.style.visibility = 'hidden'; g.style.visibility = "hidden";
} }
return true; return true;
} }
$(function () { $(function () {
loadGroupes(); loadGroupes();
}); });
/* debug:
var g = new CGroupBox('G0', 'Toto');
*/

View File

@ -22,14 +22,14 @@
{{tableau | safe}} {{tableau | safe}}
<script> <script>
const date_debut = "{{date_debut}}" const date_debut = "{{date_debut}}";
const date_fin = "{{date_fin}}" const date_fin = "{{date_fin}}";
const group_ids = "{{group_ids}}" const group_ids = "{{group_ids}}";
function stats() { function stats() {
const deb = document.querySelector('#stats_date_debut').value const deb = document.querySelector('#stats_date_debut').value;
const fin = document.querySelector('#stats_date_fin').value const fin = document.querySelector('#stats_date_fin').value;
location.href = `VisualisationAssiduitesGroupe?group_ids=${group_ids}&date_debut=${deb}&date_fin=${fin}` location.href = `VisualisationAssiduitesGroupe?group_ids=${group_ids}&date_debut=${deb}&date_fin=${fin}`;
} }
window.addEventListener('load', () => { window.addEventListener('load', () => {

View File

@ -18,6 +18,18 @@
<th>AMUE</th> <th>AMUE</th>
<th>Signification</th> <th>Signification</th>
</tr> </tr>
<tr>
<td>ABAN</td>
<td>{{codes["ABAN"]}}</td>
<td class="amue">ABAN</td>
<td>ABANdon constaté (sans lettre de démission)</td>
</tr>
<tr>
<td>ABL</td>
<td>{{codes["ABL"]}}</td>
<td class="amue">ABL</td>
<td>Année Blanche</td>
</tr>
<tr> <tr>
<td>ADM</td> <td>ADM</td>
<td>{{codes["ADM"]}}</td> <td>{{codes["ADM"]}}</td>
@ -31,10 +43,34 @@
<td>Admis par décision jury</td> <td>Admis par décision jury</td>
</tr> </tr>
<tr> <tr>
<td>PASD</td> <td>ATJ</td>
<td>{{codes["PASD"]}}</td> <td>{{codes["ATJ"]}}</td>
<td class="amue">PASD</td> <td class="amue">nd</td>
<td>Non admis, mais passage de droit</td> <td>Non validé pour une autre raison, voir règlement local</td>
</tr>
<tr>
<td>DEF</td>
<td>{{codes["DEF"]}}</td>
<td class="amue"></td>
<td>(défaillance) Non évalué par manque assiduité</td>
</tr>
<tr>
<td>DEM</td>
<td>{{codes["DEM"]}}</td>
<td class="amue"></td>
<td>Démission</td>
</tr>
<tr>
<td>EXCLU</td>
<td>{{codes["EXCLU"]}}</td>
<td class="amue">EXC</td>
<td>EXClusion, décision réservée à des décisions disciplinaires</td>
</tr>
<tr>
<td>NAR</td>
<td>{{codes["NAR"]}}</td>
<td class="amue">REO</td>
<td>Non admis, réorientation</td>
</tr> </tr>
<tr> <tr>
<td>PAS1NCI</td> <td>PAS1NCI</td>
@ -45,34 +81,10 @@
</td> </td>
</tr> </tr>
<tr> <tr>
<td>RED</td> <td>PASD</td>
<td>{{codes["RED"]}}</td> <td>{{codes["PASD"]}}</td>
<td class="amue">RED</td> <td class="amue">PASD</td>
<td>Ajourné, mais autorisé à redoubler</td> <td>Non admis, mais passage de droit</td>
</tr>
<tr>
<td>NAR</td>
<td>{{codes["NAR"]}}</td>
<td class="amue">REO</td>
<td>Non admis, réorientation</td>
</tr>
<tr>
<td>DEM</td>
<td>{{codes["DEM"]}}</td>
<td class="amue"></td>
<td>Démission</td>
</tr>
<tr>
<td>ABAN</td>
<td>{{codes["ABAN"]}}</td>
<td class="amue">ABAN</td>
<td>ABANdon constaté (sans lettre de démission)</td>
</tr>
<tr>
<td>ATJ</td>
<td>{{codes["ATJ"]}}</td>
<td class="amue">nd</td>
<td>Non validé pour une autre raison, voir règlement local</td>
</tr> </tr>
<tr> <tr>
<td>RAT</td> <td>RAT</td>
@ -81,22 +93,10 @@
<td>En attente dun rattrapage</td> <td>En attente dun rattrapage</td>
</tr> </tr>
<tr> <tr>
<td>EXCLU</td> <td>RED</td>
<td>{{codes["EXCLU"]}}</td> <td>{{codes["RED"]}}</td>
<td class="amue">EXC</td> <td class="amue">RED</td>
<td>EXClusion, décision réservée à des décisions disciplinaires</td> <td>Ajourné, mais autorisé à redoubler</td>
</tr>
<tr>
<td>DEF</td>
<td>{{codes["DEF"]}}</td>
<td class="amue"></td>
<td>(défaillance) Non évalué par manque assiduité</td>
</tr>
<tr>
<td>ABL</td>
<td>{{codes["ABL"]}}</td>
<td class="amue">ABL</td>
<td>Année Blanche</td>
</tr> </tr>
</table> </table>
</div> </div>
@ -113,16 +113,16 @@
<th>Signification</th> <th>Signification</th>
</tr> </tr>
<tr> <tr>
<th>ADM</td> <td>ABAN</td>
<td>{{codes["ADM"]}}</td> <td>{{codes["ABAN"]}}</td>
<th class="amue">VAL</td> <td class="amue"></td>
<th>Acquis</td> <td>Non évalué pour manque assiduité</td>
</tr> </tr>
<tr> <tr>
<td>CMP</td> <td>ADM</td>
<td>{{codes["CMP"]}}</td> <td>{{codes["ADM"]}}</td>
<td class="amue"></td> <td class="amue">VAL</td>
<td>Acquis par compensation annuelle</td> <td>Acquis</td>
</tr> </tr>
<tr> <tr>
<td>ADJ</td> <td>ADJ</td>
@ -149,10 +149,10 @@
<td>Non validé pour une autre raison, voir règlement local</td> <td>Non validé pour une autre raison, voir règlement local</td>
</tr> </tr>
<tr> <tr>
<td>RAT</td> <td>CMP</td>
<td>{{codes["RAT"]}}</td> <td>{{codes["CMP"]}}</td>
<td></td> <td class="amue"></td>
<td>En attente dun rattrapage</td> <td>Acquis par compensation annuelle</td>
</tr> </tr>
<tr> <tr>
<td>DEF</td> <td>DEF</td>
@ -161,10 +161,10 @@
<td>Défaillant</td> <td>Défaillant</td>
</tr> </tr>
<tr> <tr>
<td>ABAN</td> <td>RAT</td>
<td>{{codes["ABAN"]}}</td> <td>{{codes["RAT"]}}</td>
<td class="amue"></td> <td></td>
<td>Non évalué pour manque assiduité</td> <td>En attente dun rattrapage</td>
</tr> </tr>
</table> </table>
</div> </div>
@ -181,19 +181,18 @@
<th>AMUE</th> <th>AMUE</th>
<th>Signification</th> <th>Signification</th>
</tr> </tr>
<tr>
<td>ABAN</td>
<td>{{codes["ABAN"]}}</td>
<td class="amue">ABAN</td>
<td>Non évalué pour manque dassiduité Non présentation des notes de létudiant au jury</td>
</tr>
<tr> <tr>
<td>ADM</td> <td>ADM</td>
<td>{{codes["ADM"]}}</td> <td>{{codes["ADM"]}}</td>
<td class="amue">VAL</td> <td class="amue">VAL</td>
<td>Acquis (ECTS acquis, UE capitalisée)</td> <td>Acquis (ECTS acquis, UE capitalisée)</td>
</tr> </tr>
<tr>
<td>CMP</td>
<td>{{codes["CMP"]}}</td>
<td class="amue">COMP</td>
<td>Acquis par compensation UE compensée avec lUE de même compétence et de même année (ECTS acquis)
</td>
</tr>
<tr> <tr>
<td>ADJ</td> <td>ADJ</td>
<td>{{codes["ADJ"]}}</td> <td>{{codes["ADJ"]}}</td>
@ -225,10 +224,11 @@
<td>Non validé pour une autre raison, voir règlement local</td> <td>Non validé pour une autre raison, voir règlement local</td>
</tr> </tr>
<tr> <tr>
<td>RAT</td> <td>CMP</td>
<td>{{codes["RAT"]}}</td> <td>{{codes["CMP"]}}</td>
<td class="amue"></td> <td class="amue">COMP</td>
<td>En attente dun rattrapage</td> <td>Acquis par compensation UE compensée avec lUE de même compétence et de même année (ECTS acquis)
</td>
</tr> </tr>
<tr> <tr>
<td>DEF</td> <td>DEF</td>
@ -236,18 +236,18 @@
<td class="amue">ABAN</td> <td class="amue">ABAN</td>
<td>Défaillant Pas ou peu de notes par arrêt de la formation</td> <td>Défaillant Pas ou peu de notes par arrêt de la formation</td>
</tr> </tr>
<tr>
<td>ABAN</td>
<td>{{codes["ABAN"]}}</td>
<td class="amue">ABAN</td>
<td>Non évalué pour manque dassiduité Non présentation des notes de létudiant au jury</td>
</tr>
<tr> <tr>
<td>DEM</td> <td>DEM</td>
<td>{{codes["DEM"]}}</td> <td>{{codes["DEM"]}}</td>
<td class="amue"></td> <td class="amue"></td>
<td>Démission</td> <td>Démission</td>
</tr> </tr>
<tr>
<td>RAT</td>
<td>{{codes["RAT"]}}</td>
<td class="amue"></td>
<td>En attente dun rattrapage</td>
</tr>
<tr> <tr>
<td>UEBSL</td> <td>UEBSL</td>
<td>{{codes["UEBSL"]}}</td> <td>{{codes["UEBSL"]}}</td>

View File

@ -189,8 +189,19 @@ changé, enregistrer des validations "antérieures".
(c'est à dire présent dans tous les parcours de la spécialité). </p> (c'est à dire présent dans tous les parcours de la spécialité). </p>
{% if edit %} {% if edit %}
<p>Les validations sont enregistrées au fur et à mesure.</p> <p>Les validations sont enregistrées au fur et à mesure.
Attention, cette page permet une saisie "manuelle", la cohérence des décisions
n'est pas vérifiée (ni avec les notes, ni avec les décisions d'UEs, ni entre
années), et les <tt>ADSUP</tt> ne sont pas automatiquement générés. Privilégiez
lorsque c'est possible la saisie par
<a class="stdlink" href="{{url_for('notes.formsemestre_validation_but',
scodoc_dept=g.scodoc_dept,
etudid=sco.etud.id,
formsemestre_id=sco.formsemestre.id)
}}">la page de jury</a>.
</p>
{% endif %} {% endif %}
</div> </div>
<script> <script>

View File

@ -2,6 +2,13 @@
{{ sco_header|safe }} {{ sco_header|safe }}
<h2 class="formsemestre">Affectation aux groupes de {{ partition.partition_name }}</h2> <h2 class="formsemestre">Affectation aux groupes de {{ partition.partition_name }}</h2>
<p class="help">
👉💡 vous pourriez essayer <a href="{{
url_for('scolar.partition_editor',
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id)
}}" class="stdlink">le nouvel éditeur</a>
</p>
<p>Faites glisser les étudiants d'un groupe à l'autre. Les modifications ne <p>Faites glisser les étudiants d'un groupe à l'autre. Les modifications ne
sont enregistrées que lorsque vous cliquez sur le bouton "<em>Enregistrer ces groupes</em>". sont enregistrées que lorsque vous cliquez sur le bouton "<em>Enregistrer ces groupes</em>".
Vous pouvez créer de nouveaux groupes. Pour <em>supprimer</em> ou <em>renommer</em> Vous pouvez créer de nouveaux groupes. Pour <em>supprimer</em> ou <em>renommer</em>

View File

@ -59,6 +59,9 @@
document.querySelector("body").classList.add("loaded"); document.querySelector("body").classList.add("loaded");
document.querySelector('.wait').style.display = "none"; document.querySelector('.wait').style.display = "none";
{% if edit_partition %}
setEditMode();
{% endif %}
} }
function fetchData(request) { function fetchData(request) {

View File

@ -907,8 +907,12 @@ sco_publish(
@scodoc @scodoc
@permission_required(Permission.ScoView) @permission_required(Permission.ScoView)
@scodoc7func @scodoc7func
def partition_editor(formsemestre_id: int): def partition_editor(formsemestre_id: int, edit_partition=False):
"""Page édition groupes et partitions
Si edit_partition, se met en mode édition des partitions.
"""
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id) formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id)
edit_partition = bool(int(edit_partition)) if edit_partition else False
formsemestre.setup_parcours_groups() formsemestre.setup_parcours_groups()
H = [ H = [
html_sco_header.sco_header( html_sco_header.sco_header(
@ -928,6 +932,7 @@ def partition_editor(formsemestre_id: int):
read_only=not sco_groups.sco_permissions_check.can_change_groups( read_only=not sco_groups.sco_permissions_check.can_change_groups(
formsemestre_id formsemestre_id
), ),
edit_partition=edit_partition,
), ),
html_sco_header.sco_footer(), html_sco_header.sco_footer(),
] ]