[FEAT] Epic C / C4 — inventario a 2 voci + sottoclassi configurabili (mig.050)
Simon C4: nell'inventario DUE sole voci principali; le sottoclassi le crea l'utente.
Riconduzione concordata (no perdita di dettaglio): hardware/network/facility -> ID.AM-01;
software/service/data -> ID.AM-02; personnel -> Organigramma (0 asset personnel presenti).
- Config: cfg_inventory_voci (2: ID.AM-01 Hardware, ID.AM-02 Software/Servizi/Sistemi),
inventory_subclassi (12 default di sistema org NULL + sottoclassi org-scoped).
- assets.voce_code + subclass_id (FK). 20 asset esistenti MIGRATI (5 ID.AM-01 / 15 ID.AM-02).
- AssetController: list con label voce/sottoclasse; create/update validati (voce in whitelist,
sottoclasse appartenente a org/default+voce); GET/POST /assets/subclasses; import (bulkUpsert)
deriva la voce dal tipo legacy. asset_type resta come campo legacy (viste secondarie).
- assets.html: filtro per voce, form con selettore Voce + Sottoclasse (+ '+ aggiungi'),
lista/dettaglio mostrano 'voce · sottoclasse', stat-chips per voce.
- FIX bug pre-esistente: apostrofo non escapato ('l'inventario') che ROMPEVA tutto il JS
della pagina Inventario. + cache-buster common-bi.js (era a v=20260618, non bumpato dal fix C3).
Help + KB + i18n. Verifiche prod: subclasses 200, create voce/legacy OK, validazione 422,
JS valido (node --check), migrazione idempotente. version 1.18.4.
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
e281aa4970
commit
30f4614b37
@@ -70,9 +70,9 @@
|
||||
</script>
|
||||
|
||||
<!-- Stessa logica della app: api.js + common.js (helper) + common-bi.js (override BI) -->
|
||||
<script src="js/api.js?v=20260624"></script>
|
||||
<script src="js/common.js?v=20260624"></script>
|
||||
<script src="js/common-bi.js?v=20260618"></script>
|
||||
<script src="js/api.js?v=20260625"></script>
|
||||
<script src="js/common.js?v=20260625"></script>
|
||||
<script src="js/common-bi.js?v=20260625"></script>
|
||||
<script>
|
||||
// Renderizza la sidebar BI (loadSidebar è stato ridefinito da common-bi.js)
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
|
||||
@@ -1088,10 +1088,10 @@
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<script src="js/api.js?v=20260624"></script>
|
||||
<script src="js/common.js?v=20260624"></script>
|
||||
<script src="js/i18n.js?v=20260624"></script>
|
||||
<script src="js/help.js?v=20260624"></script>
|
||||
<script src="js/api.js?v=20260625"></script>
|
||||
<script src="js/common.js?v=20260625"></script>
|
||||
<script src="js/i18n.js?v=20260625"></script>
|
||||
<script src="js/help.js?v=20260625"></script>
|
||||
<script>
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
loadSidebar();
|
||||
|
||||
@@ -154,8 +154,8 @@
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<script src="/js/api.js?v=20260624"></script>
|
||||
<script src="/js/common.js?v=20260624"></script>
|
||||
<script src="/js/api.js?v=20260625"></script>
|
||||
<script src="/js/common.js?v=20260625"></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). -->
|
||||
@@ -165,9 +165,9 @@
|
||||
bootstrap.loadFonts('/vendor/bootstrap-italia/dist/fonts');
|
||||
}
|
||||
</script>
|
||||
<script src="/js/common-bi.js?v=20260618"></script>
|
||||
<script src="/js/i18n.js?v=20260624"></script>
|
||||
<script src="/js/help.js?v=20260624"></script>
|
||||
<script src="/js/common-bi.js?v=20260625"></script>
|
||||
<script src="/js/i18n.js?v=20260625"></script>
|
||||
<script src="/js/help.js?v=20260625"></script>
|
||||
<script>
|
||||
// ── Auth check ───────────────────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
+67
-30
@@ -331,14 +331,9 @@
|
||||
<!-- Filters -->
|
||||
<div class="filters-bar">
|
||||
<select id="filter-type" onchange="applyFilters()" aria-label="Filtra per tipo">
|
||||
<option value="">Tutti i tipi</option>
|
||||
<option value="hardware">Hardware</option>
|
||||
<option value="software">Software</option>
|
||||
<option value="network">Rete</option>
|
||||
<option value="data">Dati</option>
|
||||
<option value="service">Servizio</option>
|
||||
<option value="personnel">Personale</option>
|
||||
<option value="facility">Struttura</option>
|
||||
<option value="">Tutte le voci</option>
|
||||
<option value="ID.AM-01">Hardware (ID.AM-01)</option>
|
||||
<option value="ID.AM-02">Software/Servizi/Sistemi (ID.AM-02)</option>
|
||||
</select>
|
||||
<select id="filter-criticality" onchange="applyFilters()" aria-label="Filtra per criticità">
|
||||
<option value="">Tutte le criticita'</option>
|
||||
@@ -366,8 +361,8 @@
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<script src="/js/api.js?v=20260624"></script>
|
||||
<script src="/js/common.js?v=20260624"></script>
|
||||
<script src="/js/api.js?v=20260625"></script>
|
||||
<script src="/js/common.js?v=20260625"></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). -->
|
||||
@@ -377,15 +372,16 @@
|
||||
bootstrap.loadFonts('/vendor/bootstrap-italia/dist/fonts');
|
||||
}
|
||||
</script>
|
||||
<script src="/js/common-bi.js?v=20260618"></script>
|
||||
<script src="/js/i18n.js?v=20260624"></script>
|
||||
<script src="/js/help.js?v=20260624"></script>
|
||||
<script src="/js/common-bi.js?v=20260625"></script>
|
||||
<script src="/js/i18n.js?v=20260625"></script>
|
||||
<script src="/js/help.js?v=20260625"></script>
|
||||
<script>
|
||||
// ── Auth & Init ─────────────────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
loadSidebar();
|
||||
I18n.init();
|
||||
HelpSystem.init();
|
||||
loadSubclasses(); // C4 — voci+sottoclassi per i selettori (fire-and-forget, pronto al primo "Nuovo")
|
||||
|
||||
// ── Labels ──────────────────────────────────────────────
|
||||
const typeLabels = {
|
||||
@@ -411,6 +407,42 @@
|
||||
decommissioned: 'Dismesso'
|
||||
};
|
||||
|
||||
// ── Voci / sottoclassi (Epic C / C4) ────────────────────
|
||||
const VOCE_LABELS = { 'ID.AM-01': 'Hardware', 'ID.AM-02': 'Software/Servizi/Sistemi' };
|
||||
let SUBCLASSES = []; // [{voce_code,label,subclassi:[{id,label,is_default}]}]
|
||||
function assetTipo(a) {
|
||||
const v = a.voce_label || VOCE_LABELS[a.voce_code] || (typeLabels[a.asset_type] || a.asset_type || '-');
|
||||
return a.subclass_label ? (v + ' · ' + a.subclass_label) : v;
|
||||
}
|
||||
async function loadSubclasses() {
|
||||
try { const r = await api.listAssetSubclasses(); if (r && r.success) SUBCLASSES = (r.data && r.data.voci) || []; }
|
||||
catch (e) { SUBCLASSES = []; }
|
||||
}
|
||||
function voceOptionsHtml(sel) {
|
||||
return ['ID.AM-01', 'ID.AM-02'].map(v =>
|
||||
`<option value="${v}" ${sel === v ? 'selected' : ''}>${v} — ${VOCE_LABELS[v]}</option>`).join('');
|
||||
}
|
||||
function subclassOptionsHtml(voce, sel) {
|
||||
const grp = SUBCLASSES.find(g => g.voce_code === voce);
|
||||
const subs = grp ? grp.subclassi : [];
|
||||
return '<option value="">— nessuna —</option>' + subs.map(s =>
|
||||
`<option value="${s.id}" ${String(sel) === String(s.id) ? 'selected' : ''}>${escapeHtml(s.label)}</option>`).join('');
|
||||
}
|
||||
function onVoceChange() {
|
||||
const voce = document.getElementById('asset-voce').value;
|
||||
document.getElementById('asset-subclass').innerHTML = subclassOptionsHtml(voce, '');
|
||||
}
|
||||
async function addSubclassPrompt() {
|
||||
const voce = document.getElementById('asset-voce').value;
|
||||
const label = (prompt('Nuova sottoclasse per «' + VOCE_LABELS[voce] + '»:') || '').trim();
|
||||
if (!label) return;
|
||||
try {
|
||||
const r = await api.addAssetSubclass({ voce_code: voce, label: label });
|
||||
if (r && r.success) { await loadSubclasses(); document.getElementById('asset-subclass').innerHTML = subclassOptionsHtml(voce, r.data.id); showNotification('Sottoclasse aggiunta.', 'success'); }
|
||||
else showNotification((r && r.message) || 'Errore.', 'warning');
|
||||
} catch (e) { showNotification('Errore aggiunta sottoclasse.', 'warning'); }
|
||||
}
|
||||
|
||||
// ── State ───────────────────────────────────────────────
|
||||
let allAssets = [];
|
||||
|
||||
@@ -423,7 +455,6 @@
|
||||
const type = document.getElementById('filter-type').value;
|
||||
const criticality = document.getElementById('filter-criticality').value;
|
||||
const status = document.getElementById('filter-status').value;
|
||||
if (type) params.asset_type = type;
|
||||
if (criticality) params.criticality = criticality;
|
||||
if (status) params.status = status;
|
||||
|
||||
@@ -431,13 +462,14 @@
|
||||
const result = await api.listAssets(params);
|
||||
if (result.success) {
|
||||
allAssets = result.data || [];
|
||||
updateStats(allAssets);
|
||||
renderAssets(allAssets);
|
||||
const view = type ? allAssets.filter(a => a.voce_code === type) : allAssets;
|
||||
updateStats(view);
|
||||
renderAssets(view);
|
||||
} else {
|
||||
container.innerHTML = '<div class="empty-state-box"><h4>Errore nel caricamento</h4><p>' + escapeHtml(result.message || '') + '</p></div>';
|
||||
}
|
||||
} catch (e) {
|
||||
container.innerHTML = '<div class="empty-state-box"><h4>Errore di connessione</h4><p>Impossibile caricare l'inventario.</p></div>';
|
||||
container.innerHTML = '<div class="empty-state-box"><h4>Errore di connessione</h4><p>Impossibile caricare l\'inventario.</p></div>';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -455,7 +487,7 @@
|
||||
let criticalCount = 0;
|
||||
let decommCount = 0;
|
||||
assets.forEach(a => {
|
||||
const t = a.asset_type || 'unknown';
|
||||
const t = a.voce_label || VOCE_LABELS[a.voce_code] || 'Non classificato';
|
||||
typeCount[t] = (typeCount[t] || 0) + 1;
|
||||
if (a.criticality === 'critical') criticalCount++;
|
||||
if (a.status === 'decommissioned') decommCount++;
|
||||
@@ -469,7 +501,7 @@
|
||||
// Type chips
|
||||
const chipsEl = document.getElementById('stat-type-chips');
|
||||
chipsEl.innerHTML = Object.entries(typeCount).map(([type, count]) =>
|
||||
`<span class="type-chip"><strong>${count}</strong> ${typeLabels[type] || type}</span>`
|
||||
`<span class="type-chip"><strong>${count}</strong> ${escapeHtml(type)}</span>`
|
||||
).join('');
|
||||
}
|
||||
|
||||
@@ -508,7 +540,7 @@
|
||||
html += `
|
||||
<tr onclick="showAssetDetail(${asset.id})" title="Visualizza dettagli">
|
||||
<td style="font-weight:500;">${escapeHtml(asset.name)}</td>
|
||||
<td>${typeLabels[asset.asset_type] || asset.asset_type || '-'}</td>
|
||||
<td>${escapeHtml(assetTipo(asset))}</td>
|
||||
<td>${escapeHtml(asset.category || '-')}</td>
|
||||
<td><span class="criticality-badge ${crit}">${criticalityLabels[crit] || crit}</span></td>
|
||||
<td>${relevanceBadge(asset)}</td>
|
||||
@@ -656,8 +688,8 @@
|
||||
showModal(escapeHtml(a.name), `
|
||||
<div class="detail-grid">
|
||||
<div class="detail-field">
|
||||
<div class="detail-field-label">Tipo</div>
|
||||
<div class="detail-field-value">${typeLabels[a.asset_type] || a.asset_type || '-'}</div>
|
||||
<div class="detail-field-label">Voce / sottoclasse</div>
|
||||
<div class="detail-field-value">${escapeHtml(assetTipo(a))}</div>
|
||||
</div>
|
||||
<div class="detail-field">
|
||||
<div class="detail-field-label">Categoria</div>
|
||||
@@ -773,9 +805,9 @@
|
||||
function showAssetModal(title, asset, onSave) {
|
||||
const a = asset || {};
|
||||
|
||||
const typeOptions = Object.entries(typeLabels).map(([val, label]) =>
|
||||
`<option value="${val}" ${a.asset_type === val ? 'selected' : ''}>${label}</option>`
|
||||
).join('');
|
||||
const voceSel = a.voce_code || 'ID.AM-01';
|
||||
const voceOpts = voceOptionsHtml(a.voce_code);
|
||||
const subOpts = subclassOptionsHtml(voceSel, a.subclass_id);
|
||||
|
||||
const critOptions = Object.entries(criticalityLabels).map(([val, label]) =>
|
||||
`<option value="${val}" ${a.criticality === val ? 'selected' : ''}>${label}</option>`
|
||||
@@ -795,14 +827,18 @@
|
||||
</div>
|
||||
<div class="form-grid-2">
|
||||
<div class="form-group">
|
||||
<label for="asset-type" class="form-label">Tipo *</label>
|
||||
<select class="form-select" id="asset-type">${typeOptions}</select>
|
||||
<label for="asset-voce" class="form-label">Voce inventario *</label>
|
||||
<select class="form-select" id="asset-voce" onchange="onVoceChange()">${voceOpts}</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="asset-category" class="form-label">Categoria</label>
|
||||
<input type="text" class="form-input" id="asset-category" value="${escapeHtml(a.category || '')}" placeholder="Es: Server, Database...">
|
||||
<label for="asset-subclass" class="form-label">Sottoclasse <a href="#" onclick="addSubclassPrompt();return false;" style="font-weight:400;font-size:.78rem;margin-left:6px;">+ aggiungi</a></label>
|
||||
<select class="form-select" id="asset-subclass">${subOpts}</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="asset-category" class="form-label">Categoria (etichetta libera)</label>
|
||||
<input type="text" class="form-input" id="asset-category" value="${escapeHtml(a.category || '')}" placeholder="Opzionale: nota libera">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="asset-description" class="form-label">Descrizione</label>
|
||||
<textarea class="form-input" id="asset-description" rows="2">${escapeHtml(a.description || '')}</textarea>
|
||||
@@ -875,7 +911,8 @@
|
||||
|
||||
const data = {
|
||||
name: name,
|
||||
asset_type: document.getElementById('asset-type').value,
|
||||
voce_code: document.getElementById('asset-voce').value,
|
||||
subclass_id: document.getElementById('asset-subclass').value || null,
|
||||
category: document.getElementById('asset-category').value.trim() || null,
|
||||
description: document.getElementById('asset-description').value.trim() || null,
|
||||
criticality: document.getElementById('asset-criticality').value,
|
||||
|
||||
@@ -349,14 +349,14 @@
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<script src="js/api.js?v=20260624"></script>
|
||||
<script src="js/common.js?v=20260624"></script>
|
||||
<script src="js/api.js?v=20260625"></script>
|
||||
<script src="js/common.js?v=20260625"></script>
|
||||
<!-- Bootstrap Italia bundle + override sidebar BI (common-bi.js dopo common.js: ridefinisce solo loadSidebar) -->
|
||||
<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?v=20260618"></script>
|
||||
<script src="js/i18n.js?v=20260624"></script>
|
||||
<script src="js/help.js?v=20260624"></script>
|
||||
<script src="js/common-bi.js?v=20260625"></script>
|
||||
<script src="js/i18n.js?v=20260625"></script>
|
||||
<script src="js/help.js?v=20260625"></script>
|
||||
<script>
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
|
||||
@@ -183,12 +183,12 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/js/api.js?v=20260624"></script>
|
||||
<script src="/js/common.js?v=20260624"></script>
|
||||
<script src="/js/api.js?v=20260625"></script>
|
||||
<script src="/js/common.js?v=20260625"></script>
|
||||
<script src="/vendor/bootstrap-italia/dist/js/bootstrap-italia.bundle.min.js"></script>
|
||||
<script src="/js/common-bi.js?v=20260618"></script>
|
||||
<script src="/js/i18n.js?v=20260624"></script>
|
||||
<script src="/js/help.js?v=20260624"></script>
|
||||
<script src="/js/common-bi.js?v=20260625"></script>
|
||||
<script src="/js/i18n.js?v=20260625"></script>
|
||||
<script src="/js/help.js?v=20260625"></script>
|
||||
<script src="/js/competenze.js?v=20260617"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -382,8 +382,8 @@
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<script src="/js/api.js?v=20260624"></script>
|
||||
<script src="/js/common.js?v=20260624"></script>
|
||||
<script src="/js/api.js?v=20260625"></script>
|
||||
<script src="/js/common.js?v=20260625"></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). -->
|
||||
@@ -393,8 +393,8 @@
|
||||
bootstrap.loadFonts('/vendor/bootstrap-italia/dist/fonts');
|
||||
}
|
||||
</script>
|
||||
<script src="/js/common-bi.js?v=20260618"></script>
|
||||
<script src="/js/i18n.js?v=20260624"></script>
|
||||
<script src="/js/common-bi.js?v=20260625"></script>
|
||||
<script src="/js/i18n.js?v=20260625"></script>
|
||||
<script>
|
||||
const SPRITE = '/vendor/bootstrap-italia/dist/svg/sprites.svg';
|
||||
function ico(name, cls) { return `<svg class="ico ${cls||''}" aria-hidden="true"><use href="${SPRITE}#${name}"></use></svg>`; }
|
||||
|
||||
@@ -143,8 +143,8 @@
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<script src="/js/api.js?v=20260624"></script>
|
||||
<script src="/js/common.js?v=20260624"></script>
|
||||
<script src="/js/api.js?v=20260625"></script>
|
||||
<script src="/js/common.js?v=20260625"></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). -->
|
||||
@@ -154,9 +154,9 @@
|
||||
bootstrap.loadFonts('/vendor/bootstrap-italia/dist/fonts');
|
||||
}
|
||||
</script>
|
||||
<script src="/js/common-bi.js?v=20260618"></script>
|
||||
<script src="/js/i18n.js?v=20260624"></script>
|
||||
<script src="/js/help.js?v=20260624"></script>
|
||||
<script src="/js/common-bi.js?v=20260625"></script>
|
||||
<script src="/js/i18n.js?v=20260625"></script>
|
||||
<script src="/js/help.js?v=20260625"></script>
|
||||
<script>
|
||||
// ── Auth check ───────────────────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
</script>
|
||||
|
||||
<!-- Stessa logica della forgot-password.html: ZERO modifiche backend -->
|
||||
<script src="js/api.js?v=20260624"></script>
|
||||
<script src="js/api.js?v=20260625"></script>
|
||||
<script>
|
||||
const form = document.getElementById('forgot-form');
|
||||
const err = document.getElementById('err');
|
||||
|
||||
+5
-5
@@ -1142,8 +1142,8 @@
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<script src="/js/api.js?v=20260624"></script>
|
||||
<script src="/js/common.js?v=20260624"></script>
|
||||
<script src="/js/api.js?v=20260625"></script>
|
||||
<script src="/js/common.js?v=20260625"></script>
|
||||
<!-- Bootstrap Italia bundle (accordion) + override sidebar BI (common-bi.js).
|
||||
common-bi.js va DOPO common.js: ridefinisce solo loadSidebar() con markup BI. -->
|
||||
<script src="/vendor/bootstrap-italia/dist/js/bootstrap-italia.bundle.min.js"></script>
|
||||
@@ -1152,9 +1152,9 @@
|
||||
bootstrap.loadFonts('/vendor/bootstrap-italia/dist/fonts');
|
||||
}
|
||||
</script>
|
||||
<script src="/js/common-bi.js?v=20260618"></script>
|
||||
<script src="/js/i18n.js?v=20260624"></script>
|
||||
<script src="/js/help.js?v=20260624"></script>
|
||||
<script src="/js/common-bi.js?v=20260625"></script>
|
||||
<script src="/js/i18n.js?v=20260625"></script>
|
||||
<script src="/js/help.js?v=20260625"></script>
|
||||
<script>
|
||||
// La guida è accessibile anche da non autenticati (utile per onboarding)
|
||||
// ma se sei loggato carichi sidebar + i18n normalmente. Stessa logica
|
||||
|
||||
@@ -351,8 +351,8 @@
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<script src="/js/api.js?v=20260624"></script>
|
||||
<script src="/js/common.js?v=20260624"></script>
|
||||
<script src="/js/api.js?v=20260625"></script>
|
||||
<script src="/js/common.js?v=20260625"></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). -->
|
||||
@@ -362,9 +362,9 @@
|
||||
bootstrap.loadFonts('/vendor/bootstrap-italia/dist/fonts');
|
||||
}
|
||||
</script>
|
||||
<script src="/js/common-bi.js?v=20260618"></script>
|
||||
<script src="/js/i18n.js?v=20260624"></script>
|
||||
<script src="/js/help.js?v=20260624"></script>
|
||||
<script src="/js/common-bi.js?v=20260625"></script>
|
||||
<script src="/js/i18n.js?v=20260625"></script>
|
||||
<script src="/js/help.js?v=20260625"></script>
|
||||
<script>
|
||||
// ── Auth & Init ──────────────────────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
@@ -421,6 +421,8 @@ $actionMap = [
|
||||
'GET:scoringGrid' => 'scoringGrid',
|
||||
'GET:relevantSystems' => 'relevantSystems',
|
||||
'GET:dependencyMap' => 'dependencyMap',
|
||||
'GET:subclasses' => 'subclasses', // Epic C / C4 — voci + sottoclassi
|
||||
'POST:subclasses' => 'addSubclass', // Epic C / C4 — aggiunta sottoclasse org
|
||||
'GET:{id}' => 'get',
|
||||
'PUT:{id}' => 'update',
|
||||
'DELETE:{id}' => 'delete',
|
||||
|
||||
@@ -910,8 +910,8 @@ curl -H <span class="str">"X-API-Key: nis2_TUA_CHIAVE"</span> \
|
||||
|
||||
</main>
|
||||
|
||||
<script src="js/common.js?v=20260624"></script>
|
||||
<script src="js/i18n.js?v=20260624"></script>
|
||||
<script src="js/common.js?v=20260625"></script>
|
||||
<script src="js/i18n.js?v=20260625"></script>
|
||||
<script>
|
||||
function showTab(id) {
|
||||
document.querySelectorAll('.tab-btn').forEach((b, i) => {
|
||||
|
||||
+5
-5
@@ -184,8 +184,8 @@
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<script src="/js/api.js?v=20260624"></script>
|
||||
<script src="/js/common.js?v=20260624"></script>
|
||||
<script src="/js/api.js?v=20260625"></script>
|
||||
<script src="/js/common.js?v=20260625"></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). -->
|
||||
@@ -195,9 +195,9 @@
|
||||
bootstrap.loadFonts('/vendor/bootstrap-italia/dist/fonts');
|
||||
}
|
||||
</script>
|
||||
<script src="/js/common-bi.js?v=20260618"></script>
|
||||
<script src="/js/i18n.js?v=20260624"></script>
|
||||
<script src="/js/help.js?v=20260624"></script>
|
||||
<script src="/js/common-bi.js?v=20260625"></script>
|
||||
<script src="/js/i18n.js?v=20260625"></script>
|
||||
<script src="/js/help.js?v=20260625"></script>
|
||||
<script src="/js/isms.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -384,6 +384,8 @@ class NIS2API {
|
||||
scoreAsset(id, criteria) { return this.post(`/assets/${id}/score`, { criteria }); }
|
||||
listRelevantSystems() { return this.get('/assets/relevantSystems'); }
|
||||
importAssets(data) { return this.post('/assets/import', data); } // P2 import CMDB/CSV
|
||||
listAssetSubclasses() { return this.get('/assets/subclasses'); } // C4 — voci + sottoclassi
|
||||
addAssetSubclass(data) { return this.post('/assets/subclasses', data); } // C4 — nuova sottoclasse org
|
||||
getControlsMonitoring() { return this.get('/audit/controlsMonitoring'); }
|
||||
getAcnRequirements() { return this.get('/audit/acnRequirements'); } // requisiti ACN per org
|
||||
updateAcnRequirement(id, status, note) { return this.put(`/audit/acnRequirements/${id}`, { status, evidence_note: note }); }
|
||||
|
||||
+5
-5
@@ -689,12 +689,12 @@ const HelpSystem = (function () {
|
||||
intro: 'Il modulo Inventario consente di catalogare e gestire i beni ICT (hardware e software) dell\'organizzazione, fondamentale per la gestione dei rischi e la sicurezza delle reti e dei sistemi informativi ai sensi dell\'art. 24 del D.Lgs. 138/2024 (che recepisce l\'art. 21 della Direttiva (UE) 2022/2555).',
|
||||
sections: [
|
||||
{
|
||||
heading: 'Categorizzazione dei beni',
|
||||
heading: 'Le due voci dell\'inventario',
|
||||
items: [
|
||||
'<strong>Hardware</strong> - server, workstation, dispositivi di rete, dispositivi mobili, apparati di sicurezza.',
|
||||
'<strong>Software</strong> - applicativi, sistemi operativi, database, middleware, servizi cloud.',
|
||||
'<strong>Rete</strong> - reti LAN/WAN, collegamenti internet, VPN, segmenti di rete.',
|
||||
'<strong>Dati</strong> - archivi, database, backup, dati personali, dati critici per il business.'
|
||||
'La normativa prevede <strong>due sole voci principali</strong>: <strong>ID.AM-01 Hardware</strong> (apparati fisici: dispositivi IT, IoT, OT e mobili) e <strong>ID.AM-02 Software, servizi e sistemi</strong> (applicazioni commerciali/open-source/custom, servizi, sistemi, API).',
|
||||
'Il dettaglio si esprime con le <strong>sottoclassi</strong>: alcune di default (es. Server, Dispositivi di rete, Applicazioni software, Basi dati e archivi) e altre che <strong>puoi aggiungere tu</strong> con "+ aggiungi" accanto al campo Sottoclasse.',
|
||||
'Le due voci principali non sono modificabili; le sottoclassi organizzano il tuo inventario sotto di esse.',
|
||||
'I flussi di rete (ID.AM-03, solo soggetti essenziali) e i servizi dei fornitori (ID.AM-04) sono registri distinti, non voci dell\'inventario asset.'
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
+5
-5
@@ -151,8 +151,8 @@
|
||||
</div>
|
||||
|
||||
<!-- Stessa logica JS della pagina live (parita' funzionale assoluta, zero backend). -->
|
||||
<script src="/js/common.js?v=20260624"></script>
|
||||
<script src="/js/api.js?v=20260624"></script>
|
||||
<script src="/js/common.js?v=20260625"></script>
|
||||
<script src="/js/api.js?v=20260625"></script>
|
||||
<!-- Bootstrap Italia bundle (componenti) + override sidebar BI (common-bi.js).
|
||||
common-bi.js va DOPO common.js: ridefinisce solo loadSidebar() con markup BI. -->
|
||||
<script src="/vendor/bootstrap-italia/dist/js/bootstrap-italia.bundle.min.js"></script>
|
||||
@@ -161,9 +161,9 @@
|
||||
bootstrap.loadFonts('/vendor/bootstrap-italia/dist/fonts');
|
||||
}
|
||||
</script>
|
||||
<script src="/js/common-bi.js?v=20260618"></script>
|
||||
<script src="/js/i18n.js?v=20260624"></script>
|
||||
<script src="/js/help.js?v=20260624"></script>
|
||||
<script src="/js/common-bi.js?v=20260625"></script>
|
||||
<script src="/js/i18n.js?v=20260625"></script>
|
||||
<script src="/js/help.js?v=20260625"></script>
|
||||
<script src="/js/kb.js"></script>
|
||||
<script>
|
||||
// Gate auth + chrome come le altre pagine -bi.
|
||||
|
||||
@@ -515,7 +515,7 @@ body { background: var(--bg-main); }
|
||||
|
||||
<div id="toast"></div>
|
||||
|
||||
<script src="js/api.js?v=20260624"></script>
|
||||
<script src="js/api.js?v=20260625"></script>
|
||||
<script>
|
||||
// ══════════════════════════════════════════════════════
|
||||
// CONFIG
|
||||
|
||||
+2
-2
@@ -94,8 +94,8 @@
|
||||
</script>
|
||||
|
||||
<!-- Stessa logica della login attuale: ZERO modifiche backend -->
|
||||
<script src="js/api.js?v=20260624"></script>
|
||||
<script src="js/common.js?v=20260624"></script>
|
||||
<script src="js/api.js?v=20260625"></script>
|
||||
<script src="js/common.js?v=20260625"></script>
|
||||
<script>
|
||||
if (api.isAuthenticated()) { window.location.href = 'dashboard.html'; }
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<title>Misure e Requisiti - NIS2 Agile</title>
|
||||
<!-- Bootstrap Italia v2.18.1 self-hostato (regola: MAI CDN). Caricato PRIMA di style.css. -->
|
||||
<link rel="stylesheet" href="/vendor/bootstrap-italia/dist/css/bootstrap-italia.min.css">
|
||||
<link rel="stylesheet" href="/css/style.css?v=20260624">
|
||||
<link rel="stylesheet" href="/css/style.css?v=20260625">
|
||||
<style>
|
||||
.mr-intro { background:#eff6ff; border-left:4px solid var(--primary,#2563eb); padding:14px 18px; border-radius:8px; margin-bottom:14px; font-size:.92rem; line-height:1.6; }
|
||||
.mr-note { font-size:.82rem; color:#92400e; background:#fffbeb; border:1px solid #fde68a; border-radius:8px; padding:10px 12px; margin:0 0 16px; }
|
||||
@@ -162,12 +162,12 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/js/api.js?v=20260624"></script>
|
||||
<script src="/js/common.js?v=20260624"></script>
|
||||
<script src="/js/api.js?v=20260625"></script>
|
||||
<script src="/js/common.js?v=20260625"></script>
|
||||
<script src="/vendor/bootstrap-italia/dist/js/bootstrap-italia.bundle.min.js"></script>
|
||||
<script src="/js/common-bi.js?v=20260618"></script>
|
||||
<script src="/js/i18n.js?v=20260624"></script>
|
||||
<script src="/js/help.js?v=20260624"></script>
|
||||
<script src="/js/common-bi.js?v=20260625"></script>
|
||||
<script src="/js/i18n.js?v=20260625"></script>
|
||||
<script src="/js/help.js?v=20260625"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
/*
|
||||
|
||||
@@ -424,6 +424,6 @@ curl https://nis2.agile.software/api/services/status</pre>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script src="js/common.js?v=20260624"></script>
|
||||
<script src="js/common.js?v=20260625"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -112,8 +112,8 @@
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<script src="/js/api.js?v=20260624"></script>
|
||||
<script src="/js/common.js?v=20260624"></script>
|
||||
<script src="/js/api.js?v=20260625"></script>
|
||||
<script src="/js/common.js?v=20260625"></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). -->
|
||||
@@ -123,9 +123,9 @@
|
||||
bootstrap.loadFonts('/vendor/bootstrap-italia/dist/fonts');
|
||||
}
|
||||
</script>
|
||||
<script src="/js/common-bi.js?v=20260618"></script>
|
||||
<script src="/js/i18n.js?v=20260624"></script>
|
||||
<script src="/js/help.js?v=20260624"></script>
|
||||
<script src="/js/common-bi.js?v=20260625"></script>
|
||||
<script src="/js/i18n.js?v=20260625"></script>
|
||||
<script src="/js/help.js?v=20260625"></script>
|
||||
<script>
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
loadSidebar();
|
||||
|
||||
@@ -494,8 +494,8 @@
|
||||
</script>
|
||||
|
||||
<!-- Stessa logica della onboarding.html: ZERO modifiche backend -->
|
||||
<script src="js/api.js?v=20260624"></script>
|
||||
<script src="js/common.js?v=20260624"></script>
|
||||
<script src="js/api.js?v=20260625"></script>
|
||||
<script src="js/common.js?v=20260625"></script>
|
||||
<script>
|
||||
// ── Auth check ──────────────────────────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
@@ -138,12 +138,12 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/js/api.js?v=20260624"></script>
|
||||
<script src="/js/common.js?v=20260624"></script>
|
||||
<script src="/js/api.js?v=20260625"></script>
|
||||
<script src="/js/common.js?v=20260625"></script>
|
||||
<script src="/vendor/bootstrap-italia/dist/js/bootstrap-italia.bundle.min.js"></script>
|
||||
<script src="/js/common-bi.js?v=20260618"></script>
|
||||
<script src="/js/i18n.js?v=20260624"></script>
|
||||
<script src="/js/help.js?v=20260624"></script>
|
||||
<script src="/js/common-bi.js?v=20260625"></script>
|
||||
<script src="/js/i18n.js?v=20260625"></script>
|
||||
<script src="/js/help.js?v=20260625"></script>
|
||||
<script src="/js/organigramma.js?v=20260617"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -333,8 +333,8 @@
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<script src="/js/api.js?v=20260624"></script>
|
||||
<script src="/js/common.js?v=20260624"></script>
|
||||
<script src="/js/api.js?v=20260625"></script>
|
||||
<script src="/js/common.js?v=20260625"></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). -->
|
||||
@@ -344,9 +344,9 @@
|
||||
bootstrap.loadFonts('/vendor/bootstrap-italia/dist/fonts');
|
||||
}
|
||||
</script>
|
||||
<script src="/js/common-bi.js?v=20260618"></script>
|
||||
<script src="/js/i18n.js?v=20260624"></script>
|
||||
<script src="/js/help.js?v=20260624"></script>
|
||||
<script src="/js/common-bi.js?v=20260625"></script>
|
||||
<script src="/js/i18n.js?v=20260625"></script>
|
||||
<script src="/js/help.js?v=20260625"></script>
|
||||
<script>
|
||||
// ── Auth & Init ─────────────────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
+5
-5
@@ -131,12 +131,12 @@
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<script src="/js/api.js?v=20260624"></script>
|
||||
<script src="/js/common.js?v=20260624"></script>
|
||||
<script src="/js/api.js?v=20260625"></script>
|
||||
<script src="/js/common.js?v=20260625"></script>
|
||||
<script src="/vendor/bootstrap-italia/dist/js/bootstrap-italia.bundle.min.js"></script>
|
||||
<script src="/js/common-bi.js?v=20260618"></script>
|
||||
<script src="/js/i18n.js?v=20260624"></script>
|
||||
<script src="/js/help.js?v=20260624"></script>
|
||||
<script src="/js/common-bi.js?v=20260625"></script>
|
||||
<script src="/js/i18n.js?v=20260625"></script>
|
||||
<script src="/js/help.js?v=20260625"></script>
|
||||
<script src="/js/raci.js?v=20260619"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -268,8 +268,8 @@
|
||||
</script>
|
||||
|
||||
<!-- Stessa logica della register.html: ZERO modifiche backend -->
|
||||
<script src="js/api.js?v=20260624"></script>
|
||||
<script src="js/common.js?v=20260624"></script>
|
||||
<script src="js/api.js?v=20260625"></script>
|
||||
<script src="js/common.js?v=20260625"></script>
|
||||
<script>
|
||||
if (api.isAuthenticated()) { window.location.href = 'dashboard.html'; }
|
||||
|
||||
|
||||
+5
-5
@@ -443,8 +443,8 @@
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<script src="/js/api.js?v=20260624"></script>
|
||||
<script src="/js/common.js?v=20260624"></script>
|
||||
<script src="/js/api.js?v=20260625"></script>
|
||||
<script src="/js/common.js?v=20260625"></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). -->
|
||||
@@ -454,9 +454,9 @@
|
||||
bootstrap.loadFonts('/vendor/bootstrap-italia/dist/fonts');
|
||||
}
|
||||
</script>
|
||||
<script src="/js/common-bi.js?v=20260618"></script>
|
||||
<script src="/js/i18n.js?v=20260624"></script>
|
||||
<script src="/js/help.js?v=20260624"></script>
|
||||
<script src="/js/common-bi.js?v=20260625"></script>
|
||||
<script src="/js/i18n.js?v=20260625"></script>
|
||||
<script src="/js/help.js?v=20260625"></script>
|
||||
<script>
|
||||
// ── Auth & Init ─────────────────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
@@ -141,12 +141,12 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/js/api.js?v=20260624"></script>
|
||||
<script src="/js/common.js?v=20260624"></script>
|
||||
<script src="/js/api.js?v=20260625"></script>
|
||||
<script src="/js/common.js?v=20260625"></script>
|
||||
<script src="/vendor/bootstrap-italia/dist/js/bootstrap-italia.bundle.min.js"></script>
|
||||
<script src="/js/common-bi.js?v=20260618"></script>
|
||||
<script src="/js/i18n.js?v=20260624"></script>
|
||||
<script src="/js/help.js?v=20260624"></script>
|
||||
<script src="/js/common-bi.js?v=20260625"></script>
|
||||
<script src="/js/i18n.js?v=20260625"></script>
|
||||
<script src="/js/help.js?v=20260625"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
/*
|
||||
|
||||
+5
-5
@@ -494,8 +494,8 @@
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<script src="/js/api.js?v=20260624"></script>
|
||||
<script src="/js/common.js?v=20260624"></script>
|
||||
<script src="/js/api.js?v=20260625"></script>
|
||||
<script src="/js/common.js?v=20260625"></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). -->
|
||||
@@ -505,9 +505,9 @@
|
||||
bootstrap.loadFonts('/vendor/bootstrap-italia/dist/fonts');
|
||||
}
|
||||
</script>
|
||||
<script src="/js/common-bi.js?v=20260618"></script>
|
||||
<script src="/js/i18n.js?v=20260624"></script>
|
||||
<script src="/js/help.js?v=20260624"></script>
|
||||
<script src="/js/common-bi.js?v=20260625"></script>
|
||||
<script src="/js/i18n.js?v=20260625"></script>
|
||||
<script src="/js/help.js?v=20260625"></script>
|
||||
<script>
|
||||
// ── Auth & Init ──────────────────────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
@@ -672,8 +672,8 @@
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<script src="/js/api.js?v=20260624"></script>
|
||||
<script src="/js/common.js?v=20260624"></script>
|
||||
<script src="/js/api.js?v=20260625"></script>
|
||||
<script src="/js/common.js?v=20260625"></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). -->
|
||||
@@ -683,9 +683,9 @@
|
||||
bootstrap.loadFonts('/vendor/bootstrap-italia/dist/fonts');
|
||||
}
|
||||
</script>
|
||||
<script src="/js/common-bi.js?v=20260618"></script>
|
||||
<script src="/js/i18n.js?v=20260624"></script>
|
||||
<script src="/js/help.js?v=20260624"></script>
|
||||
<script src="/js/common-bi.js?v=20260625"></script>
|
||||
<script src="/js/i18n.js?v=20260625"></script>
|
||||
<script src="/js/help.js?v=20260625"></script>
|
||||
<script>
|
||||
// ── Auth check ───────────────────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
@@ -165,8 +165,8 @@
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<script src="js/api.js?v=20260624"></script>
|
||||
<script src="js/common.js?v=20260624"></script>
|
||||
<script src="js/api.js?v=20260625"></script>
|
||||
<script src="js/common.js?v=20260625"></script>
|
||||
<script>
|
||||
// ── Auth check ───────────────────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
@@ -124,12 +124,12 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/js/api.js?v=20260624"></script>
|
||||
<script src="/js/common.js?v=20260624"></script>
|
||||
<script src="/js/api.js?v=20260625"></script>
|
||||
<script src="/js/common.js?v=20260625"></script>
|
||||
<script src="/vendor/bootstrap-italia/dist/js/bootstrap-italia.bundle.min.js"></script>
|
||||
<script src="/js/common-bi.js?v=20260618"></script>
|
||||
<script src="/js/i18n.js?v=20260624"></script>
|
||||
<script src="/js/help.js?v=20260624"></script>
|
||||
<script src="/js/common-bi.js?v=20260625"></script>
|
||||
<script src="/js/i18n.js?v=20260625"></script>
|
||||
<script src="/js/help.js?v=20260625"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
/*
|
||||
|
||||
@@ -477,8 +477,8 @@
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<script src="/js/api.js?v=20260624"></script>
|
||||
<script src="/js/common.js?v=20260624"></script>
|
||||
<script src="/js/api.js?v=20260625"></script>
|
||||
<script src="/js/common.js?v=20260625"></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). -->
|
||||
@@ -488,9 +488,9 @@
|
||||
bootstrap.loadFonts('/vendor/bootstrap-italia/dist/fonts');
|
||||
}
|
||||
</script>
|
||||
<script src="/js/common-bi.js?v=20260618"></script>
|
||||
<script src="/js/i18n.js?v=20260624"></script>
|
||||
<script src="/js/help.js?v=20260624"></script>
|
||||
<script src="/js/common-bi.js?v=20260625"></script>
|
||||
<script src="/js/i18n.js?v=20260625"></script>
|
||||
<script src="/js/help.js?v=20260625"></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.18.3';
|
||||
const CACHE = 'nis2-shell-v1.18.4';
|
||||
|
||||
const PRECACHE = [
|
||||
'/offline.html',
|
||||
|
||||
@@ -292,8 +292,8 @@
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<script src="/js/api.js?v=20260624"></script>
|
||||
<script src="/js/common.js?v=20260624"></script>
|
||||
<script src="/js/api.js?v=20260625"></script>
|
||||
<script src="/js/common.js?v=20260625"></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). -->
|
||||
@@ -303,9 +303,9 @@
|
||||
bootstrap.loadFonts('/vendor/bootstrap-italia/dist/fonts');
|
||||
}
|
||||
</script>
|
||||
<script src="/js/common-bi.js?v=20260618"></script>
|
||||
<script src="/js/i18n.js?v=20260624"></script>
|
||||
<script src="/js/help.js?v=20260624"></script>
|
||||
<script src="/js/common-bi.js?v=20260625"></script>
|
||||
<script src="/js/i18n.js?v=20260625"></script>
|
||||
<script src="/js/help.js?v=20260625"></script>
|
||||
<script>
|
||||
// ── Auth & Init ─────────────────────────────────────────
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
{"version": "1.18.3", "build": "2026-06-16-v1.18.3", "date": "2026-06-16", "changelog": "Epic C / C3 - rimosso il modulo 'Analisi GAP ACN' (superato da C1: elenco Misure/Requisiti + valutazione per requisito). Tabelle acn_assessments/acn_assessment_responses droppate (erano vuote, 0 dati persi). RaciController ripuntato su cfg_nis2_misure (ex acn_measures.json). Sidebar/help/i18n/api/routing/tour demo ripuliti; integrazione lg231 (services/gap-analysis) intatta. Additivo-sottrattivo, nessun dato utente perso."}
|
||||
{"version": "1.18.4", "build": "2026-06-16-v1.18.4", "date": "2026-06-16", "changelog": "Epic C / C4 - inventario a DUE voci (ID.AM-01 Hardware, ID.AM-02 Software/Servizi/Sistemi) + sottoclassi configurabili (default di sistema + create dall'utente). mig.050: cfg_inventory_voci, inventory_subclassi, assets.voce_code/subclass_id; 20 asset migrati. AssetController voce/subclass + endpoint subclasses; assets.html selettori voce+sottoclasse. Fix: apostrofo non escapato che rompeva il JS dell'Inventario; cache-buster common-bi.js (fix sidebar C3). Additivo."}
|
||||
|
||||
@@ -207,8 +207,8 @@
|
||||
|
||||
<!-- Report Detail Modal handled by common.js showModal -->
|
||||
|
||||
<script src="/js/api.js?v=20260624"></script>
|
||||
<script src="/js/common.js?v=20260624"></script>
|
||||
<script src="/js/api.js?v=20260625"></script>
|
||||
<script src="/js/common.js?v=20260625"></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). -->
|
||||
@@ -218,9 +218,9 @@
|
||||
bootstrap.loadFonts('/vendor/bootstrap-italia/dist/fonts');
|
||||
}
|
||||
</script>
|
||||
<script src="/js/common-bi.js?v=20260618"></script>
|
||||
<script src="/js/i18n.js?v=20260624"></script>
|
||||
<script src="/js/help.js?v=20260624"></script>
|
||||
<script src="/js/common-bi.js?v=20260625"></script>
|
||||
<script src="/js/i18n.js?v=20260625"></script>
|
||||
<script src="/js/help.js?v=20260625"></script>
|
||||
<script>
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
loadSidebar();
|
||||
|
||||
@@ -319,9 +319,9 @@
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<script src="js/api.js?v=20260624"></script>
|
||||
<script src="js/common.js?v=20260624"></script>
|
||||
<script src="js/i18n.js?v=20260624"></script>
|
||||
<script src="js/api.js?v=20260625"></script>
|
||||
<script src="js/common.js?v=20260625"></script>
|
||||
<script src="js/i18n.js?v=20260625"></script>
|
||||
<script>
|
||||
if (!checkAuth()) throw new Error('Not authenticated');
|
||||
loadSidebar();
|
||||
|
||||
Reference in New Issue
Block a user