Several panels
An application can have several panels: one for each group of users with its own purpose, look and rules.
public array $panels = [ \App\Panels\AdminPanel::class, // /admin – back office \App\Panels\PortalPanel::class, // /portal – self service for all employees];Example: back office and portal
Section titled “Example: back office and portal”final class AdminPanel extends Panel{ public function id(): string { return 'admin'; } public function brand(): string { return 'ACME Back Office'; } public function primaryColor(): ?string { return '#0f3d76'; } public function permission(): ?string { return 'admin.access'; } public function requiresMfa(): bool { return true; }
public function resources(): array { return [PersonResource::class, RequestResource::class, ...Access::resources()]; }}
final class PortalPanel extends Panel{ public function id(): string { return 'portal'; } public function brand(): string { return 'ACME Portal'; } public function primaryColor(): ?string { return '#15803d'; }
public function resources(): array { return [MyRequestResource::class]; }
public function pages(): array { return [Dashboard::class, ...Access::pages()]; }}- The back office is closed to users without
admin.accessand needs a second factor. - The portal is open to every user who logged in;
MyRequestResourcerestricts its query to the requests of the user (scopeQuery()).
What is shared and what is not
Section titled “What is shared and what is not”| Shared | Per panel |
|---|---|
| login, users, roles, tenants | path, brand, colour, assets |
| models, data, audit log | resources, pages, navigation, widgets |
permissions of resources (invoices.view) |
permissions of pages (admin.page.reports) and of the panel |
| notifications | component tokens (a token of one panel is not valid in another) |
| saved views and widget layouts of the users |
Permissions of a resource are named by its slug, not by the panel: a role
with requests.view may list requests in every panel that registers a
resource with that slug. Use different slugs when the panels must differ.
Files of records belong to the resource class, so two resource classes
never share attachments.
The same resource in several panels
Section titled “The same resource in several panels”A resource class can be registered in several panels. It is instantiated per panel, builds its URLs from the panel and applies the same permissions and policies. Restrict it per panel with a subclass:
final class MyRequestResource extends RequestResource{ protected ?string $slug = 'my-requests';
public function scopeQuery(Model $model): void { $model->where('requester_id', auth()->id()); }}The API publishes the resources of the panels listed in
Config\Anvil::$apiPanels under /api/v1/<resource slug>.