[UI] SWAP V2: Bootstrap Italia ora UFFICIALE su 27 pagine app (kill della vecchia UI)
Promosse le pagine -bi a nomi ufficiali (contenuto BI), link -bi->plain, titoli '(BI)' rimossi.
La vecchia UI delle pagine app e sostituita. Backup: git (commit 36967f9) + /tmp/nis2-v1-backup.
Promosse (27): auth (login/register/onboarding/forgot/reset) + app (dashboard/assessment/
risks/incidents/policies/supply-chain/training/assets/reports/settings/isms/acn-gap/normative/
whistleblowing/kb/cross-analysis/service-continuity/guida/companies) + admin (index/orgs/users).
common-bi.js: sidebar BI ora linka le pagine ufficiali.
ESCLUSA: index.html (landing marketing 1298 righe) -> conversione dedicata a parte (la -bi
era 557 righe, rischio perdita contenuti). Pagine marketing/demo (presentation/simulate/
workflow/architecture/index-en) restano vecchio stile (fuori scope app autenticata).
Verifica produzione: 27/27 servite 200 con BI, 0 link -bi residui, 0 '(BI)' nei titoli,
auth intatta (401 su pwd errata), common-bi.js node --check OK.
Rollback: git revert HEAD (oppure ripristino da /tmp/nis2-v1-backup).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
36967f9452
commit
1c64211685
+60
-46
@@ -4,6 +4,10 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Gestione Rischi - NIS2 Agile</title>
|
||||
<!-- Bootstrap Italia v2.18.1 self-hostato (regola: MAI CDN). Caricato PRIMA di style.css
|
||||
cosi' style.css (design system esistente) resta autorevole per i widget renderizzati
|
||||
via JS (tabelle/matrice/modali) -> parita' funzionale assoluta. BI veste la chrome. -->
|
||||
<link rel="stylesheet" href="/vendor/bootstrap-italia/dist/css/bootstrap-italia.min.css">
|
||||
<link rel="stylesheet" href="/css/style.css">
|
||||
<style>
|
||||
/* ── View Toggle ─────────────────────────────────────── */
|
||||
@@ -301,7 +305,7 @@
|
||||
|
||||
<main class="main-content">
|
||||
<header class="content-header">
|
||||
<h2 data-i18n="risks.title">Gestione Rischi</h2>
|
||||
<h1 class="h2" data-i18n="risks.title">Gestione Rischi</h1>
|
||||
<div class="content-header-actions">
|
||||
<div class="view-toggle" id="view-toggle">
|
||||
<button class="active" onclick="switchView('table')">Tabella</button>
|
||||
@@ -321,7 +325,7 @@
|
||||
<!-- Table View -->
|
||||
<div id="view-table">
|
||||
<div class="filters-bar">
|
||||
<select class="form-select" id="filter-category" onchange="loadRisks()">
|
||||
<select class="form-select" id="filter-category" onchange="loadRisks()" aria-label="Filtra per categoria">
|
||||
<option value="">Tutte le categorie</option>
|
||||
<option value="cyber">Cyber</option>
|
||||
<option value="operational">Operativo</option>
|
||||
@@ -330,7 +334,7 @@
|
||||
<option value="physical">Fisico</option>
|
||||
<option value="human">Umano</option>
|
||||
</select>
|
||||
<select class="form-select" id="filter-status" onchange="loadRisks()">
|
||||
<select class="form-select" id="filter-status" onchange="loadRisks()" aria-label="Filtra per stato">
|
||||
<option value="">Tutti gli stati</option>
|
||||
<option value="identified">Identificato</option>
|
||||
<option value="analyzing">In Analisi</option>
|
||||
@@ -345,14 +349,14 @@
|
||||
<table class="table-clickable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Codice</th>
|
||||
<th>Titolo</th>
|
||||
<th>Categoria</th>
|
||||
<th>Probabilita'</th>
|
||||
<th>Impatto</th>
|
||||
<th>Score</th>
|
||||
<th>Stato</th>
|
||||
<th>Azioni</th>
|
||||
<th scope="col">Codice</th>
|
||||
<th scope="col">Titolo</th>
|
||||
<th scope="col">Categoria</th>
|
||||
<th scope="col">Probabilita'</th>
|
||||
<th scope="col">Impatto</th>
|
||||
<th scope="col">Score</th>
|
||||
<th scope="col">Stato</th>
|
||||
<th scope="col">Azioni</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="risks-table-body">
|
||||
@@ -421,15 +425,15 @@
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div style="display:grid; grid-template-columns:repeat(auto-fit,minmax(140px,1fr)); gap:12px; margin-bottom:16px;">
|
||||
<div><label class="form-label">Rischio</label>
|
||||
<div><label for="fair-risk-select" class="form-label">Rischio</label>
|
||||
<select class="form-select" id="fair-risk-select"><option value="">— seleziona —</option></select></div>
|
||||
<div><label class="form-label">TEF min <small>(ev/anno)</small></label><input type="number" step="0.1" class="form-input" id="fair-tef-min" value="0.5"></div>
|
||||
<div><label class="form-label">TEF probabile</label><input type="number" step="0.1" class="form-input" id="fair-tef-ml" value="1"></div>
|
||||
<div><label class="form-label">TEF max</label><input type="number" step="0.1" class="form-input" id="fair-tef-max" value="2"></div>
|
||||
<div><label class="form-label">Vulnerabilita <small>(0-1)</small></label><input type="number" step="0.05" min="0" max="1" class="form-input" id="fair-vuln" value="0.3"></div>
|
||||
<div><label class="form-label">Perdita min <small>(EUR)</small></label><input type="number" step="1000" class="form-input" id="fair-lm-min" value="50000"></div>
|
||||
<div><label class="form-label">Perdita probabile</label><input type="number" step="1000" class="form-input" id="fair-lm-ml" value="300000"></div>
|
||||
<div><label class="form-label">Perdita max</label><input type="number" step="1000" class="form-input" id="fair-lm-max" value="2000000"></div>
|
||||
<div><label for="fair-tef-min" class="form-label">TEF min <small>(ev/anno)</small></label><input type="number" step="0.1" class="form-input" id="fair-tef-min" value="0.5"></div>
|
||||
<div><label for="fair-tef-ml" class="form-label">TEF probabile</label><input type="number" step="0.1" class="form-input" id="fair-tef-ml" value="1"></div>
|
||||
<div><label for="fair-tef-max" class="form-label">TEF max</label><input type="number" step="0.1" class="form-input" id="fair-tef-max" value="2"></div>
|
||||
<div><label for="fair-vuln" class="form-label">Vulnerabilita <small>(0-1)</small></label><input type="number" step="0.05" min="0" max="1" class="form-input" id="fair-vuln" value="0.3"></div>
|
||||
<div><label for="fair-lm-min" class="form-label">Perdita min <small>(EUR)</small></label><input type="number" step="1000" class="form-input" id="fair-lm-min" value="50000"></div>
|
||||
<div><label for="fair-lm-ml" class="form-label">Perdita probabile</label><input type="number" step="1000" class="form-input" id="fair-lm-ml" value="300000"></div>
|
||||
<div><label for="fair-lm-max" class="form-label">Perdita max</label><input type="number" step="1000" class="form-input" id="fair-lm-max" value="2000000"></div>
|
||||
</div>
|
||||
<button class="btn btn-primary" onclick="runFair()" id="btn-run-fair">Calcola ALE</button>
|
||||
<div id="fair-result" class="hidden" style="margin-top:20px;">
|
||||
@@ -450,7 +454,7 @@
|
||||
<span class="text-muted" style="font-size:0.8rem;">ALE di portafoglio: <strong id="fair-portfolio">—</strong></span></div>
|
||||
<div class="table-container">
|
||||
<table class="table-clickable"><thead><tr>
|
||||
<th>Codice</th><th>Titolo</th><th>Categoria</th><th>ALE Min</th><th>ALE Mediana</th><th>ALE Max</th><th>ALE Media</th>
|
||||
<th scope="col">Codice</th><th scope="col">Titolo</th><th scope="col">Categoria</th><th scope="col">ALE Min</th><th scope="col">ALE Mediana</th><th scope="col">ALE Max</th><th scope="col">ALE Media</th>
|
||||
</tr></thead><tbody id="fair-register-body"><tr><td colspan="7" class="text-muted" style="text-align:center;padding:20px;">Nessun rischio quantificato</td></tr></tbody></table>
|
||||
</div>
|
||||
</div>
|
||||
@@ -465,7 +469,7 @@
|
||||
<div class="card">
|
||||
<div class="table-container">
|
||||
<table class="table-clickable"><thead><tr>
|
||||
<th>Stato</th><th>Indicatore</th><th>Categoria</th><th>Valore</th><th>Soglia Warning</th><th>Soglia Critica</th><th>Azioni</th>
|
||||
<th scope="col">Stato</th><th scope="col">Indicatore</th><th scope="col">Categoria</th><th scope="col">Valore</th><th scope="col">Soglia Warning</th><th scope="col">Soglia Critica</th><th scope="col">Azioni</th>
|
||||
</tr></thead><tbody id="kri-table-body"><tr><td colspan="7"><div class="spinner" style="margin:30px auto;"></div></td></tr></tbody></table>
|
||||
</div>
|
||||
</div>
|
||||
@@ -479,6 +483,16 @@
|
||||
|
||||
<script src="/js/api.js"></script>
|
||||
<script src="/js/common.js"></script>
|
||||
<!-- Bootstrap Italia bundle (componenti) + override sidebar BI (common-bi.js).
|
||||
common-bi.js va DOPO common.js: ridefinisce solo loadSidebar() con markup BI,
|
||||
riusando tutti gli helper di common.js (zero backend). -->
|
||||
<script src="/vendor/bootstrap-italia/dist/js/bootstrap-italia.bundle.min.js"></script>
|
||||
<script>
|
||||
if (window.bootstrap && bootstrap.loadFonts) {
|
||||
bootstrap.loadFonts('/vendor/bootstrap-italia/dist/fonts');
|
||||
}
|
||||
</script>
|
||||
<script src="/js/common-bi.js"></script>
|
||||
<script src="/js/i18n.js"></script>
|
||||
<script src="/js/help.js"></script>
|
||||
<script>
|
||||
@@ -747,17 +761,17 @@
|
||||
function showKriModal(kri = null) {
|
||||
const k = kri || {};
|
||||
const body = `
|
||||
<div class="form-group"><label class="form-label">Nome indicatore *</label><input class="form-input" id="kri-name" value="${escapeHtml(k.name || '')}"></div>
|
||||
<div class="form-group"><label class="form-label">Descrizione</label><input class="form-input" id="kri-desc" value="${escapeHtml(k.description || '')}"></div>
|
||||
<div class="form-group"><label for="kri-name" class="form-label">Nome indicatore *</label><input class="form-input" id="kri-name" value="${escapeHtml(k.name || '')}"></div>
|
||||
<div class="form-group"><label for="kri-desc" class="form-label">Descrizione</label><input class="form-input" id="kri-desc" value="${escapeHtml(k.description || '')}"></div>
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:10px;">
|
||||
<div class="form-group"><label class="form-label">Categoria</label><select class="form-select" id="kri-cat">
|
||||
<div class="form-group"><label for="kri-cat" class="form-label">Categoria</label><select class="form-select" id="kri-cat">
|
||||
${['cyber', 'operational', 'compliance', 'supply_chain', 'physical', 'human'].map(c => `<option value="${c}" ${k.category === c ? 'selected' : ''}>${CATEGORY_LABELS[c] || c}</option>`).join('')}</select></div>
|
||||
<div class="form-group"><label class="form-label">Unita (%, count, EUR...)</label><input class="form-input" id="kri-unit" value="${escapeHtml(k.unit || '')}"></div>
|
||||
<div class="form-group"><label class="form-label">Valore corrente</label><input type="number" step="any" class="form-input" id="kri-cur" value="${k.current_value ?? ''}"></div>
|
||||
<div class="form-group"><label class="form-label">Obiettivo</label><input type="number" step="any" class="form-input" id="kri-target" value="${k.target_value ?? ''}"></div>
|
||||
<div class="form-group"><label class="form-label">Soglia Warning</label><input type="number" step="any" class="form-input" id="kri-warn" value="${k.threshold_warning ?? ''}"></div>
|
||||
<div class="form-group"><label class="form-label">Soglia Critica</label><input type="number" step="any" class="form-input" id="kri-crit" value="${k.threshold_critical ?? ''}"></div>
|
||||
<div class="form-group" style="grid-column:span 2;"><label class="form-label">Direzione</label><select class="form-select" id="kri-dir">
|
||||
<div class="form-group"><label for="kri-unit" class="form-label">Unita (%, count, EUR...)</label><input class="form-input" id="kri-unit" value="${escapeHtml(k.unit || '')}"></div>
|
||||
<div class="form-group"><label for="kri-cur" class="form-label">Valore corrente</label><input type="number" step="any" class="form-input" id="kri-cur" value="${k.current_value ?? ''}"></div>
|
||||
<div class="form-group"><label for="kri-target" class="form-label">Obiettivo</label><input type="number" step="any" class="form-input" id="kri-target" value="${k.target_value ?? ''}"></div>
|
||||
<div class="form-group"><label for="kri-warn" class="form-label">Soglia Warning</label><input type="number" step="any" class="form-input" id="kri-warn" value="${k.threshold_warning ?? ''}"></div>
|
||||
<div class="form-group"><label for="kri-crit" class="form-label">Soglia Critica</label><input type="number" step="any" class="form-input" id="kri-crit" value="${k.threshold_critical ?? ''}"></div>
|
||||
<div class="form-group" style="grid-column:span 2;"><label for="kri-dir" class="form-label">Direzione</label><select class="form-select" id="kri-dir">
|
||||
<option value="higher_worse" ${k.direction === 'higher_worse' ? 'selected' : ''}>Valori alti = peggio</option>
|
||||
<option value="lower_worse" ${k.direction === 'lower_worse' ? 'selected' : ''}>Valori bassi = peggio</option></select></div>
|
||||
</div>`;
|
||||
@@ -1065,16 +1079,16 @@
|
||||
|
||||
const content = `
|
||||
<div class="form-group">
|
||||
<label class="form-label">Titolo <span class="required">*</span></label>
|
||||
<label for="risk-title" class="form-label">Titolo <span class="required">*</span></label>
|
||||
<input type="text" class="form-input" id="risk-title" value="${escapeHtml(risk.title || '')}" placeholder="Titolo del rischio">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Descrizione</label>
|
||||
<label for="risk-description" class="form-label">Descrizione</label>
|
||||
<textarea class="form-textarea" id="risk-description" rows="3" placeholder="Descrizione dettagliata">${escapeHtml(risk.description || '')}</textarea>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Categoria</label>
|
||||
<label for="risk-category" class="form-label">Categoria</label>
|
||||
<select class="form-select" id="risk-category">
|
||||
<option value="cyber" ${risk.category==='cyber'?'selected':''}>Cyber</option>
|
||||
<option value="operational" ${risk.category==='operational'?'selected':''}>Operativo</option>
|
||||
@@ -1085,7 +1099,7 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Trattamento</label>
|
||||
<label for="risk-treatment" class="form-label">Trattamento</label>
|
||||
<select class="form-select" id="risk-treatment">
|
||||
<option value="mitigate" ${risk.treatment==='mitigate'?'selected':''}>Mitigare</option>
|
||||
<option value="accept" ${risk.treatment==='accept'?'selected':''}>Accettare</option>
|
||||
@@ -1096,24 +1110,24 @@
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Sorgente Minaccia</label>
|
||||
<label for="risk-threat-source" class="form-label">Sorgente Minaccia</label>
|
||||
<input type="text" class="form-input" id="risk-threat-source" value="${escapeHtml(risk.threat_source || '')}" placeholder="Es. attaccante esterno">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Vulnerabilita'</label>
|
||||
<label for="risk-vulnerability" class="form-label">Vulnerabilita'</label>
|
||||
<input type="text" class="form-input" id="risk-vulnerability" value="${escapeHtml(risk.vulnerability || '')}" placeholder="Es. software non aggiornato">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Probabilita' <span style="color:var(--gray-400); font-size:0.75rem; font-weight:400;">(frequenza stimata annua)</span></label>
|
||||
<label for="risk-likelihood" class="form-label">Probabilita' <span style="color:var(--gray-400); font-size:0.75rem; font-weight:400;">(frequenza stimata annua)</span></label>
|
||||
<div class="range-value-display" id="likelihood-value">${likelihood}</div>
|
||||
<input type="range" class="form-range" id="risk-likelihood" min="1" max="5" value="${likelihood}" oninput="updateRiskScore()">
|
||||
<div style="font-size:0.75rem; color:var(--gray-500); margin-top:4px; padding:6px 8px; background:var(--gray-50); border-radius:4px;" id="likelihood-detail">${LIKELIHOOD_DETAILS[likelihood]}</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Impatto <span style="color:var(--gray-400); font-size:0.75rem; font-weight:400;">(danno economico / utenti)</span></label>
|
||||
<label for="risk-impact" class="form-label">Impatto <span style="color:var(--gray-400); font-size:0.75rem; font-weight:400;">(danno economico / utenti)</span></label>
|
||||
<div class="range-value-display" id="impact-value">${impact}</div>
|
||||
<input type="range" class="form-range" id="risk-impact" min="1" max="5" value="${impact}" oninput="updateRiskScore()">
|
||||
<div style="font-size:0.75rem; color:var(--gray-500); margin-top:4px; padding:6px 8px; background:var(--gray-50); border-radius:4px;" id="impact-detail">${IMPACT_DETAILS[impact]}</div>
|
||||
@@ -1127,16 +1141,16 @@
|
||||
|
||||
<div class="form-row" style="margin-top:16px;">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Responsabile (ID utente)</label>
|
||||
<label for="risk-owner" class="form-label">Responsabile (ID utente)</label>
|
||||
<input type="text" class="form-input" id="risk-owner" value="${escapeHtml(risk.owner_user_id || '')}" placeholder="ID utente responsabile">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Data Revisione</label>
|
||||
<label for="risk-review-date" class="form-label">Data Revisione</label>
|
||||
<input type="date" class="form-input" id="risk-review-date" value="${risk.review_date ? risk.review_date.split(' ')[0] : ''}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Articolo NIS2 di riferimento</label>
|
||||
<label for="risk-nis2-article" class="form-label">Articolo NIS2 di riferimento</label>
|
||||
<input type="text" class="form-input" id="risk-nis2-article" value="${escapeHtml(risk.nis2_article || '')}" placeholder="Es. Art. 21, par. 2">
|
||||
</div>
|
||||
`;
|
||||
@@ -1249,21 +1263,21 @@
|
||||
function showAddTreatmentModal(riskId) {
|
||||
const content = `
|
||||
<div class="form-group">
|
||||
<label class="form-label">Descrizione Azione <span class="required">*</span></label>
|
||||
<label for="treatment-description" class="form-label">Descrizione Azione <span class="required">*</span></label>
|
||||
<textarea class="form-textarea" id="treatment-description" rows="3" placeholder="Descrizione dell'azione di trattamento"></textarea>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Responsabile (ID utente)</label>
|
||||
<label for="treatment-responsible" class="form-label">Responsabile (ID utente)</label>
|
||||
<input type="text" class="form-input" id="treatment-responsible" placeholder="ID utente">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Data Scadenza</label>
|
||||
<label for="treatment-due-date" class="form-label">Data Scadenza</label>
|
||||
<input type="date" class="form-input" id="treatment-due-date">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Stato</label>
|
||||
<label for="treatment-status" class="form-label">Stato</label>
|
||||
<select class="form-select" id="treatment-status">
|
||||
<option value="planned">Pianificato</option>
|
||||
<option value="in_progress">In Corso</option>
|
||||
@@ -1271,7 +1285,7 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Note</label>
|
||||
<label for="treatment-notes" class="form-label">Note</label>
|
||||
<textarea class="form-textarea" id="treatment-notes" rows="2" placeholder="Note aggiuntive"></textarea>
|
||||
</div>
|
||||
`;
|
||||
|
||||
Reference in New Issue
Block a user