⌘K

Admin

Admin shell

Volitelný admin shell — co instalace zapíše, co shell čte a jeden řádek pro Tailwind, bez kterého se sidebar vykreslí jako nic.

Na této stránce

Všechno, co admin potřebuje, ve frameworku už bylo — kromě rámu kolem toho: co je zaregistrované (Catalog), jak se to seskupuje a řadí (Workspace), kde žije stránka každého klíče (ResolvesPageUrls), samotné stránky, command palette, toasty. Co žádný balíček nevezl, byl layout se sidebarem — takže tuhle část psala každá aplikace znovu.

wire-admin je přesně tahle část a nic víc.

Instalace

composer require nyoncode/wire-admin
php artisan wire-admin:install

Instalátor udělá tři věci, které composer require udělat nemůže, a u každé řekne, jak dopadla:

Krok Co zapíše
Publikuje App\Providers\WireAdminServiceProvider Ten jeden řádek, který jmenuje layout, config('livewire.component_layout')
Zapíše resources/views/components/layouts/admin.blade.php Váš layout, který jmenuje komponentu shellu a plní její sloty
Zaregistruje provider v bootstrap/providers.php Aby řádek výš vůbec běžel
Přidá jeden řádek @source do resources/css/app.css Aby Tailwind zkompiloval třídy, které views shellu používají
Přidá tamtéž @plugin "@tailwindcss/forms" a @custom-variant dark (&:where(.dark, .dark *)) a do package.json balíček @tailwindcss/forms Pole formulářů berou rámeček a odsazení z forms pluginu a přepínač motivu funguje přes třídu dark — bez nich má čerstvá aplikace přihlašovací pole jako holé čáry a noční režim nedělá nic. Řádek, který už tam je, zůstane, jak je
Publikuje překlady Těch pár řetězců, které sidebar ukazuje
Zapíše app/Dashboards/OverviewDashboard.php a app/Livewire/Dashboards/ShowOverview.php a ten první zaregistruje v config/wire-core.php Někam přistát — viz níž

Nic se nepřepisuje, takže druhý běh je bezpečný: layout, který jste upravili, zůstane a nahlásí se jako už existující. Aplikace, která si providery drží jinde - Laravel 10 nebo vlastní konvence - dostane řádek k doplnění místo tichého úspěchu a zbytek instalace doběhne.

Někam přistát

Admin potřebuje vlastní stránku, na které se otevře, a dokud ji instalátor nezačal psát, žádná nebyla: adresa shellu přesměrovávala na tu obrazovku, která se v sidebaru řadila první — což u wire:install --all znamenalo, že vás přihlášení otevřelo v knihovně médií. Aplikace bez modulů neměla kam přesměrovat vůbec a na vlastní adrese odpovídala 404.

Instalátor proto zapíše dashboard — dva malé soubory, oba vaše:

// app/Dashboards/OverviewDashboard.php
class OverviewDashboard extends Dashboard implements ConfiguresRoutes, ProvidesNavigation, ProvidesPages
{
public function widgets(): array
{
return [
StatsOverviewWidget::make()->key('accounts')->heading('Accounts')->stats([
Stat::make('Users', (string) User::query()->count())->icon('users')->color('primary'),
]),
];
}
 
public static function pages(): array { return ['index' => ShowOverview::class]; }
 
public static function routePrefix(): ?string { return self::ROOT; }
}

Počítá uživatele, protože to je jediná tabulka, kterou má každá aplikace. Nahraďte to — přesně proto je to kód aplikace a ne něco, co dodává balíček. Co tam můžete dát, vypisují Widgety.

routePrefix() s hodnotou ConfiguresRoutes::ROOT nepřidává žádný segment URI, takže stránka přistane na vlastní cestě panelu: /admin je ten dashboard, ne přesměrování jinam. Tu cestu si smí nárokovat jen jedna věc, takže vlastní landing page tohle nahradí, ne doplní. Smažte ty tři routovací metody a je z toho běžná stránka na /admin/overview — a adresa shellu se vrátí k přesměrovávání.

Jeho položka v menu nemá skupinu, což ji staví nad každou skupinu, kterou deklarují moduly: položka bez skupiny se vykreslí první a bez nadpisu.

Jeden řádek, který Tailwind potřebuje

Třetí řádek tabulky je krok, který nikoho nenapadne a narazí na něj každý. Tailwind 4 hledá třídy skenováním zdrojů a přeskakuje to, co přeskakuje .gitignore - tedy vendor/, kde leží každý view z wire-admin, wire-panels i z modulů. Bez toho řádku se ty třídy nikdy nezkompilují: sidebar se vykreslí bez šířky, bez barvy a bez odsazení a nikde se neobjeví žádná chyba. Markup je správně a stylesheet o tom mlčí.

Instalátor ho zapíše za vás a míří na celý vendor adresář místo na jeden balíček, takže modul, který doinstalujete zítra, je pokrytý bez další úpravy:

@import "tailwindcss";
@source "../../vendor/nyoncode";

Když si píšete vlastní layout

Layout shellu nese vedle markupu ještě tři věci a vlastní layout je musí nést také. Dvě z nich jsou pravidla:

@include('wire-core::partials.density')
@include('wire-core::partials.shape')

Jsou to pravidla za Vzhled → Hustota a Tvar. Bez nich nastavení pořád vyrenderuje svůj atribut na <html> a nikdo podle něj nic neudělá — stránka, která tvrdí, že je kompaktní, a není. Je to ta samá tichá podoba jako chybějící řádek @source výše.

