Estendere Griglia¶
Griglia è un package, non uno starter kit: la tua applicazione resta tua e la board si cambia da fuori. Ogni punto qui sotto è una giuntura pubblica — pubblichi un file, registri qualcosa in un service provider, ascolti un evento. Nessuno di questi passa dal fare un fork del package.
| Voglio… | Dove |
|---|---|
| Cambiare l'aspetto di una pagina | Pubblicare le viste |
| Cambiare le parole, o aggiungere una lingua | Pubblicare le traduzioni |
| Aggiungere una combinazione di colori | Temi generici |
| Dare a un look componenti, viste e rotta sue | Stili dedicati |
Vestire /settings come quel look |
Skin delle impostazioni |
| Fare qualcosa quando un task cambia | TodoChanged |
| Decidere chi entra, e con quale modello | Accessi |
| Tenermi le URL | Rotte tue |
Viste: pubblica solo quelle che cambi¶
Le viste del package finiscono in resources/views/vendor/griglia/. Un file lì vince su quello del
package, file per file — quindi cancella tutto quello che non hai toccato: le viste che lasci continuano a
seguire il package, quelle che tieni in casa si fermano alla versione che hai pubblicato.
Valgono anche i componenti Blade: <x-griglia::icon name="working" /> si risolve come vista
griglia::components.icon, quindi un components/icon.blade.php pubblicato sovrascrive anche il set di
icone.
| Cosa | File |
|---|---|
La cornice della pagina (font, <head>, classe del tema) |
layouts/themed.blade.php |
| La board | livewire/todo-list.blade.php (con livewire/partials/*) |
| Il modale del task | livewire/ingredient-modal.blade.php |
| La pagina delle impostazioni | livewire/settings-page.blade.php |
| Icone, toast, pezzi condivisi | components/*.blade.php |
Le viste pubblicate non si aggiornano da sole
Una versione nuova può aggiungere un wire: o un partial a una vista che hai copiato. Quando
aggiorni, confronta le tue copie con quelle del package — oppure butta la
copia e usa le variabili CSS e un tema, che non invecchiano.
Stringhe, e una terza lingua¶
Ottieni lang/vendor/griglia/en/t.php e .../it/t.php. Laravel fonde il file pubblicato sopra quello
del package chiave per chiave, quindi tieni solo le stringhe che riscrivi: tutto il resto continua a seguire
il package.
La board parla inglese (lingua base) e italiano. Per aggiungerne una terza:
- Pubblica le traduzioni, poi copia il file inglese:
- Traduci i valori di
fr/t.php. I segnaposto (:title,:agent,:count) devono sopravvivere alla traduzione. Una chiave che non hai ancora tradotto ricade suapp.fallback_locale, quindi un file tradotto a metà è comunque usabile. - Il cablaggio finisce qui:
Alle80\Griglia\Support\Locale::available()guarda dentroresources/lang/*del package elang/vendor/griglia/*, quindi il francese compare in Impostazioni → App → Lingua della board e il middlewareSetLocalelo applica a ogni pagina, richieste Livewire comprese.
Due dettagli che vale la pena conoscere:
- Il nome nel menu a tendina.
Locale::NAMESscrive per estesoeneit; ogni altro codice lo nominaext-intl(Français), e senza quell'estensione resta il codice maiuscolo (FR). - Le date seguono. Applicare la lingua imposta anche quella di Carbon, quindi «3 ore fa» lo traduce
Carbon, non
t.php.
Anche i testi di un tema scritti come chiave di traduzione (griglia::t.theme.add, come fa il tema Slate
integrato) seguono la lingua nuova — vedi Temi per le forme letterale
e per lingua.
Due traduzioni diverse
Questa è la lingua della board. La lingua di queste pagine di documentazione è un'altra cosa — vedi Traduzioni.
Un tema generico: colori e parole¶
Un tema generico è uno slug, una manciata di parole e un blocco CSS .theme-<slug> di variabili. Lo registri
in configurazione…
// config/griglia.php
'themes' => [
'lagoon' => [
'label' => 'Lagoon',
'icon' => '🌊',
'fonts' => 'inter:400,700', // passato a config('griglia.fonts_url')
'claim' => 'cose da fare',
'counter' => 'fatti',
'done_all' => 'tutto fatto',
'add' => 'aggiungi',
'stamp' => 'fatto',
'footer' => '',
'confirm' => 'elimino «:title»?',
'placeholder' => 'scrivi qui…',
'deco' => ['🌊', '⛵'],
],
],
…oppure a runtime, quando la definizione va calcolata:
// app/Providers/AppServiceProvider.php
use Alle80\Griglia\Themes;
public function boot(): void
{
Themes::registerTheme('lagoon', [/* le stesse chiavi */]);
}
Poi aggiungi le variabili al tuo CSS e scegli il tema in Impostazioni → App → Tema:
Una voce il cui slug è quello di un tema integrato lo sovrascrive chiave per chiave
(['slate' => ['icon_img' => '/images/slate.svg']] cambia l'icona e lascia tutto il resto, traduzioni
comprese). Ogni altro slug sostituisce l'intera definizione.
Preferisci distribuirlo come uno zip che un amministratore installa dalla board? Quello è un pacchetto di
tema — Temi ne accompagna uno, pollon, dall'esportazione
all'installazione.
Uno stile dedicato: componenti tuoi¶
Un tema generico riusa le viste del package. Quando vuoi un look che cambia il markup — un'altra impaginazione della board, un tuo template di riga — registri uno stile dedicato: componente Livewire tuo, viste tue, rotta tua, elencato nel selettore degli stili accanto ai temi generici.
// app/Livewire/RetroBoard.php
namespace App\Livewire;
use Alle80\Griglia\Livewire\ThemedTodoList;
use Livewire\Attributes\Layout;
#[Layout('layouts.retro')] // (1)!
class RetroBoard extends ThemedTodoList
{
public function render()
{
return view('livewire.retro-board', [
'todos' => $this->todos(),
't' => \Alle80\Griglia\Themes::get($this->theme),
'listName' => $this->listName(),
'archivedCount' => $this->archivedCount(),
'filtering' => $this->isFiltering(),
'plan' => $this->planStatus(),
]);
}
}
- Questa riga non è facoltativa. Un
#[Layout]ereditato dalla classe base vince su->layout()chiamato inrender(): una sottoclasse che dimentica il proprio attributo si disegna dentro il layout del package.
Estendere ThemedTodoList (o direttamente TodoList) ti regala tutta la board: scoping delle liste, stati,
avanzamento, domande, allegati, aggiornamenti dal vivo. Tu cambi render(), le viste e il layout — nient'altro.
Metti la rotta nella tua applicazione e dillo alla board:
// routes/web.php
Route::get('/retro', \App\Livewire\RetroBoard::class)->middleware('web');
// app/Providers/AppServiceProvider.php
use Alle80\Griglia\Themes;
Themes::registerStyle('retro', [
'label' => 'Retro',
'icon' => '🕹️',
'icon_img' => '/images/retro.svg', // facoltativo: un'immagine al posto dell'emoji
'route' => '/retro',
]);
Il selettore degli stili adesso elenca Retro per primo (gli stili dedicati vengono prima dei temi generici) e
punta a /retro. Alle80\Griglia\Http\Middleware\RememberStyle ricorda in sessione lo stile della pagina in
cui sei, così le pagine senza un look proprio — /settings, /context — possono vestirsi come lui.
La skin delle impostazioni¶
Che è appunto a cosa serve una skin: le classi e le variabili CSS che /settings usa quando lo stile
corrente è il tuo. I temi generici ne ricevono una gratis dalle loro variabili --tl-*; uno stile dedicato
registra la sua.
Themes::registerSkin('retro', [
'layout' => 'layouts.retro', 'layoutData' => [], 'home' => '/retro',
'card' => 'retro-card p-5',
'h1' => 'retro-display text-2xl',
'h2' => 'retro-display text-xl',
'sub' => 'text-sm italic opacity-70',
'label' => 'font-bold',
'help' => 'text-sm opacity-70',
'input' => 'retro-input px-3 py-1.5 focus:outline-none',
'back' => 'retro-key cursor-pointer px-3 py-1.5',
'divide' => 'divide-y divide-current/15',
'vars' => '--set-on:#33d17a;--set-off:#05130a;--set-border:#2c5c3f;--set-knob:#fff;--set-shadow:none',
]);
Ogni chiave è usata così com'è: layout/layoutData finiscono nel ->layout() di Livewire, home è il
link «indietro», vars colora gli interruttori (--set-on, --set-off, --set-border, --set-knob,
--set-shadow) e le altre sono stringhe di classi. Mettile tutte: la pagina legge ogni chiave direttamente.
La skin generica che Themes::settingsSkin() restituisce per un tema qualsiasi è la cosa più corta da
copiare e modificare.
Reagire a un cambiamento¶
Ogni modifica a un todo, a un sotto-task, a una domanda o a un allegato emette
Alle80\Griglia\Events\TodoChanged — trasmesso al browser, e a disposizione dei tuoi listener:
Event::listen(\Alle80\Griglia\Events\TodoChanged::class, function ($event) {
if ($event->stateChanged && $event->state === 'done') {
// manda un messaggio in chat, scrivi una metrica, chiama un webhook…
}
});
Il payload, i canali e come ascoltarlo da JavaScript sono in Eventi e broadcasting.
Chi entra, e con quale modello¶
In modalità server il package sostituisce il middleware auth con il proprio gate e fa due domande alla
tua applicazione:
// app/Models/User.php
public function canAccessGriglia(): bool
{
return $this->hasTeam(); // può aprire la board
}
public function canManageGriglia(): bool
{
return $this->is_admin; // può aprire /settings, /context e installare pacchetti di tema
}
Preferisci i Gate? GRIGLIA_ACCESS_GATE=access-griglia e GRIGLIA_ADMIN_GATE=manage-griglia vengono
consultati quando i metodi non ci sono, e GRIGLIA_ADMINS="1,alice@example.com" è l'ultima parola. L'ordine
completo sta in Accessi, amministratori e modalità.
Anche il modello si configura: GRIGLIA_USER_MODEL (default App\Models\User) è la classe che possiede le
liste. Puntalo al tuo modello e le relazioni del package lo seguono.
Rotte tue¶
Spegni le rotte del package e monta i componenti dove vuoi:
// routes/web.php
use Alle80\Griglia\Http\Middleware\{GrigliaAccess, OpenFromLink, RememberStyle, SetLocale};
Route::middleware(['web', GrigliaAccess::class, SetLocale::class, RememberStyle::class, OpenFromLink::class])
->prefix('board')
->group(function () {
Route::get('/', \Alle80\Griglia\Livewire\ThemedTodoList::class)->name('griglia.home');
Route::get('/settings', \Alle80\Griglia\Livewire\SettingsPage::class)
->middleware(\Alle80\Griglia\Http\Middleware\GrigliaAdmin::class)->name('griglia.settings');
});
Tieni tutti e quattro i middleware: GrigliaAccess è l'autenticazione del package (auth viene
ignorato), SetLocale applica la lingua della board, RememberStyle alimenta la skin delle impostazioni e
OpenFromLink apre un task arrivato da una notifica. Tieni anche i nomi delle rotte: la board ci si
collega.
Se ti serve solo un prefisso diverso, lascia accese le rotte e imposta GRIGLIA_ROUTE_PREFIX=board; il
package si registra dopo le rotte della tua applicazione, quindi in ogni caso la tua / ha la precedenza.
Quanto è stabile tutto questo?¶
Finché il package è sullo 0.x, queste giunture sono ciò che una versione minore cerca di non rompere, e una
rottura viene annunciata nel changelog e in
Aggiornare. Le viste pubblicate sono l'eccezione: sono una copia, e le copie
invecchiano.
Vedi anche¶
- Temi — pacchetti di tema, le variabili
--tl-*, i testi dei temi. - Eventi e broadcasting · Accessi, amministratori e modalità
- File di configurazione — tutte le chiavi, generate dal codice.