[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:
DevEnv nis2-agile
2026-06-12 14:49:15 +02:00
co-authored by Claude Opus 4.8
parent 36967f9452
commit 1c64211685
28 changed files with 2474 additions and 3105 deletions
+43 -29
View File
@@ -4,6 +4,10 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Impostazioni - 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/modali/form) -> 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>
.settings-tabs {
@@ -199,7 +203,7 @@
<main class="main-content">
<header class="content-header">
<h2 data-i18n="settings.title">Impostazioni</h2>
<h1 class="h2" data-i18n="settings.title">Impostazioni</h1>
<div class="content-header-actions">
<span class="text-muted" id="header-org-name"></span>
</div>
@@ -245,11 +249,11 @@
<form id="org-form" onsubmit="saveOrganization(event)">
<div class="form-row">
<div class="form-group">
<label class="form-label">Nome Organizzazione <span class="required">*</span></label>
<label for="org-name" class="form-label">Nome Organizzazione <span class="required">*</span></label>
<input type="text" class="form-input" id="org-name" required>
</div>
<div class="form-group">
<label class="form-label">Settore NIS2 <span class="required">*</span></label>
<label for="org-sector" class="form-label">Settore NIS2 <span class="required">*</span></label>
<select class="form-select" id="org-sector" required>
<option value="">Seleziona settore...</option>
<option value="energy">Energia</option>
@@ -275,55 +279,55 @@
<div class="form-row">
<div class="form-group">
<label class="form-label">Partita IVA</label>
<label for="org-vat" class="form-label">Partita IVA</label>
<input type="text" class="form-input" id="org-vat" placeholder="IT12345678901">
</div>
<div class="form-group">
<label class="form-label">Codice Fiscale</label>
<label for="org-fiscal" class="form-label">Codice Fiscale</label>
<input type="text" class="form-input" id="org-fiscal">
</div>
</div>
<div class="form-row">
<div class="form-group">
<label class="form-label">Numero Dipendenti</label>
<label for="org-employees" class="form-label">Numero Dipendenti</label>
<input type="number" class="form-input" id="org-employees" min="0" placeholder="0">
</div>
<div class="form-group">
<label class="form-label">Fatturato Annuo (EUR)</label>
<label for="org-turnover" class="form-label">Fatturato Annuo (EUR)</label>
<input type="number" class="form-input" id="org-turnover" min="0" step="1000" placeholder="0">
</div>
</div>
<div class="form-row">
<div class="form-group">
<label class="form-label">Paese</label>
<label for="org-country" class="form-label">Paese</label>
<input type="text" class="form-input" id="org-country" placeholder="IT">
</div>
<div class="form-group">
<label class="form-label">Citta'</label>
<label for="org-city" class="form-label">Citta'</label>
<input type="text" class="form-input" id="org-city">
</div>
</div>
<div class="form-group">
<label class="form-label">Indirizzo</label>
<label for="org-address" class="form-label">Indirizzo</label>
<input type="text" class="form-input" id="org-address">
</div>
<div class="form-row">
<div class="form-group">
<label class="form-label">Sito Web</label>
<label for="org-website" class="form-label">Sito Web</label>
<input type="url" class="form-input" id="org-website" placeholder="https://...">
</div>
<div class="form-group">
<label class="form-label">Email di Contatto</label>
<label for="org-email" class="form-label">Email di Contatto</label>
<input type="email" class="form-input" id="org-email">
</div>
</div>
<div class="form-group">
<label class="form-label">Telefono di Contatto</label>
<label for="org-phone" class="form-label">Telefono di Contatto</label>
<input type="tel" class="form-input" id="org-phone" style="max-width:320px;">
</div>
@@ -349,24 +353,24 @@
<form id="profile-form" onsubmit="saveProfile(event)">
<div class="form-group">
<label class="form-label">Email</label>
<label for="profile-email" class="form-label">Email</label>
<input type="email" class="form-input" id="profile-email" disabled style="background:var(--gray-50); max-width:400px;">
<span class="form-help">L'email non puo' essere modificata.</span>
</div>
<div class="form-row">
<div class="form-group">
<label class="form-label">Nome Completo <span class="required">*</span></label>
<label for="profile-name" class="form-label">Nome Completo <span class="required">*</span></label>
<input type="text" class="form-input" id="profile-name" required>
</div>
<div class="form-group">
<label class="form-label">Telefono</label>
<label for="profile-phone" class="form-label">Telefono</label>
<input type="tel" class="form-input" id="profile-phone">
</div>
</div>
<div class="form-group" style="max-width:320px;">
<label class="form-label">Lingua Preferita</label>
<label for="profile-language" class="form-label">Lingua Preferita</label>
<select class="form-select" id="profile-language">
<option value="it">Italiano</option>
<option value="en">English</option>
@@ -391,12 +395,12 @@
<form id="password-form" onsubmit="changePassword(event)">
<div class="form-group" style="max-width:400px;">
<label class="form-label">Password Attuale <span class="required">*</span></label>
<label for="pw-current" class="form-label">Password Attuale <span class="required">*</span></label>
<input type="password" class="form-input" id="pw-current" required autocomplete="current-password">
</div>
<div class="form-group" style="max-width:400px;">
<label class="form-label">Nuova Password <span class="required">*</span></label>
<label for="pw-new" class="form-label">Nuova Password <span class="required">*</span></label>
<input type="password" class="form-input" id="pw-new" required autocomplete="new-password" oninput="checkPasswordStrength(this.value)">
<div class="strength-bar" id="pw-strength-bar">
<div class="strength-segment" id="pw-seg-1"></div>
@@ -408,7 +412,7 @@
</div>
<div class="form-group" style="max-width:400px;">
<label class="form-label">Conferma Nuova Password <span class="required">*</span></label>
<label for="pw-confirm" class="form-label">Conferma Nuova Password <span class="required">*</span></label>
<input type="password" class="form-input" id="pw-confirm" required autocomplete="new-password">
</div>
@@ -465,14 +469,14 @@
</div>
<div class="form-group">
<label style="display:flex; gap:10px; align-items:center; font-size:.9rem;">
<label for="pref-notif-email" style="display:flex; gap:10px; align-items:center; font-size:.9rem;">
<input type="checkbox" id="pref-notif-email">
<span>Ricevi notifiche via email (incidenti, deadline, training)</span>
</label>
</div>
<div class="form-group">
<label style="display:flex; gap:10px; align-items:center; font-size:.9rem;">
<label for="pref-notif-inapp" style="display:flex; gap:10px; align-items:center; font-size:.9rem;">
<input type="checkbox" id="pref-notif-inapp">
<span>Mostra notifiche in-app (badge sidebar)</span>
</label>
@@ -657,6 +661,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>
@@ -936,7 +950,7 @@
// Voluntary toggle (only visible for not_applicable entities)
const voluntaryToggle = type === 'not_applicable' ? `
<div style="margin-top:16px; padding:16px; background:var(--gray-50); border-radius:var(--border-radius); border:1px solid var(--gray-200);">
<label style="display:flex; align-items:center; gap:10px; cursor:pointer;">
<label for="org-voluntary" style="display:flex; align-items:center; gap:10px; cursor:pointer;">
<input type="checkbox" id="org-voluntary" ${isVoluntary ? 'checked' : ''}
onchange="toggleVoluntaryCompliance(this.checked)"
style="accent-color:var(--primary); width:18px; height:18px; flex-shrink:0;">
@@ -1234,11 +1248,11 @@
showModal('Invita Membro', `
<p style="margin-bottom:16px; font-size:0.875rem; color:var(--gray-600);">Aggiungi un membro esistente alla tua organizzazione. L'utente deve gia' essere registrato sulla piattaforma.</p>
<div class="form-group">
<label class="form-label">Email del Membro <span class="required">*</span></label>
<label for="invite-email" class="form-label">Email del Membro <span class="required">*</span></label>
<input type="email" class="form-input" id="invite-email" placeholder="utente@esempio.it" required>
</div>
<div class="form-group">
<label class="form-label">Ruolo <span class="required">*</span></label>
<label for="invite-role" class="form-label">Ruolo <span class="required">*</span></label>
<select class="form-select" id="invite-role">
<option value="employee">Dipendente</option>
<option value="compliance_manager">Compliance Manager</option>
@@ -1368,7 +1382,7 @@
function showCreateApiKeyModal() {
showModal('Crea API Key', `
<div class="form-group">
<label class="form-label">Nome *</label>
<label for="apikey-name" class="form-label">Nome *</label>
<input type="text" id="apikey-name" class="form-control" placeholder="Es. SIEM Integration, Dashboard ESG..." required>
</div>
<div class="form-group">
@@ -1383,7 +1397,7 @@
</div>
</div>
<div class="form-group">
<label class="form-label">Scadenza (opzionale)</label>
<label for="apikey-expires" class="form-label">Scadenza (opzionale)</label>
<input type="date" id="apikey-expires" class="form-control">
</div>
`, '<button class="btn btn-primary" onclick="createApiKey()">Crea API Key</button>');
@@ -1485,11 +1499,11 @@
).join('');
showModal('Crea Webhook', `
<div class="form-group">
<label class="form-label">Nome *</label>
<label for="wh-name" class="form-label">Nome *</label>
<input type="text" id="wh-name" class="form-control" placeholder="Es. SIEM Integration, 231 Agile Notify...">
</div>
<div class="form-group">
<label class="form-label">URL Endpoint * (https://...)</label>
<label for="wh-url" class="form-label">URL Endpoint * (https://...)</label>
<input type="url" id="wh-url" class="form-control" placeholder="https://your-siem.example.com/webhooks/nis2">
</div>
<div class="form-group">