[FEAT] Cruscotto Studio (frontend): companies.html vista d'insieme + menu

companies.html diventa il cruscotto dello studio consulente: barra KPI (aziende,
compliance media, scadenze in ritardo/in arrivo), griglia aziende (compliance/
rischi/incidenti + badge ritardo, clic = entra nell'azienda) e sezione "Scadenze
generali" aggregata su TUTTE le aziende ordinata per data. Una sola chiamata
api.consultantPortfolio(). Voce menu V3 "Le mie aziende" (icona briefcase) gata a
consultant/super_admin. help.js + i18n (nav.studio + companies.*) aggiornati.
Cache-buster api/topnav-v3/i18n/help ?v=20260729. version 1.25.9.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
DevEnv nis2-agile
2026-07-29 14:49:37 +02:00
co-authored by Claude Opus 4.8
parent 2bd97a6bd8
commit 15010f7dc3
46 changed files with 404 additions and 234 deletions
+3
View File
@@ -177,6 +177,9 @@ class NIS2API {
updateOrganization(id, data) { return this.put(`/organizations/${id}`, data); }
classifyEntity(data) { return this.post('/organizations/classify', data); }
// Cruscotto Studio (dashboard consulente) — portfolio aggregato read-only.
consultantPortfolio() { return this.get('/consultant/portfolio'); }
// ═══════════════════════════════════════════════════════════════════
// Assessments
// ═══════════════════════════════════════════════════════════════════
+15 -8
View File
@@ -1389,28 +1389,35 @@ const HelpSystem = (function () {
// ─── Aziende (consulente) ────────────────────────────────────
'companies': {
title: 'Guida - Aziende Gestite',
intro: 'Il modulo Aziende è dedicato a consulenti e studi: permette di gestire più organizzazioni clienti e passare rapidamente dall\'una all\'altra mantenendo i dati separati.',
title: 'Guida - Cruscotto Studio',
intro: 'Il Cruscotto Studio è la dashboard dedicata a consulenti e studi: in un\'unica pagina raccoglie tutte le aziende clienti che gestisci con il loro stato di compliance, i rischi e gli incidenti aperti, e l\'elenco aggregato di tutte le scadenze in arrivo o in ritardo.',
sections: [
{
heading: 'Gestione del portafoglio clienti',
heading: 'Panoramica dello studio',
items: [
'Visualizzi l\'elenco delle <strong>aziende che gestisci</strong> con il relativo livello di compliance.',
'Puoi <strong>aggiungere</strong> una nuova azienda cliente e accedere ai suoi moduli.',
'Il pulsante <strong>"Entra"</strong> imposta l\'organizzazione attiva: tutti i moduli (rischi, incidenti, policy, fornitori...) mostrano i dati di quell\'azienda.'
'La <strong>barra KPI</strong> in alto riepiloga il portafoglio: numero di aziende, compliance media, scadenze in ritardo (in rosso) e scadenze in arrivo.',
'Ogni <strong>scheda azienda</strong> mostra settore, classificazione NIS2 (essenziale/importante/volontaria), barra di compliance, rischi e incidenti aperti e un badge rosso se ci sono scadenze scadute.',
'Il <strong>clic su una scheda</strong> imposta l\'organizzazione attiva e apre la sua dashboard: tutti i moduli (rischi, incidenti, policy, fornitori...) mostrano poi i dati di quell\'azienda.'
]
},
{
heading: 'Scadenze generali (tutte le aziende)',
items: [
'La sezione in fondo elenca <strong>tutte le scadenze</strong> del portafoglio ordinate per data: per ciascuna vedi azienda, tipo di adempimento (Early Warning, Notifica CSIRT, Report finale, Revisione policy, Trattamento rischio, Formazione), data e stato.',
'Le scadenze <strong>scadute</strong> sono evidenziate in rosso; le altre indicano tra quanti giorni cadono.'
]
},
{
heading: 'Separazione dei dati',
items: [
'Ogni azienda è un\'organizzazione isolata: i dati non si mescolano mai tra clienti diversi (multi-tenancy).',
'Il cambio di contesto è tracciato a fini di audit.'
'Il cambio di contesto (ingresso in un\'azienda) è tracciato a fini di audit.'
]
}
],
references: [
'Architettura multi-tenant: ogni organizzazione ha dati isolati',
'Ruolo consulente con accesso a più organizzazioni'
'Ruolo consulente/super admin con accesso a più organizzazioni'
]
},
+10
View File
@@ -108,6 +108,7 @@ const I18n = (function () {
'nav.integrations': { it: 'Integrazioni Esterne', en: 'External Integrations' },
'nav.workflow': { it: 'Compliance Journey', en: 'Compliance Journey' },
'nav.audit_acn': { it: 'Audit ACN', en: 'ACN Audit' },
'nav.studio': { it: 'Le mie aziende', en: 'My companies' },
// ── Etichette gruppi mega-menu V3 ──
'nav.grp_stakeholders': { it: 'Stakeholders', en: 'Stakeholders' },
'nav.grp_internal': { it: 'Struttura interna', en: 'Internal structure' },
@@ -116,6 +117,15 @@ const I18n = (function () {
'nav.grp_lexiso': { it: 'Lex e ISO', en: 'Law & ISO' },
'nav.grp_ai': { it: 'AI', en: 'AI' },
'nav.grp_guide': { it: 'Guida', en: 'Guide' },
// ── Cruscotto Studio (dashboard consulente) ──
'companies.title': { it: 'Cruscotto Studio', en: 'Studio Dashboard' },
'companies.subtitle': { it: 'Portafoglio clienti, compliance e scadenze in un colpo d\'occhio', en: 'Client portfolio, compliance and deadlines at a glance' },
'companies.kpi_total': { it: 'Aziende gestite', en: 'Managed companies' },
'companies.kpi_avg': { it: 'Compliance media', en: 'Average compliance' },
'companies.kpi_overdue': { it: 'Scadenze in ritardo', en: 'Overdue deadlines' },
'companies.kpi_upcoming': { it: 'Scadenze in arrivo', en: 'Upcoming deadlines' },
'companies.deadlines_title': { it: 'Scadenze generali (tutte le aziende)', en: 'General deadlines (all companies)' },
'companies.deadlines_empty': { it: 'Nessuna scadenza nei prossimi 30 giorni', en: 'No deadlines in the next 30 days' },
// ── Titoli pagina aggiunti dalla flotta V3 (mancavano → si vedeva la chiave) ──
'mr.title': { it: 'Misure e Requisiti', en: 'Measures & Requirements' },
'normative.title': { it: 'Aggiornamenti Normativi', en: 'Regulatory Updates' },
+12
View File
@@ -23,6 +23,8 @@
// top-level: voce diretta (href) oppure gruppo con mega-menu (cols).
var NAV_GROUPS = [
{ label: 'Dashboard', i18n: 'nav.dashboard', icon: 'layout-dashboard', href: 'dashboard.html' },
// Voce riservata a consulenti/super_admin — gate applicato in loadTopnavV3().
{ label: 'Le mie aziende', i18n: 'nav.studio', icon: 'briefcase', href: 'companies.html', studioOnly: true },
{ label: 'Calendario', i18n: 'nav.calendar', icon: 'calendar', href: 'calendario.html' },
{
label: 'Stakeholders', icon: 'users',
@@ -220,6 +222,16 @@
'</div></nav>' +
'</header>';
// ── Gate voce "Le mie aziende": visibile solo a consulenti / super_admin ──
try {
var role = (typeof api !== 'undefined' && api.getUserRole) ? api.getUserRole() : null;
if (['consultant', 'super_admin'].indexOf(role) === -1) {
var studioLink = host.querySelector('#topnav-bar a[data-nav="companies"]');
var studioItem = studioLink && studioLink.closest('.nav-item');
if (studioItem) studioItem.remove();
}
} catch (e) { /* in caso di errore lasciamo la voce (backend gate comunque presente) */ }
// ── Riuso helper common.js (utente/avatar/ruolo + org-switcher + versione + branding + impersonate) ──
if (typeof _loadUserInfo === 'function') _loadUserInfo();
if (typeof _loadVersionFooter === 'function') _loadVersionFooter();