[FEAT] Rischi #501 p3: sezione all-hazard mantenuta ma "Rischi trasversali" comprimibile
Compromesso approvato (Simon/Cristiano) al posto della cancellazione richiesta al punto 3 del #501 — validato nis2-expert (all-hazards = obbligo art.21.2 Direttiva -> art.24 D.Lgs.138/2024; rimuoverla = lacuna di conformità). - risks.html: la sezione diventa un <details> comprimibile. Header sempre visibile con titolo "Rischi trasversali (approccio multirischio / all-hazards) - art. 24 D.Lgs. 138/2024" + contatore. Apri-se-vuota (updateAllhazardHeader): vuota -> aperta (presidiata in audit), con voci -> chiusa (meno ingombro). Nota riformulata che la distingue dai "rischi di non conformità". - i18n.js custom_heading/custom_help (IT+EN) + help.js allineati. - Manuale + KB RISCHI_MODELLO.md aggiornati. Cache-buster help/i18n 20260731. - Solo frontend/statico. 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
8736d6bb4f
commit
ed0b16eee2
@@ -17,7 +17,7 @@ La tabella mostra **solo i requisiti applicabili alla tua classe** (soggetto *im
|
||||
Allegato 1; *essenziale* → Allegato 2). Se l'elenco è lungo, il riquadro **scorre in verticale**
|
||||
con l'intestazione fissa.
|
||||
|
||||
Sotto trovi una seconda tabella, **Rischi aggiuntivi (all-hazard)**: qui i profili amministrativi
|
||||
Sotto trovi una seconda sezione (comprimibile), **Rischi trasversali (all-hazards) — art. 24 D.Lgs. 138/2024**: qui i profili amministrativi
|
||||
aggiungono rischi non legati a un singolo requisito (minacce fisiche, fornitori, eventi naturali,
|
||||
errore umano) — copre l'approccio multirischio richiesto dall'art. 24 D.Lgs. 138/2024.
|
||||
|
||||
@@ -79,8 +79,7 @@ sono due piani distinti. Questa scelta evita di far dire al sistema "sei conform
|
||||
è basso", che sarebbe normativamente scorretto.
|
||||
|
||||
## 6. La matrice 5×5
|
||||
Ogni rischio con **inerente** valutato compare nella matrice 5×5 (sempre visibile), insieme ai
|
||||
rischi aggiuntivi. La matrice è uno **strumento di rappresentazione**, non un obbligo (art. 24
|
||||
Ogni rischio con **inerente** valutato compare nella matrice 5×5 (sempre visibile), insieme ai rischi trasversali. La matrice è uno **strumento di rappresentazione**, non un obbligo (art. 24
|
||||
D.Lgs. 138/2024). Esclude i requisiti "non applicabili".
|
||||
|
||||
## 7. Chi può fare cosa
|
||||
|
||||
@@ -32,8 +32,8 @@ I profili che valutano (super_admin/org_admin/compliance_manager) compilano Prob
|
||||
- **Impatto** è una scala di severità 1-5 (non euro). La matrice 5×5 (sempre visibile) esclude i requisiti "non applicabili".
|
||||
- Dall'Alert si possono creare **azioni** sul rischio (seme del futuro Modulo Azioni: registro azioni, audit, KPI, budget).
|
||||
|
||||
## Rischi aggiuntivi (all-hazard)
|
||||
Oltre ai rischi derivati dai requisiti, i profili **amministrativi** possono aggiungere "Rischi aggiuntivi" non coperti da un singolo requisito (minacce fisiche, catena di fornitura, eventi naturali, errore umano). Serve a coprire l'approccio **multirischio/all-hazard** richiesto dall'art. 24. Gli utenti non amministrativi non vedono i tasti di inserimento.
|
||||
## Rischi trasversali (all-hazards) — sezione comprimibile
|
||||
Oltre ai rischi derivati dai requisiti, i profili **amministrativi** possono registrare **rischi trasversali** non riconducibili a un singolo requisito (ambiente fisico, catena di fornitura, eventi naturali, errore umano). Copre l'approccio **multirischio/all-hazards** richiesto dall'art. 24 D.Lgs. 138/2024 (recepisce l'art. 21 §2 Direttiva UE 2022/2555). Si distingue dai «rischi di non conformità» derivati dai requisiti. La sezione è **comprimibile** e riservata agli amministrativi; resta sempre presente e, se vuota, si apre da sola. NON è stata cancellata (ticket #501 p3): rimuoverla lascerebbe scoperto un obbligo.
|
||||
|
||||
## Regole per l'assistente
|
||||
- Indirizza alla pagina dal **menu in alto "Rischi" → "Mappa dei rischi"**.
|
||||
|
||||
@@ -166,8 +166,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script>
|
||||
// ── Auth check ───────────────────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
@@ -89,8 +89,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script>
|
||||
// ── Auth check ───────────────────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
@@ -96,8 +96,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script>
|
||||
// ── Auth check ───────────────────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
@@ -1126,8 +1126,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script>
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
loadSidebar(); // = loadTopnavV3()
|
||||
|
||||
@@ -274,8 +274,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script>
|
||||
// ── Auth check ───────────────────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
+2
-2
@@ -381,8 +381,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script>
|
||||
// ── Auth & Init ─────────────────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
@@ -194,8 +194,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
/*
|
||||
|
||||
@@ -201,8 +201,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script>
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
|
||||
@@ -196,8 +196,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script src="/js/competenze.js?v=20260627"></script>
|
||||
<script>
|
||||
function v3Icons() { if (window.lucide && lucide.createIcons) { try { lucide.createIcons(); } catch (e) {} } }
|
||||
|
||||
@@ -102,8 +102,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script src="/js/connettori-discovery.js?v=20260627"></script>
|
||||
<script>
|
||||
if (typeof checkAuth === 'function' && !checkAuth()) {
|
||||
|
||||
@@ -159,8 +159,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
/* Controlli periodici (control monitoring §9.1/A.8.16): controlli ricorrenti + esecuzioni (evidenza) + NC/AC. */
|
||||
|
||||
@@ -226,8 +226,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script>
|
||||
// ── Icone inline (Lucide stroke) usate nelle stringhe HTML generate dal JS.
|
||||
// Renderizzate immediatamente (no createIcons re-run), self-host, niente sprite BI. ──
|
||||
|
||||
@@ -116,8 +116,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script src="/js/dashboard.js?v=20260724a"></script>
|
||||
<script>
|
||||
// ── Auth check ───────────────────────────────────────────
|
||||
|
||||
+2
-2
@@ -1181,8 +1181,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script>
|
||||
// La guida è accessibile anche da non autenticati (utile per onboarding)
|
||||
// ma se sei loggato carichi chrome + i18n normalmente. ZERO modifiche backend.
|
||||
|
||||
@@ -363,8 +363,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script>
|
||||
// ── Auth & Init ──────────────────────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
@@ -935,8 +935,8 @@ curl -H <span class="str">"X-API-Key: nis2_TUA_CHIAVE"</span> \
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script>
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
loadSidebar(); // = loadTopnavV3()
|
||||
|
||||
@@ -164,8 +164,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
/*
|
||||
|
||||
+2
-2
@@ -203,8 +203,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script src="/js/isms.js?v=20260627v3"></script>
|
||||
<script>
|
||||
// Icone Lucide della chrome + crumb/page-head statici. L'init dati e il wiring
|
||||
|
||||
+1
-1
@@ -611,7 +611,7 @@ const HelpSystem = (function () {
|
||||
'La colonna <strong>Alert</strong> compare in base al punteggio inerente: <em>Azione Prioritaria</em> (15–25), <em>Azione Critica</em> (9–12), <em>Azione Necessaria</em> (3–8), <em>Azione Suggerita</em> (1–2). Le soglie sono una <strong>scelta metodologica</strong> dell\'organizzazione (rif. ISO/IEC 27001 §6.1.2), <strong>non un obbligo di legge</strong>. Cliccando l\'Alert si apre l\'elenco delle azioni passate su quel rischio e si può <strong>creare una nuova azione</strong>.',
|
||||
'La colonna <strong>Esito residuo</strong> segnala se il rischio residuo va <strong>rivalutato</strong> (punteggio 9–25) o è <strong>adeguato</strong> (1–8). <strong>Importante</strong>: il punteggio di rischio residuo <strong>non</strong> determina automaticamente lo <em>stato di conformità</em> del requisito. La <strong>conformità</strong> dipende dall\'attuazione della misura e dalle evidenze e si aggiorna in modo esplicito dal link "stato" nella colonna Rischio Residuo. Sono due piani distinti (punteggio di rischio ≠ conformità al requisito).',
|
||||
'La tabella elenca <strong>solo i requisiti applicabili alla tua classe</strong> (importante → Allegato 1, essenziale → Allegato 2 della Determinazione ACN 164179/2025). Se l\'elenco e\' lungo, il riquadro <strong>scorre verticalmente</strong> con l\'intestazione fissa.',
|
||||
'La seconda tabella, <strong>Rischi aggiuntivi (approccio multirischio / all-hazard)</strong>, permette ai <strong>profili amministrativi</strong> 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.'
|
||||
'La seconda sezione, <strong>Rischi trasversali (approccio multirischio / all-hazards)</strong> — comprimibile, riservata ai <strong>profili amministrativi</strong> — serve a registrare le minacce non riconducibili a un singolo requisito (ambiente fisico, catena di fornitura, eventi naturali, errore umano): copre l\'approccio multirischio richiesto dall\'art. 24 D.Lgs. 138/2024 (che recepisce l\'art. 21 §2 della Direttiva (UE) 2022/2555). Si distingue dai «rischi di non conformità» derivati dai requisiti. La sezione resta sempre presente: se è vuota si apre da sola.'
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
+2
-2
@@ -182,8 +182,8 @@ const I18n = (function () {
|
||||
'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.custom_heading': { it: 'Rischi trasversali (approccio multirischio / all-hazards) — art. 24 D.Lgs. 138/2024', en: 'Cross-cutting risks (multi-risk / all-hazards approach) — art. 24 Legislative Decree 138/2024' },
|
||||
'risks.custom_help': { it: 'Qui si registrano le minacce non riconducibili a un singolo requisito (ambiente fisico, catena di fornitura, eventi naturali, errore umano), come richiesto dall\'approccio multirischio/all-hazards (art. 24 D.Lgs. 138/2024, che recepisce l\'art. 21 §2 della Direttiva (UE) 2022/2555). Si distinguono dai «rischi di non conformità» della tabella qui sopra, che misurano il mancato o parziale soddisfacimento dei singoli requisiti.', en: 'Register here the threats not attributable to a single requirement (physical environment, supply chain, natural events, human error), as required by the multi-risk / all-hazards approach (art. 24 Legislative Decree 138/2024, transposing art. 21(2) of Directive (EU) 2022/2555). They differ from the “non-compliance risks” in the table above, which measure the missed or partial fulfilment of individual requirements.' },
|
||||
'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).' },
|
||||
'risks.matrix_subtitle': { it: 'Rischi da requisiti (valutati) + aggiuntivi — esclusi i non applicabili', en: 'Requirement-derived risks (evaluated) + additional ones — non-applicable excluded' },
|
||||
'risks.col_probability': { it: 'Probabilità', en: 'Likelihood' },
|
||||
|
||||
+2
-2
@@ -179,8 +179,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script src="/js/kb.js"></script>
|
||||
<script>
|
||||
// Gate auth + chrome come le altre pagine V3.
|
||||
|
||||
@@ -151,8 +151,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
/*
|
||||
|
||||
@@ -179,8 +179,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
/*
|
||||
|
||||
@@ -141,8 +141,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script>
|
||||
// ── Auth + chrome + i18n + help ──────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
@@ -155,8 +155,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script src="/js/organigramma.js?v=20260627"></script>
|
||||
<script>
|
||||
// Render icone Lucide (chrome + crumb + bottoni). organigramma.js fa render albero
|
||||
|
||||
@@ -344,8 +344,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script>
|
||||
// ── Auth & Init ─────────────────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
+2
-2
@@ -145,8 +145,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script src="/js/raci.js?v=20260627"></script>
|
||||
<script>
|
||||
function v3Icons() { if (window.lucide && lucide.createIcons) { try { lucide.createIcons(); } catch (e) {} } }
|
||||
|
||||
+2
-2
@@ -236,8 +236,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script>
|
||||
// ── Auth & Init ─────────────────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
@@ -161,8 +161,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
/*
|
||||
|
||||
+50
-6
@@ -344,6 +344,24 @@
|
||||
.act-row .act-when { font-size:0.72rem; color:var(--gray-500); white-space:nowrap; min-width:74px; }
|
||||
.act-row .act-desc { flex:1; font-size:0.82rem; color:var(--gray-800); }
|
||||
.act-row .act-st { font-size:0.68rem; font-weight:700; text-transform:uppercase; color:var(--gray-500); }
|
||||
/* ── Sezione "Rischi trasversali (all-hazards)" comprimibile (#501 p3) ── */
|
||||
details.allhazard { margin: 4px 0 8px; }
|
||||
details.allhazard > summary {
|
||||
list-style: none; cursor: pointer; display: flex; align-items: center; gap: 10px;
|
||||
padding: 12px 14px; border: 1px solid var(--gray-200, #e4e9f1); border-radius: 10px;
|
||||
background: var(--gray-50, #f7f9fc); font-weight: 700; color: var(--gray-800, #1e2e46);
|
||||
font-size: 1.02rem;
|
||||
}
|
||||
details.allhazard > summary::-webkit-details-marker { display: none; }
|
||||
details.allhazard > summary:hover { background: #eef2f8; }
|
||||
details.allhazard .ah-caret { display: inline-flex; color: var(--gray-500, #7382a0); transition: transform .15s; }
|
||||
details.allhazard[open] > summary .ah-caret { transform: rotate(90deg); }
|
||||
details.allhazard .ah-title { flex: 1; min-width: 0; }
|
||||
details.allhazard .ah-count {
|
||||
display: inline-flex; align-items: center; justify-content: center; min-width: 26px; height: 22px;
|
||||
padding: 0 8px; border-radius: 20px; background: #e5edfb; color: #1f529e; font-size: 0.8rem; font-weight: 800;
|
||||
}
|
||||
details.allhazard .ah-count.empty { background: #fdeaea; color: #c0392b; }
|
||||
</style>
|
||||
<!-- PWA:start -->
|
||||
<link rel="manifest" href="/manifest.webmanifest">
|
||||
@@ -434,11 +452,18 @@
|
||||
</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>
|
||||
<!-- ── SEZIONE 2: Rischi trasversali (multirischio / all-hazards) — accordion (#501 p3) ── -->
|
||||
<details id="allhazard-section" class="allhazard" open>
|
||||
<summary class="allhazard-summary">
|
||||
<span class="ah-caret" aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2"><path d="m9 18 6-6-6-6"/></svg>
|
||||
</span>
|
||||
<span class="ah-title" data-i18n="risks.custom_heading">Rischi trasversali (approccio multirischio / all-hazards) — art. 24 D.Lgs. 138/2024</span>
|
||||
<span class="ah-count" id="allhazard-count" aria-hidden="true"></span>
|
||||
</summary>
|
||||
<p class="text-muted" style="font-size:0.82rem;margin:10px 0 16px;line-height:1.5;" data-i18n="risks.custom_help">Qui si registrano le minacce non riconducibili a un singolo requisito (ambiente fisico, catena di fornitura, eventi naturali, errore umano), come richiesto dall'approccio multirischio/all-hazards (art. 24 D.Lgs. 138/2024, che recepisce l'art. 21 §2 della Direttiva (UE) 2022/2555). Si distinguono dai «rischi di non conformità» della tabella qui sopra, che misurano il mancato o parziale soddisfacimento dei singoli requisiti.</p>
|
||||
|
||||
<!-- Table View (rischi custom) -->
|
||||
<!-- Table View (rischi trasversali) -->
|
||||
<div id="view-table">
|
||||
<div class="filters-bar">
|
||||
<select class="form-select" id="filter-category" onchange="loadRisks()" aria-label="Filtra per categoria">
|
||||
@@ -486,6 +511,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<!-- Matrix View (sempre visibile) -->
|
||||
<div id="view-matrix" style="margin-top:16px;">
|
||||
@@ -544,8 +570,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script>
|
||||
// ── Auth & Init ──────────────────────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
@@ -1018,6 +1044,7 @@
|
||||
if (result.success) {
|
||||
risksData = (result.data && result.data.items) || [];
|
||||
renderRisksTable(risksData);
|
||||
updateAllhazardHeader(risksData.length);
|
||||
} else {
|
||||
showNotification(result.message || 'Errore nel caricamento rischi', 'error');
|
||||
}
|
||||
@@ -1026,6 +1053,23 @@
|
||||
}
|
||||
}
|
||||
|
||||
// ── Header sezione "Rischi trasversali": contatore + apri-se-vuota (una volta).
|
||||
// Normativo: la sezione resta sempre presente; se è VUOTA si apre da sola così
|
||||
// in audit risulta presidiata, non nascosta (parere nis2-expert, #501 p3). ──
|
||||
let _allhazardInit = false;
|
||||
function updateAllhazardHeader(count) {
|
||||
const badge = document.getElementById('allhazard-count');
|
||||
const sec = document.getElementById('allhazard-section');
|
||||
if (badge) {
|
||||
badge.textContent = count;
|
||||
badge.classList.toggle('empty', count === 0);
|
||||
}
|
||||
if (sec && !_allhazardInit) {
|
||||
_allhazardInit = true;
|
||||
sec.open = (count === 0); // vuota → aperta; con voci → chiusa (meno ingombro)
|
||||
}
|
||||
}
|
||||
|
||||
// ── Table Render ─────────────────────────────────────────────
|
||||
function renderRisksTable(risks) {
|
||||
const tbody = document.getElementById('risks-table-body');
|
||||
|
||||
@@ -739,8 +739,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script>
|
||||
// ── Auth check ───────────────────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
@@ -219,8 +219,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
/*
|
||||
|
||||
@@ -214,8 +214,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
/*
|
||||
|
||||
@@ -546,8 +546,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script>
|
||||
// ── Auth & Init ─────────────────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
@@ -194,8 +194,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script>
|
||||
// ── Auth & Init (ordine V3) ─────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
@@ -262,8 +262,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script>
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
loadSidebar();
|
||||
|
||||
@@ -147,8 +147,8 @@
|
||||
<script src="/js/common.js?v=20260729b"></script>
|
||||
<script src="/vendor/lucide/lucide.min.js"></script>
|
||||
<script src="/js/topnav-v3.js?v=20260729"></script>
|
||||
<script src="/js/i18n.js?v=20260730b"></script>
|
||||
<script src="/js/help.js?v=20260730b"></script>
|
||||
<script src="/js/i18n.js?v=20260731"></script>
|
||||
<script src="/js/help.js?v=20260731"></script>
|
||||
<script>
|
||||
// ── Auth + chrome + i18n + help ──────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
Reference in New Issue
Block a user