Skip to content
docsv0.34.0

AdminShell

The panel's shell, composed — not hand-written — from Milpa Components. `<milpa:dashboard-shell>` holds the panel's own sidebar (`admin-sidebar`: one group per distinct section group — ADMIN, APP, AGENT, then any other — each item with its glyph), a topbar (the active section's title, and the chips: who signed in when a gate authenticated the request, the gate in effect, the locale) and a main region carrying the section header (`admin-section-header`: the title and «declared by <Plugin>», read from the catalogue) above the active section's component, wrapped in the section body (`.admin-section__body` — the shell's, not the section's: the part of main that scrolls, and the box a section fills when it wants the remaining height), all compiled by `XhtmlComponentCompiler` over the {@see ComponentBook}. Two lifecycle pairs make it extensible without touching it: `admin.section.before_render`/`after_render` (the section's props, then its HTML) and `admin.shell.before_render`/`after_render` (the composition and items, then the HTML) — declared as data by {@see self::events()}, so the dispatcher can count them (greenhouse decisions/0228). What every section receives (greenhouse decisions/0210): the {@see ComponentContext} it mounts with carries the `principal` the gate authenticated — the same actor id the topbar shows, null when nobody — the `locale` the page answers in and the panel's `route`, so a section decides its own state by what the host knows and agrees with the topbar; and the request's query params reach it as `props['query']` (decisions/0205) — a drill-down, a filter — without the shell knowing what they mean. A section may also declare a whole {@see DeclaredView} instead of one component (greenhouse decisions/0211): then the shell compiles the guest's tree in the same place, ROOT BY ROOT, so a component that throws while mounting paints its failure inside its own region and the panel around it stands ({@see ViewMarkup}); it collects what every rendered renderer DECLARED, so the document emits each stylesheet and module once through `LiveBoot`; and it merges the view's signal seeds with the panel's own ({@see LiveSeeds}). Host facts a guest needs but no contract carries travel in `ComponentContext::$meta`: {@see self::META_GATE}, {@see self::META_SECTION}, {@see self::META_QUERY}. {@see self::compose()} returns all three (HTML, assets, seeds); {@see self::render()} is the same call when only the HTML is wanted.

AdminShell::__construct()

public function __construct(Milpa\Admin\AdminSettings $settings, Milpa\Admin\I18n\Catalog $catalog, Milpa\Live\Contracts\Transport\StateTransferCodecInterface $codec, ?Milpa\Interfaces\Event\MilpaEventDispatcherInterface $events = null, Milpa\Interfaces\Di\DIContainerInterface|string $rootOrContainer = ''):

Parameters

Parameters of __construct()
NameTypeDescription
$settingsMilpa\Admin\AdminSettings
$catalogMilpa\Admin\I18n\Catalog
$codecMilpa\Live\Contracts\Transport\StateTransferCodecInterface
$events?Milpa\Interfaces\Event\MilpaEventDispatcherInterface
$rootOrContainerMilpa\Interfaces\Di\DIContainerInterface|string

AdminShell::events()

public static function events(): array

What this shell dispatches, as data — one declaration per name, built from the SAME constants its `dispatch()` calls use, so a renamed event cannot leave a stale declaration behind (greenhouse decisions/0228). Every subject is a mutable object the subscriber is meant to change; none carries an interception slot. {@see \Milpa\Admin\Event\AdminEvents} hands these to the dispatcher at boot.

AdminShell::withCatalog()

public function withCatalog(Milpa\Admin\I18n\Catalog $catalog): self

The same shell answering in another catalog — a request's `?lang=` — with everything else shared.

Parameters

Parameters of withCatalog()
NameTypeDescription
$catalogMilpa\Admin\I18n\Catalog

AdminShell::render()

public function render(Milpa\Admin\Section\SectionCatalogue $catalogue, Milpa\Admin\Section\AdminSection $active, array $query = [], ?string $principal = null): string

Renders the shell with every discovered section in the sidebar, under its group, and the active one in main under its header.

Parameters

Parameters of render()
NameTypeDescription
$catalogueMilpa\Admin\Section\SectionCatalogue
$activeMilpa\Admin\Section\AdminSection
$queryarray<string, mixed>the request's query params, handed to the active section as `props['query']`
$principal(string | null)who the gate let in — the authenticated actor's id, never a session id — or null when nobody is signed in; handed to every component's `ComponentContext`, the active section's included

AdminShell::compose()

public function compose(Milpa\Admin\Section\SectionCatalogue $catalogue, Milpa\Admin\Section\AdminSection $active, array $query = [], ?string $principal = null, ?array $scopes = null): Milpa\Admin\View\ShellOutput

The whole composed page: the shell's HTML, the client files every rendered component declared, and the seeds the panel and the active section's view agreed on — what {@see AdminPage} needs to emit ONE runtime for the page (greenhouse decisions/0211).

Parameters

Parameters of compose()
NameTypeDescription
$catalogueMilpa\Admin\Section\SectionCatalogue
$activeMilpa\Admin\Section\AdminSection
$queryarray<string, mixed>the request's query params, handed to the active section as `props['query']` and to every node as `meta['query']`
$principal(string | null)who the gate let in — the authenticated actor's id, never a session id — or null when nobody is signed in
$scopes(list<string> | null)the authenticated actor's declared scopes, without permission expansion

AdminShell::renderEmpty()

public function renderEmpty(Milpa\Admin\Section\SectionCatalogue $catalogue, ?string $principal = null): string

The empty-state body when no plugin declared a section — still inside the shell, chips included.

Parameters

Parameters of renderEmpty()
NameTypeDescription
$catalogueMilpa\Admin\Section\SectionCatalogue
$principal(string | null)who the gate let in, or null when nobody is signed in

AdminShell::composeEmpty()

public function composeEmpty(Milpa\Admin\Section\SectionCatalogue $catalogue, ?string $principal = null): Milpa\Admin\View\ShellOutput

The empty state, composed like any other page — its assets (the primitives declare none today) and the panel's own seeds, so a panel with no section still emits exactly one runtime.

Parameters

Parameters of composeEmpty()
NameTypeDescription
$catalogueMilpa\Admin\Section\SectionCatalogue
$principal(string | null)who the gate let in, or null when nobody is signed in

AdminShell::title()

public function title(Milpa\Admin\Section\AdminSection $section): string

The title the panel shows for a section: a catalog key when it knows it, the literal otherwise.

Parameters

Parameters of title()
NameTypeDescription
$sectionMilpa\Admin\Section\AdminSection