[FEAT] #384 p.2.2/3 — colonne multi-valore + link attivi bidirezionali Policy<->Misure e Requisiti

Misure e Requisiti: colonna Policy (default) mostra tutte le policy collegate al
requisito come codici Policy.NN cliccabili -> aprono la policy (policies.html?policy=ID).
Policy: colonna Requisito NIS2 mostra tutti i requisiti collegati (codifica MISURA+
REQUISITO, es. 'DE.CM-01 comma 1.') come link -> evidenziano il requisito
(misure-requisiti.html?requisito=ID). Backend: FrameworkController::catalog espone
policies[] per requisito e PolicyController::list espone requisiti[] per policy
(org-scoped, tabella requisito_policy mig.059, try/catch con degrado al dato di default).
Solo lettura/visualizzazione: nessuna modifica dati, nessuna migrazione.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
DevEnv nis2-agile
2026-06-18 19:25:16 +02:00
co-authored by Claude Opus 4.8
parent 02f3e69227
commit cb238e8380
5 changed files with 114 additions and 5 deletions
+19 -2
View File
@@ -410,6 +410,19 @@
currentView = 'list';
}
// Ticket #384 p.2.2/p.3 — colonna "Requisito NIS2" multi-valore con link attivi a MISURE E REQUISITI.
// Il codice mostrato e' MISURA + REQUISITO (dal backend, tabella requisito_policy). In assenza di
// associazioni degrada al campo nis2_article, com'era prima.
function renderReqLinks(p) {
const reqs = (p && p.requisiti) || [];
if (reqs.length) {
return reqs.map(r =>
`<a class="text-link" href="misure-requisiti.html?requisito=${r.id}" title="Vai al requisito in Misure e Requisiti">${escapeHtml(r.code || r.misura_code || '')}</a>`
).join(', ');
}
return escapeHtml(p.nis2_article || '-');
}
// ── Load Policies ───────────────────────────────────────
async function loadPolicies() {
const params = {};
@@ -475,7 +488,7 @@
<span class="text-link" onclick="viewPolicy(${p.id})">${escapeHtml(p.title)}</span>
</td>
<td>${escapeHtml(catLabel)}</td>
<td>${escapeHtml(p.nis2_article || '-')}</td>
<td>${renderReqLinks(p)}</td>
<td>${escapeHtml(p.version || '1.0')}</td>
<td><span class="badge ${badgeClass}">${escapeHtml(statusLabel)}</span></td>
<td>${formatDate(p.next_review_date)}</td>
@@ -1075,7 +1088,11 @@
}
// ── Init ────────────────────────────────────────────────
loadPolicies();
loadPolicies().then(function () {
// Ticket #384 p.3 — deep-link da MISURE E REQUISITI: ?policy=ID apre il dettaglio della policy.
const pid = parseInt(new URLSearchParams(location.search).get('policy') || '', 10);
if (pid) viewPolicy(pid);
});
</script>
</body>
</html>