Samotné atributy pocházejí taky z layoutu:

<html data-density="{{ \NyonCode\WireCore\Foundation\Enums\Density::configured()->value }}"
data-shape="{{ \NyonCode\WireCore\Foundation\Enums\Shape::configured()->value }}">

Třetí je page chrome — registr, přes který balíčky vloží view do layoutu, aniž by věděly, který layout to je. Z něj pochází panel průvodce, jeho položka „Spustit průvodce znovu“ v uživatelském menu i modal výběru médií. Layout, který registr nevykresluje, tiše nemá nic z toho:

{{-- na konci <body> --}}
@foreach (app(\NyonCode\WireCore\Foundation\View\PageChrome::class)->views() as $view)
@include($view)
@endforeach
 
{{-- uvnitř uživatelského menu --}}
@foreach (app(\NyonCode\WireCore\Foundation\View\PageChrome::class)->views(\NyonCode\WireCore\Foundation\View\PageChrome::USER_MENU) as $view)
@include($view)
@endforeach

Pokud váš stylesheet není resources/css/app.css nebo Tailwind neimportuje, instalátor to řekne a řádek vám dá místo toho, aby ho zapsal do souboru, který Tailwind nikdy nečte. Doplňte ho pod import a cestu upravte podle toho, kde stylesheet leží.

Pak stránky zaroutujte a vykreslí se uvnitř shellu:

// routes/web.php
Route::middleware(['web', 'auth'])->prefix('admin')->group(fn () => Route::wireResources());

Instalace balíčku pořád není jeho přijetí. Žádný provider uvnitř wire-admin nenastavuje livewire.component_layout - spuštění instalátoru je to, čím si o něj aplikace řekne, a to je něco jiného než mít balíček na disku. Když příkaz přeskočíte, komponenty máte dál a váš vlastní rám může použít samotný sidebar.

Jak to funguje

Je to samostatný balíček a právě to je ten opt-in. Nic ho nevyžaduje; on vyžaduje wire-panels a všechno pod ním. Aplikace, která si nainstaluje wire-panels kvůli stránkám a routovacímu makru, dostane přesně to, bez chrome, které by musela vypínat — protože přepínač je composer require.

Instalace ještě není přijetí. Žádný provider nenastavuje livewire.component_layout. Shell je Blade komponenta, takže se stránka vykreslí uvnitř něj, až když to řekne váš vlastní layout — což zároveň umožňuje nechat si svůj rám a použít jen sidebar.

Čte seamy, které už existovaly, a nepřidává žádný stav. Menu pochází z Workspace, každý odkaz z ResolvesPageUrls (které neodpovídá vůbec nic, dokud routování někdo nevlastní) a aktivní položka z názvu aktuální routy. Není tu žádný registr, žádné URL schéma ani objekt Panel.

Zóna i aktivní položka se čtou jednou, při renderu stránky. Ne při každém renderu: během Livewire updatu je Route::currentRouteName() rovno livewire.update, takže cokoli z něj odvozeného by bylo správně při prvním vykreslení a špatně navždycky potom — a vypadalo by to bezvadně. Layout se vykresluje jen při plném načtení stránky, a to je důvod, proč je to čtení správné, ne šťastné.

Základní použití

Napište layout, který vaše stránky jmenují, a naplňte jeho sloty:

{{-- resources/views/components/layouts/admin.blade.php --}}
<x-wire-admin::layout :title="$title ?? config('app.name')">
<x-slot:head>
@vite(['resources/css/app.css', 'resources/js/app.js'])
</x-slot:head>
 
<x-slot:brand>{{ config('app.name') }}</x-slot:brand>
 
<x-slot:user>
<x-app-user-menu />
</x-slot:user>
 
{{ $slot }}
</x-wire-admin::layout>

Pak ho jednou pojmenujte tam, kde aplikace konfiguruje Livewire:

// V boot() service provideru, nebo v config/livewire.php.
// Klíč je `component_layout`, ne `layout` — Livewire 4 čte první z nich
// a druhý selže jako „No hint path defined for [layouts]".
config()->set('livewire.component_layout', 'components.layouts.admin');

Každá full-page komponenta — včetně stránek, které registruje Route::wireResources() — se teď vykresluje uvnitř shellu, s menu vedle sebe.

Co nedělá

Tohle ne Protože
Objekt Panel s fluent API Riziko, kterému se tenhle návrh vyhýbá. Třída držící konfiguraci shellu je přesně to, co by registry pod ním nakonec musely znát
Vlastní URL schéma Zóna je name() route skupiny; URL vlastní router
Vlastní cestu registrace Vykresluje to, co už Catalog drží, a neučí se, co která položka je za typ
Konfiguraci auth, tenancy nebo brandingu Sloty a vaše vlastní middleware

V této sekci

Stránka Co pokrývá
Layout Sloty, přihlašovací rám a roh s přihlášeným uživatelem
Sidebar Komponenta menu, sbalená lišta a jak se k ní dostane zóna
Branding a motiv Logo, značka, třístavový přepínač motivu a publikování views

Související

  • Panely — vrstva, jejíž stránky se v tomhle shellu vykreslují
  • Navigace — z čeho je menu složené
  • Moduly — oblasti, kterými do něj přispívá nainstalovaný balíček
  • Globální vyhledávání — palette, kterou rám mountuje