173 lines
8.3 KiB
Markdown
173 lines
8.3 KiB
Markdown
# 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` (in `keycloak.provider.ts`) usa il client pubblico
|
|
`scouthub-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 via `withAutoRefreshToken` (logout
|
|
automatico dopo 5 minuti di inattività).
|
|
- **requireAuthGuard** (`core/require-auth.guard.ts`): applicato sulla route radice in
|
|
`app.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
|
|
di `verify-token.middleware.ts` sul backend — i ruoli sono `realm_access.roles` più i ruoli
|
|
sull'organizzazione attiva (claim `organization`), le branche vengono dal claim standard
|
|
`groups` (path tipo `/Lupetti`, normalizzati togliendo lo slash iniziale). Non esiste ancora un
|
|
claim branca dedicato.
|
|
- **hasBrancaAccess / hasAnyBrancaAccess** (`core/auth/branca-access.ts`): `capo-gruppo` ha
|
|
accesso in scrittura a qualunque branca dell'organizzazione; `capo-unita` solo alle branche a
|
|
cui appartiene. Usate solo per nascondere via routing gli entry point non pertinenti: **il
|
|
controllo autoritativo resta lato backend** (`assertBrancaAccess` su `POST`/`PUT /eventi`).
|
|
- Le chiamate verso `eventiApiBaseUrl` ricevono automaticamente l'header
|
|
`Authorization: Bearer <token>` tramite l'interceptor `includeBearerTokenInterceptor` di
|
|
`keycloak-angular`, condizionato via regex sull'URL base dell'API in `app.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`
|
|
(vedi `docker-compose.yml` e `scouthub-eventi-be/README.md` nella 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 (default `http://localhost:8081`, coerente
|
|
con `KEYCLOAK_PORT` in `.env` alla root del repo)
|
|
- `keycloakRealm` — realm Keycloak (`scouthub`)
|
|
- `keycloakClientId` — client pubblico condiviso già definito in `keycloak/realm-export.json`
|
|
(`scouthub-frontend`)
|
|
- `eventiApiBaseUrl` — URL base di `scouthub-eventi-be` (default `http://localhost:8084`)
|
|
|
|
## Collegare Keycloak in locale
|
|
|
|
1. Avviare Keycloak (e Postgres) dalla root del repo:
|
|
```bash
|
|
docker compose up -d keycloak-db keycloak
|
|
```
|
|
Il realm `scouthub` viene importato automaticamente da `keycloak/realm-export.json` al primo
|
|
avvio (`--import-realm`).
|
|
2. Il client pubblico `scouthub-frontend` ha `redirectUris`/`webOrigins` che includono anche
|
|
`http://localhost:4204` (porta di default di questo progetto, vedi sotto) — se si cambia porta,
|
|
aggiornare `keycloak/realm-export.json` di conseguenza e reimportare il realm (o aggiornarlo
|
|
da console admin Keycloak).
|
|
3. `provideKeycloakAngular()` (`src/app/core/auth/keycloak.provider.ts`) inizializza il client con
|
|
`onLoad: '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
|
|
|
|
1. Avviare `scouthub-eventi-be` seguendo il suo README (`npm run dev`, porta di default `8084`).
|
|
2. Le richieste verso `eventiApiBaseUrl` ricevono automaticamente l'header
|
|
`Authorization: Bearer <token>` tramite l'interceptor `includeBearerTokenInterceptor` di
|
|
`keycloak-angular`, configurato in `app.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`):
|
|
|
|
```bash
|
|
ng serve
|
|
```
|
|
|
|
Apri il browser su `http://localhost:4204/`.
|
|
|
|
## Build
|
|
|
|
```bash
|
|
ng build
|
|
```
|
|
|
|
Artefatti di build in `dist/scouthub-eventi-fe/browser` (percorso usato anche dal `Dockerfile`
|
|
multistage node→nginx).
|
|
|
|
## Test
|
|
|
|
```bash
|
|
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
|
|
```
|