Configuració d'un Panel
Un Panel és la unitat d'incrustació d'Arrel: agrupa els Resources, les pàgines i els widgets que vols exposar sota una URL, amb la seva pròpia marca. Una aplicació pot registrar-ne més d'un (per exemple, un panell admin i un panell branded-demo amb colors diferents per a un client concret).
Registrar un Panel
Es registra contra el singleton PanelRegistry que el ServiceProvider d'Arrel ja enllaça, normalment des del boot() d'un ServiceProvider propi de la teva aplicació:
use Arrel\Panels\Panel;
use Arrel\Panels\PanelRegistry;
public function boot(PanelRegistry $panels): void
{
$panels->register(
Panel::make('admin')
->resources([
PostResource::class,
])
->pages([
SiteSettingsPage::class,
])
->customPages([
CustomPage::make('about', 'About'),
])
->widgets([
Widget::make('total_posts')
->label('Total Posts')
->value(fn (): int => Post::count()),
])
);
}Panel::make($id) pren l'identificador que apareixerà a la URL. Els mètodes resources(), pages(), widgets() i customPages() són tots opcionals i es poden combinar lliurement. Demanar un panell que no està registrat respon 404.
Prefix i panells
Per defecte, el panell admin viu a /arrel/admin. Es pot canviar amb config/arrel.php:
return [
'prefix' => 'arrel',
'panels' => [],
'middleware' => [],
'authenticated_middleware' => [],
'extra_scripts' => [],
];| Clau | Descripció |
|---|---|
prefix | Primer segment de la URL de la SPA: /{prefix}/{panel}. Pot ser qualsevol cadena, o buit. |
panels | Llista d'identificadors de panell. Només cal quan el prefix és buit. |
middleware | Middleware que s'executa abans de l'autenticació. Vegeu Middleware. |
authenticated_middleware | Middleware que s'executa després d'autenticar. |
extra_scripts | URLs de scripts que es carreguen a tots els panells. Vegeu Scripts i fulls d'estils. |
Un panell a l'arrel del domini necessita el prefix buit i la llista dels seus identificadors, perquè Arrel només respongui a aquests i no s'empassi la resta de rutes de l'aplicació:
'prefix' => '',
'panels' => ['admin'],Amb això, el panell admin viu a /admin. L'API continua sota /arrel/api/{panel}/..., sigui quin sigui el prefix.
Per construir la URL d'una pàgina del panell des del teu codi, fes servir Arrel\Support\PanelUrl:
use Arrel\Support\PanelUrl;
PanelUrl::to('admin', 'posts'); // "/arrel/admin/posts"Marca pròpia
Panel::make('branded-demo')
->brandName('Branded Demo')
->logo('/images/branded-demo-logo.svg')
->colors(['brand' => '#2E7D32', 'brand-strong' => '#1B5E20'])
->resources([PostResource::class]);brandName(), logo() i colors() s'exposen al frontend via window.Arrel (nom de la marca al <title> i a la interfície, logo, i els tokens de color que sobreescriuen la paleta per defecte). Sense brandName(), el panell es diu «Arrel».
Per a tipografia pròpia, fonts() i stylesheet() funcionen igual que colors() però per a famílies de lletra:
Panel::make('branded-demo')
->fonts(['sans' => '"Poppins", sans-serif'])
->stylesheet('https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&display=swap');fonts() sobreescriu els tokens de família de lletra (sans, display...) igual que colors() fa amb els de color. stylesheet() carrega una fulla d'estils externa (típicament un enllaç de Google Fonts) al <head>, abans del propi CSS d'Arrel, perquè el @font-face ja estigui registrat quan calgui.
Tema
Panel::make('admin')->theme('light');theme() accepta auto (per defecte, segueix el sistema), light o dark. Qualsevol altre valor llança una InvalidArgumentException.
Peu de pàgina
Panel::make('admin')->footer(fn (): array => [
'text' => '© '.now()->year.' Acme',
'links' => [
['label' => 'Cookies', 'url' => '/cookies'],
],
]);footer() pren un array, o una closure que el retorna, amb text i una llista de links. Es mostra sota totes les pàgines del panell.
Textos de la interfície
Els textos de la interfície (botons, estats, pantalles de seguretat...) estan en anglès. Es poden traduir amb translations(), que pren un array de clau => text o una closure que el retorna. La closure s'avalua a cada petició, així que pot dependre de l'idioma actiu:
Panel::make('admin')->translations(fn (): array => (array) __('arrel'));Les claus que Arrel reconeix són:
save, cancel, remove, saved, loading, search_placeholder, searching, no_results, clear_filters, select_all, clear_selection, sign_in, sign_out, dashboard, email, password, invalid_credentials, something_went_wrong, any, new_prefix, edit_prefix, main_navigation, active, all_with_trashed, trashed_only, selected_suffix, columns, select_row_prefix, home, date_placeholder, today, clear, previous_month, next_month, two_factor_code, two_factor_code_hint, verify, use_another_account, security, two_factor_title, two_factor_on, two_factor_off, two_factor_required, two_factor_enable, two_factor_disable, two_factor_scan, two_factor_secret, two_factor_confirm, recovery_codes_title, recovery_codes_hint, continue, two_factor_disable_hint, verify_email_title, verify_email_hint, verify_email_send, verify_email_resend, verify_email_sent, verify_email_continue, verify_email_pending, notifications, mark_all_as_read i no_notifications.
Una clau que no declares conserva el text per defecte.
Els missatges d'error que genera el servidor (inici de sessió, segon factor, verificació del correu) i els noms de les accions incloses són traduccions de Laravel sota el namespace arrel::, i es poden sobreescriure amb fitxers a lang/vendor/arrel.
Pàgina de perfil i pàgina d'inici
Panel::make('admin')
->profile(AccountPage::class)
->home(fn (): ?string => auth()->user()?->is_teacher ? PanelUrl::to('admin', 'custom/pass-list') : null);profile()pren unaPagei la converteix en l'enllaç de perfil de l'usuari a la barra lateral. Només es mostra sicanView()de la pàgina és cert.home()pren una closure que retorna la ruta on ha d'aterrar l'usuari en obrir el panell (en carregar-lo, o en venir de l'inici de sessió o de la pàgina de seguretat). Ambnull, o amb un valor buit, l'usuari aterra al dashboard. La closure s'avalua per usuari, així que cadascú pot tenir la seva pàgina d'inici.
Scripts i fulls d'estils
Per carregar el JavaScript de les teves pàgines personalitzades hi ha dues vies:
Panel::make('admin')
->scripts(fn (): array => [Vite::asset('resources/js/arrel/pages.ts')])
->stylesheets(fn (): array => [Vite::asset('resources/css/arrel.css')]);scripts() afegeix <script type="module"> després d'arrel.js, i stylesheets() afegeix <link rel="stylesheet"> després del CSS d'Arrel. Tots dos pren un array d'URLs o una closure que el retorna, i són per panell. config('arrel.extra_scripts') fa el mateix per a tots els panells.
Autenticació i seguretat
Tot el que fa referència a Sanctum, verificació del correu, segon factor i notificacions és a Autenticació. L'autorització i els límits d'intents, a Seguretat i autorització.
Middleware
config('arrel.middleware') s'afegeix, en ordre, abans del propi middleware d'Arrel a totes les rutes web i API. És el punt d'entrada per a qualsevol cosa que la teva aplicació necessiti resoldre abans que Arrel consulti res. El cas més habitual és el multi-tenancy:
// config/arrel.php
'middleware' => [
\App\Http\Middleware\IdentifyTenant::class,
],config('arrel.authenticated_middleware') s'executa després que Arrel ja hagi resolt l'usuari, i després de la verificació del correu i del segon factor. middleware s'executa abans que Sanctum resolgui la sessió, així que encara no veu cap usuari autenticat: qualsevol cosa que en necessiti un ha d'anar a authenticated_middleware.
// config/arrel.php
'authenticated_middleware' => [
\App\Http\Middleware\RecordLastSeen::class,
],L'ordre complet de les rutes de l'API és:
[
...config('arrel.middleware'),
ForceJsonResponse::class,
EnsureFrontendRequestsAreStateful::class,
'web',
'auth:sanctum',
EnsureEmailIsVerified::class,
EnsureTwoFactorIsSetUp::class,
...config('arrel.authenticated_middleware'),
]Els endpoints de les pàgines personalitzades que escriguis a la teva aplicació han d'usar aquesta mateixa pila, perquè hereten les mateixes garanties (vegeu Pàgines personalitzades).
Següent pas
Amb el Panel registrat, defineix el teu primer Resource.