← Torna ai documenti

VRV Kickstart — Passa questo file all'inizio di ogni sessione

Dove sei

Progetto in breve

Diario di viaggio (vittrosviaggi). Stack: PHP + TinyMCE + MariaDB + CSS custom.

Migrazione graduale `vv_*` → `vrv_*`. Deploy: work → test → prod.

NON fare big bang. NON rimuovere alias `vv_*` (BASE_URL non è ancora config-driven).

File più importanti

| File | Cosa fa |

|------|---------|

| `lib/core/3_2_1_Go.php` | Entry point universale (sostituisce bootstrap.php ovunque) |

| `lib/caricaTinyMCE.php` | Tutto l'editor + logica Maserati (slideshow foto) |

| `css/vv-post-content.css` | CSS visualizzazione post + content_css TinyMCE |

| `js/vv-carousel.js` | Inizializza slideshow in visualizzazione pubblica |

| `js/modifica_post.js` | Legacy: autosave, callSave(), restore/release |

| `js/vrv_modifica_post_exit.js` | Nuovo: dropdown esci, salva/esci, scarta, modal note |

| `ajax/release_post.php` | **BUG GRAVE**: DELETE draft è commentato (patch emergenziale) |

| `ajax/handle_set_visibility.php` | Aggiorna visibilità post da lista admin |

| `inc/diario_list_lib.php` | HTML+JS lista post (JS visibility change handler) |

CSS per contesto

| Dove | CSS caricato |

|------|-------------|

| Visualizzazione pubblica | `vv-post-content.css`, `vv-post-content-images.css` + `vv-carousel.js` |

| TinyMCE content (body class: `vv-editor-body`) | `vv-post-content.css` |

| Pagina modifica_post | `vrv_base.css`, `vrv_layout.css`, `vrv_components.css`, `vrv_modifica_post.css` |

| Lista admin/guest | `diario_lista_admin.css` (slice) → importa `diario.css` → importa `diario_header.css` |

CSS chain lista admin — IMPORTANTE

`diario_lista_admin.php` carica `theme-default.d/diario.css` (esplicito) e viene servito anche

lo slice `theme-default.d/diario_lista_admin.css` (automatico). Entrambi importano `diario_header.css`

che contiene i file **vrv-filter-select**, toolbar, bottoni. Se qualcosa appare non stilizzato nella lista,

prima cosa: verificare che `diario_header.css` esista in `theme-default.d/`.

Bug aperti (non toccare senza context)

1. **release_post.php**: `DELETE FROM post_drafts` commentato → bozza sopravvive al release

2. **TinyMCE blob URI**: paste immagini produce `src="data:image/jpeg;base64,..."` invalidi o `blobid0.jpg`

3. **Hidden version**: numero versione non si aggiorna a schermo fino al refresh dopo hide

Fix applicati (2026-05-16) — in work E test (deploy completato)

| Fix | File | Dettaglio |

|-----|------|-----------|

| Maserati annidato — display | `js/vv-carousel.js` | Salta slot nested con `parentElement.closest()` |

| Maserati annidato — editor | `lib/caricaTinyMCE.php` | `vvNormalizeOldSlots`: unwrappa outer se contiene solo inner vv-slots |

| Immagini in `<p>` dentro slot | `lib/caricaTinyMCE.php` | `vvCleanSlot()`: rimuove wrapper spuri, chiamata in vvAddImgToSlot + normalize |

| HTTP 500 visibilità | `ajax/handle_set_visibility.php` | Mancava `'` di chiusura nella require_once |

| CSS lista rotto | `css/theme-default.d/diario_header.css` | File cancellato per errore dal refactor CSS — ripristinato da vv_test |

| CSS lista rotto (2) | `css/theme-default.d/diario_lista.css` | Ripristinato da vv_test (`.vv-visibility-pill` contrast fix) |

| CSS bottoni mancanti | `css/theme-default.d/buttons.css` | Ripristinato da vv_test (`.vrv-btn`, `.vv-btn`) |

