diff --git a/README.md b/README.md index fb29dc3..e710e64 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ Tutte le impostazioni globali sono **flag build-time** nel file [`lib/config.ts` | Variabile | Default | Descrizione | |---|---|---| | `EXTERNAL_LINK_ENABLED` | `true` | Mostra il tipo di card "External Link" nel menu dell'admin. Le card di quel tipo già esistenti restano comunque visibili e cliccabili anche se messo a `false`. | -| `FACTORY_RESET_ENABLED` | `false` | Mostra la sezione "Factory Preset" nell'admin (funzione developer). Vedi [Factory Preset](#factory-preset-developer). Gli endpoint API restano attivi a prescindere. | +| `FACTORY_PRESET_SAVE_ENABLED` | `false` | Mostra il bottone "💾 Salva come Factory Preset" nell'admin (funzione developer per ricreare/aggiornare il preset). Il bottone "🏭 Factory Reset" e lo stato del preset sono **sempre visibili** indipendentemente da questo flag — vedi [Factory Preset](#factory-preset-developer). L'endpoint API `POST /api/admin/factory-preset` resta attivo a prescindere. | | `DEFAULT_FONT` | `''` | Font di default se il portale non ne ha impostato uno. Stringa vuota = font di sistema (Arial). Altrimenti il nome esatto di un file in `data/fonts/` (es. `"Geist-Variable.woff2"`). | | `TEXT_LIMITS` | vedi sotto | Limiti caratteri di tutti i campi testuali. | | `UPLOAD_LIMITS` | vedi sotto | Dimensioni massime upload per famiglia di file. | @@ -230,7 +230,7 @@ Lo zip così prodotto è caricabile direttamente dal pulsante "Ripristina da ZIP Stato "di fabbrica" ripristinabile con un click. Pensato per preparare preset standard (es. banner + icona + una card di redirect) da distribuire a più macchine MajorNet. -**Visibile nell'admin solo se** `FACTORY_RESET_ENABLED = true` in `lib/config.ts`. Gli endpoint API restano comunque attivi anche con il flag a `false`. +**La sezione è sempre visibile in admin.** Il bottone "🏭 Factory Reset" e lo stato del preset corrente sono mostrati sempre (è un'operazione lecita per qualunque amministratore). Il bottone "💾 Salva come Factory Preset" — che riscrive il preset di fabbrica — è invece **gated** da `FACTORY_PRESET_SAVE_ENABLED = true` in `lib/config.ts` (default `false`): tienilo attivo solo sulla macchina di sviluppo dove prepari/aggiorni il preset. Gli endpoint API restano comunque attivi a prescindere dal flag. Il preset è un file fisso: **`factory/preset.zip`** alla radice del progetto (fuori da `data/`, quindi non viene toccato dai reset; fuori da `public/`, quindi non scaricabile via web). @@ -510,4 +510,4 @@ rm -rf .next && npm run build **Recupero dopo un ripristino sbagliato**: lo stato precedente è in `data.bak-/`. Ferma il server, rinomina quella cartella in `data/` e riavvia. -**La sezione Factory Preset non compare**: è dietro il flag `FACTORY_RESET_ENABLED` in `lib/config.ts`. Mettilo a `true` e ricostruisci. +**Il bottone "Salva come Factory Preset" non compare**: è dietro il flag `FACTORY_PRESET_SAVE_ENABLED` in `lib/config.ts`. Mettilo a `true` e ricostruisci (di norma lo si tiene `false` in produzione). Il bottone "🏭 Factory Reset" e lo stato del preset restano comunque sempre visibili. diff --git a/app/admin/page.tsx b/app/admin/page.tsx index b296f54..e47699f 100644 --- a/app/admin/page.tsx +++ b/app/admin/page.tsx @@ -2,18 +2,20 @@ import { useState, useEffect, useRef } from 'react'; import { Card, Portal, MediaItem, CardType } from '@/types'; -import { EXTERNAL_LINK_ENABLED as EXTERNAL_LINK_DEFAULT, FACTORY_RESET_ENABLED } from '@/lib/config'; +import { EXTERNAL_LINK_ENABLED as EXTERNAL_LINK_DEFAULT, FACTORY_PRESET_SAVE_ENABLED } from '@/lib/config'; import { CARD_LIMITS, PORTAL_LIMITS } from '@/lib/validation'; import { withBasePath } from '@/lib/url'; type CharCounterProps = { value: string | undefined; limit: number }; function CharCounter({ value, limit }: CharCounterProps) { const len = (value ?? '').length; - if (len < limit * 0.8) return null; + const remaining = limit - len; const overflow = len > limit; + const near = !overflow && len >= limit * 0.8; + const color = overflow ? 'text-red-600 font-semibold' : near ? 'text-amber-600' : 'text-gray-400'; return ( -

- {len} / {limit} +

+ {len} / {limit} · {remaining < 0 ? `${Math.abs(remaining)} oltre il limite` : `${remaining} rimanenti`}

); } @@ -614,7 +616,8 @@ export default function AdminDashboard() { } }; - // Factory preset (developer): UI visibile solo se FACTORY_RESET_ENABLED. + // Factory preset: la sezione è sempre visibile (per chi accede a /admin); solo + // il bottone "Salva come preset" è gated da FACTORY_PRESET_SAVE_ENABLED. const [factoryPreset, setFactoryPreset] = useState<{ exists: boolean; sizeBytes?: number; modifiedAt?: string } | null>(null); const [savingPreset, setSavingPreset] = useState(false); const [factoryResetting, setFactoryResetting] = useState(false); @@ -626,7 +629,7 @@ export default function AdminDashboard() { } catch { /* ignore */ } }; useEffect(() => { - if (FACTORY_RESET_ENABLED) void refreshFactoryPreset(); + void refreshFactoryPreset(); }, []); const handleSaveFactoryPreset = async () => { @@ -904,40 +907,40 @@ export default function AdminDashboard() { - {FACTORY_RESET_ENABLED && ( -
-

Factory Preset developer

-

- Stato “di fabbrica” sempre ripristinabile con un click. Utile per preparare preset standard da distribuire alle macchine MajorNet: - configura il portale come vuoi, salvalo come preset, poi copia factory/preset.zip sulle altre macchine. -

-

- Preset attuale: {factoryPreset === null ? '…' - : factoryPreset.exists - ? presente · {((factoryPreset.sizeBytes ?? 0) / (1024 * 1024)).toFixed(1)} MB · {factoryPreset.modifiedAt ? new Date(factoryPreset.modifiedAt).toLocaleString('it-IT') : '?'} - : nessun preset configurato} -

-
+
+

Factory Preset

+

+ Stato “di fabbrica” ripristinabile con un click. Il preset (factory/preset.zip) viene preparato sulla macchina di sviluppo e distribuito alle macchine MajorNet. +

+

+ Preset attuale: {factoryPreset === null ? '…' + : factoryPreset.exists + ? presente · {((factoryPreset.sizeBytes ?? 0) / (1024 * 1024)).toFixed(1)} MB · {factoryPreset.modifiedAt ? new Date(factoryPreset.modifiedAt).toLocaleString('it-IT') : '?'} + : nessun preset configurato} +

+
+ + {FACTORY_PRESET_SAVE_ENABLED && ( - -
+ )}
- )} +