Assegna pesava 387 KB e Livewire li rimandava a ogni interazione.
- Elenco dei territori assegnati in un componente lazy a sé
(ElencoAssegnati): il form compare subito e non lo ridisegna.
- Ricerca nell'elenco e anteprima della miniatura nel browser: nessuna
richiesta al server mentre si scrive o si sceglie il territorio.
- Icone SVG come simboli richiamati con <use>.
- Assegnazione::giorni: cast a int (Carbon 3 restituisce un float).
Home: "Vedi tutti" diventa un pulsante nella testata dei riquadri.
README e HANDOFF aggiornati.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Al posto delle tendine (Assegna, Registro, editor delle piantine) un
campo in cui si scrive e compaiono le proposte più vicine: uguale, inizia
con, contiene, errore di battitura ("forse cercavi"); parole in qualsiasi
ordine, senza badare a maiuscole e accenti. Campo vuoto: la tendina
completa. Fatto anche per il telefono (16px, voci da 44px, scelta al tocco).
- Logica pura in resources/js/scelta.js con test node (tests/js).
- Opzioni dal server: Territorio/Proclamatore::opzioneScelta(); i
territori già assegnati si trovano ("già assegnato a …") ma non si
scelgono. Nomi cifrati ordinati e cercati decifrati, mai in SQL.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Gli elenchi tengono ricerca, filtri e ordinamento nell'indirizzo
(#[Url]); la pagina c'era già.
- I link verso schede e operazioni (data-ritorno) portano ?da= con la
pagina di partenza, o il da già ricevuto: si risale all'origine
(elenco -> scheda -> Rientra -> elenco filtrato).
- Ritorno::valida accetta solo percorsi interni: niente rimandi esterni.
- Trait RicordaRitorno: redirect dopo il salvataggio, Annulla e
"Torna indietro" usano la pagina di partenza. Senza da, tutto come prima.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Dopo l'assegnazione si apre una finestra con i canali (copia link
sempre; WhatsApp ed email solo se il proclamatore ha numero /
indirizzo, l'email solo con la posta configurata) e la domanda "Hai
inviato il link?". Si va avanti solo dopo la risposta.
- L'email la manda l'app con notifyNow, mai in coda: l'indirizzo è
cifrato nel database e non deve finire in chiaro nei job.
- Procedura interrotta o "non ancora": assegnazioni.link_da_inviare
resta vero e "Link ancora da inviare" compare nell'elenco Assegna e
nella scheda territorio, con "Invia link" per riprendere.
- Colonne link_da_inviare e link_canale (anche nell'XML); log con
canale e proclamatore_id, senza dati personali.
- "Nuovo territorio" apre il designer delle piantine già in disegno, con
la prima piantina pronta a creare il territorio.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Annullata su richiesta: anche gli amministratori devono confermare
l'email. Torna valido il comportamento di fc8623f.
This reverts commit ac78703.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Chi ha il ruolo amministratore non deve confermare l'indirizzo
(User::esenteDaConfermaEmail): non riceve l'email di conferma né alla
creazione né al cambio d'indirizzo, in Utenti compare "esente". Se perde
il ruolo torna a valere email_verified_at.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Server di posta in Impostazioni (password cifrata, email di prova): se
compilato prende il posto del .env; non si esporta e l'import XML non lo
cancella. MAIL_SCHEME=tls nel .env.example non era valido per Laravel 11.
- Proclamatori con email e telefono facoltativi, cifrati, nell'XML e
cancellati dall'anonimizzazione; il numero apre WhatsApp.
- Dopo l'assegnazione un riquadro in evidenza con il link del PDF,
"Invia su WhatsApp" con il messaggio pronto e la scelta "inviato /
non ancora", che resta finché non si sceglie.
- Conferma dell'email obbligatoria per tutti gli utenti, anche esistenti:
email in italiano, link valido senza login, nuova conferma a ogni cambio
di indirizzo, "Reinvia conferma" in Utenti. Senza conferma restano
raggiungibili profilo, cambio password e, per l'admin, il server di
posta; comando utenti:conferma-email per l'emergenza.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Lo stato "Pubblicata" non dipende più dall'id del territorio, che il
ripristino ricrea: l'impronta usa il numero, e la piantina ricorda il
percorso del PDF pubblicato (pdf_pubblicato, con migrazione che riconosce
le piantine già pubblicate).
- BackupOperationState: corrente() in sola lettura e liberaCorrente() sotto
lo stesso mutex di occupa(), così una lettura non cancella il puntatore
di un'operazione appena avviata.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Blocco 2
- Esiti delle azioni Livewire come avvisi (trait Avvisa) invece di flash
che comparivano alla pagina dopo.
- PDF, miniature e versioni dei territori non più serviti da nginx su
/storage: TerritorioFileController con login, permessi e cache privata.
- Ripristino tutto o niente: verifica dell'archivio, una transazione con
import, piantine, blocco account e scambio dei file annullabile.
- Backup formato 2 con piantine, storico PDF e area KML.
- Posto unico preso in un passo (Cache::lock) e rispettato anche da
import XML e PDF.
- Import PDF da cartella: abbinamento corretto (1-A, 12 B, ambigui),
caricamento a lotti, file non PDF ignorati, PDF sostituito nello storico.
- L'import XML elimina i file dei territori che non usa più; comando
territori:file-orfani per quelli accumulati prima.
Blocco 3
- Password attuale richiesta al cambio volontario; AuthenticateSession
chiude le sessioni aperte altrove.
- Niente nomi dei proclamatori in chiaro nel registro attività.
- Export XML senza remember_token; chi riceve l'hash dal file deve
cambiare password.
- Campagne: ultimo giorno incluso, percentuale sui territori distinti.
- Coda: retry_after 960 s, stop_grace_period 16m, Redis volatile-lru,
impostazioni rilette a ogni job.
- Azzeramento che cancella anche piantine, area KML e anteprime.
- Pulsanti profilo e menu che non si nascondevano; icona del sito.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Il disegno è bozza e si salva da solo; i dati del territorio si
modificano dall'editor e valgono subito nel gestionale.
- Un solo "Pubblica" (immagine + PDF), uguale in editor e gestione:
anteprima preparata in coda su disco privato, conferma obbligatoria,
rifiutata se nel frattempo è cambiato qualcosa di stampato.
- Stati Bozza / Pubblicata / Modifiche da pubblicare, calcolati
sull'impronta di confine e dati stampati e sul PDF in uso.
- Gestione riscritta: stato, ricerca, filtri, storico paginato.
- Editor ridisegnato a tre zone, utilizzabile anche su tablet e telefono.
- Avvisi via evento (trait Avvisa + <x-avvisi>).
- .gitattributes: script shell sempre LF, altrimenti il container
locale su Windows non parte.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Modulo S-13
- Il PDF scrive sopra il modulo ufficiale (FPDI, matrice convertita in PDF 1.4)
invece di ricostruirlo in HTML: 20 righe per foglio come l'originale.
- Una riga per ogni territorio attivo; riporto dell'ultimo rientro prima
dell'anno; assegnazioni a cavallo d'anno su entrambi i fogli; scelta per
data e non per anno registrato; nomi come "Cognome I.".
- Logica spostata in App\Services\Registro\ModuloS13.
Integrità dei dati
- Export/import XML (e quindi backup/ripristino): le date non slittano più di
un giorno; i file vecchi in UTC tornano al giorno giusto.
- Import XML: rifiuta file estranei o incompleti senza toccare i dati, errore
con riga e motivo, territori senza zona importati con il loro storico,
caratteri di controllo rimossi in export, chi importa conserva password e
ruolo di amministratore.
- Assegnazioni: assegnazioneCorrente corretta (filtro dentro ofMany), periodi
sovrapposti rifiutati in Assegna e Registro sotto lock, anno di servizio
ricavato dalla data, niente date future nel Registro.
- Utenti: non si declassa sé stessi né l'ultimo amministratore.
- Entrypoint: non sovrascrive più la copia persistente di APP_KEY con un
valore diverso; serve APP_KEY_ROTATE=1 per un cambio voluto.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Le piantine non dipendono piu' da un territorio esistente: territorio_id e'
nullable, la chiave esterna e' nullOnDelete invece di cascadeOnDelete, e `nome`
fa da etichetta finche' il collegamento manca. Si disegna guardando le strade e
si decide dopo di chi e' il disegno; se il territorio non c'e', lo si crea
dall'editor con numero, zona, tipologia e confini — zona e tipologia comprese,
create sul posto quando mancano.
Il cambio di cascata chiude anche una perdita di dati silenziosa: ogni import
XML svuota `territori` in blocco e finora si portava via tutte le piantine.
Il disegno passa su /piantine/editor, a schermo intero con telaio proprio: su
una mappa larga un terzo di schermo un confine si sbaglia, e finisce stampato.
/piantine resta la gestione — area, generazione, collegamenti, storico.
Cartolina S-12 reimpaginata: pagina 1 il modulo con la Localita' (che ora e' il
nome della zona, non un campo duplicato) e i confini scritti nello spazio
centrale, con il corpo del testo che si adatta alla lunghezza; pagina 2 la
piantina sola al 98%. Aggiunta l'anteprima, che compone il PDF al volo senza
toccare pdf_path ne' lo storico.
Immagine: JPEG invece di PNG (0,9 MB contro 5 per territorio), composta alle
tessere dello zoom piu' alto e ridotta con Lanczos, nelle proporzioni della
pagina cosi' riempie il foglio invece di lasciare fasce bianche. Il tratto del
confine e' espresso in pixel dell'immagine finale: si vede il confine e si legge
la via che ci passa sotto. L'attribuzione OSM si dimensiona con l'immagine,
come la ODbL richiede.
Rimossa la rigenerazione massiva: job, stato in cache e interfaccia.
Sistema visivo ripassato su tutta l'applicazione: le scale gray e indigo di
Tailwind sono ridefinite nei token, cosi' le 37 viste si riallineano insieme
invece di essere riscritte una per una. Grigi caldi, un accento solo con quattro
significati, carattere servito dall'applicazione e non da Google Fonts, via il
gradiente della testata. Aggiunto il link "salta al contenuto", che mancava.
Corretto un guasto d'ambiente che bloccava TUTTI gli upload in sviluppo: dalla
1.26 il fastcgi_params di nginx passa HTTP_HOST come $host, che perde la porta,
e ogni URL firmato smetteva di validare — l'endpoint di upload di Livewire
rispondeva 401.
294 test verdi.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
I due file compose andavano tenuti allineati a mano, e gli anchor
(x-app-env, <<:) sono sintassi che va conosciuta per riuscire a leggere il
file. Per un deploy che deve restare semplice era complessita' non
giustificata.
Ora c'e' un solo docker-compose.yml, esplicito, che copre produzione e
sviluppo:
- ogni servizio dichiara quello che usa, senza merge key
- mailpit e' dietro il profilo "dev", quindi non parte mai in produzione
- la porta e' legata a 127.0.0.1 per default: in produzione il traffico
arriva da Traefik sulla rete interna, in locale basta localhost:8080.
Per esporla davvero: APP_PORT=0.0.0.0:8080
- .env diventa l'unica fonte di configurazione, senza valori ridichiarati
Compromesso accettato: sparendo i valori fissati nel compose, DB_HOST e
REDIS_HOST devono contenere i nomi dei servizi (mariadb, redis) e non un
indirizzo. E' segnalato in .env.example, nel README e in HANDOFF.md.
Per le modifiche al codice senza ricostruire l'immagine il README documenta
un docker-compose.override.yml, che Compose applica da solo ed e' gia'
ignorato da git.
Verificato: sei servizi healthy, login e pagine a 200, redeploy idempotente,
porta esposta solo su localhost, mailpit assente senza il profilo dev.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Il Dockerfile compilava l'applicazione in /app-src mentre il runtime girava
da /var/www/html, popolato solo dal bind mount del sorgente: l'immagine
costruita non veniva mai usata. L'entrypoint rieseguiva composer install e
npm run build a ogni avvio, dentro il container. Su Dokploy, senza sorgente
sull'host, questo significava build a runtime a ogni deploy.
Ora vendor/ e public/build sono compilati in stage separati e copiati
nell'immagine finale. I container di produzione non montano il sorgente e
non eseguono build all'avvio: un redeploy e' build, migrazioni, online.
- Dockerfile multi-stage (composer, node, runtime)
- nginx e php-fpm nello stesso container via supervisor: con container
separati nginx avrebbe bisogno di una copia di public/ e del volume
storage solo per servire file statici
- clear_env = no in www.conf, senza cui php-fpm nasconde a Laravel tutte
le variabili d'ambiente
- configurazione da ambiente di processo invece di .env riscritto con sed;
il compose fissa solo i valori dettati dalla topologia
- fail-fast su APP_URL, DB_PASSWORD, DB_ROOT_PASSWORD, REDIS_PASSWORD
- servizio scheduler dedicato: schedule:work non veniva mai eseguito,
quindi la pulizia dell'audit log non e' mai partita
- solo il container app esegue le migrazioni, per evitare che due
container in gara lascino uno schema applicato a meta'
- healthcheck separati per worker e scheduler, che non espongono HTTP
- docker-compose.dev.yml per lo sviluppo locale
- documentazione unificata in README.md e HANDOFF.md
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>