| CSS action bar mancante | `css/theme-default.d/vv-actions.css` | Ripristinato da vv_test (`.vv-actions` per modifica_post) |

| Maserati vuoto invisibile | `css/vv-post-content.css` | Bordo tratteggiato + placeholder testo su `.vv-slot` nell'editor |

Deploy 2026-05-16 (maserati)

Fix applicati (2026-05-16) — Upload + picker foto TinyMCE — in work E test

| Fix | File | Dettaglio |

|-----|------|-----------|

| URL hardcoded upload | `lib/caricaTinyMCE.php` | `fetch('/vittrosviaggi_work/...')` → `window.BASE_URL + 'ajax/handle_upload_media.php'` |

| POST_ID zero | `lib/caricaTinyMCE.php` | Toast esplicito + reject se POST_ID non definito |

| Errori silenti upload | `lib/caricaTinyMCE.php` | Toast su HTTP error e su risposta server non-ok |

| Picker nomi file invisibili | `lib/caricaTinyMCE.php` | `vvPickerDialog`: miniatura avvolta in div, nome file sotto ogni foto |

Note: `foto/` è symlink a `/srv/http/vittrosviaggi_shared/foto` — condivisa tra tutti i branch.

Note: upload intermittente su MacBook Air 4GB → causa memoria; workaround: caricare 2-3 foto alla volta.

Picker Maserati — struttura thumbnail (2026-05-16)

`vvPickerDialog` in `lib/caricaTinyMCE.php`: ogni miniatura è ora un `<div>` con:

Fix applicati (2026-05-16) — Admin page restyling + CSS globali — in work E test

| Fix | File | Dettaglio |

|-----|------|-----------|

| admin.php riscritto | `admin.php` | Standard VRV: vv_enqueue_theme_css, header_badge, vv-container, vv-card, footer. Eliminata gestione temi. Log viewer → `testing/log_viewer.php`. |

| CSS admin | `css/theme-default.d/vrv_admin.css` | Nuovo file. Classi: `vrv-admin-section`, `vrv-admin-tools`, `vrv-admin-tool-link`, `vrv-admin-debug-table` |

| @import mancante | `css/theme-default.css` | Rimosso `@import vv-post-container.css` (file inesistente). Spostato Google Fonts `@import` in cima al file (era a riga 1041). |

| is-hidden modale | `admin.php` | Aggiunto `'lib' => ['info_modal']` in vv_enqueue_theme_css — senza non caricava `.is-hidden { display:none }` |

Deploy 2026-05-16 (admin + CSS globali)

Fix applicati (2026-05-20) — Gestione utenti + pannello admin — in work E test

| Fix | File | Dettaglio |

|-----|------|-----------|

| `admin.php` riscritto | `admin.php` | Pannello con action bar (🐷 welcome, Categorie, Utenti, Log, Strumenti). Categorie CRUD inline, utenti con ricerca+paginazione dinamica, log lazy-load, modal reset password |

| Gestione utenti | `admin_utenti.php` | Pagina completa: avatar (GD 200×200 crop), cambio ruolo/attivo/password, sezione richieste pendenti |

| Profilo utente | `profilo.php` | Nuovo file. Utente non-admin: cambio avatar + cambio password. Redirect a login se non autenticato |

| Registrazione | `login.php` | Aggiunta `<details>` in fondo al form: richiesta accesso → `richieste_accesso` DB + mail a `senecavittanicarissimo@gmail.com` |

| AJAX utenti | `ajax/admin_utenti.php` | Nuovo. Azioni: list, change_role, toggle_active, reset_password, delete, approva_richiesta, rifiuta_richiesta, upload avatar. Solo admin |

| AJAX registrazione | `ajax/registra_utente.php` | Nuovo. Pubblico. Valida username, inserisce in `richieste_accesso`, invia mail |

