diff --git a/app/static/js/table_recap.js b/app/static/js/table_recap.js index 56d43e3d..11a5db4d 100644 --- a/app/static/js/table_recap.js +++ b/app/static/js/table_recap.js @@ -1,285 +1,311 @@ // Tableau recap notes $(function () { - $(function () { - if ($('table.table_recap').length == 0) { return; } + $(function () { + if ($("table.table_recap").length == 0) { + return; + } - let hidden_colums = [ - "etud_codes", "identite_detail", - "partition_aux", "partition_rangs", "admission", - "col_empty" - ]; - // Etat (tri des colonnes) de la table: + let hidden_colums = [ + "etud_codes", + "identite_detail", + "partition_aux", + "partition_rangs", + "admission", + "col_empty", + ]; + // Etat (tri des colonnes) de la table: - const url = new URL(document.URL); - const formsemestre_id = url.searchParams.get("formsemestre_id"); - const order_info_key = JSON.stringify([url.pathname, formsemestre_id]); - const etudids_key = JSON.stringify(["etudids", url.origin, formsemestre_id]); - const noms_key = JSON.stringify(["noms", url.origin, formsemestre_id]); - let order_info; - if (formsemestre_id) { - const x = localStorage.getItem(order_info_key); - if (x) { - try { - order_info = JSON.parse(x); - } catch (error) { - console.error(error); - } - } - } - - // Les colonnes visibles sont mémorisées, il faut initialiser l'état des boutons - function update_buttons_labels(dt) { - // chaque bouton controle une classe stockée dans le data-group du span - document.querySelectorAll("button.dt-button").forEach(but => { - let g_span = but.querySelector("span > span"); - if (g_span) { - let group = g_span.dataset["group"]; - if (group) { - // si le group (= la 1ere col.) est visible, but_on - if (dt.columns("." + group).visible()[0]) { - but.classList.add("but_on"); - but.classList.remove("but_off"); - } else { - but.classList.add("but_off"); - but.classList.remove("but_on"); - } - } - } - }); - } - - // Changement visibilité groupes colonnes (boutons) - function toggle_col_but_visibility(e, dt, node, config) { - let group = node.children()[0].firstChild.dataset.group; - toggle_col_group_visibility(dt, group, node.hasClass("but_on")); - } - function toggle_col_ident_visibility(e, dt, node, config) { - let onoff = node.hasClass("but_on"); - toggle_col_group_visibility(dt, "identite_detail", onoff); - toggle_col_group_visibility(dt, "identite_court", !onoff); - } - function toggle_col_ressources_visibility(e, dt, node, config) { - let onoff = node.hasClass("but_on"); - toggle_col_group_visibility(dt, "col_res", onoff); - toggle_col_group_visibility(dt, "col_ue_bonus", onoff); - toggle_col_group_visibility(dt, "col_malus", onoff); - } - function toggle_col_group_visibility(dt, group, onoff) { - if (onoff) { - dt.columns('.' + group).visible(false); - } else { - dt.columns('.' + group).visible(true); - } - update_buttons_labels(dt); - } - // Definition des boutons au dessus de la table: - let buttons = [ - { - extend: 'copyHtml5', - text: 'Copier', - exportOptions: { orthogonal: 'export' } - }, - { - extend: 'excelHtml5', - // footer: true, // ne fonctionne pas ? - exportOptions: { orthogonal: 'export' }, - title: document.querySelector('table.table_recap').dataset.filename - }, - { - // force affichage de toutes les colonnes - text: '', - action: function (e, dt, node, config) { - dt.columns().visible(true); - update_buttons_labels(dt); - } - }, - { - text: '🔄', - action: function (e, dt, node, config) { - localStorage.clear(); - console.log("cleared localStorage"); - location.reload(); - } - }, - { - text: 'Civilité', - action: toggle_col_ident_visibility, - }, - { - text: 'Groupes', - action: toggle_col_but_visibility, - }, - { - text: 'Rg', - action: toggle_col_but_visibility, - }, - ]; // fin des boutons communs à toutes les tables recap - - if ($('table.table_recap').hasClass("jury")) { - // Table JURY: - // avec ou sans codes enregistrés - buttons.push( - { - text: 'Codes jury', - action: toggle_col_but_visibility, - }); - if ($('table.table_recap').hasClass("apc")) { - // Boutons spécifiques à la table JURY BUT - buttons.push( - { - text: 'Compétences', - action: toggle_col_but_visibility, - }); - buttons.push( - { - text: 'RCUEs', - action: toggle_col_but_visibility, - }); - } - } else { - // BOUTONS SPECIFIQUES A LA TABLE RECAP NON JURY - buttons.push( - $('table.table_recap').hasClass("apc") ? - { - text: 'Ressources', - action: toggle_col_ressources_visibility, - } : { - name: "toggle_mod", - text: "Cacher les modules", - action: function (e, dt, node, config) { - let onoff = node.hasClass("but_on"); - toggle_col_group_visibility(dt, "col_mod:not(.col_empty)", onoff); - toggle_col_group_visibility(dt, "col_ue_bonus", onoff); - toggle_col_group_visibility(dt, "col_malus", onoff); - } - } - ); - if ($('table.table_recap').hasClass("apc")) { - buttons.push({ - text: 'SAÉs', - action: toggle_col_but_visibility, - }); - } - // S'il y a des colonnes vides: - if ($('table.table_recap td.col_empty').length > 0) { - buttons.push({ // modules vides - text: 'Vides', - action: toggle_col_but_visibility, - }); - } - // Boutons admission (pas en jury) - if (!$('table.table_recap').hasClass("jury")) { - buttons.push( - { - text: 'Admission', - action: toggle_col_but_visibility, - } - ); - } - } - // Boutons évaluations (si présentes) - if ($('table.table_recap').hasClass("with_evaluations")) { - buttons.push( - { - text: 'Évaluations', - action: toggle_col_but_visibility, - } - ); - } - - // ------------- LA TABLE --------- + const url = new URL(document.URL); + const formsemestre_id = url.searchParams.get("formsemestre_id"); + const order_info_key = JSON.stringify([url.pathname, formsemestre_id]); + const etudids_key = JSON.stringify([ + "etudids", + url.origin, + formsemestre_id, + ]); + const noms_key = JSON.stringify(["noms", url.origin, formsemestre_id]); + let order_info; + if (formsemestre_id) { + const x = localStorage.getItem(order_info_key); + if (x) { try { - let table = $('table.table_recap').DataTable( - { - paging: false, - searching: true, - info: false, - autoWidth: false, - fixedHeader: { - header: true, - footer: false - }, - orderCellsTop: true, // cellules ligne 1 pour tri - aaSorting: [], // Prevent initial sorting - colReorder: true, - stateSave: true, // enregistre état de la table (tris, ...) - "columnDefs": [ - { - // cache les codes, le détail de l'identité, les groupes, les colonnes admission et les vides - targets: hidden_colums, - visible: false, - }, - { - // Elimine les 0 à gauche pour les exports excel et les "copy" - targets: ["col_mod", "col_moy_gen", "col_moy_ue", "col_res", "col_sae", "evaluation", "col_rcue"], - render: function (data, type, row) { - return type === 'export' ? data.replace(/0(\d\..*)/, '$1') : data; - } - }, - { - // Elimine les "+"" pour les exports - targets: ["col_ue_bonus", "col_malus"], - render: function (data, type, row) { - return type === 'export' ? data.replace(/.*\+(\d?\d?\.\d\d).*/m, '$1').replace(/0(\d\..*)/, '$1') : data; - } - }, - { - // Elimine emoji warning sur UEs - targets: ["col_ues_validables"], - render: function (data, type, row) { - return type === 'export' ? data.replace(/(\d+\/\d+).*/, '$1') : data; - } - } - - ], - dom: 'Bfrtip', - buttons: buttons, - "drawCallback": function (settings) { - // permet de conserver l'ordre de tri des colonnes - let table = $('table.table_recap').DataTable(); - let order_info = JSON.stringify(table.order()); - if (formsemestre_id) { - localStorage.setItem(order_info_key, order_info); - } - let etudids = []; - document.querySelectorAll("td.identite_court").forEach(e => { - etudids.push(e.dataset.etudid); - }); - let noms = []; - document.querySelectorAll("td.identite_court").forEach(e => { - noms.push(e.dataset.nomprenom); - }); - localStorage.setItem(etudids_key, JSON.stringify(etudids)); - localStorage.setItem(noms_key, JSON.stringify(noms)); - }, - "order": order_info, - } - ); - update_buttons_labels(table); + order_info = JSON.parse(x); } catch (error) { - // l'erreur peut etre causee par un ancien storage: - localStorage.removeItem(etudids_key); - localStorage.removeItem(noms_key); - localStorage.removeItem(order_info_key); - location.reload(); + console.error(error); } - }); - $('table.table_recap tbody').on('click', 'tr', function () { - if ($(this).hasClass('selected')) { - $(this).removeClass('selected'); + } + } + + // Les colonnes visibles sont mémorisées, il faut initialiser l'état des boutons + function update_buttons_labels(dt) { + // chaque bouton controle une classe stockée dans le data-group du span + document.querySelectorAll("button.dt-button").forEach((but) => { + let g_span = but.querySelector("span > span"); + if (g_span) { + let group = g_span.dataset["group"]; + if (group) { + // si le group (= la 1ere col.) est visible, but_on + if (dt.columns("." + group).visible()[0]) { + but.classList.add("but_on"); + but.classList.remove("but_off"); + } else { + but.classList.add("but_off"); + but.classList.remove("but_on"); + } + } } - else { - $('table.table_recap tr.selected').removeClass('selected'); - $(this).addClass('selected'); - } - }); - // Pour montrer et surligner l'étudiant sélectionné: - $(function () { - let row_selected = document.querySelector(".row_selected"); - if (row_selected) { - row_selected.scrollIntoView(); - window.scrollBy(0, -125); - row_selected.classList.add("selected"); - } - }); + }); + } + + // Changement visibilité groupes colonnes (boutons) + function toggle_col_but_visibility(e, dt, node, config) { + let group = node.children()[0].firstChild.dataset.group; + toggle_col_group_visibility(dt, group, node.hasClass("but_on")); + } + function toggle_col_ident_visibility(e, dt, node, config) { + let onoff = node.hasClass("but_on"); + toggle_col_group_visibility(dt, "identite_detail", onoff); + toggle_col_group_visibility(dt, "identite_court", !onoff); + } + function toggle_col_ressources_visibility(e, dt, node, config) { + let onoff = node.hasClass("but_on"); + toggle_col_group_visibility(dt, "col_res", onoff); + toggle_col_group_visibility(dt, "col_ue_bonus", onoff); + toggle_col_group_visibility(dt, "col_malus", onoff); + } + function toggle_col_group_visibility(dt, group, onoff) { + if (onoff) { + dt.columns("." + group).visible(false); + } else { + dt.columns("." + group).visible(true); + } + update_buttons_labels(dt); + } + // Definition des boutons au dessus de la table: + let buttons = [ + { + extend: "copyHtml5", + text: "Copier", + exportOptions: { orthogonal: "export" }, + }, + { + extend: "excelHtml5", + // footer: true, // ne fonctionne pas ? + exportOptions: { orthogonal: "export" }, + title: document.querySelector("table.table_recap").dataset.filename, + }, + { + // force affichage de toutes les colonnes + text: '', + action: function (e, dt, node, config) { + dt.columns().visible(true); + update_buttons_labels(dt); + }, + }, + { + text: '🔄', + action: function (e, dt, node, config) { + localStorage.clear(); + console.log("cleared localStorage"); + location.reload(); + }, + }, + { + text: 'Civilité', + action: toggle_col_ident_visibility, + }, + { + text: 'Groupes', + action: toggle_col_but_visibility, + }, + { + text: 'Rg', + action: toggle_col_but_visibility, + }, + ]; // fin des boutons communs à toutes les tables recap + + if ($("table.table_recap").hasClass("jury")) { + // Table JURY: + // avec ou sans codes enregistrés + buttons.push({ + text: 'Codes jury', + action: toggle_col_but_visibility, + }); + if ($("table.table_recap").hasClass("apc")) { + // Boutons spécifiques à la table JURY BUT + buttons.push({ + text: 'Compétences', + action: toggle_col_but_visibility, + }); + buttons.push({ + text: 'RCUEs', + action: toggle_col_but_visibility, + }); + } + } else { + // BOUTONS SPECIFIQUES A LA TABLE RECAP NON JURY + buttons.push( + $("table.table_recap").hasClass("apc") + ? { + text: 'Ressources', + action: toggle_col_ressources_visibility, + } + : { + name: "toggle_mod", + text: "Cacher les modules", + action: function (e, dt, node, config) { + let onoff = node.hasClass("but_on"); + toggle_col_group_visibility( + dt, + "col_mod:not(.col_empty)", + onoff + ); + toggle_col_group_visibility(dt, "col_ue_bonus", onoff); + toggle_col_group_visibility(dt, "col_malus", onoff); + }, + } + ); + if ($("table.table_recap").hasClass("apc")) { + buttons.push({ + text: 'SAÉs', + action: toggle_col_but_visibility, + }); + } + // S'il y a des colonnes vides: + if ($("table.table_recap td.col_empty").length > 0) { + buttons.push({ + // modules vides + text: 'Vides', + action: toggle_col_but_visibility, + }); + } + // Boutons admission (pas en jury) + if (!$("table.table_recap").hasClass("jury")) { + buttons.push({ + text: 'Admission', + action: toggle_col_but_visibility, + }); + } + } + // Boutons évaluations (si présentes) + if ($("table.table_recap").hasClass("with_evaluations")) { + buttons.push({ + text: 'Évaluations', + action: toggle_col_but_visibility, + }); + } + + // ------------- LA TABLE --------- + try { + let table = $("table.table_recap").DataTable({ + paging: false, + searching: true, + info: false, + autoWidth: false, + fixedHeader: { + header: true, + footer: false, + }, + orderCellsTop: true, // cellules ligne 1 pour tri + aaSorting: [], // Prevent initial sorting + colReorder: true, + stateSave: true, // enregistre état de la table (tris, ...) + columnDefs: [ + { + // cache les codes, le détail de l'identité, les groupes, les colonnes admission et les vides + targets: hidden_colums, + visible: false, + }, + { + // Elimine les 0 à gauche pour les exports excel et les "copy" + targets: [ + "col_mod", + "col_moy_gen", + "col_moy_ue", + "col_res", + "col_sae", + "evaluation", + "col_rcue", + ], + render: function (data, type, row) { + return type === "export" ? data.replace(/0(\d\..*)/, "$1") : data; + }, + }, + { + // Elimine les "+"" pour les exports + targets: ["col_ue_bonus", "col_malus"], + render: function (data, type, row) { + return type === "export" + ? data + .replace(/.*\+(\d?\d?\.\d\d).*/m, "$1") + .replace(/0(\d\..*)/, "$1") + : data; + }, + }, + { + // Elimine emoji warning sur UEs + targets: ["col_ues_validables"], + render: function (data, type, row) { + return type === "export" + ? data.replace(/(\d+\/\d+).*/, "$1") + : data; + }, + }, + ], + dom: "Bfrtip", + buttons: buttons, + drawCallback: function (settings) { + // permet de conserver l'ordre de tri des colonnes + let table = $("table.table_recap").DataTable(); + let order_info = JSON.stringify(table.order()); + if (formsemestre_id) { + localStorage.setItem(order_info_key, order_info); + } + let etudids = []; + document.querySelectorAll("td.identite_court").forEach((e) => { + etudids.push(e.dataset.etudid); + }); + let noms = []; + document.querySelectorAll("td.identite_court").forEach((e) => { + noms.push(e.dataset.nomprenom); + }); + localStorage.setItem(etudids_key, JSON.stringify(etudids)); + localStorage.setItem(noms_key, JSON.stringify(noms)); + }, + order: order_info, + }); + update_buttons_labels(table); + } catch (error) { + // l'erreur peut etre causee par un ancien storage: + localStorage.removeItem(etudids_key); + localStorage.removeItem(noms_key); + localStorage.removeItem(order_info_key); + location.reload(); + } + }); + $("table.table_recap tbody").on("click", "tr", function () { + if ($(this).hasClass("selected")) { + $(this).removeClass("selected"); + } else { + $("table.table_recap tr.selected").removeClass("selected"); + $(this).addClass("selected"); + } + }); + // Pour montrer et surligner l'étudiant sélectionné: + $(function () { + let row_selected = document.querySelector(".row_selected"); + if (row_selected) { + row_selected.scrollIntoView(); + window.scrollBy(0, -125); + row_selected.classList.add("selected"); + } + }); + // Ajoute bulle aide sur colonne RCUEs + $(function () { + // explication colonne RCUEs + let th = document.querySelector( + "table.table_recap.apc th.col_rcues_validables" + ); + th.title = "RCUEs validables avec ces notes"; + }); });