Aggiorna la versione a 1.1.009 e aggiunge nuove funzionalità: pulsante per copiare il catalogo corsi in JSON, tool per la selezione della sede preferita, e miglioramenti nell'ordinamento dei pulsanti nella sidebar.
This commit is contained in:
parent
d23bee3a33
commit
8d88454abe
2 changed files with 285 additions and 40 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -1,2 +1,4 @@
|
||||||
_ignored
|
_ignored
|
||||||
.venv
|
.venv
|
||||||
|
.playwright-mcp
|
||||||
|
.vscode
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
// @downloadURL 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
|
// @changelogURL https://luigidacunto.com/scripts/gaia-swissknife/tampermonkey-script/CHANGELOG.md
|
||||||
// @author Luigi D'Acunto
|
// @author Luigi D'Acunto
|
||||||
// @version 1.1.006
|
// @version 1.1.009
|
||||||
// @description Aggiunge funzionalità alle pagine di GAIA
|
// @description Aggiunge funzionalità alle pagine di GAIA
|
||||||
// @match https://gaia.cri.it/*
|
// @match https://gaia.cri.it/*
|
||||||
// @require https://code.jquery.com/jquery-3.6.0.min.js
|
// @require https://code.jquery.com/jquery-3.6.0.min.js
|
||||||
|
|
@ -13,6 +13,8 @@
|
||||||
// @resource DataTablesCSS https://cdn.datatables.net/1.13.6/css/jquery.dataTables.min.css
|
// @resource DataTablesCSS https://cdn.datatables.net/1.13.6/css/jquery.dataTables.min.css
|
||||||
// @grant GM_addStyle
|
// @grant GM_addStyle
|
||||||
// @grant GM_getResourceText
|
// @grant GM_getResourceText
|
||||||
|
// @grant GM_getValue
|
||||||
|
// @grant GM_setValue
|
||||||
// @run-at document-idle
|
// @run-at document-idle
|
||||||
// ==/UserScript==
|
// ==/UserScript==
|
||||||
|
|
||||||
|
|
@ -29,18 +31,21 @@ GM_addStyle(GM_getResourceText("DataTablesCSS"));
|
||||||
|
|
||||||
// Inizializza le funzionalità
|
// Inizializza le funzionalità
|
||||||
|
|
||||||
// Funzione per aggiungere il blocco di intestazione
|
// Funzione per aggiungere il blocco di intestazione in cima alla sidebar
|
||||||
function ensureSwissknifeHeader() {
|
function ensureSwissknifeHeader() {
|
||||||
console.log("GAIA Swissknife: Aggiungo intestazione GAIA Swissknife...");
|
if ($('#sezione').length === 0 || $('#gaia-swissknife-header').length > 0) return;
|
||||||
if ($('#sezione').length > 0 && $('#gaia-swissknife-header').length === 0) {
|
console.log("GAIA Swissknife: Aggiungo intestazione GAIA Swissknife in cima...");
|
||||||
const headerHTML = `
|
const $header = $(`<li id="gaia-swissknife-header" class="dropdown-header grassetto piu-grande">GAIA Swissknife v${currentVersion}</li>`);
|
||||||
<hr>
|
const $divider = $('<hr id="gaia-swissknife-divider">');
|
||||||
<li id="gaia-swissknife-header" class="dropdown-header grassetto piu-grande">
|
// Prepend: header prima, poi divider — risultato: [header][divider][voci esistenti]
|
||||||
GAIA Swissknife v${currentVersion}
|
// I pulsanti vengono inseriti tra header e divider
|
||||||
</li>
|
$('#sezione').prepend($divider).prepend($header);
|
||||||
`;
|
}
|
||||||
$('#sezione').append(headerHTML);
|
|
||||||
}
|
// Helper: inserisce un <li> con il pulsante tra l'header Swissknife e il divider
|
||||||
|
function appendToSwissknifeSection($li) {
|
||||||
|
ensureSwissknifeHeader();
|
||||||
|
$('#gaia-swissknife-divider').before($li);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Funzione per correggere i filtri della sidebar delle autorizzazioni
|
// Funzione per correggere i filtri della sidebar delle autorizzazioni
|
||||||
|
|
@ -231,26 +236,18 @@ GM_addStyle(GM_getResourceText("DataTablesCSS"));
|
||||||
if ($('#sezione').length > 0) {
|
if ($('#sezione').length > 0) {
|
||||||
console.log("GAIA Swissknife: Elementi trovati, aggiungo i pulsanti nel menu laterale...");
|
console.log("GAIA Swissknife: Elementi trovati, aggiungo i pulsanti nel menu laterale...");
|
||||||
|
|
||||||
ensureSwissknifeHeader();
|
|
||||||
// Aggiungi i pulsanti per settare gli esiti
|
// Aggiungi i pulsanti per settare gli esiti
|
||||||
const buttonsHTML = `
|
[
|
||||||
<li role="presentation">
|
{ id: 'button_set_ampp', label: 'Ammessi, Positivo, Positivo', color: '#007BFF' },
|
||||||
<button id="button_set_ampp" style="margin: 5px; padding: 8px; width: 97%; background-color: #007BFF; color: #FFF; border: none; border-radius: 4px; cursor: pointer;">
|
{ id: 'button_set_ampo', label: 'Ammessi, Positivo, Non previsto', color: '#28a745' },
|
||||||
Ammessi, Positivo, Positivo
|
{ id: 'button_set_amop', label: 'Ammessi, Non previsto, Positivo', color: 'rgb(167, 40, 99)' }
|
||||||
</button>
|
].forEach(({ id, label, color }) => {
|
||||||
</li>
|
appendToSwissknifeSection(
|
||||||
<li role="presentation">
|
$('<li role="presentation"></li>').append(
|
||||||
<button id="button_set_ampo" style="margin: 5px; padding: 8px; width: 97%; background-color: #28a745; color: #FFF; border: none; border-radius: 4px; cursor: pointer;">
|
$(`<button id="${id}" type="button" style="margin:5px;padding:8px;width:97%;background-color:${color};color:#FFF;border:none;border-radius:4px;cursor:pointer;">${label}</button>`)
|
||||||
Ammessi, Positivo, Non previsto
|
)
|
||||||
</button>
|
);
|
||||||
</li>
|
});
|
||||||
<li role="presentation">
|
|
||||||
<button id="button_set_amop" style="margin: 5px; padding: 8px; width: 97%; background-color:rgb(167, 40, 99); color: #FFF; border: none; border-radius: 4px; cursor: pointer;">
|
|
||||||
Ammessi, Non previsto, Positivo
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
`;
|
|
||||||
$('#sezione').append(buttonsHTML);
|
|
||||||
|
|
||||||
// Evento per il pulsante "Tutti Ammessi/Esito Positivo x2"
|
// Evento per il pulsante "Tutti Ammessi/Esito Positivo x2"
|
||||||
$('#button_set_ampp').click(() => {
|
$('#button_set_ampp').click(() => {
|
||||||
|
|
@ -344,9 +341,7 @@ GM_addStyle(GM_getResourceText("DataTablesCSS"));
|
||||||
|
|
||||||
// Inserimento del pulsante nel menu laterale o in floating
|
// Inserimento del pulsante nel menu laterale o in floating
|
||||||
if ($('#sezione').length > 0) {
|
if ($('#sezione').length > 0) {
|
||||||
ensureSwissknifeHeader();
|
appendToSwissknifeSection(
|
||||||
|
|
||||||
$('#sezione').append(
|
|
||||||
$('<li role="presentation"></li>').append(openButton)
|
$('<li role="presentation"></li>').append(openButton)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -585,6 +580,240 @@ GM_addStyle(GM_getResourceText("DataTablesCSS"));
|
||||||
applyColoring();
|
applyColoring();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Funzione per la selezione rapida del comitato preferito (persistente cross-sessione)
|
||||||
|
function addSediPreferitaTool() {
|
||||||
|
if ($('table tbody input[name="sedi"]').length === 0) return;
|
||||||
|
|
||||||
|
console.log("GAIA Swissknife: Aggiungo tool selezione sede preferita...");
|
||||||
|
|
||||||
|
// Costruisce la mappa di tutte le sedi dalla tabella
|
||||||
|
function buildSediMap() {
|
||||||
|
const map = [];
|
||||||
|
document.querySelectorAll('table tbody tr').forEach(row => {
|
||||||
|
const cb = row.querySelector('input[name="sedi"]');
|
||||||
|
const nameTd = row.querySelector('td.grassetto');
|
||||||
|
if (!cb || !nameTd) return;
|
||||||
|
map.push({
|
||||||
|
value: cb.value,
|
||||||
|
label: nameTd.innerText.trim(),
|
||||||
|
numCells: row.querySelectorAll('td').length
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sediMap = buildSediMap();
|
||||||
|
const savedValue = GM_getValue('preferred_sede_value', '');
|
||||||
|
|
||||||
|
// Select con indentazione visiva per la gerarchia
|
||||||
|
const $select = $('<select id="gaia-preferred-sede-select"></select>').css({
|
||||||
|
width: '100%', padding: '4px', margin: '4px 5px 4px 5px',
|
||||||
|
fontSize: '12px', boxSizing: 'border-box', width: 'calc(100% - 10px)'
|
||||||
|
});
|
||||||
|
$select.append('<option value="">-- Comitato preferito --</option>');
|
||||||
|
sediMap.forEach(({ value, label, numCells }) => {
|
||||||
|
const prefix = numCells === 4 ? '' : numCells === 5 ? '\u00a0\u00a0\u00a0' : '\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0';
|
||||||
|
const $opt = $(`<option value="${value}">${prefix}${label}</option>`);
|
||||||
|
if (value === savedValue) $opt.prop('selected', true);
|
||||||
|
$select.append($opt);
|
||||||
|
});
|
||||||
|
|
||||||
|
$select.on('change', function () {
|
||||||
|
GM_setValue('preferred_sede_value', $(this).val());
|
||||||
|
});
|
||||||
|
|
||||||
|
// Pulsante: seleziona solo il preferito (+ figli se è Regionale o Locale)
|
||||||
|
const $btnSolo = $('<button type="button" style="margin:2px 5px;padding:6px;width:calc(100% - 10px);background-color:#e67e00;color:#FFF;border:none;border-radius:4px;cursor:pointer;font-size:12px;">Solo preferito</button>');
|
||||||
|
$btnSolo.on('click', function () {
|
||||||
|
const val = $select.val();
|
||||||
|
if (!val) { alert('Seleziona prima un comitato preferito.'); return; }
|
||||||
|
|
||||||
|
$('input[name="sedi"]').prop('checked', false);
|
||||||
|
|
||||||
|
const idx = sediMap.findIndex(s => s.value === val);
|
||||||
|
if (idx === -1) return;
|
||||||
|
|
||||||
|
const selected = sediMap[idx];
|
||||||
|
$(`#c_${selected.value}`).prop('checked', true);
|
||||||
|
|
||||||
|
// Se è Regionale (4) o Locale (5), seleziona anche tutti i figli
|
||||||
|
if (selected.numCells <= 5) {
|
||||||
|
for (let i = idx + 1; i < sediMap.length; i++) {
|
||||||
|
if (sediMap[i].numCells <= selected.numCells) break;
|
||||||
|
$(`#c_${sediMap[i].value}`).prop('checked', true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`GAIA Swissknife: Selezionato solo "${selected.label}" e figli.`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Pulsante: seleziona tutto
|
||||||
|
const $btnAll = $('<button type="button" style="margin:2px 5px 6px 5px;padding:6px;width:calc(100% - 10px);background-color:#6c757d;color:#FFF;border:none;border-radius:4px;cursor:pointer;font-size:12px;">Seleziona tutto</button>');
|
||||||
|
$btnAll.on('click', function () {
|
||||||
|
$('input[name="sedi"]').prop('checked', true);
|
||||||
|
console.log('GAIA Swissknife: Tutte le sedi selezionate.');
|
||||||
|
});
|
||||||
|
|
||||||
|
appendToSwissknifeSection(
|
||||||
|
$('<li role="presentation"></li>').append($select, $btnSolo, $btnAll)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Funzione per copiare il catalogo corsi in clipboard come JSON
|
||||||
|
function addCopyCatalogButton() {
|
||||||
|
if (!window.location.href.includes('/courses/catalog')) return;
|
||||||
|
if (!$('.corso-nome').length) return;
|
||||||
|
|
||||||
|
console.log("GAIA Swissknife: Aggiungo pulsante copia catalogo corsi...");
|
||||||
|
|
||||||
|
function extractCatalogo() {
|
||||||
|
const main = document.querySelector('.col-md-9');
|
||||||
|
if (!main) return [];
|
||||||
|
const results = [];
|
||||||
|
let currentTipo = '';
|
||||||
|
for (const el of [...main.children]) {
|
||||||
|
if (el.classList.contains('area-nome')) {
|
||||||
|
currentTipo = el.textContent.trim();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (el.classList.contains('area-levels') && currentTipo) {
|
||||||
|
let currentObiettivo = '';
|
||||||
|
for (const child of [...el.children]) {
|
||||||
|
if (child.classList.contains('area-nome')) {
|
||||||
|
currentObiettivo = child.textContent.trim();
|
||||||
|
} else if (child.classList.contains('area-levels') && currentObiettivo) {
|
||||||
|
let currentLivello = '';
|
||||||
|
for (const inner of [...child.children]) {
|
||||||
|
if (inner.tagName === 'H4') {
|
||||||
|
currentLivello = inner.textContent.trim();
|
||||||
|
} else if (inner.tagName === 'SECTION') {
|
||||||
|
const corsoNome = inner.querySelector('.corso-nome');
|
||||||
|
if (!corsoNome) continue;
|
||||||
|
const codice = corsoNome.querySelector('strong')?.textContent.trim() || '';
|
||||||
|
const nome = corsoNome.textContent.trim().replace(/\s*\([^)]*\)\s*$/, '').trim();
|
||||||
|
const scheda_pdf = inner.querySelector('.corso-scheda-completa a')?.href || null;
|
||||||
|
results.push({ nome, codice, livello: currentLivello, tipo: currentTipo, obiettivo: currentObiettivo, scheda_pdf });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
const $btn = $('<button type="button" style="margin: 5px; padding: 8px; width: 97%; background-color: #c0504d; color: #FFF; border: none; border-radius: 4px; cursor: pointer;">Copia catalogo corsi (JSON)</button>');
|
||||||
|
|
||||||
|
$btn.on('click', function () {
|
||||||
|
const catalogo = extractCatalogo();
|
||||||
|
if (!catalogo.length) { alert('Nessun corso trovato.'); return; }
|
||||||
|
|
||||||
|
navigator.clipboard.writeText(JSON.stringify(catalogo, null, 2)).then(() => {
|
||||||
|
console.log(`GAIA Swissknife: Catalogo copiato — ${catalogo.length} corsi.`);
|
||||||
|
const orig = $(this).text();
|
||||||
|
$(this).text(`✓ Copiato! (${catalogo.length} corsi)`).css('background-color', '#28a745');
|
||||||
|
setTimeout(() => $(this).text(orig).css('background-color', '#c0504d'), 3000);
|
||||||
|
}).catch(err => {
|
||||||
|
console.error('GAIA Swissknife: Errore clipboard:', err);
|
||||||
|
alert('Errore durante la copia in clipboard.');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if ($('#sezione').length > 0) {
|
||||||
|
appendToSwissknifeSection($('<li role="presentation"></li>').append($btn));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Funzione per estrarre la gerarchia sedi e copiarla in clipboard come JSON
|
||||||
|
function addCopyStructureButton() {
|
||||||
|
if (!window.location.href.includes('/us/elenchi/volontari/')) return;
|
||||||
|
|
||||||
|
// Il pulsante ha senso solo quando la tabella sedi è visibile (non nella vista risultati con iframe)
|
||||||
|
if ($('table tbody tr').length === 0) return;
|
||||||
|
|
||||||
|
console.log("GAIA Swissknife: Aggiungo pulsante copia struttura sedi...");
|
||||||
|
|
||||||
|
function extractStructure() {
|
||||||
|
const rows = document.querySelectorAll('table tbody tr');
|
||||||
|
const regionali = [];
|
||||||
|
let currentRegionale = null;
|
||||||
|
let currentLocale = null;
|
||||||
|
|
||||||
|
rows.forEach(row => {
|
||||||
|
const cells = row.querySelectorAll('td');
|
||||||
|
const numCells = cells.length;
|
||||||
|
|
||||||
|
// Il nome è sempre nella cella con classe "grassetto"
|
||||||
|
let nome = '';
|
||||||
|
cells.forEach(td => {
|
||||||
|
if (td.className.trim() === 'grassetto') {
|
||||||
|
nome = td.innerText.trim();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!nome) return;
|
||||||
|
|
||||||
|
if (numCells === 4) {
|
||||||
|
// Comitato Regionale
|
||||||
|
currentRegionale = { nome, comitati_locali: [] };
|
||||||
|
regionali.push(currentRegionale);
|
||||||
|
currentLocale = null;
|
||||||
|
} else if (numCells === 5) {
|
||||||
|
// Comitato Locale
|
||||||
|
currentLocale = { nome, sottosedi: [] };
|
||||||
|
if (currentRegionale) {
|
||||||
|
currentRegionale.comitati_locali.push(currentLocale);
|
||||||
|
}
|
||||||
|
} else if (numCells >= 6) {
|
||||||
|
// Unità / Sottosede
|
||||||
|
if (currentLocale) {
|
||||||
|
currentLocale.sottosedi.push(nome);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Se c'è un solo regionale, restituisce l'oggetto direttamente (non array)
|
||||||
|
return regionali.length === 1 ? regionali[0] : regionali;
|
||||||
|
}
|
||||||
|
|
||||||
|
const $btn = $(`
|
||||||
|
<button id="gaia-copy-structure-btn" type="button" style="margin: 5px; padding: 8px; width: 97%; background-color: #5a3d8a; color: #FFF; border: none; border-radius: 4px; cursor: pointer;">
|
||||||
|
Copia struttura sedi (JSON)
|
||||||
|
</button>
|
||||||
|
`);
|
||||||
|
|
||||||
|
$btn.on('click', function () {
|
||||||
|
const structure = extractStructure();
|
||||||
|
const json = JSON.stringify(structure, null, 2);
|
||||||
|
|
||||||
|
navigator.clipboard.writeText(json).then(() => {
|
||||||
|
const locali = Array.isArray(structure)
|
||||||
|
? structure.reduce((acc, r) => acc + r.comitati_locali.length, 0)
|
||||||
|
: structure.comitati_locali.length;
|
||||||
|
const sottosedi = Array.isArray(structure)
|
||||||
|
? structure.reduce((acc, r) => acc + r.comitati_locali.reduce((a, l) => a + l.sottosedi.length, 0), 0)
|
||||||
|
: structure.comitati_locali.reduce((a, l) => a + l.sottosedi.length, 0);
|
||||||
|
|
||||||
|
console.log("GAIA Swissknife: JSON struttura sedi copiato in clipboard.");
|
||||||
|
console.log(` Locali: ${locali}, Sottosedi: ${sottosedi}`);
|
||||||
|
|
||||||
|
const orig = $(this).text();
|
||||||
|
$(this).text(`✓ Copiato! (${locali} locali, ${sottosedi} sottosedi)`).css('background-color', '#28a745');
|
||||||
|
setTimeout(() => $(this).text(orig).css('background-color', '#5a3d8a'), 3000);
|
||||||
|
}).catch(err => {
|
||||||
|
console.error("GAIA Swissknife: Errore copia clipboard:", err);
|
||||||
|
alert("Errore durante la copia in clipboard.");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Inserisce in cima alla sidebar, nella sezione Swissknife
|
||||||
|
if ($('#sezione').length > 0) {
|
||||||
|
appendToSwissknifeSection(
|
||||||
|
$('<li role="presentation"></li>').append($btn)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$(document).ready(() => {
|
$(document).ready(() => {
|
||||||
applyStyleFixes();
|
applyStyleFixes();
|
||||||
addExamOutcomeButtons();
|
addExamOutcomeButtons();
|
||||||
|
|
@ -592,21 +821,35 @@ GM_addStyle(GM_getResourceText("DataTablesCSS"));
|
||||||
addAuthorizationProfileTool();
|
addAuthorizationProfileTool();
|
||||||
enhanceCurriculumTable();
|
enhanceCurriculumTable();
|
||||||
highlightRejectedCourses();
|
highlightRejectedCourses();
|
||||||
|
addSediPreferitaTool();
|
||||||
|
addCopyCatalogButton();
|
||||||
|
addCopyStructureButton();
|
||||||
console.log("GAIA Swissknife: Funzioni caricate con successo!");
|
console.log("GAIA Swissknife: Funzioni caricate con successo!");
|
||||||
});
|
});
|
||||||
|
|
||||||
})(jQuery.noConflict(true));
|
})(jQuery.noConflict(true));
|
||||||
|
|
||||||
// ==CHANGELOG==
|
// ==CHANGELOG==
|
||||||
|
// v1.1.009 - Nuove funzioni:
|
||||||
|
// - Aggiunto pulsante "Copia catalogo corsi (JSON)" nella sidebar di /courses/catalog/
|
||||||
|
// - Estrae nome, codice, livello, tipo, obiettivo per ogni corso e copia il JSON in clipboard
|
||||||
|
// - Aggiunto tool "Sede preferita" nelle pagine con selezione sedi: select persistente (GM_setValue/getValue),
|
||||||
|
// pulsante "Solo preferito" (deseleziona tutto, seleziona il comitato scelto + figli), pulsante "Seleziona tutto"
|
||||||
|
// - Pulsanti Swissknife ora posizionati in cima alla sidebar con header e separatore
|
||||||
|
// v1.1.008 - Nuova funzione:
|
||||||
|
// - Aggiunto pulsante "Copia struttura sedi (JSON)" nel menu laterale della pagina /us/elenchi/volontari/
|
||||||
|
// - Estrae la gerarchia Comitato Regionale > Comitato Locale > Sottosedi dalla tabella sedi
|
||||||
|
// - Copia il JSON in clipboard con feedback visivo; se presente un solo Regionale restituisce l'oggetto diretto, altrimenti un array
|
||||||
|
// - Visibile solo quando la tabella sedi è presente (non nella vista risultati con iframe)
|
||||||
|
// v1.0.4 - Fix:
|
||||||
|
// - Modificata regex per il matching dei codici corso, compatibile con i codici che contengono caratteri alfanumerici
|
||||||
|
// v1.0.2 - Fix:
|
||||||
|
// - Modificata regex per il matching dei codici corso, compatibile con i codici che contengono spazi
|
||||||
|
// - Aggiunto link per aprire la pagina del corso nella modale dove compaiono i corsi rilevati
|
||||||
// v1.0.0 - Versione stabile, con:
|
// v1.0.0 - Versione stabile, con:
|
||||||
// - DataTable integrata nella tabella curriculum
|
// - DataTable integrata nella tabella curriculum
|
||||||
// - Evidenziazione "Respinto"
|
// - Evidenziazione "Respinto"
|
||||||
// - Correzioni grafiche file/link
|
// - Correzioni grafiche file/link
|
||||||
// - Gestione richieste iscrizioni con modale mobile
|
// - Gestione richieste iscrizioni con modale mobile
|
||||||
// - Funzioni esiti massivi su termina corso
|
// - Funzioni esiti massivi su termina corso
|
||||||
// v1.0.2 - Fix:
|
|
||||||
// - Modificata regex per il matching dei codici corso, compatibile con i codici che contengono spazi
|
|
||||||
// - Aggiunto link per aprire la pagina del corso nella modale dove compaiono i corsi rilevati
|
|
||||||
// v1.0.4 - Fix:
|
|
||||||
// - Modificata regex per il matching dei codici corso, compatibile con i codici che contengono caratteri alfanumerici
|
|
||||||
// ==/CHANGELOG==
|
// ==/CHANGELOG==
|
||||||
Loading…
Add table
Add a link
Reference in a new issue