[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
+41
-19
@@ -3,7 +3,12 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Segnalazioni - NIS2 Agile</title>
|
||||
<title>Segnalazioni Sicurezza - NIS2 Agile</title>
|
||||
<!-- Bootstrap Italia v2.18.1 self-hostato (regola: MAI CDN). Caricato PRIMA di
|
||||
style.css cosi' il design system esistente resta autorevole per i widget
|
||||
renderizzati via JS (tabelle/modali/timeline) -> parita' funzionale assoluta.
|
||||
BI veste la chrome (sidebar + font istituzionale). -->
|
||||
<link rel="stylesheet" href="/vendor/bootstrap-italia/dist/css/bootstrap-italia.min.css">
|
||||
<link rel="stylesheet" href="/css/style.css">
|
||||
<style>
|
||||
.priority-badge { display: inline-flex; align-items: center; padding: 2px 10px; border-radius: 12px; font-size: 0.7rem; font-weight: 700; }
|
||||
@@ -22,11 +27,13 @@
|
||||
.art32-banner h3 { font-size: 0.9375rem; font-weight: 700; color: var(--gray-800); margin-bottom: 6px; }
|
||||
.art32-banner p { font-size: 0.8125rem; color: var(--gray-600); }
|
||||
.track-form { background: var(--gray-50); border: 1px solid var(--gray-200); border-radius: var(--border-radius); padding: 20px; margin-bottom: 24px; }
|
||||
/* Icone sprite BI dimensionate inline per i bottoni azione */
|
||||
.icon-inline { width: 16px; height: 16px; fill: currentColor; vertical-align: text-bottom; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="app-layout">
|
||||
<div id="sidebar-container"></div>
|
||||
<aside class="sidebar" id="sidebar"></aside>
|
||||
<main class="main-content">
|
||||
<div class="page-header">
|
||||
<div class="page-header-content">
|
||||
@@ -35,11 +42,11 @@
|
||||
</div>
|
||||
<div class="page-header-actions">
|
||||
<button class="btn btn-secondary" onclick="switchView('track')">
|
||||
<svg viewBox="0 0 20 20" fill="currentColor" width="16" height="16"><path fill-rule="evenodd" d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z" clip-rule="evenodd"/></svg>
|
||||
<svg class="icon-inline" aria-hidden="true"><use href="/vendor/bootstrap-italia/dist/svg/sprites.svg#it-search"></use></svg>
|
||||
Traccia Segnalazione Anonima
|
||||
</button>
|
||||
<button class="btn btn-primary" onclick="switchView('submit')">
|
||||
<svg viewBox="0 0 20 20" fill="currentColor" width="16" height="16"><path fill-rule="evenodd" d="M10 3a1 1 0 011 1v5h5a1 1 0 110 2h-5v5a1 1 0 11-2 0v-5H4a1 1 0 110-2h5V4a1 1 0 011-1z" clip-rule="evenodd"/></svg>
|
||||
<svg class="icon-inline" aria-hidden="true"><use href="/vendor/bootstrap-italia/dist/svg/sprites.svg#it-plus"></use></svg>
|
||||
Nuova Segnalazione
|
||||
</button>
|
||||
</div>
|
||||
@@ -62,7 +69,8 @@
|
||||
<div class="card mb-16">
|
||||
<div class="card-body" style="padding:16px 20px;">
|
||||
<div style="display:flex; gap:12px; flex-wrap:wrap; align-items:center;">
|
||||
<select id="filter-status" class="form-control" style="width:auto;" onchange="loadReports()">
|
||||
<label for="filter-status" class="sr-only">Filtra per stato</label>
|
||||
<select id="filter-status" class="form-control" style="width:auto;" onchange="loadReports()" aria-label="Filtra per stato">
|
||||
<option value="">Tutti gli stati</option>
|
||||
<option value="received">Ricevute</option>
|
||||
<option value="under_review">In revisione</option>
|
||||
@@ -70,14 +78,16 @@
|
||||
<option value="resolved">Risolte</option>
|
||||
<option value="closed">Chiuse</option>
|
||||
</select>
|
||||
<select id="filter-priority" class="form-control" style="width:auto;" onchange="loadReports()">
|
||||
<label for="filter-priority" class="sr-only">Filtra per priorità</label>
|
||||
<select id="filter-priority" class="form-control" style="width:auto;" onchange="loadReports()" aria-label="Filtra per priorità">
|
||||
<option value="">Tutte le priorità</option>
|
||||
<option value="critical">Critica</option>
|
||||
<option value="high">Alta</option>
|
||||
<option value="medium">Media</option>
|
||||
<option value="low">Bassa</option>
|
||||
</select>
|
||||
<select id="filter-category" class="form-control" style="width:auto;" onchange="loadReports()">
|
||||
<label for="filter-category" class="sr-only">Filtra per categoria</label>
|
||||
<select id="filter-category" class="form-control" style="width:auto;" onchange="loadReports()" aria-label="Filtra per categoria">
|
||||
<option value="">Tutte le categorie</option>
|
||||
<option value="security_incident">Incidente sicurezza</option>
|
||||
<option value="data_breach">Data breach</option>
|
||||
@@ -102,7 +112,7 @@
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div style="margin-bottom:20px; padding:12px 16px; background:rgba(16,185,129,0.08); border:1px solid rgba(16,185,129,0.2); border-radius:var(--border-radius); display:flex; align-items:center; gap:10px;">
|
||||
<svg viewBox="0 0 20 20" fill="currentColor" width="18" height="18" style="color:var(--success); flex-shrink:0;"><path fill-rule="evenodd" d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z" clip-rule="evenodd"/></svg>
|
||||
<svg class="icon-inline" style="width:18px; height:18px; color:var(--success); flex-shrink:0;" aria-hidden="true"><use href="/vendor/bootstrap-italia/dist/svg/sprites.svg#it-lock"></use></svg>
|
||||
<label style="display:flex; align-items:center; gap:8px; font-size:0.875rem; cursor:pointer;">
|
||||
<input type="checkbox" id="is-anonymous" checked style="accent-color:var(--success);">
|
||||
<span><strong>Segnalazione anonima</strong> — La tua identità non verrà registrata</span>
|
||||
@@ -111,7 +121,7 @@
|
||||
|
||||
<form id="submit-form" onsubmit="submitReport(event)">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Categoria *</label>
|
||||
<label class="form-label" for="rep-category">Categoria *</label>
|
||||
<select id="rep-category" class="form-control" required>
|
||||
<option value="">Seleziona categoria...</option>
|
||||
<option value="security_incident">Incidente di sicurezza</option>
|
||||
@@ -125,15 +135,15 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Titolo *</label>
|
||||
<label class="form-label" for="rep-title">Titolo *</label>
|
||||
<input type="text" id="rep-title" class="form-control" placeholder="Breve descrizione dell'anomalia..." required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Descrizione dettagliata *</label>
|
||||
<label class="form-label" for="rep-description">Descrizione dettagliata *</label>
|
||||
<textarea id="rep-description" class="form-control" rows="6" placeholder="Descrivi cosa hai osservato, quando è successo, chi è coinvolto (se noto), e qualsiasi altra informazione utile..." required></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Priorità stimata</label>
|
||||
<label class="form-label" for="rep-priority">Priorità stimata</label>
|
||||
<select id="rep-priority" class="form-control">
|
||||
<option value="medium">Media</option>
|
||||
<option value="high">Alta</option>
|
||||
@@ -142,11 +152,11 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Articolo NIS2 violato (opzionale)</label>
|
||||
<label class="form-label" for="rep-article">Articolo NIS2 violato (opzionale)</label>
|
||||
<input type="text" id="rep-article" class="form-control" placeholder="Es. Art.21, Art.23...">
|
||||
</div>
|
||||
<div class="form-group" id="contact-email-group">
|
||||
<label class="form-label">Email per follow-up (opzionale)</label>
|
||||
<label class="form-label" for="rep-email">Email per follow-up (opzionale)</label>
|
||||
<input type="email" id="rep-email" class="form-control" placeholder="Email solo per ricevere aggiornamenti">
|
||||
<p style="font-size:0.75rem; color:var(--gray-500); margin-top:4px;">Lascia vuoto per mantenere l'anonimato completo. Oppure fornisci un'email temporanea.</p>
|
||||
</div>
|
||||
@@ -168,7 +178,7 @@
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Token Segnalazione</label>
|
||||
<label class="form-label" for="track-token">Token Segnalazione</label>
|
||||
<input type="text" id="track-token" class="form-control" placeholder="Inserisci il token...">
|
||||
</div>
|
||||
<div style="display:flex; gap:12px;">
|
||||
@@ -186,6 +196,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>
|
||||
@@ -269,7 +289,7 @@
|
||||
if (!reports.length) {
|
||||
container.innerHTML = `
|
||||
<div class="empty-state">
|
||||
<svg viewBox="0 0 20 20" fill="currentColor" width="40" height="40" style="color:var(--gray-300)"><path fill-rule="evenodd" d="M10 1.944A11.954 11.954 0 012.166 5C2.056 5.649 2 6.319 2 7c0 5.225 3.34 9.67 8 11.317C14.66 16.67 18 12.225 18 7c0-.682-.057-1.35-.166-2.001A11.954 11.954 0 0110 1.944zM11 14a1 1 0 11-2 0 1 1 0 012 0zm0-7a1 1 0 10-2 0v3a1 1 0 102 0V7z" clip-rule="evenodd"/></svg>
|
||||
<svg class="icon-inline" style="width:40px; height:40px; color:var(--gray-300);" aria-hidden="true"><use href="/vendor/bootstrap-italia/dist/svg/sprites.svg#it-warning-circle"></use></svg>
|
||||
<h4>Nessuna segnalazione trovata</h4>
|
||||
<p>Il canale di segnalazione è attivo. Le segnalazioni appariranno qui.</p>
|
||||
</div>`;
|
||||
@@ -277,7 +297,7 @@
|
||||
}
|
||||
|
||||
let html = `<div class="table-container"><table>
|
||||
<thead><tr><th>Codice</th><th>Categoria</th><th>Titolo</th><th>Priorità</th><th>Stato</th><th>Anonima</th><th>Assegnata</th><th>Data</th><th></th></tr></thead><tbody>`;
|
||||
<thead><tr><th scope="col">Codice</th><th scope="col">Categoria</th><th scope="col">Titolo</th><th scope="col">Priorità</th><th scope="col">Stato</th><th scope="col">Anonima</th><th scope="col">Assegnata</th><th scope="col">Data</th><th scope="col"></th></tr></thead><tbody>`;
|
||||
|
||||
reports.forEach(r => {
|
||||
html += `<tr>
|
||||
@@ -286,7 +306,7 @@
|
||||
<td><strong style="font-size:0.875rem;">${escapeHtml(r.title)}</strong></td>
|
||||
<td><span class="priority-badge priority-${r.priority}">${escapeHtml(priorityLabels[r.priority] || r.priority)}</span></td>
|
||||
<td><span class="status-badge status-${r.status}">${escapeHtml(statusLabels[r.status] || r.status)}</span></td>
|
||||
<td>${r.is_anonymous ? '<span class="anonymous-shield"><svg viewBox="0 0 20 20" fill="currentColor" width="12" height="12"><path fill-rule="evenodd" d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z" clip-rule="evenodd"/></svg>Anonima</span>' : '<span style="color:var(--gray-400); font-size:0.75rem;">Firmata</span>'}</td>
|
||||
<td>${r.is_anonymous ? '<span class="anonymous-shield"><svg class="icon-inline" style="width:12px;height:12px;" aria-hidden="true"><use href="/vendor/bootstrap-italia/dist/svg/sprites.svg#it-lock"></use></svg>Anonima</span>' : '<span style="color:var(--gray-400); font-size:0.75rem;">Firmata</span>'}</td>
|
||||
<td>${r.assigned_to_name ? escapeHtml(r.assigned_to_name) : '<span style="color:var(--gray-400);">—</span>'}</td>
|
||||
<td style="font-size:0.8rem;">${formatDate(r.created_at)}</td>
|
||||
<td><button class="btn btn-sm btn-secondary" onclick="viewReport(${r.id})">Gestisci</button></td>
|
||||
@@ -315,7 +335,7 @@
|
||||
<div style="display:flex; gap:10px; flex-wrap:wrap; margin-bottom:16px;">
|
||||
<span class="priority-badge priority-${r.priority}">${escapeHtml(priorityLabels[r.priority] || r.priority)}</span>
|
||||
<span class="status-badge status-${r.status}">${escapeHtml(statusLabels[r.status] || r.status)}</span>
|
||||
${r.is_anonymous ? '<span class="anonymous-shield"><svg viewBox="0 0 20 20" fill="currentColor" width="12" height="12"><path fill-rule="evenodd" d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z" clip-rule="evenodd"/></svg>Anonima</span>' : ''}
|
||||
${r.is_anonymous ? '<span class="anonymous-shield"><svg class="icon-inline" style="width:12px;height:12px;" aria-hidden="true"><use href="/vendor/bootstrap-italia/dist/svg/sprites.svg#it-lock"></use></svg>Anonima</span>' : ''}
|
||||
</div>
|
||||
<div style="padding:12px 16px; background:var(--gray-50); border-radius:var(--border-radius); margin-bottom:16px; font-size:0.875rem; line-height:1.6;">
|
||||
${escapeHtml(r.description)}
|
||||
@@ -329,12 +349,14 @@
|
||||
<h4 style="font-size:0.8125rem; font-weight:700; margin-bottom:8px;">Timeline</h4>
|
||||
<div>${timelineHtml || '<p style="color:var(--gray-400); font-size:0.8rem;">Nessun evento in timeline.</p>'}</div>
|
||||
<div style="margin-top:20px; display:flex; flex-direction:column; gap:10px;">
|
||||
<label for="modal-status" class="sr-only">Cambia stato</label>
|
||||
<select id="modal-status" class="form-control">
|
||||
<option value="">Cambia stato...</option>
|
||||
${['under_review','investigating','resolved','closed','rejected'].map(s =>
|
||||
`<option value="${s}" ${r.status === s ? 'selected' : ''}>${escapeHtml(statusLabels[s])}</option>`
|
||||
).join('')}
|
||||
</select>
|
||||
<label for="modal-notes" class="sr-only">Note di risoluzione</label>
|
||||
<textarea id="modal-notes" class="form-control" rows="3" placeholder="Note di risoluzione...">${escapeHtml(r.resolution_notes || '')}</textarea>
|
||||
</div>
|
||||
`, `<button class="btn btn-primary" onclick="updateReport(${id})">Salva</button>
|
||||
|
||||
Reference in New Issue
Block a user