[FEAT] Supply chain UI: i18n sp.* IT/EN + import mostra errors[] dettaglio righe scartate
- public/js/i18n.js: +38 chiavi sp.* (IT+EN) per pulsanti header, categorie, template, import. - supply-chain.html: data-i18n sui 4 pulsanti header; l'import CSV ora mostra il dettaglio delle righe scartate (d.errors[] dal backend) in un <details> e tiene aperta la modale se ci sono errori (prima si chiudeva sempre, errori invisibili). - version 1.10.1. Inline JS validato (node --check). File statici -> live via nginx. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
ce0387ed4f
commit
b7f361b87c
@ -384,6 +384,51 @@ const I18n = (function () {
|
||||
'feedback.notif_open': { it: 'Segnalazione registrata. Il team la prenderà in carico.', en: 'Report registered. The team will handle it.' },
|
||||
});
|
||||
|
||||
// ── Supply Chain / Fornitori (modulo questionari Fase 1) ────────────
|
||||
addTranslations({
|
||||
'sp.import_btn': { it: 'Importa', en: 'Import' },
|
||||
'sp.categories_btn': { it: 'Categorie', en: 'Categories' },
|
||||
'sp.templates_btn': { it: 'Template', en: 'Templates' },
|
||||
'sp.new_supplier': { it: '+ Nuovo Fornitore', en: '+ New Supplier' },
|
||||
'sp.category_field': { it: 'Categoria fornitore', en: 'Supplier category' },
|
||||
'sp.category_none': { it: '— Nessuna —', en: '— None —' },
|
||||
'sp.category_hint': { it: 'Classifica il fornitore (es. Cloud Provider). Gestisci le categorie dal pulsante "Categorie".', en: 'Classify the supplier (e.g. Cloud Provider). Manage categories from the "Categories" button.' },
|
||||
// Categorie
|
||||
'sp.cat_title': { it: 'Categorie fornitore', en: 'Supplier categories' },
|
||||
'sp.cat_new': { it: '+ Nuova categoria', en: '+ New category' },
|
||||
'sp.cat_preset': { it: 'Preset', en: 'Preset' },
|
||||
'sp.cat_custom': { it: 'Personalizzata', en: 'Custom' },
|
||||
'sp.cat_not_editable': { it: 'non modificabile', en: 'not editable' },
|
||||
'sp.cat_name': { it: 'Nome categoria', en: 'Category name' },
|
||||
'sp.cat_desc': { it: 'Descrizione', en: 'Description' },
|
||||
'sp.cat_preset_note': { it: 'Le categorie preset sono fornite dal sistema e non sono modificabili. Puoi creare categorie personalizzate per la tua organizzazione.', en: 'Preset categories are provided by the system and cannot be modified. You can create custom categories for your organization.' },
|
||||
'sp.cat_name_required': { it: 'Il nome della categoria è obbligatorio.', en: 'Category name is required.' },
|
||||
'sp.cat_created': { it: 'Categoria creata.', en: 'Category created.' },
|
||||
'sp.cat_updated': { it: 'Categoria aggiornata.', en: 'Category updated.' },
|
||||
'sp.cat_deleted': { it: 'Categoria eliminata.', en: 'Category deleted.' },
|
||||
'sp.cat_delete_confirm': { it: 'Eliminare la categoria?', en: 'Delete this category?' },
|
||||
'sp.cat_in_use': { it: 'Impossibile eliminare (categoria in uso?).', en: 'Cannot delete (category in use?).' },
|
||||
// Template
|
||||
'sp.tpl_title': { it: 'Template questionari', en: 'Questionnaire templates' },
|
||||
'sp.tpl_empty': { it: 'Nessun template questionario per questa organizzazione.', en: 'No questionnaire template for this organization.' },
|
||||
'sp.tpl_active': { it: 'Attivo', en: 'Active' },
|
||||
'sp.tpl_default': { it: 'Default', en: 'Default' },
|
||||
'sp.tpl_view_questions': { it: 'Vedi domande', en: 'View questions' },
|
||||
'sp.tpl_back': { it: '← Torna ai template', en: '← Back to templates' },
|
||||
'sp.tpl_readonly': { it: "Sola lettura. L'editor delle domande sarà disponibile in una prossima versione.", en: 'Read-only. The question editor will be available in a future version.' },
|
||||
'sp.tpl_required': { it: 'Obbligatoria', en: 'Required' },
|
||||
'sp.tpl_high_crit': { it: 'Solo alta criticità', en: 'High criticality only' },
|
||||
'sp.tpl_weight': { it: 'Peso', en: 'Weight' },
|
||||
'sp.tpl_questions': { it: 'domande', en: 'questions' },
|
||||
// Import
|
||||
'sp.import_title': { it: 'Importa fornitori', en: 'Import suppliers' },
|
||||
'sp.import_run': { it: 'Importa', en: 'Import' },
|
||||
'sp.import_no_rows': { it: 'Nessuna riga valida (serve intestazione + almeno un fornitore con "name").', en: 'No valid rows (header + at least one supplier with "name" required).' },
|
||||
'sp.import_too_many': { it: 'Troppi record (max 1000).', en: 'Too many records (max 1000).' },
|
||||
'sp.import_done': { it: 'Completato: creati {created}, aggiornati {updated}, saltati {skipped}.', en: 'Done: {created} created, {updated} updated, {skipped} skipped.' },
|
||||
'sp.conn_error': { it: 'Errore di connessione.', en: 'Connection error.' },
|
||||
});
|
||||
|
||||
return { init, getLang, setLang, t, applyTranslations, addTranslations };
|
||||
})();
|
||||
|
||||
|
||||
@ -370,10 +370,10 @@
|
||||
<header class="content-header">
|
||||
<h2 data-i18n="supply_chain.title">Sicurezza Supply Chain</h2>
|
||||
<div class="content-header-actions">
|
||||
<button class="btn btn-secondary" onclick="openCategoriesModal()"><i class="fas fa-tags"></i> Categorie</button>
|
||||
<button class="btn btn-secondary" onclick="openTemplatesModal()"><i class="fas fa-clipboard-list"></i> Template</button>
|
||||
<button class="btn btn-secondary" onclick="openImportModal()"><i class="fas fa-file-import"></i> Importa</button>
|
||||
<button class="btn btn-primary" onclick="openCreateModal()">+ Nuovo Fornitore</button>
|
||||
<button class="btn btn-secondary" onclick="openCategoriesModal()"><i class="fas fa-tags"></i> <span data-i18n="sp.categories_btn">Categorie</span></button>
|
||||
<button class="btn btn-secondary" onclick="openTemplatesModal()"><i class="fas fa-clipboard-list"></i> <span data-i18n="sp.templates_btn">Template</span></button>
|
||||
<button class="btn btn-secondary" onclick="openImportModal()"><i class="fas fa-file-import"></i> <span data-i18n="sp.import_btn">Importa</span></button>
|
||||
<button class="btn btn-primary" onclick="openCreateModal()"><span data-i18n="sp.new_supplier">+ Nuovo Fornitore</span></button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@ -1277,10 +1277,16 @@
|
||||
const res = await api.importSuppliers(rows);
|
||||
if (res.success) {
|
||||
const d = res.data || {};
|
||||
resEl.innerHTML = `<span style="color:#16a34a;">Completato: creati ${d.created||0}, aggiornati ${d.updated||0}, saltati ${d.skipped||0}.</span>`;
|
||||
let html = `<span style="color:#16a34a;">Completato: creati ${d.created||0}, aggiornati ${d.updated||0}, saltati ${d.skipped||0}.</span>`;
|
||||
if (Array.isArray(d.errors) && d.errors.length) {
|
||||
const items = d.errors.slice(0, 20).map(e => `<li>Riga ${(e.row != null ? e.row + 1 : '?')}: ${escapeHtml(String(e.error || ''))}</li>`).join('');
|
||||
html += `<details style="margin-top:8px;"><summary style="cursor:pointer;color:#b45309;">${d.errors.length} riga/e scartata/e — dettagli</summary><ul style="margin:6px 0 0 18px;color:#b45309;font-size:13px;">${items}</ul></details>`;
|
||||
}
|
||||
resEl.innerHTML = html;
|
||||
showNotification(`Import: ${d.created||0} creati, ${d.updated||0} aggiornati`, 'success');
|
||||
loadSuppliers();
|
||||
setTimeout(() => { const m = document.getElementById('importModalDyn'); if (m) m.remove(); }, 1800);
|
||||
const keepOpen = Array.isArray(d.errors) && d.errors.length > 0;
|
||||
if (!keepOpen) setTimeout(() => { const m = document.getElementById('importModalDyn'); if (m) m.remove(); }, 1800);
|
||||
} else {
|
||||
resEl.innerHTML = `<span style="color:#dc2626;">${res.message || 'Errore import'}</span>`;
|
||||
}
|
||||
|
||||
@ -1 +1 @@
|
||||
{"version":"1.10.0","build":"2026-05-31-v1.10.0","date":"2026-05-31","changelog":"UI modulo questionari fornitori: dropdown categoria nel form fornitore, gestione categorie (preset+custom CRUD), visualizzazione template questionari con domande GV.SC e badge nis2_ref (read-only). Backend Fase 1 ora pienamente usabile dalla UI."}
|
||||
{"version":"1.10.1","build":"2026-05-31-v1.10.1","date":"2026-05-31","changelog":"Supply chain UI: chiavi i18n IT/EN (sp.*) per pulsanti modulo fornitori; import CSV mostra il dettaglio delle righe scartate (errors[]) e tiene aperta la modale in caso di errori. Completamento Fase 1 modulo questionari fornitori."}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user