// ==UserScript== // @name GAIA - Swissknife // @namespace https://gitlab.luigidacunto.com/consultant/gaia-swissknife // @updateURL https://luigidacunto.com/scripts/gaia-swissknife/tampermonkey-script/GAIA-Swissknife.user.js // @downloadURL https://luigidacunto.com/scripts/gaia-swissknife/tampermonkey-script/GAIA-Swissknife.user.js // @changelogURL https://luigidacunto.com/scripts/gaia-swissknife/tampermonkey-script/CHANGELOG.md // @author Luigi D'Acunto // @version 1.1.001 // @description Aggiunge funzionalità alle pagine di GAIA // @match https://gaia.cri.it/* // @require https://code.jquery.com/jquery-3.6.0.min.js // @require https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js // @resource DataTablesCSS https://cdn.datatables.net/1.13.6/css/jquery.dataTables.min.css // @grant GM_addStyle // @grant GM_getResourceText // @run-at document-idle // ==/UserScript== GM_addStyle(GM_getResourceText("DataTablesCSS")); (function($) { 'use strict'; console.log("GAIA Swissknife: Inizializzazione in corso!"); // Recupera la versione dallo script se disponibile, altrimenti usa un valore di fallback const currentVersion = (typeof GM_info !== 'undefined' && GM_info.script && GM_info.script.version) ? GM_info.script.version : 'x.x'; console.log(`GAIA Swissknife: Versione ${currentVersion}`); // Inizializza le funzionalità // Funzione per aggiungere il blocco di intestazione function ensureSwissknifeHeader() { console.log("GAIA Swissknife: Aggiungo intestazione GAIA Swissknife..."); if ($('#sezione').length > 0 && $('#gaia-swissknife-header').length === 0) { const headerHTML = `
`; $('#sezione').append(headerHTML); } } // Funzione per correggere i filtri della sidebar delle autorizzazioni function fixAutorizzazioniSidebarFilters() { const $ul = $("#sezione-2"); if (!$ul.length) return; const voci = {}; // Scansiona tutti i link $ul.find("li[role='presentation'] a").each(function () { const $a = $(this); const text = $a.clone().children().remove().end().text().trim(); const badge = parseInt($a.find(".badge").text().trim(), 10); const href = $a.attr("href"); if (!text || isNaN(badge)) return; if (!voci[text]) { voci[text] = { count: 0, href: href }; } voci[text].count += badge; }); $ul.find("li[role='presentation']").remove(); Object.entries(voci).forEach(([tipo, info]) => { const $li = $(`
  • ${tipo} ${info.count}
  • `); $ul.append($li); }); } // Funzione per ricostruire le celle con i dettagli delle qualifiche nel curriculum in modo pulito function rebuildCurriculumDetailCells() { $("td.piu-piccolo").each(function (cellIndex) { const $td = $(this); const rawNodes = Array.from(this.childNodes); const nodes = rawNodes.filter(n => { if (n.nodeType === 3) return n.nodeValue.trim() !== ""; return true; }); console.log(`\n📦 [Cella ${cellIndex + 1}] Analizzo ${nodes.length} nodi validi...`); const newContent = $('
    '); for (let i = 0; i < nodes.length; i++) { const node = nodes[i]; if (node.nodeType === 1 && node.tagName === "I") { const $icon = $(node).clone(); const $row = $('
    ').css({ "display": "flex", "align-items": "baseline", "gap": "5px", "line-height": "1.4", "margin-bottom": "2px" }); $icon.css({ "margin-right": "4px", "vertical-align": "middle" }); $row.append($icon); let content = null; let nextIndex = i + 1; while (nextIndex < nodes.length) { const nextNode = nodes[nextIndex]; if (nextNode.nodeType === 3) { const text = nextNode.nodeValue.trim(); if (text) { content = $('').text(text); if (text.length > 40) { content.css({ "display": "inline-block", "max-width": "200px", "white-space": "nowrap", "overflow": "hidden", "text-overflow": "ellipsis", "vertical-align": "middle" }).attr("title", text); } break; } } else if (nextNode.nodeType === 1) { const $el = $(nextNode); if (nextNode.tagName === "A") { let text = $el.text().trim(); if (!text) { const href = $el.attr("href") || ""; const fallback = href.split("/").pop(); text = fallback || "(documento)"; $el.text(text); } $el.css({ "display": "inline-block", "max-width": "200px", "white-space": "nowrap", "overflow": "hidden", "text-overflow": "ellipsis", "vertical-align": "middle", "color": "#a94442" }).attr("title", text); content = $el; break; } else if (nextNode.tagName === "SPAN") { const text = $el.text().trim(); if (text) { content = $el.clone(); content.css({ "display": "inline-block", "max-width": "200px", "white-space": "nowrap", "overflow": "hidden", "text-overflow": "ellipsis", "vertical-align": "middle" }).attr("title", text); break; } } } nextIndex++; } i = nextIndex - 1; if (content) { $row.append(content); newContent.append($row); console.log(`✅ Riga generata: ${$icon.attr("class")} + contenuto`); } else { console.warn(`⚠️ Riga ignorata: icona "${$icon.attr("class")}" senza contenuto`); } } } $td.empty().append(newContent); }); } // Funzione per applicare le correzioni di stile alle celle del curriculum function applyStyleFixes() { const url = window.location.href; // Correzione per le celle del curriculum if (url.match(/\/profilo\/\d+\/curriculum\//)) { console.log("GAIA Swissknife: Ricostruzione celle curriculum in modo ordinato..."); rebuildCurriculumDetailCells(); } // Correzione per menu laterale autorizzazioni if (url.includes("/autorizzazioni")) { console.log("GAIA Swissknife: Correzione menu laterale autorizzazioni..."); fixAutorizzazioniSidebarFilters(); } } // Funzione per aggiungere i pulsanti per settare gli esiti degli esami function addExamOutcomeButtons() { console.log("GAIA Swissknife: esecuzione di addExamOutcomeButtons() ..."); // Verifica che ci siano i select che gestiscono gli esiti if ($("select[id^='id_part_'][id$='-ammissione']").length > 0) { // Cerca il menu laterale (ul#sezione) dove inserire il blocco if ($('#sezione').length > 0) { console.log("GAIA Swissknife: Elementi trovati, aggiungo i pulsanti nel menu laterale..."); ensureSwissknifeHeader(); // Aggiungi i pulsanti per settare gli esiti const buttonsHTML = `
  • `; $('#sezione').append(buttonsHTML); // Evento per il pulsante "Tutti Ammessi/Esito Positivo x2" $('#button_set_ampp').click(() => { $("select[id^='id_part_'][id$='-ammissione']").val("AM").trigger('change'); $("select[id^='id_part_'][id$='-esito_parte_1']").val("P").trigger('change'); $("select[id^='id_part_'][id$='-esito_parte_2']").val("P").trigger('change'); console.log("GAIA Swissknife: Valori impostati - Ammessi, Positivo, Positivo"); }); // Evento per il pulsante "Ammessi, Positivo, Non previsto" $('#button_set_ampo').click(() => { $("select[id^='id_part_'][id$='-ammissione']").val("AM").trigger('change'); $("select[id^='id_part_'][id$='-esito_parte_1']").val("P").trigger('change'); $("select[id^='id_part_'][id$='-esito_parte_2']").val("O").trigger('change'); console.log("GAIA Swissknife: Valori impostati - Ammessi, Positivo, Non previsto"); }); // Evento per il pulsante "Ammessi, Non previsto, Positivo" $('#button_set_amop').click(() => { $("select[id^='id_part_'][id$='-ammissione']").val("AM").trigger('change'); $("select[id^='id_part_'][id$='-esito_parte_1']").val("O").trigger('change'); $("select[id^='id_part_'][id$='-esito_parte_2']").val("P").trigger('change'); console.log("GAIA Swissknife: Valori impostati - Ammessi, Non previsto, Positivo"); }); } else { console.log("GAIA Swissknife: Elemento ul#sezione non trovato."); } } else { console.log("GAIA Swissknife: Nessun elemento trovato, i pulsanti non verranno mostrati."); } } // Funzione per aggiungere il pulsante "Apri tutti i Curriculum" sezione iscritti di un corso function addOpenAllProfilesButton() { if (!window.location.href.includes('/iscritti/')) return; const openButton = $(` `); openButton.on('click', () => { const iframe = document.querySelector('iframe.embed-responsive-item'); if (!iframe) { alert("Impossibile trovare l'iframe con la lista."); console.log("GAIA Swissknife: iframe non trovato."); return; } // Verifica che il contenuto sia accessibile (same-origin) let iframeDoc; try { iframeDoc = iframe.contentDocument || iframe.contentWindow.document; } catch (err) { alert("Accesso all'iframe bloccato per motivi di sicurezza (cross-origin)."); console.error("GAIA Swissknife: accesso iframe negato.", err); return; } const $iframeLinks = $(iframeDoc).find("a[href^='/profilo/'][href*='?fpc']"); if ($iframeLinks.length === 0) { alert("Nessun profilo trovato all'interno dell'iframe."); console.log("GAIA Swissknife: Nessun link profilo nell'iframe."); return; } const profileLinks = $iframeLinks.map(function() { const href = $(this).attr('href'); const match = href.match(/\/profilo\/(\d+)\//); if (match && match[1]) { const id = match[1]; return `https://gaia.cri.it/profilo/${id}/curriculum/?us`; } return null; }).get().filter(Boolean); // Mostra le URL in console sempre console.log("GAIA Swissknife: Profili trovati:"); profileLinks.forEach(link => console.log(link)); if (!confirm(`Vuoi aprire ${profileLinks.length} profili in nuove schede?`)) return; profileLinks.forEach(link => { window.open(link, '_blank'); }); console.log(`GAIA Swissknife: Aperte ${profileLinks.length} schede da iframe.`); }); // Inserimento del pulsante nel menu laterale o in floating if ($('#sezione').length > 0) { ensureSwissknifeHeader(); $('#sezione').append( $('
  • ').append(openButton) ); } else { openButton.css({ position: 'fixed', top: '10px', right: '10px', zIndex: 9999 }).appendTo('body'); } } // Funzione per evidenziare le righe con "Respinto" function highlightRejectedCourses() { if (!window.location.href.match(/\/profilo\/\d+\/curriculum\//)) return; console.log("GAIA Swissknife: Avvio evidenziazione 'Respinto'…"); const $table = $(".table.table-striped"); if (!$table.length || !$.fn.DataTable.isDataTable($table)) return; const api = $table.DataTable(); function applyRejectionStyle() { // Prima puliamo tutte le righe (reset) api.rows().every(function () { const $row = $(this.node()); $row.css({ "box-shadow": "", "background-color": "" }); }); // Poi coloriamo solo le righe che contengono Respinto $table.find("span.text-danger").each(function () { const text = $(this).text().trim().toLowerCase(); if (text === "respinto") { const $row = $(this).closest("tr"); console.log("🟥 Evidenzio riga:", $row.index(), $row.find("p.grassetto").text().trim()); $row.css({ "box-shadow": "inset 8px 0 0 0 #dc3545", "background-color": "#fbe9ea" }); } }); } applyRejectionStyle(); $table.on("draw.dt", applyRejectionStyle); } // Funzione per aggiungere il tool per i profili delle richieste iscrizioni function addAuthorizationProfileTool() { if (!window.location.href.includes("/autorizzazioni/")) return; console.log("GAIA Swissknife: Attivo tool per gestione richieste iscrizione..."); const richieste = []; $(".panel.panel-default").each(function () { const $panel = $(this); const $corsoLink = $panel.find("a[href^='/aspirante/corso-base/']"); if ($corsoLink.length === 0) return; // blocco non relativo a richiesta corso const corsoText = $corsoLink.text().trim(); const match = corsoText.match(/([A-Z]{3,}\/\d{4}\/[A-Z]+(?: [A-Z]+)?\/\d+)/); if (!match) return; const codiceCorso = match[1]; const $profileLink = $panel.find("a[href^='/profilo/']").first(); const nome = $profileLink.text().trim(); const href = $profileLink.attr("href"); const idMatch = href.match(/\/profilo\/(\d+)\//); if (idMatch && idMatch[1]) { richieste.push({ codice: codiceCorso, nome, id: idMatch[1], $panel }); } }); const corsiUnici = [...new Set(richieste.map(r => r.codice))]; if (corsiUnici.length === 0) return; // === CREAZIONE MODALE === const $modal = $(`
    🛠 GAIA Swissknife – Richieste iscrizione
    📋 Richieste trovate:
    ${corsiUnici.map(c => { const count = richieste.filter(r => r.codice === c).length; const plural = count === 1 ? "richiesta" : "richieste"; return `• ${c} – ${count} ${plural}`; }).join("
    ")}
    `); $('body').append($modal); // Riduci / Espandi let isCollapsed = false; $('#gaia-auth-toggle').on('click', function (e) { isCollapsed = !isCollapsed; $('#gaia-auth-body').slideToggle(200); $(this).text(isCollapsed ? '+' : '−'); e.stopPropagation(); }); // Modal mobile let isDragging = false, dragOffsetX = 0, dragOffsetY = 0; $('#gaia-auth-header').on('mousedown', function (e) { const rect = document.getElementById('gaia-auth-tool').getBoundingClientRect(); isDragging = true; dragOffsetX = e.clientX - rect.left; dragOffsetY = e.clientY - rect.top; e.preventDefault(); }); $(document).on('mousemove', function (e) { if (!isDragging) return; const $modal = $('#gaia-auth-tool'); let left = e.clientX - dragOffsetX; let top = e.clientY - dragOffsetY; left = Math.max(0, Math.min(left, window.innerWidth - $modal.outerWidth())); top = Math.max(0, Math.min(top, window.innerHeight - $modal.outerHeight())); $modal.css({ left: left + 'px', top: top + 'px', right: 'auto' }); }).on('mouseup', () => isDragging = false); // Recupera profili $('#gaia-auth-btn').on('click', function () { const codiceSelezionato = $('#gaia-auth-select').val(); const $results = $('#gaia-auth-results').empty(); $('#gaia-auth-openall-container').hide(); if (!codiceSelezionato) { alert("Seleziona un codice corso."); return; } // Reset evidenziazione $(".panel.panel-default").css("background-color", ""); const trovati = richieste.filter(r => r.codice === codiceSelezionato); if (trovati.length === 0) { $results.append(`
    Nessun risultato trovato.
    `); return; } trovati.forEach(r => { r.$panel.css("background-color", "#d4edda"); const link = `https://gaia.cri.it/profilo/${r.id}/curriculum/?us`; $results.append(`
    ${r.nome}
    `); }); $('#gaia-auth-openall-container').show(); $('#gaia-auth-openall').off('click').on('click', function () { trovati.forEach(r => window.open(`https://gaia.cri.it/profilo/${r.id}/curriculum/?us`, '_blank')); }); }); } // Funzione per migliorare la tabella del curriculum function enhanceCurriculumTable() { if (!window.location.href.match(/\/profilo\/\d+\/curriculum\//)) return; const palette = { "Qualifica CRI": "#e6f0ff", // blu chiaro "Altra Qualifica": "#e6fff0", // verde chiaro "Esperienze Professionali": "#fff3e6", // arancione chiaro "Competenza Personale": "#e6faff", // ciano chiaro "Patente Civile": "#f0f0f0", // grigio chiaro "Patente CRI": "#f3e6ff" // lilla chiaro }; const $table = $(".table.table-striped"); const $tbody = $table.find("tbody"); if (!$table.length || !$tbody.length) return; console.log("GAIA Swissknife: DataTable + Colorazione permanente per tipologia..."); $table.DataTable({ paging: false, order: [[0, 'asc'], [1, 'asc']], columnDefs: [ { orderable: false, targets: 3 } ], language: { search: "Filtra qualifiche:", zeroRecords: "Nessuna qualifica trovata", info: "Mostrate _TOTAL_ qualifiche", infoEmpty: "Nessuna qualifica disponibile", infoFiltered: "(filtrate da _MAX_ totali)" } }); function applyColoring() { const tableApi = $table.DataTable(); tableApi.rows().every(function () { const $row = $(this.node()); const $tipoCell = $row.find("td").eq(0); const tipo = $tipoCell.text().trim(); if (palette[tipo]) { $tipoCell.css("background-color", palette[tipo]); } }); } // Applica le correzioni le colorazioni dei tipi di qualifica in lista applyColoring(); } $(document).ready(() => { applyStyleFixes(); addExamOutcomeButtons(); addOpenAllProfilesButton(); addAuthorizationProfileTool(); enhanceCurriculumTable(); highlightRejectedCourses(); console.log("GAIA Swissknife: Funzioni caricate con successo!"); }); })(jQuery.noConflict(true)); // ==CHANGELOG== // v1.0.0 - Versione stabile, con: // - DataTable integrata nella tabella curriculum // - Evidenziazione "Respinto" // - Correzioni grafiche file/link // - Gestione richieste iscrizioni con modale mobile // - Funzioni esiti massivi su termina corso // v1.0.1 - Fix: // - Modificata regex per il matching dei codici corso, compatibile con i codici che contengono spazi // ==/CHANGELOG==