aggiunta calendario

This commit is contained in:
2026-06-02 22:07:16 +02:00
parent aa4e582925
commit c9d66c2a80
31 changed files with 4435 additions and 86 deletions
+44 -34
View File
@@ -1,7 +1,8 @@
# 🧠 MEMORY.md — Stato Progetto
## Goal
- Correggere tutti i bug critici identificati nell'applicazione Glastree, a partire dal bug segnalato "rimuovendo un individuo da un gruppo, l'individuo perdeva tutti i contatti"
- Correggere tutti i bug critici identificati nell'applicazione Glastree
- Implementare nuove funzionalità richieste: cancellazione account email, fix firma editor, sincronizzazione calendario con Google Calendar / CalDAV
## Constraints & Preferences
- Laravel 13, PHP 8.4, AdminLTE 4, MySQL/MariaDB
@@ -11,23 +12,25 @@
## Progress
### Done
- **Cancellata cache Laravel** (`php artisan optimize:clear`)
- **Fix BUG CRITICO 3** `IndividuoController::update()` (riga 216): avvolto `$individuo->contatti()->delete()` dentro `if ($request->has('contatti'))`. Se il request non contiene il campo `contatti` (es. submit da form annidato), i contatti NON vengono eliminati.
- **Fix BUG CRITICO 1** `individui/edit.blade.php`: convertiti 4 form annidati in pulsanti `type="button"` + `fetch()` AJAX:
- Linea 235-240: rimozione gruppo → `deleteGruppoFromEdit()`
- Linea 245-267: modifica gruppo inline → `submitEditGruppo()`
- Linea 291-319: upload documento → `submitUploadDocumentoIndividuo()`
- Linea 350-355: eliminazione documento → `deleteDocumentoFromEdit()`
- **Fix BUG CRITICO 2** `gruppi/edit.blade.php`: convertiti 3 form annidati in pulsanti `type="button"` + `fetch()` AJAX:
- Linea 155-180: modifica membro inline → `submitEditMembro()`
- Linea 204-231: upload documento → `submitUploadDocumentoGruppo()`
- Linea 261-266: eliminazione documento → `deleteDocumentoFromEdit()`
- **Fix BUG CRITICO 4** `gruppi/show.blade.php`: spostati i flash messages (session success/error) DENTRO `@section('content')` invece di essere fuori (non venivano mai visualizzati)
- **Fix BUG CRITICO 5** `eventi/show.blade.php`: rimossi 2 tag `</div>` extra alle linee 214-217 che rompevano la struttura HTML
- **Fix BUG CRITICO 6** `eventi/show.blade.php`: escape JS di `$evento->nome_evento` nella `confirm()` (riga 307) per prevenire stored XSS
- **Fix BUG CRITICO 7** `ImpostazioniController.php`: aggiunto `use App\Models\Documento;` mancante (causava Fatal error in `saveAppSettings()` e `migrateStoragePath()`)
- **Fix BUG CRITICO 8** `ImpostazioniController.php`: sostituito `JSON_CONTAINS()` (non supportato da SQLite) con iterazione PHP su `json_decode()` — compatibile MySQL e SQLite
- **Fix BUG CRITICO 9** `ReportController.php`: corretto `$contatto->email``$contatto->valore` (riga 605, colonna `email` non esiste)
- **Fix BUG CRITICO 10** `DocumentoController.php`: prevenuta morph injection in `massUpdate()` sostituendo il fallback `?? $data['visibilita_target_type']` con un `isset()` check sul typeMap + `return back()->with('error')` se il tipo non è valido
- **Fix BUG CRITICO 3** `IndividuoController::update()` (riga 216): avvolto `$individuo->contatti()->delete()` dentro `if ($request->has('contatti'))`.
- **Fix BUG CRITICO 1** `individui/edit.blade.php`: convertiti 4 form annidati in pulsanti `type="button"` + `fetch()` AJAX
- **Fix BUG CRITICO 2** `gruppi/edit.blade.php`: convertiti 3 form annidati in pulsanti `type="button"` + `fetch()` AJAX
- **Fix BUG CRITICO 4** `gruppi/show.blade.php`: flash messages spostati dentro `@section('content')`
- **Fix BUG CRITICO 5/6** `eventi/show.blade.php`: rimossi div extra, XSS escape in confirm()
- **Fix BUG CRITICO 7/8** `ImpostazioniController.php`: use Documento + JSON_CONTAINS → PHP
- **Fix BUG CRITICO 9** `ReportController.php`: `$contatto->email``$contatto->valore`
- **Fix BUG CRITICO 10** `DocumentoController.php`: morph injection prevention in massUpdate()
- **NUOVA FEATURE Cancellazione account email**: Aggiunto metodo `destroy()` in `EmailSettingsController`, rotta `DELETE /impostazioni/email`, pulsante "Elimina Configurazione" in entrambe le viste (admin dedicata e unificata)
- **FIX Doppia barra icone firma**: Cambiata la guardia di `createEditor()` e `initSignatureEditor()` da `container.querySelector('.ql-toolbar')` (che non funziona perché Quill crea la toolbar come sibling, non child) a flag `quillEditorInstance` in entrambe le viste
- **NUOVA FEATURE Sincronizzazione calendario**: Implementata sincronizzazione con Google Calendar e CalDAV (Infomaniak/NextCloud):
- Migration `create_calendario_connessioni_table` + `add_uid_esterno_to_eventi_table`
- Model `CalendarioConnessione` con encrypt/decrypt config
- Service `CalDavService` (PROPFIND, REPORT, calendar-query, PUT)
- Service `GoogleCalendarSyncService` (Google Calendar API v3)
- Controller `CalendarioConnessioneController` (CRUD + test + sync + reorder)
- Routes RESTful per calendario-connessioni
- UI nella tab "Calendario" delle impostazioni unificate con tabella, modale CRUD, pulsanti test/sync/elimina, Sortable drag&drop
- Installati pacchetti: `sabre/vobject`, `google/apiclient`
### In Progress
- *(nessuno)*
@@ -36,25 +39,32 @@
- *(nessuno)*
## Key Decisions
- Per i form annidati si è scelto l'approccio `type="button"` + `fetch()` AJAX, già utilizzato in `individui/show.blade.php` e `gruppi/edit.blade.php` per funzioni esistenti (`deleteMembro`, `submitGruppoForm`, `uploadAvatar`, etc.)
- Per documenti (upload/delete) il controller torna `redirect()`, non JSON. Le funzioni AJAX eseguono `window.location.reload()` dopo il fetch per aggiornare la vista.
- `JSON_CONTAINS` sostituito con approccio PHP+json_decode per garantire compatibilità SQLite senza modificare lo schema DB.
- `$request->has('contatti')` è la guardia corretta: se il form principale non invia il campo `contatti` (perché il submit proviene da un form annidato), non si cancella nulla.
- Per i form annidati si è scelto l'approccio `type="button"` + `fetch()` AJAX
- Per la cancellazione account email si usa `EmailSetting::first()->delete()` con verifica esistenza
- Per il fix Quill: variabile flag `quillEditorInstance` invece di `container.querySelector('.ql-toolbar')` perché Quill inserisce `.ql-toolbar` come elemento sibling, non child
- Per CalDAV: usato Guzzle (già in Laravel) per HTTP + `sabre/vobject` per parsing iCal
- Per Google Calendar: usato `google/apiclient` con OAuth 2.0 (refresh token)
- La sync può essere bidirezionale, solo import o solo export
- I campi sensibili delle connessioni calendario sono criptati con `Crypt`
## Next Steps
- *(nessuno)* - Tutti i bug critici risolti
- *(nessuno)*
## Critical Context
- **CAUSA DEL BUG SEGNALATO**: I form annidati in `individui/edit.blade.php` facevano sì che il browser ignorasse i form interni. I pulsanti "Rimuovi" inviavano il form principale → `IndividuoController::update()``$individuo->contatti()->delete()` incondizionato.
- **Tutti i 10 bug critici sono stati risolti**
- I controller di rimozione membro (`GruppoMembroController::destroy()` e `GruppoIndividuoController::destroy()`) usano già `detach()` correttamente — nessun problema lato backend
- Le connessioni calendario supportano: Google Calendar, CalDAV (NextCloud, Infomaniak, Synology)
- La direzione di sync è configurabile per ogni connessione
- Le password/refresh token sono automaticamente criptati all salvataggio via `encryptAndSetConfig()`
- Il campo `uid_esterno` sugli eventi traccia la corrispondenza con eventi remoti
## Relevant Files
- `app/Http/Controllers/IndividuoController.php`: Fix BUG 3 contatti condizionale
- `app/Http/Controllers/ImpostazioniController.php`: Fix BUG 7 (use Documento) + BUG 8 (JSON_CONTAINS → PHP)
- `app/Http/Controllers/ReportController.php`: Fix BUG 9 (email → valore)
- `app/Http/Controllers/DocumentoController.php`: Fix BUG 10 (morph injection prevention)
- `resources/views/individui/edit.blade.php`: Fix BUG 1 (4 nested forms → AJAX)
- `resources/views/gruppi/edit.blade.php`: Fix BUG 2 (3 nested forms → AJAX)
- `resources/views/gruppi/show.blade.php`: Fix BUG 4 (flash inside @section)
- `resources/views/eventi/show.blade.php`: Fix BUG 5 (extra divs) + BUG 6 (XSS escape)
- `app/Http/Controllers/Admin/EmailSettingsController.php`: +destroy() method
- `app/Http/Controllers/CalendarioConnessioneController.php`: NEW CRUD + test + sync
- `app/Models/CalendarioConnessione.php`: NEW model con encrypt config
- `app/Services/CalDavService.php`: NEW CalDAV sync
- `app/Services/GoogleCalendarSyncService.php`: NEW Google Calendar sync
- `app/Http/Controllers/ImpostazioniController.php`: +calendarioConnessioni in index()
- `resources/views/admin/email-settings/index.blade.php`: +delete button, fix Quill guard
- `resources/views/impostazioni/index.blade.php`: +delete button, fix Quill guard, +calendario tab UI, +calendario modal, +JS funcs
- `routes/web.php`: +email destroy route, +calendario-connessioni routes
- `database/migrations/2026_06_02_000001_create_calendario_connessioni_table.php`: NEW
- `database/migrations/2026_06_02_000002_add_uid_esterno_to_eventi_table.php`: NEW