scouthub-eventi-fe
Frontend Angular per la gestione degli eventi Scouthub (calendario per branca, con
sotto-eventi a due livelli), affianca scouthub-attivita-fe, scouthub-home-fe e
scouthub-magazzino-fe nello stesso ecosistema. Parla con scouthub-eventi-be per le API e con
Keycloak per l'autenticazione.
Componenti standalone (nessun NgModule), routing con lazy loading per feature, Angular Material per la UI.
Stato del progetto
Le viste calendario (annuale, mensile) e il form di creazione/modifica evento sono implementati e funzionanti. L'intera app è privata (richiede login): non esiste ancora una vista pubblica del calendario.
Struttura cartelle
src/app/
core/
auth/
keycloak.provider.ts provideKeycloakAngular() — login OIDC Authorization Code + PKCE
auth-context.ts extractAuthContext() — ruoli + branche ("groups") dal token
branca-access.ts hasBrancaAccess()/hasAnyBrancaAccess(), rispecchia assertBrancaAccess del BE
require-branca-access.guard.ts guard di routing per creazione/modifica evento
require-auth.guard.ts requireAuthGuard — richiede login, altrimenti avvia keycloak.login()
eventi-api.service.ts client HTTP verso GET/POST/PUT /eventi (dettaglio, crea, aggiorna)
utils/
colore-tipo.ts colore deterministico per "tipo" evento (hash su palette fissa)
nomi-mesi.ts nomi mesi in italiano per le viste calendario
vista-annuale/ feature "calendario annuale" (/vista-annuale, lazy-loaded)
vista-annuale-api.service.ts client verso GET /eventi?vista=anno
vista-mensile/ feature "calendario mensile" (/vista-mensile, lazy-loaded, home di default)
vista-mensile-api.service.ts client verso GET /eventi?vista=mese, filtro branca lato client
vista-evento/ feature "dettaglio/form evento" (/vista-evento, lazy-loaded)
evento-form/ form condiviso per crea/modifica/sotto-evento
src/environments/ environment.ts / environment.development.ts
public/
silent-check-sso.html richiesto dal flusso check-sso silenzioso di Keycloak
Modulo di autenticazione
- Login:
provideKeycloak(inkeycloak.provider.ts) usa il client pubblicoscouthub-frontend— condiviso con tutti gli altri frontend (scouthub-attivita-fe,scouthub-home-fe,scouthub-magazzino-fe) — con Authorization Code Flow + PKCE,onLoad: 'check-sso'e refresh automatico del token viawithAutoRefreshToken(logout automatico dopo 5 minuti di inattività). - requireAuthGuard (
core/require-auth.guard.ts): applicato sulla route radice inapp.routes.ts, protegge quindi tutte le sotto-route in un colpo solo (l'app non ha aree pubbliche). - extractAuthContext (
core/auth/auth-context.ts): rispecchia lato client la stessa logica diverify-token.middleware.tssul backend — i ruoli sonorealm_access.rolespiù i ruoli sull'organizzazione attiva (claimorganization), le branche vengono dal claim standardgroups(path tipo/Lupetti, normalizzati togliendo lo slash iniziale). Non esiste ancora un claim branca dedicato. - hasBrancaAccess / hasAnyBrancaAccess (
core/auth/branca-access.ts):capo-gruppoha accesso in scrittura a qualunque branca dell'organizzazione;capo-unitasolo alle branche a cui appartiene. Usate solo per nascondere via routing gli entry point non pertinenti: il controllo autoritativo resta lato backend (assertBrancaAccesssuPOST/PUT /eventi). - Le chiamate verso
eventiApiBaseUrlricevono automaticamente l'headerAuthorization: Bearer <token>tramite l'interceptorincludeBearerTokenInterceptordikeycloak-angular, condizionato via regex sull'URL base dell'API inapp.config.ts.
Feature vista-mensile (/vista-mensile, home di default)
Calendario del mese corrente/selezionato: carica tutti gli eventi del mese (radice e figli,
trasversali a tutte le branche) tramite GET /eventi?vista=mese, e filtra lato client per branca
tramite un select — così il filtro resta popolato con tutte le branche presenti nel mese anche
dopo aver selezionato una branca specifica.
Feature vista-annuale (/vista-annuale)
Vista d'insieme dell'anno: per ogni giorno con almeno un evento radice, mostra un conteggio e
l'elenco sintetico (titolo/tipo/branca) tramite GET /eventi?vista=anno. Nessun dettaglio
descrizione/risorse in questa vista (aggregato leggero, coerente con quanto espone il backend).
Feature vista-evento (/vista-evento)
/vista-evento/:id— dettaglio completo di un evento, con i suoi eventuali figli (2° livello) e le risorse collegate create da altri backend (RisorsaCollegata)./vista-evento/nuovo— crea un evento radice su una branca a scelta tra quelle dell'utente (requireCreaEventoGuard, visibile solo a chi ha accesso ad almeno una branca)./vista-evento/:id/modifica— modifica un evento esistente (requireBrancaAccessEventoGuard, carica prima l'evento per conoscerne la branca e poter decidere l'accesso)./vista-evento/:id/sotto-evento— crea un sotto-evento del padre:id; il form eredita branca/vincoli di data dal genitore e blocca il campo branca. Non disponibile se:idè già esso stesso un sotto-evento (massimo due livelli di annidamento, imposto anche lato backend).
Il form (evento-form/) valida che la data/ora di fine non preceda l'inizio e, in modalità
sotto-evento/modifica-di-un-figlio, vincola l'intervallo selezionabile a quello del genitore;
resta comunque il backend l'autorità finale su questi vincoli.
Prerequisiti
- Node.js 20+
- I servizi dell'ecosistema Scouthub in esecuzione: Keycloak e
scouthub-eventi-be(vedidocker-compose.ymlescouthub-eventi-be/README.mdnella root del repo)
Configurazione ambiente
src/environments/environment.ts (produzione) e environment.development.ts (dev, usato
automaticamente da ng serve/ng build --configuration development) espongono:
keycloakBaseUrl— URL base dell'istanza Keycloak (defaulthttp://localhost:8081, coerente conKEYCLOAK_PORTin.envalla root del repo)keycloakRealm— realm Keycloak (scouthub)keycloakClientId— client pubblico condiviso già definito inkeycloak/realm-export.json(scouthub-frontend)eventiApiBaseUrl— URL base discouthub-eventi-be(defaulthttp://localhost:8084)
Collegare Keycloak in locale
- Avviare Keycloak (e Postgres) dalla root del repo:
Il realm
docker compose up -d keycloak-db keycloakscouthubviene importato automaticamente dakeycloak/realm-export.jsonal primo avvio (--import-realm). - Il client pubblico
scouthub-frontendharedirectUris/webOriginsche includono anchehttp://localhost:4204(porta di default di questo progetto, vedi sotto) — se si cambia porta, aggiornarekeycloak/realm-export.jsondi conseguenza e reimportare il realm (o aggiornarlo da console admin Keycloak). provideKeycloakAngular()(src/app/core/auth/keycloak.provider.ts) inizializza il client cononLoad: 'check-sso': all'avvio l'app verifica in un iframe nascosto se esiste già una sessione Keycloak, senza forzare subito un redirect di login.
Collegare scouthub-eventi-be in locale
- Avviare
scouthub-eventi-beseguendo il suo README (npm run dev, porta di default8084). - Le richieste verso
eventiApiBaseUrlricevono automaticamente l'headerAuthorization: Bearer <token>tramite l'interceptorincludeBearerTokenInterceptordikeycloak-angular, configurato inapp.config.ts.
Development server
Questo progetto usa la porta 4204 (per non collidere con scouthub-attivita-fe sulla 4200,
scouthub-home-fe sulla 4201 e scouthub-magazzino-fe sulla 4203):
ng serve
Apri il browser su http://localhost:4204/.
Build
ng build
Artefatti di build in dist/scouthub-eventi-fe/browser (percorso usato anche dal Dockerfile
multistage node→nginx).
Test
ng test
Esegue gli unit test con il builder @angular/build:unit-test (Vitest).
Versione Angular CLI usata per lo scaffold
Angular CLI : 22.0.7
Angular : 22.0.8
Node.js : 24.16.0
Package Manager : npm 11.12.0
Operating System : win32 x64