diff --git a/README.md b/README.md index e8480a4a..6f95e6e5 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,10 @@ [![Build Status](https://travis-ci.org/kontenta/kontour.svg?branch=master)](https://travis-ci.org/kontenta/kontour) -Kontour is a package of admin page utilities for Laravel. -It provides a shared "frame" for the admin routes you create -in your Laravel apps, or in packages you write. +Kontour is a package of admin page utilities for +[Laravel](https://laravel.com/docs). +It provides a shared "frame" for the admin tool routes you create +in your Laravel apps, or in packages you install or create. The idea is that your admin tools can pull in and use functionality from Kontour to provide a consistent experience for the whole admin area of a website. @@ -15,10 +16,22 @@ area. You need at least **Laravel 5.8** and **PHP 7.2** to use this package. +## Using Kontour in a Laravel app + +This document aims to provide instructions on how to configure Kontour in a +Laravel app. Once configured you can log in to the Kontour admin area and use +any admin tools from installed packages. + +## Creating admin tools using Kontour + +For documentation how to create and register your own tools leveraging the +features Kontour provides, you'll find the documentation and helpful guides in +[Using Kontour to build admin tools](docs/tool-creation.md). + ## Features - Admin login and password reset routes with configurable Guard - to separate admin users from frontend users. + to separate admin users from frontend users. Bring your own `AdminUser` model! - Extendable Blade Layouts with named sections for admin tool views and configurable stylesheet and javascript dependencies. - Widgets that are placeable in named Blade sections: @@ -34,15 +47,22 @@ You need at least **Laravel 5.8** and **PHP 7.2** to use this package. ## Architecture -- Kontour is installed as a dependency, not a boilerplate. +- Kontour is installed as a dependency in a Laravel project, not a boilerplate. - Kontour uses core Laravel functionality wherever possible, - for example authentication and authorization. + like authentication and authorization, and has no dependencies outside of the + Laravel ecosystem. +- Everything Kontour provides is optional and can be configured to leave a + minimal footprint in the Laravel app in which it has been installed. ## Install Maybe you're here because some package you installed requires Kontour for its -admin pages? In that case it's already installed by composer, but you may still -want to read further below about how to configure Kontour to your liking. +admin pages? In that case Kontour is already installed by composer, but you will +still want to read further below about how to configure Kontour to your liking. + +You are the owner of your Laravel app, even if Kontour was required by some +other package, and you'll at least need to setup the admin user model before +you can log in to the Kontour admin area. Installing Kontour explicitly in your Laravel project: @@ -90,7 +110,7 @@ By default the Kontour dashboard route `kontour.index` is reached by going to To enable login you need to make sure the user model you want to give access to the admin area implements the [`Kontenta\Kontour\Contracts\AdminUser` contract](src/Contracts/AdminUser.php) -which has method `getDisplayName()` that should return... a display name! +which has a method `getDisplayName()` that should return... a display name! The default Kontour configuration uses Laravel's `web` Guard from `config/auth.php` which in turn uses the Eloquent user provider with model @@ -101,8 +121,8 @@ the interface, by having it extend `Kontenta\Kontour\Auth\AdminUser`. This requirement is deliberate to avoid any situation where someone accidentally gives front end users access to their admin routes. -You need to make an active choice about which user model to let into the admin -area. +**You need to make an active choice about which user model to let into the admin +area.** ### Creating a separate user provider for admins @@ -182,13 +202,13 @@ $user->password = ''; $user->save(); ``` -If you're feeling adventuorus, you can then create an admin tool within Kontour +If you're feeling adventurous, you can then create an admin tool within Kontour to let a logged in admin create and invite new admin users! ## Publish the default CSS and js in your Laravel project You probably want to add some style to your admin area, -perhaps pure HTML is too brutalist for your taste... +pure HTML with default browser styles is too brutalist for most people... A good place to start is the default Kontour stylesheet. The included javascript includes a feature to confirm any delete-action before @@ -248,106 +268,6 @@ In `config/kontour.php` Casting Mix's output to a string in the config file makes it possible to cache the config in a production environment. -## Registering admin routes - -In a service provider you can register your admin routes -using methods from the -[`RegistersAdminRoutes` trait](src/Concerns/RegistersAdminWidgets.php). - -## Running code only before admin routes are accessed - -For anything that needs to be "booted" before an admin page/route is loaded, -inject `Kontenta\Kontour\Contracts\AdminBootManager` and add callables to it -using `beforeRoute()`. -Those callables will be called (with any dependencies injected) by a middleware. -This avoids running admin-related code on every page load on the public site. - -## Extending Kontour's Blade layouts - -In the Blade views you create for your admin pages you can inject -a "view manager" instance: - -```php -@inject('view_manager', 'Kontenta\Kontour\Contracts\AdminViewManager') -``` - -...that can be used to pull out one of the common Blade layouts to extend for -any admin pages that wants to be part of the family: - -```php -@extends($view_manager->toolLayout()) -``` - -The `toolLayout` has sections `kontourToolHeader`, `kontourToolMain`, -`kontourToolWidgets`, and `kontourToolFooter` for you to populate. - -```php -@section('kontourToolHeader') -

A splendid tool

- @parent -@endsection - -@section('kontourToolMain') -
- - -
-@endsection -``` - -It's a good idea to include `@parent` in your sections for other content, -for example registered widgets. - -## Adding menu items - -Usually adding menu items is done in a service provider's boot method: - -```php -use Kontenta\Kontour\Contracts\AdminBootManager; -use Kontenta\Kontour\Contracts\MenuWidget; -use Kontenta\Kontour\AdminLink; - -$this->app->make(AdminBootManager::class)->beforeRoute(function (MenuWidget $menuWidget) { - $menuWidget->addLink( - AdminLink::create('A menu item', route('named.route')) - ->registerAbilityForAuthorization('gate or other ability'), - 'A menu heading' - ); -}); -``` - -## Authorizing controller actions - -The -[`AuthorizesAdminRequests` trait](src/Concerns/AuthorizesAdminRequests.php) -has convenince methods for controllers that both authorizes the current user -against an ability, and dispatches an event that records the visit for the -recent visits widgets. - -With the trait used on your controller you can call -`$this->authorizeShowAdminVisit()` for view-only routes or -`$this->authorizeEditAdminVisit()` for routes that present a form. - -Both methods take 4 parameters: - -- The name of the ability to authorize against -- The name of the link to present in recent visits widgets -- The description string for link `title` attribute (optional) -- Arguments for the ability (optional) - -## Registering widgets - -All widgets implement the -[`AdminWidget` interface](src/Contracts/AdminWidget.php) -and can be registered into a section from a service provider -or controller using methods from the -[`RegistersAdminWidgets`](src/Concerns/RegistersAdminWidgets.php) -trait. - -In the `kontour.php` config file you may specify the widgets for all -admin pages using the `global_widgets` array, mapping classname/contract to the -desired section name. - ## Fallback implementations This package contains implementations of the Kontour contracts that are used as diff --git a/docs/tool-creation.md b/docs/tool-creation.md new file mode 100644 index 00000000..64fa6a86 --- /dev/null +++ b/docs/tool-creation.md @@ -0,0 +1,171 @@ +# Using Kontour to build admin tools + +You can create a set of admin tools specific to your Laravel app within the app +itself after [installing Kontour with composer](../README.md#install). + +## Using Kontour in packages + +If you author a composer package that would benefit from some Laravel admin +tools, a good strategy is to release a separate package for the admin tools +related to the main package. +This way consumers of your main package can actively choose to install the +Kontour admin tools if they want to. + +You may even release alternative admin packages for other admin systems like +[Laravel Nova](https://nova.laravel.com), and let the consumer pick the best +match for their Laravel app. +If you create a companion Kontour admin package of your own, consider suffixing +the name like `-kontour-admin`, so you may release `-nova-admin` and possibly +others too! + +### Example packages using Kontour + +The Laravel package +[`bjuppa/laravel-blog`](https://github.com/bjuppa/laravel-blog), +created by one of the main contributors to Kontour, provides add-on blog +functionality for any Laravel app. +Public routes, controllers, views, styling, and models & migrations +are all included there – but it doesn't provide any admin tools for editors to +manage the blog posts. + +Consumers of the package are free to create their own admin area, but there +is also the option to install the companion package +[`bjuppa/laravel-blog-admin`](https://github.com/bjuppa/laravel-blog-admin), +that in turn depends on Kontour. + +If you're a source diver you'll find many examples of Kontour usage there. +A good place to start is in the +[`BlogAdminServiceProvider`](https://github.com/bjuppa/laravel-blog-admin/blob/master/src) +and then look at the +[controllers](https://github.com/bjuppa/laravel-blog-admin/tree/master/src/Http/Controllers) +and [routes](https://github.com/bjuppa/laravel-blog-admin/tree/master/routes). + +## Kontour tools are just Laravel controllers + +Admin tools that leverage Kontour are built as any other Laravel controller with +corresponding routes. Usually a +[resource controller](https://laravel.com/docs/controllers#resource-controllers) +is suitable to create admin tools that edit instances of a specific model. + +## Registering admin routes + +In a service provider you can register your admin routes +using methods from the +[`RegistersAdminRoutes` trait](../src/Concerns/RegistersAdminRoutes.php) +that will group the routes with all route attributes configured with Kontour, +like middleware etc. + +In a Laravel app you can for example create a routes file `routes/kontour.php` +to keep routes for all Kontour tools you create. A service provider using the +trait may then register them in the boot method. + +```php +use Kontenta\Kontour\Concerns\RegistersAdminRoutes; + +public function boot() +{ + $this->registerAdminRoutes(base_path('routes/kontour.php')); +} +``` + +If you're writing a package, the routes file would probably be named something +more package specific, and the service provider would need to use a relative +path, like +`__DIR__ . '/../routes/kontour.php'` to register the routes. + +## Running code only before admin routes are accessed + +For anything that needs to be "booted" before an admin page/route is loaded, +inject `Kontenta\Kontour\Contracts\AdminBootManager` and add callables to it +using `beforeRoute()`. +Those callables will be called (with any dependencies injected) by a middleware. +This avoids running admin-related code on every page load on the public site. + +A good use case when [adding menu items](#adding-menu-items) +is documented below. + +## Extending Kontour Blade layouts + +In the Blade views you create for your admin pages you can inject +a "view manager" instance: + +```php +@inject('view_manager', 'Kontenta\Kontour\Contracts\AdminViewManager') +``` + +...that can be used to pull out one of the common Blade layouts to extend for +any admin pages that wants to be part of the family: + +```php +@extends($view_manager->toolLayout()) +``` + +The `toolLayout` has sections `kontourToolHeader`, `kontourToolMain`, +`kontourToolWidgets`, and `kontourToolFooter` for you to populate. + +```php +@section('kontourToolHeader') +

A splendid tool

+ @parent +@endsection + +@section('kontourToolMain') +
+ + +
+@endsection +``` + +It's a good idea to include `@parent` in your sections for other content, +for example registered widgets. + +## Adding menu items + +Usually adding menu items is done in a service provider's boot method: + +```php +use Kontenta\Kontour\Contracts\AdminBootManager; +use Kontenta\Kontour\Contracts\MenuWidget; +use Kontenta\Kontour\AdminLink; + +$this->app->make(AdminBootManager::class)->beforeRoute(function (MenuWidget $menuWidget) { + $menuWidget->addLink( + AdminLink::create('A menu item', route('named.route')) + ->registerAbilityForAuthorization('gate or other ability'), + 'A menu heading' + ); +}); +``` + +## Authorizing controller actions + +The +[`AuthorizesAdminRequests` trait](../src/Concerns/AuthorizesAdminRequests.php) +has convenience methods for controllers that both authorizes the current user +against an ability, and dispatches an event that records the visit for the +recent visits widgets. + +With the trait used on your controller you can call +`$this->authorizeShowAdminVisit()` for view-only routes or +`$this->authorizeEditAdminVisit()` for routes that present a form. + +Both methods take 4 parameters: + +- The name of the ability to authorize against +- The name of the link to present in recent visits widgets +- The description string for link `title` attribute (optional) +- Arguments for the ability (optional) + +## Registering widgets + +All widgets implement the +[`AdminWidget` interface](../src/Contracts/AdminWidget.php) +and can be registered into a section from a service provider +or controller using methods from the +[`RegistersAdminWidgets`](../src/Concerns/RegistersAdminWidgets.php) +trait. + +In the `kontour.php` config file you may specify the widgets for all +admin pages using the `global_widgets` array, mapping classname/contract to the +desired section name.