| CSS pannello admin | `css/theme-default.d/vrv_admin.css` | Aggiunte classi `vrv-ap-*`: action bar, pane toggle, welcome piggies, badge, subsection pending |

| CSS utenti | `css/theme-default.d/vrv_utenti.css` | Nuovo file. Classi `vvu-*`: tabella, avatar (36px/110px), bottoni, modal password, select, ricerca+paginazione |

| Label filtri | `diario_lista_admin.php`, `diario_lista_guest.php` | "Tutte/Tutti" → "Categorie", "Stato", "Visibilità" |

DB (già applicato — DB condiviso work/test/prod)


ALTER TABLE utenti ADD COLUMN IF NOT EXISTS avatar VARCHAR(255) DEFAULT NULL;
CREATE TABLE IF NOT EXISTS richieste_accesso (
  id INT AUTO_INCREMENT PRIMARY KEY,
  username VARCHAR(50) NOT NULL,
  password_hash VARCHAR(255) NOT NULL,
  note TEXT DEFAULT NULL,
  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  INDEX idx_username (username)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Note architetturali

Deploy 2026-05-20 (utenti + admin panel)

Fix applicati (2026-05-21) — Profilo utente + admin utenti — in work E test

| Fix | File | Dettaglio |

|-----|------|-----------|

| Lightbox avatar doppio click | `profilo.php` | Rimosso ctrl+click (non funzionava: label intercettava tutto). Nuovo meccanismo: listener su `click` del label con `preventDefault()` + timer 300ms — singolo click → apre file dialog programmatico, doppio click → apre lightbox |

| Admin modifica altri utenti | `profilo.php` | Accetta `?id=X` se admin. Titolo "Profilo di [username]". Form password: senza campo "vecchia password" quando admin resetta altri. Fetch user da `$targetId` invece di `$me` |

| Link profilo in admin utenti | `admin_utenti.php` | Aggiunto bottone `👤` in colonna azioni per ogni utente — link a `profilo.php` (proprio) o `profilo.php?id=X` (altri) |

Deploy 2026-05-21 (profilo + admin utenti)

Roadmap aggiornata (2026-05-21)

Fix applicati (2026-05-16) — Fisarmonica traduzioni — in work E test

| Fix | File | Dettaglio |

|-----|------|-----------|

| Fisarmonica lista admin | `inc/diario_list_lib.php` | `vv_fetch_children_for_parents()` + toggle ▶/▼ + render figli inline |

| Fisarmonica lista admin | `diario_lista_admin.php` | Fetch children + passa al render |

| CSS fisarmonica | `css/theme-default.d/diario_lista_admin.css` | `.vv-children`, `.vv-fis-toggle`, `.vv-own-lang` |

Logica fisarmonica

Deploy 2026-05-16 (fisarmonica)

Maserati — HTML corretto


<div class="vv-slot vv-slot--md vv-slot--carousel" contenteditable="false">
  <img src="foto/post_NNN/foto1.jpg" alt="">
  <img src="foto/post_NNN/foto2.jpg" alt="">
</div>

Classi size: `sm/md/lg` (landscape 16:9) | `smP/mdP/lgP` (portrait 3:4) | `mix` (misto)

Le funzioni JS chiave in `caricaTinyMCE.php`:

Database


post              -- contenuto principale (campo: contenuto)
post_drafts       -- una bozza per post (upsert su post_id, updated_at)
post_versions     -- storico versioni (version_no crescente, note = label)
vw_post_effective -- VIEW: draft se esiste, altrimenti ultima versione released

Post di test

| ID | Titolo | Nota |

|----|--------|------|

| 143 | Maserati! | Post privato per test maserati — usalo liberamente |

| 142 | 20260417 Repubbliche Baltiche | Elena usa i maserati qui — non rompere |

| 117 | Vitti alle Olimpiadi | Primo post con maserati — non rompere |

Scripts di gestione — `/home/vitti/scripts/manage_web_projects/bin/`

| Script | Funzione |

|--------|----------|

| `backup/backup_vv.sh` | Backup VRV completo (codice + DB, opzioni embed) |

| `backup/backup_multi.sh` | Backup multipli progetti |

| `backup/snapshot_{code,db,photos}.sh` | Snapshot selettivi |

| `backup/vv_backup_sacro.sh` | Backup completo su NAS montato |

| `deploy/rollback.sh` | Rollback a release precedente |

| `deploy/verify_release.sh` | Verifica integrità release |

| `deploy/vv_deploy_link.sh` | Aggiorna symlink di deploy |

| `deploy/vv_rotate_channels.sh` | Rotazione guidata work→test→prod |

| `service/cleanup_saves.sh` | Pulizia salvataggi temporanei |

| `service/clone_release.sh` | Clona una release |

| `service/prune_releases.sh` | Rimuove release vecchie |

| `service/vv_fix_perms.sh` | Fix ownership/permessi |

| `service/vv_cleanup.sh` | Quarantena file junk (usa output di vv_inventory) |

| `service/post_deploy_report.sh` | Report post-deploy HTML |

| `stato/vrv_status.sh` | Stato symlink vv/vv_test/vv_work |

| `stato/vrv_scripts_map.sh` | Rigenera scripts_map.txt |

| `stato/vv_diff.sh` | Diff tra release |

| `stato/vv_inventory.sh` | Inventario file/junk di una release |

| `stato/vv_logs_tail.sh` | Tail log nginx/php-fpm |

| `lib/cerca_blocco_con_stringa.sh` | Utility awk: trova blocchi `{}` contenenti stringa |

Script da correggere: `service/share_cleanup.sh` (DB_PASS hardcoded), `service/db_migrate.sh` (usa sudo mysql root).

Cartelle `_old/` e `_attic/` sono archivio — non usare.

Deploy

Sviluppa su work → testa → copia file modificati in test → Elena valida → fix mirati in prod.

Quando copi su test: aggiorna anche `version.json` con changelog.

Prossimi lavori (roadmap — non fare senza context)

1. ~~Portare i fix di oggi in vv_test~~ ✅ FATTO (2026-05-16)

2. Bottoni "nuvolette" su tutte le pagine

3. Standardizzare caricamento CSS/JS via vv_enqueue_theme_css

4. ~~Migrazione bootstrap.php → 3_2_1_Go.php~~ ✅ FATTO (2026-05-16)

5. Resize immagini client-side prima dell'upload (TODO)

**Resize server-side già fatto (2026-05-16)**: post 142 — 22 foto ridimensionate a max 1920px

`mogrify -resize '1920x1920>' -quality 85 /srv/http/vittrosviaggi_shared/foto/post_NNN/*.jpg`

Da fare su altri post se necessario.

5b. Resize immagini client-side prima dell'upload (TODO)

6. ~~Pagine admin — refactor e nuove feature~~ ✅ FATTO (2026-05-20)

5. Fisarmonica — visibilità sui figli (da decidere con Elena)

5. Maserati — highlight nell'editor

---

Progetto Mappa (`/srv/http/maps`)

Stack

File chiave

| File | Cosa fa |

|------|---------|

| `index.html` | Pagina principale mappa |

| `js/map_google.js` | Logica mappa Google Maps (marker, route, search, Ctrl+click) |

| `search_place.php` | Geocoding via Nominatim con viewbox del viewport corrente |

| `insert_waypoint.php` | Inserisce waypoint nel DB/JSON |

| `build_map_points.py` | Genera punti mappa da CSV foto |

Ricerca luoghi (search_place.php + map_google.js)

**Ricerca per nome**: digita il nome della via/luogo → Nominatim favorisce l'area visibile a schermo (viewbox dinamico). Zoom risultato: 13. Per città dell'Est Europa (Estonia, Lettonia ecc.) la copertura OSM è buona ma non perfetta — se non trova, aggiungere "Tallinn" o il nome città davanti.

**Ricerca per coordinate**: digita `59.437, 24.745` (lat, lon — formato Park4night, Google Maps ecc.) → salta Nominatim, mappa va direttamente alle coordinate, zoom 17, pin rosso temporaneo per 8 secondi. Poi Ctrl+click per piazzare il waypoint.

**TODO**: zoom adattivo per ricerca per nome (città → 12, via → 16) in base al `type` restituito da Nominatim.

Workflow aggiunta waypoint da Park4night / Google Maps

1. Trova il posto su Park4night → copia le coordinate (es. `59.437, 24.745`)

2. Incollale nella casella di ricerca della mappa → clic sul risultato `📍`

3. Pin rosso indica la posizione esatta → Ctrl+click per piazzare il waypoint

Cache busting

I file JS usano `?v=TIMESTAMP` per il cache busting. Quando modifichi `map_google.js`,

aggiorna il timestamp in `js/map_bootstrap.js` (riga `loadScript`) e in `index.html`.

Comando rapido: `date +%s` per il nuovo valore.

Waypoint pianificati

Salvati in `routes/planned_waypoints.json`. Per rimuovere un punto manualmente: modifica il file JSON.

Workflow pianificazione tappa: Ctrl+click → inserisci punti → Calcola → Salva → Trasferisci.

Fix applicati (2026-05-16)

Tappa 2026-05-21 — sorve-parnu (segmento 30)

**Cartella:** `img/baltici/sorve-parnu/` — 9 foto, 3 punti mappa: Kuressaare, Liiva, Parnu

**Pernottamento attuale:** Parnu, Estonia — segmento 30 di 30

**Correzione punto "Saaremaa":** il punto notte era posizionato erroneamente vicino a Kuressaare (58.248, 22.503). Rinominato "Sorve, Saaremaa" con coordinate corrette dal faro (57.910753, 22.055342 — foto IMG_20260520_163539.jpg). Segmenti 29 e 30 rigenerati.

**Bug noti build_map_points.py** (da correggere a mano dopo ogni run):

1. I nuovi punti non hanno `route_group`, `route_mode`, `valid`, `route_order`, `notte` → aggiungere manualmente

2. I `files[]` vengono salvati senza prefisso cartella (`IMG_xxx.jpg` invece di `NOME_TAPPA/IMG_xxx.jpg`) → correggere manualmente

3. Foto da tablet/Amazon Photos senza GPS nell'EXIF → inserire coordinate manuali nel coords.csv

**Permessi:** `sudo chown -R vitti:http /srv/http/maps/routes/itinerario_baltici/` (fatto — non dovrebbe ricapitare)

Fix applicati (2026-06-01) — marker invisibili + flag notte

**Marker Aizpute e Brusperk non si trovavano sulla mappa.** Causa: il marker usa come icona la

thumbnail `/maps/img/baltici/thumbs/<basename(files[0])>`; se quella non esiste, il marker è

rotto/invisibile (righe ~106-117 di `map_google.js`: niente marker se mancano `files`, e icona = thumb del 1° file).

state rinominate `NN_Aizpute_…` (convenzione `NN_Localita_YYYYMMDD_HHMMSS`). → aggiornati i 11 `files[]`.

(`02_/03_`). → rinominate `mv 02→01`, `03→02` in `img/baltici/thumbs/`.

0 marker rotti. La Svizzera è a posto (nessuna notte: Borgosoprano/Maloggia transito `hidden`, Sils/Scuol

soste-foto `photo`).

⚠️ **Regola d'oro**: quando rinomini le foto (`NN_Localita_…`), aggiorna SEMPRE i `files[]` in

`map_points.js` (live **e** `maps_dev/trips/baltici/map_points.js`), altrimenti il marker sparisce.

**Flag `notte` usato per i segmenti.** `computeSegmentMap()` contava le notti cercando la parola "notte"

nella **descrizione**. Ora usa il flag `p.notte === true` quando presente (fallback alla descrizione solo

per i punti vecchi senza flag).