[FEAT] Rischi #500 fase 2 (frontend): elenco rischi = requisiti Lex&ISO
La pagina Gestione Rischi mostra come tabella primaria (read-only) i requisiti del framework Lex&ISO come rischi, codice RSK-<misura>Com.N via /api/risks/derived, filtrati per classe (importante All.1 / essenziale All.2). Framing normativo (validato nis2-expert): ogni voce = "rischio derivante dal mancato/parziale soddisfacimento del requisito", mai "requisito = rischio"; RSK e "92" NON come codici/numeri ufficiali ACN; matrice = strumento di rappresentazione (art.24). - Rischi CUSTOM mantenuti in sezione "Rischi aggiuntivi (all-hazard)". - Tasti "Nuovo Rischio"/"AI Suggerisci" limitati a super_admin/org_admin (non rimossi): l'inserimento libero serve al multirischio (art.24 D.Lgs.138/2024). - api.js derivedRisks(); help.js + i18n aggiornati; version 1.25.4; SW v1.25.4. - Cache-buster api/help/i18n ?v=20260727r. Backend/DB non toccati. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
571e151305
commit
4e7e75582a
@@ -70,7 +70,7 @@
|
||||
</script>
|
||||
|
||||
<!-- Stessa logica della app: api.js + common.js (helper) + common-bi.js (override BI) -->
|
||||
<script src="js/api.js?v=20260627u"></script>
|
||||
<script src="js/api.js?v=20260727r"></script>
|
||||
<script src="js/common.js?v=20260624g"></script>
|
||||
<script src="js/common-bi.js?v=20260625d"></script>
|
||||
<script>
|
||||
|
||||
@@ -162,12 +162,12 @@
|
||||
</main>
|
||||
|
||||
<!-- Scripts V3: api.js → common.js (helper+FAB reali) → Lucide → topnav-v3.js (chrome) → i18n → init pagina -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script>
|
||||
// ── Auth check ───────────────────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
@@ -85,12 +85,12 @@
|
||||
</main>
|
||||
|
||||
<!-- Scripts V3: api.js → common.js (helper+FAB reali) → Lucide → topnav-v3.js (chrome) → i18n → init pagina -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script>
|
||||
// ── Auth check ───────────────────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
@@ -92,12 +92,12 @@
|
||||
</main>
|
||||
|
||||
<!-- Scripts V3: api.js → common.js (helper+FAB reali) → Lucide → topnav-v3.js (chrome) → i18n → init pagina -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script>
|
||||
// ── Auth check ───────────────────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
@@ -1122,12 +1122,12 @@
|
||||
|
||||
<!-- Scripts V3: api.js → common.js (helper+FAB reali) → Lucide self-host →
|
||||
topnav-v3.js (chrome, ridefinisce loadSidebar) → i18n → help -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script>
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
loadSidebar(); // = loadTopnavV3()
|
||||
|
||||
@@ -270,12 +270,12 @@
|
||||
<!-- Scripts V3: api.js → common.js (helper+FAB reali) → Lucide self-host →
|
||||
topnav-v3.js (chrome, ridefinisce loadSidebar) → i18n → help. La logica
|
||||
pagina (wizard GAP) resta inline: usa gli stessi id/funzioni di prima. -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script>
|
||||
// ── Auth check ───────────────────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
+3
-3
@@ -377,12 +377,12 @@
|
||||
|
||||
<!-- Scripts V3: api.js → common.js (helper+FAB reali) → Lucide self-host →
|
||||
topnav-v3.js (chrome, ridefinisce loadSidebar) → i18n → help → pagina -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script>
|
||||
// ── Auth & Init ─────────────────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
@@ -190,12 +190,12 @@
|
||||
<!-- Scripts V3: api.js → common.js (helper+FAB reali) → Lucide self-host →
|
||||
topnav-v3.js (chrome, ridefinisce loadSidebar) → i18n → help. La logica del
|
||||
calendario (aggregatore read-only) resta inline e usa gli stessi id/funzioni. -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
/*
|
||||
|
||||
@@ -139,12 +139,12 @@
|
||||
</main>
|
||||
|
||||
<!-- Scripts V3: api.js → common.js (helper+FAB reali) → Lucide → topnav-v3.js (chrome) → i18n → help → init pagina -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script>
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
|
||||
@@ -192,12 +192,12 @@
|
||||
</div>
|
||||
|
||||
<!-- Scripts V3. competenze.js si auto-inizializza su DOMContentLoaded (checkAuth/loadSidebar/I18n/Help). -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script src="/js/competenze.js?v=20260627"></script>
|
||||
<script>
|
||||
function v3Icons() { if (window.lucide && lucide.createIcons) { try { lucide.createIcons(); } catch (e) {} } }
|
||||
|
||||
@@ -98,12 +98,12 @@
|
||||
|
||||
<!-- Scripts V3: api.js → common.js (helper+FAB reali) → Lucide self-host →
|
||||
topnav-v3.js (chrome, ridefinisce loadSidebar) → i18n → help → pagina -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script src="/js/connettori-discovery.js?v=20260627"></script>
|
||||
<script>
|
||||
if (typeof checkAuth === 'function' && !checkAuth()) {
|
||||
|
||||
@@ -155,12 +155,12 @@
|
||||
|
||||
<!-- Scripts V3: api.js → common.js (helper+FAB reali) → Lucide self-host →
|
||||
topnav-v3.js (chrome, ridefinisce loadSidebar) → i18n → help → init pagina -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
/* Controlli periodici (control monitoring §9.1/A.8.16): controlli ricorrenti + esecuzioni (evidenza) + NC/AC. */
|
||||
|
||||
@@ -222,12 +222,12 @@
|
||||
|
||||
<!-- Scripts V3: api.js → common.js (helper+FAB reali) → Lucide self-host →
|
||||
topnav-v3.js (chrome, ridefinisce loadSidebar) → i18n → help → init pagina -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script>
|
||||
// ── Icone inline (Lucide stroke) usate nelle stringhe HTML generate dal JS.
|
||||
// Renderizzate immediatamente (no createIcons re-run), self-host, niente sprite BI. ──
|
||||
|
||||
@@ -112,12 +112,12 @@
|
||||
<!-- Scripts V3: api.js (client REST, prima) → common.js (helper+FAB reali) →
|
||||
Lucide self-host → topnav-v3.js (chrome, ridefinisce loadSidebar) →
|
||||
i18n → help → dashboard.js -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script src="/js/dashboard.js?v=20260724a"></script>
|
||||
<script>
|
||||
// ── Auth check ───────────────────────────────────────────
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
</script>
|
||||
|
||||
<!-- Stessa logica della forgot-password.html: ZERO modifiche backend -->
|
||||
<script src="js/api.js?v=20260627u"></script>
|
||||
<script src="js/api.js?v=20260727r"></script>
|
||||
<script>
|
||||
const form = document.getElementById('forgot-form');
|
||||
const err = document.getElementById('err');
|
||||
|
||||
+3
-3
@@ -1177,12 +1177,12 @@
|
||||
|
||||
<!-- Scripts V3: api.js → common.js (helper+FAB reali) → Lucide self-host →
|
||||
topnav-v3.js (chrome, ridefinisce loadSidebar) → i18n → help -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script>
|
||||
// La guida è accessibile anche da non autenticati (utile per onboarding)
|
||||
// ma se sei loggato carichi chrome + i18n normalmente. ZERO modifiche backend.
|
||||
|
||||
@@ -359,12 +359,12 @@
|
||||
|
||||
<!-- Scripts V3: api.js → common.js (helper+FAB reali) → Lucide self-host →
|
||||
topnav-v3.js (chrome, ridefinisce loadSidebar) → i18n → help → pagina -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script>
|
||||
// ── Auth & Init ──────────────────────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
@@ -931,12 +931,12 @@ curl -H <span class="str">"X-API-Key: nis2_TUA_CHIAVE"</span> \
|
||||
|
||||
<!-- Scripts V3: api.js → common.js (helper+FAB reali) → Lucide self-host →
|
||||
topnav-v3.js (chrome, ridefinisce loadSidebar) → i18n → help -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script>
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
loadSidebar(); // = loadTopnavV3()
|
||||
|
||||
@@ -160,12 +160,12 @@
|
||||
|
||||
<!-- Scripts V3: api.js → common.js (helper+FAB reali) → Lucide self-host →
|
||||
topnav-v3.js (chrome, ridefinisce loadSidebar) → i18n → help → init pagina -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
/*
|
||||
|
||||
+3
-3
@@ -199,12 +199,12 @@
|
||||
<!-- Scripts V3: api.js → common.js (helper+FAB reali) → Lucide self-host →
|
||||
topnav-v3.js (chrome, ridefinisce loadSidebar) → i18n → help → isms.js.
|
||||
isms.js si auto-inizializza su DOMContentLoaded (checkAuth/I18n/loadSidebar/Help/render). -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script src="/js/isms.js?v=20260627v3"></script>
|
||||
<script>
|
||||
// Icone Lucide della chrome + crumb/page-head statici. L'init dati e il wiring
|
||||
|
||||
@@ -410,6 +410,7 @@ class NIS2API {
|
||||
updateRisk(id, data) { return this.put(`/risks/${id}`, data); }
|
||||
deleteRisk(id) { return this.del(`/risks/${id}`); }
|
||||
getRiskMatrix() { return this.get('/risks/matrix'); }
|
||||
derivedRisks() { return this.get('/risks/derived'); }
|
||||
aiSuggestRisks() { return this.post('/risks/ai-suggest', {}); }
|
||||
// FAIR quantitativo + KRI (P2)
|
||||
computeFair(id, data) { return this.post(`/risks/${id}/fair`, data); }
|
||||
|
||||
+11
-1
@@ -599,11 +599,21 @@ const HelpSystem = (function () {
|
||||
// ─── Risk Management ─────────────────────────────────────────
|
||||
'risks': {
|
||||
title: 'Guida - Gestione Rischi',
|
||||
intro: 'Il modulo di Gestione Rischi consente di identificare, valutare e trattare i rischi di sicurezza informatica in conformita\' con l\'art. 24 del D.Lgs. 138/2024 (che recepisce l\'art. 21 della Direttiva (UE) 2022/2555). Include una matrice di rischio interattiva e strumenti per il monitoraggio continuo.',
|
||||
intro: 'In questa pagina i rischi corrispondono ai requisiti del framework di sicurezza applicabili alla tua organizzazione e alla loro valutazione. I requisiti derivano dalle misure di sicurezza di base della Determinazione ACN n. 164179 del 14/4/2025 (Allegato 1 per i soggetti importanti, Allegato 2 per gli essenziali). Ogni voce rappresenta il rischio derivante dal mancato o parziale soddisfacimento del requisito, non il requisito in se\'. Tutto in conformita\' con l\'art. 24 del D.Lgs. 138/2024 (che recepisce l\'art. 21 della Direttiva (UE) 2022/2555).',
|
||||
sections: [
|
||||
{
|
||||
heading: 'Come leggere i rischi in questa pagina',
|
||||
items: [
|
||||
'La <strong>prima tabella</strong> elenca i rischi <strong>derivati dai requisiti</strong> del framework di sicurezza: ogni voce e\' il <strong>rischio di non conformita\'</strong> legato al mancato o parziale soddisfacimento di un requisito, <strong>non il requisito in se\'</strong>. E\' un elenco in <strong>sola lettura</strong>.',
|
||||
'Il codice <strong>RSK-‹misura›Com.‹n›</strong> e\' una <strong>codifica interna di NIS2 Agile</strong>; ‹misura› (es. GV.OC-04) e\' il codice della misura del Framework Nazionale richiamato dalla Determinazione ACN 164179/2025. <strong>Non</strong> e\' un codice o numero ufficiale ACN.',
|
||||
'La colonna <strong>Conformita\'</strong> mostra lo stato di valutazione del requisito (Da valutare, Non conforme, Parziale, Conforme). I requisiti <strong>non applicabili alla tua classe</strong> (importante vs essenziale) sono mostrati in grigio.',
|
||||
'La seconda tabella, <strong>Rischi aggiuntivi (approccio multirischio / all-hazard)</strong>, permette ai <strong>profili amministrativi</strong> (org_admin, super_admin) di aggiungere rischi non coperti da un singolo requisito (minacce fisiche, catena di fornitura, eventi naturali): copre l\'approccio multirischio richiesto dall\'art. 24 D.Lgs. 138/2024.'
|
||||
]
|
||||
},
|
||||
{
|
||||
heading: 'Matrice di Rischio',
|
||||
items: [
|
||||
'La matrice 5×5 e\' uno <strong>strumento di rappresentazione</strong>, non un obbligo normativo: l\'art. 24 D.Lgs. 138/2024 richiede un\'analisi dei rischi proporzionata e con approccio multirischio, senza imporre una metodologia specifica.',
|
||||
'La <strong>matrice Probabilita\' x Impatto</strong> (5x5) classifica automaticamente i rischi in base alla loro gravita\'.',
|
||||
'I livelli di probabilita\' vanno da <em>Molto Bassa</em> a <em>Molto Alta</em>.',
|
||||
'I livelli di impatto vanno da <em>Trascurabile</em> a <em>Critico</em>.',
|
||||
|
||||
@@ -159,6 +159,16 @@ const I18n = (function () {
|
||||
'risks.accept': { it: 'Accettare', en: 'Accept' },
|
||||
'risks.transfer': { it: 'Trasferire', en: 'Transfer' },
|
||||
'risks.avoid': { it: 'Evitare', en: 'Avoid' },
|
||||
'risks.derived_heading': { it: 'Rischi dai requisiti del framework di sicurezza', en: 'Risks from security framework requirements' },
|
||||
'risks.derived_code_legend': { it: 'RSK-‹misura›Com.‹n› è una codifica interna di NIS2 Agile; ‹misura› (es. GV.OC-04) è il codice della misura del Framework Nazionale richiamato dalla Determinazione ACN 164179/2025. Elenco in sola lettura.', en: 'RSK-‹measure›Com.‹n› is an internal NIS2 Agile code; ‹measure› (e.g. GV.OC-04) is the National Framework measure code referenced by ACN Determination 164179/2025. Read-only list.' },
|
||||
'risks.col_code': { it: 'Codice', en: 'Code' },
|
||||
'risks.col_risk': { it: 'Rischio', en: 'Risk' },
|
||||
'risks.col_measure': { it: 'Misura', en: 'Measure' },
|
||||
'risks.col_conformity': { it: 'Conformità', en: 'Conformity' },
|
||||
'risks.col_evaluation': { it: 'Valutazione', en: 'Evaluation' },
|
||||
'risks.custom_heading': { it: 'Rischi aggiuntivi (approccio multirischio / all-hazard)', en: 'Additional risks (multi-risk / all-hazard approach)' },
|
||||
'risks.custom_help': { it: 'Oltre ai rischi derivati dai requisiti, i profili amministrativi possono aggiungere rischi non coperti da un singolo requisito (es. minacce fisiche, catena di fornitura, eventi naturali): copre l\'approccio multirischio/all-hazard (art. 24 D.Lgs. 138/2024).', en: 'Beyond the requirement-derived risks, administrative profiles can add risks not covered by a single requirement (e.g. physical threats, supply chain, natural events): this covers the multi-risk/all-hazard approach (art. 24 Legislative Decree 138/2024).' },
|
||||
'risks.matrix_caption': { it: 'La matrice 5×5 è uno strumento di rappresentazione, non un obbligo normativo (art. 24 D.Lgs. 138/2024).', en: 'The 5×5 matrix is a representation tool, not a regulatory obligation (art. 24 Legislative Decree 138/2024).' },
|
||||
|
||||
// ── Incidenti ──────────────────────────────────
|
||||
'incidents.title': { it: 'Gestione Incidenti', en: 'Incident Management' },
|
||||
|
||||
+3
-3
@@ -175,12 +175,12 @@
|
||||
|
||||
<!-- Scripts V3: api.js → common.js (helper+FAB reali) → Lucide self-host →
|
||||
topnav-v3.js (chrome, ridefinisce loadSidebar) → i18n → help → kb.js -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script src="/js/kb.js"></script>
|
||||
<script>
|
||||
// Gate auth + chrome come le altre pagine V3.
|
||||
|
||||
@@ -515,7 +515,7 @@ body { background: var(--bg-main); }
|
||||
|
||||
<div id="toast"></div>
|
||||
|
||||
<script src="js/api.js?v=20260627u"></script>
|
||||
<script src="js/api.js?v=20260727r"></script>
|
||||
<script>
|
||||
// ══════════════════════════════════════════════════════
|
||||
// CONFIG
|
||||
|
||||
+1
-1
@@ -94,7 +94,7 @@
|
||||
</script>
|
||||
|
||||
<!-- Stessa logica della login attuale: ZERO modifiche backend -->
|
||||
<script src="js/api.js?v=20260627u"></script>
|
||||
<script src="js/api.js?v=20260727r"></script>
|
||||
<script src="js/common.js?v=20260624g"></script>
|
||||
<script>
|
||||
if (api.isAuthenticated()) { window.location.href = 'dashboard.html'; }
|
||||
|
||||
@@ -147,12 +147,12 @@
|
||||
|
||||
<!-- Scripts V3: api.js → common.js (helper+FAB reali) → Lucide self-host →
|
||||
topnav-v3.js (chrome, ridefinisce loadSidebar) → i18n → help → init pagina -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
/*
|
||||
|
||||
@@ -175,12 +175,12 @@
|
||||
</div>
|
||||
|
||||
<!-- Scripts V3 (ordine ESATTO come dashboard.html) -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
/*
|
||||
|
||||
@@ -137,12 +137,12 @@
|
||||
</main>
|
||||
|
||||
<!-- Scripts V3 (ordine ESATTO come dashboard.html) -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script>
|
||||
// ── Auth + chrome + i18n + help ──────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
@@ -494,7 +494,7 @@
|
||||
</script>
|
||||
|
||||
<!-- Stessa logica della onboarding.html: ZERO modifiche backend -->
|
||||
<script src="js/api.js?v=20260627u"></script>
|
||||
<script src="js/api.js?v=20260727r"></script>
|
||||
<script src="js/common.js?v=20260624g"></script>
|
||||
<script>
|
||||
// ── Auth check ──────────────────────────────────────────────────
|
||||
|
||||
@@ -151,12 +151,12 @@
|
||||
<!-- Scripts V3: api.js → common.js (helper+FAB reali) → Lucide self-host →
|
||||
topnav-v3.js (chrome, ridefinisce loadSidebar) → i18n → help → organigramma.js.
|
||||
organigramma.js si auto-inizializza su DOMContentLoaded (checkAuth/loadSidebar/I18n/Help). -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script src="/js/organigramma.js?v=20260627"></script>
|
||||
<script>
|
||||
// Render icone Lucide (chrome + crumb + bottoni). organigramma.js fa render albero
|
||||
|
||||
@@ -340,12 +340,12 @@
|
||||
|
||||
<!-- Scripts V3: api.js → common.js (helper+FAB reali) → Lucide self-host →
|
||||
topnav-v3.js (chrome, ridefinisce loadSidebar) → i18n → help → pagina -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script>
|
||||
// ── Auth & Init ─────────────────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
+3
-3
@@ -141,12 +141,12 @@
|
||||
</main>
|
||||
|
||||
<!-- Scripts V3. raci.js si auto-inizializza su DOMContentLoaded (checkAuth/loadSidebar/I18n/Help). -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script src="/js/raci.js?v=20260627"></script>
|
||||
<script>
|
||||
function v3Icons() { if (window.lucide && lucide.createIcons) { try { lucide.createIcons(); } catch (e) {} } }
|
||||
|
||||
@@ -268,7 +268,7 @@
|
||||
</script>
|
||||
|
||||
<!-- Stessa logica della register.html: ZERO modifiche backend -->
|
||||
<script src="js/api.js?v=20260627u"></script>
|
||||
<script src="js/api.js?v=20260727r"></script>
|
||||
<script src="js/common.js?v=20260624g"></script>
|
||||
<script>
|
||||
if (api.isAuthenticated()) { window.location.href = 'dashboard.html'; }
|
||||
|
||||
+3
-3
@@ -232,12 +232,12 @@
|
||||
|
||||
<!-- Scripts V3: api.js → common.js (helper+FAB reali) → Lucide self-host →
|
||||
topnav-v3.js (chrome, ridefinisce loadSidebar) → i18n → help → init pagina -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script>
|
||||
// ── Auth & Init ─────────────────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
@@ -157,12 +157,12 @@
|
||||
</div>
|
||||
|
||||
<!-- Scripts V3 (ordine ESATTO come dashboard.html) -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
/*
|
||||
|
||||
+155
-6
@@ -331,12 +331,57 @@
|
||||
<button class="btn-ghost" id="btn-ai-suggest" onclick="aiSuggest()">
|
||||
<i data-lucide="sparkles" class="ic"></i>AI Suggerisci
|
||||
</button>
|
||||
<button class="btn-primary" onclick="showRiskModal()"><i data-lucide="plus" class="ic"></i>Nuovo Rischio</button>
|
||||
<button class="btn-primary" id="btn-new-risk" onclick="showRiskModal()"><i data-lucide="plus" class="ic"></i>Nuovo Rischio</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-body">
|
||||
<!-- Table View -->
|
||||
<!-- ── Nota introduttiva (framing normativo) ───────────── -->
|
||||
<div class="risk-intro-note" style="display:flex;gap:12px;align-items:flex-start;padding:16px 18px;background:var(--gray-50);border:1px solid var(--gray-200);border-left:4px solid var(--primary);border-radius:var(--border-radius);margin-bottom:24px;">
|
||||
<i data-lucide="info" class="ic" style="flex-shrink:0;color:var(--primary);margin-top:2px;"></i>
|
||||
<p style="font-size:0.85rem;color:var(--gray-700);line-height:1.55;margin:0;">
|
||||
In questa pagina i rischi corrispondono ai requisiti del framework di sicurezza applicabili alla tua organizzazione e alla loro valutazione. I requisiti derivano dalle misure di sicurezza di base della Determinazione ACN n. 164179 del 14/4/2025 (Allegato 1 per i soggetti importanti, Allegato 2 per gli essenziali). Ogni voce rappresenta il rischio derivante dal mancato o parziale soddisfacimento del requisito, non il requisito in sé. La valutazione e la matrice 5×5 sono uno strumento di rappresentazione: la normativa (art. 24 D.Lgs. 138/2024) richiede un'analisi dei rischi proporzionata e con approccio multirischio, senza imporre una metodologia specifica.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- ── SEZIONE 1: Rischi derivati dai requisiti (PRIMARIA, read-only) ── -->
|
||||
<div id="view-derived" style="margin-bottom:32px;">
|
||||
<div style="display:flex;justify-content:space-between;align-items:baseline;flex-wrap:wrap;gap:8px;margin-bottom:10px;">
|
||||
<h2 style="font-size:1.05rem;margin:0;" data-i18n="risks.derived_heading">Rischi dai requisiti del framework di sicurezza</h2>
|
||||
<span class="text-muted" style="font-size:0.78rem;" id="derived-source-note"></span>
|
||||
</div>
|
||||
<p class="text-muted" style="font-size:0.78rem;margin:0 0 12px;">
|
||||
<span data-i18n="risks.derived_code_legend">RSK-‹misura›Com.‹n› è una codifica interna di NIS2 Agile; ‹misura› (es. GV.OC-04) è il codice della misura del Framework Nazionale richiamato dalla Determinazione ACN 164179/2025. Elenco in sola lettura.</span>
|
||||
</p>
|
||||
<div class="card">
|
||||
<div class="table-container">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" data-i18n="risks.col_code">Codice</th>
|
||||
<th scope="col" data-i18n="risks.col_risk">Rischio</th>
|
||||
<th scope="col" data-i18n="risks.col_measure">Misura</th>
|
||||
<th scope="col" data-i18n="risks.col_conformity">Conformità</th>
|
||||
<th scope="col" data-i18n="risks.col_evaluation">Valutazione</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="derived-table-body">
|
||||
<tr>
|
||||
<td colspan="5">
|
||||
<div class="spinner" style="margin:40px auto;"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── SEZIONE 2: Rischi aggiuntivi (multirischio / all-hazard) ── -->
|
||||
<h2 style="font-size:1.05rem;margin:0 0 6px;" data-i18n="risks.custom_heading">Rischi aggiuntivi (approccio multirischio / all-hazard)</h2>
|
||||
<p class="text-muted" style="font-size:0.82rem;margin:0 0 16px;line-height:1.5;" data-i18n="risks.custom_help">Oltre ai rischi derivati dai requisiti, i profili amministrativi possono aggiungere rischi non coperti da un singolo requisito (es. minacce fisiche, catena di fornitura, eventi naturali): copre l'approccio multirischio/all-hazard (art. 24 D.Lgs. 138/2024).</p>
|
||||
|
||||
<!-- Table View (rischi custom) -->
|
||||
<div id="view-table">
|
||||
<div class="filters-bar">
|
||||
<select class="form-select" id="filter-category" onchange="loadRisks()" aria-label="Filtra per categoria">
|
||||
@@ -426,6 +471,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-muted" style="font-size:0.78rem;text-align:center;margin:16px auto 0;max-width:640px;line-height:1.5;" data-i18n="risks.matrix_caption">La matrice 5×5 è uno strumento di rappresentazione, non un obbligo normativo (art. 24 D.Lgs. 138/2024).</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -437,12 +483,12 @@
|
||||
|
||||
<!-- Scripts V3: api.js → common.js (helper+FAB reali) → Lucide self-host →
|
||||
topnav-v3.js (chrome, ridefinisce loadSidebar) → i18n → help → pagina -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script>
|
||||
// ── Auth & Init ──────────────────────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
@@ -489,11 +535,112 @@
|
||||
// ── State ────────────────────────────────────────────────────
|
||||
let currentView = 'table';
|
||||
let risksData = [];
|
||||
let derivedData = [];
|
||||
let orgClass = null;
|
||||
|
||||
// ── Gating ruolo: creazione/AI riservate ai profili amministrativi ──
|
||||
const ADMIN_ROLES = ['super_admin', 'org_admin'];
|
||||
(function gateAdminActions() {
|
||||
const role = (api.getUserRole && api.getUserRole()) || '';
|
||||
if (!ADMIN_ROLES.includes(role)) {
|
||||
['btn-ai-suggest', 'btn-new-risk'].forEach(id => {
|
||||
const el = document.getElementById(id);
|
||||
if (el) el.style.display = 'none';
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
||||
// ── Load ─────────────────────────────────────────────────────
|
||||
loadDerivedRisks();
|
||||
loadRisks();
|
||||
loadMatrix();
|
||||
|
||||
// ── Derived Risks (requisiti del framework) ──────────────────
|
||||
// Badge conformità per lo stato di valutazione del requisito.
|
||||
const DERIVED_STATUS_BADGE = {
|
||||
da_valutare: { cls: 'badge-neutral', label: 'Da valutare' },
|
||||
non_applicabile: { cls: 'badge-neutral', label: 'Non applicabile' },
|
||||
non_conforme: { cls: 'badge-danger', label: 'Non conforme' },
|
||||
parziale: { cls: 'badge-warning', label: 'Parziale' },
|
||||
conforme: { cls: 'badge-success', label: 'Conforme' },
|
||||
};
|
||||
|
||||
function isDerivedApplicable(r) {
|
||||
// important → applicabili solo i requisiti Allegato 1; essential → Allegato 2;
|
||||
// classe non determinata / adesione volontaria → tutti applicabili.
|
||||
if (orgClass === 'important') return r.applies_important == 1;
|
||||
if (orgClass === 'essential') return r.applies_essential == 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
async function loadDerivedRisks() {
|
||||
try {
|
||||
const result = await api.derivedRisks();
|
||||
if (result && result.success && result.data) {
|
||||
orgClass = result.data.org_class || null;
|
||||
derivedData = result.data.risks || [];
|
||||
const src = result.data.source || '';
|
||||
const note = document.getElementById('derived-source-note');
|
||||
if (note && src) note.textContent = 'Fonte: ' + src;
|
||||
renderDerivedTable(derivedData);
|
||||
} else {
|
||||
renderDerivedTable([]);
|
||||
}
|
||||
} catch (e) {
|
||||
renderDerivedTable([]);
|
||||
}
|
||||
}
|
||||
|
||||
function renderDerivedTable(rows) {
|
||||
const tbody = document.getElementById('derived-table-body');
|
||||
if (!rows || rows.length === 0) {
|
||||
tbody.innerHTML = `
|
||||
<tr><td colspan="5">
|
||||
<div class="empty-state">
|
||||
<svg viewBox="0 0 20 20" fill="currentColor"><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.944z" clip-rule="evenodd"/></svg>
|
||||
<h4>Nessun requisito applicabile</h4>
|
||||
<p>Non risultano requisiti del framework di sicurezza per questa organizzazione.</p>
|
||||
</div>
|
||||
</td></tr>`;
|
||||
return;
|
||||
}
|
||||
|
||||
let html = '';
|
||||
rows.forEach(r => {
|
||||
const applicable = isDerivedApplicable(r);
|
||||
const st = DERIVED_STATUS_BADGE[r.stato] || DERIVED_STATUS_BADGE.da_valutare;
|
||||
const measureCode = r.misura_code || '-';
|
||||
const reqCode = r.requisito_code || '';
|
||||
const reqDescr = r.requisito_descr || '';
|
||||
const measureDescr = r.misura_descr || '';
|
||||
const evalVal = (r.valutazione_rischio !== null && r.valutazione_rischio !== undefined && r.valutazione_rischio !== '')
|
||||
? escapeHtml(String(r.valutazione_rischio)) : '—';
|
||||
const rowStyle = applicable ? '' : 'style="opacity:0.5;"';
|
||||
const riskTooltip = `Rischio derivante dal mancato o parziale soddisfacimento del requisito ${measureCode} ${reqCode}`.trim();
|
||||
|
||||
// Colonna "Rischio": etichetta + requisito come OGGETTO del rischio (mai il requisito nudo).
|
||||
const conformityCell = applicable
|
||||
? `<span class="badge ${st.cls}">${escapeHtml(st.label)}</span>`
|
||||
: `<span class="badge badge-neutral">Non applicabile alla tua classe</span>`;
|
||||
|
||||
html += `
|
||||
<tr ${rowStyle}>
|
||||
<td><code style="font-size:0.78rem;color:var(--primary);">${escapeHtml(r.risk_code || '-')}</code></td>
|
||||
<td title="${escapeHtml(riskTooltip)}">
|
||||
<div style="font-size:0.68rem;text-transform:uppercase;letter-spacing:0.04em;font-weight:600;color:var(--gray-500);margin-bottom:2px;">Rischio di non conformità</div>
|
||||
<div style="font-size:0.86rem;color:var(--gray-800);">${escapeHtml(reqDescr)}</div>
|
||||
</td>
|
||||
<td>
|
||||
<code style="font-size:0.75rem;color:var(--gray-600);">${escapeHtml(measureCode)}</code>
|
||||
${measureDescr ? `<div style="font-size:0.78rem;color:var(--gray-500);margin-top:2px;">${escapeHtml(measureDescr)}</div>` : ''}
|
||||
</td>
|
||||
<td>${conformityCell}</td>
|
||||
<td>${evalVal}</td>
|
||||
</tr>`;
|
||||
});
|
||||
tbody.innerHTML = html;
|
||||
}
|
||||
|
||||
async function loadRisks() {
|
||||
const params = {};
|
||||
const cat = document.getElementById('filter-category').value;
|
||||
@@ -666,6 +813,7 @@
|
||||
}
|
||||
|
||||
function renderDetail(risk) {
|
||||
document.getElementById('view-derived').classList.add('hidden');
|
||||
document.getElementById('view-table').classList.add('hidden');
|
||||
document.getElementById('view-matrix').classList.add('hidden');
|
||||
const container = document.getElementById('view-detail');
|
||||
@@ -839,7 +987,8 @@
|
||||
|
||||
function backToList() {
|
||||
document.getElementById('view-detail').classList.add('hidden');
|
||||
// Tabella e matrice sono entrambe sempre visibili.
|
||||
// Sezione derivati, tabella custom e matrice sono sempre visibili.
|
||||
document.getElementById('view-derived').classList.remove('hidden');
|
||||
document.getElementById('view-table').classList.remove('hidden');
|
||||
document.getElementById('view-matrix').classList.remove('hidden');
|
||||
}
|
||||
|
||||
@@ -735,12 +735,12 @@
|
||||
<!-- Scripts V3: api.js (client REST, prima) → common.js (helper+FAB reali) →
|
||||
Lucide self-host → topnav-v3.js (chrome, ridefinisce loadSidebar) →
|
||||
i18n → help → init pagina (inline, invariato). -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script>
|
||||
// ── Auth check ───────────────────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
@@ -215,12 +215,12 @@
|
||||
|
||||
<!-- Scripts V3: api.js → common.js (helper+FAB reali) → Lucide self-host →
|
||||
topnav-v3.js (chrome, ridefinisce loadSidebar) → i18n → help → init pagina -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
/*
|
||||
|
||||
@@ -210,12 +210,12 @@
|
||||
|
||||
<!-- Scripts V3: api.js → common.js (helper+FAB reali) → Lucide self-host →
|
||||
topnav-v3.js (chrome, ridefinisce loadSidebar) → i18n → help → init pagina -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
/*
|
||||
|
||||
@@ -542,12 +542,12 @@
|
||||
|
||||
<!-- Scripts V3: api.js → common.js (helper+FAB reali) → Lucide self-host →
|
||||
topnav-v3.js (chrome, ridefinisce loadSidebar) → i18n → help → init pagina -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script>
|
||||
// ── Auth & Init ─────────────────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@
|
||||
* Il nome cache include la release: va BUMPATO ad ogni rilascio (vedi version.json),
|
||||
* cosi' activate elimina automaticamente la shell vecchia.
|
||||
*/
|
||||
const CACHE = 'nis2-shell-v1.25.0';
|
||||
const CACHE = 'nis2-shell-v1.25.4';
|
||||
|
||||
// Shell V3 (top-nav): niente più style.css/common-bi.js/bootstrap-italia (UI V2).
|
||||
const PRECACHE = [
|
||||
|
||||
@@ -190,12 +190,12 @@
|
||||
<!-- Scripts V3: api.js → common.js (helper+FAB reali+showModal/showNotification) →
|
||||
Lucide self-host → topnav-v3.js (chrome, ridefinisce loadSidebar) → i18n → help.
|
||||
La logica della pagina e' inline (nessun training.js): preservata invariata. -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script>
|
||||
// ── Auth & Init (ordine V3) ─────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
{"version": "1.25.3", "build": "2026-07-27-v1.25.3", "date": "2026-07-27", "changelog": "Gestione Rischi (ticket #500 fase 2, backend): nuovo endpoint GET /api/risks/derived che deriva l'elenco dei rischi dai requisiti del framework LEX&ISO (Determinazione ACN n. 164179/2025) con codifica RSK-<misura>Com.N (es. RSK-GV.OC-04Com.1). Additivo, read-only, non tocca la tabella rischi. Prossimo passo: la pagina rischi consumera' questo elenco e verranno rimossi i bottoni 'Nuovo Rischio' e 'AI Suggerisci'."}
|
||||
{"version": "1.25.4", "build": "2026-07-27-v1.25.4", "date": "2026-07-27", "changelog": "Gestione Rischi (ticket #500): l'elenco dei rischi mostra ora i requisiti del framework Lex&ISO applicabili alla tua organizzazione, con codice interno RSK-<misura>Com.N (es. RSK-GV.OC-04Com.1) e lo stato di conformita'. Ogni voce rappresenta il rischio derivante dal mancato o parziale soddisfacimento del requisito (Determinazione ACN n. 164179/2025). I 'Rischi aggiuntivi' (approccio multirischio/all-hazard) restano inseribili dai profili amministrativi. La matrice 5x5 e' uno strumento di rappresentazione (art. 24 D.Lgs. 138/2024)."}
|
||||
|
||||
@@ -258,12 +258,12 @@
|
||||
|
||||
<!-- Scripts V3: api.js → common.js (helper+FAB reali) → Lucide self-host →
|
||||
topnav-v3.js (chrome, ridefinisce loadSidebar) → i18n → help → init pagina -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script>
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
loadSidebar();
|
||||
|
||||
@@ -143,12 +143,12 @@
|
||||
|
||||
<!-- Scripts V3: api.js → common.js (helper+FAB reali) → Lucide self-host →
|
||||
topnav-v3.js (chrome, ridefinisce loadSidebar) → i18n → help → init pagina. -->
|
||||
<script src="/js/api.js?v=20260627u"></script>
|
||||
<script src="/js/api.js?v=20260727r"></script>
|
||||
<script src="/js/common.js?v=20260627t"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260627t"></script>
|
||||
<script src="/js/i18n.js?v=20260627p"></script>
|
||||
<script src="/js/help.js?v=20260727a"></script>
|
||||
<script src="/js/i18n.js?v=20260727r"></script>
|
||||
<script src="/js/help.js?v=20260727r"></script>
|
||||
<script>
|
||||
// ── Auth + chrome + i18n + help ──────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
Reference in New Issue
Block a user