Skip to content

Commit

Permalink
Merge pull request #174 from kontenta/separate-docs
Browse files Browse the repository at this point in the history
Break out and improve docs for tool creation
  • Loading branch information
erik-epineer authored May 8, 2020
2 parents c741ef0 + 5de6c88 commit 73825fe
Show file tree
Hide file tree
Showing 2 changed files with 204 additions and 113 deletions.
146 changes: 33 additions & 113 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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:
Expand All @@ -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:

Expand Down Expand Up @@ -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
Expand All @@ -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

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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')
<h1>A splendid tool</h1>
@parent
@endsection

@section('kontourToolMain')
<form ...>
<input ...>
<button type="submit">Save</button>
</form>
@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
Expand Down
171 changes: 171 additions & 0 deletions docs/tool-creation.md
Original file line number Diff line number Diff line change
@@ -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')
<h1>A splendid tool</h1>
@parent
@endsection

@section('kontourToolMain')
<form ...>
<input ...>
<button type="submit">Save</button>
</form>
@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.

0 comments on commit 73825fe

Please sign in to comment.