Skip to content

Commit

Permalink
Merge branch 'CollectiveDesign-feature/options'
Browse files Browse the repository at this point in the history
  • Loading branch information
toonvandenbos committed Jul 26, 2019
2 parents 2efff6c + a3c5402 commit 5707642
Show file tree
Hide file tree
Showing 28 changed files with 696 additions and 256 deletions.
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ This package adds basic **flat-file CMS features** to Laravel Nova in a breeze u

## Quick start

Here's a very condensed guide to get you started asap.
See the full docs at https://whitecube.github.io/nova-page
Here's a very condensed guide to get you started asap. For more details, examples and advanced features, take a look at [the full docs](https://whitecube.github.io/nova-page).

### Install

Expand Down Expand Up @@ -118,13 +117,22 @@ Retrieving the page's static values in your application's blade templates is pos
<p>{{ Page::get('title') }}</p>
```
Please note it is also possible to define [Option Templates](https://whitecube.github.io/nova-page/#/?id=option-templates) for repeated data, which can be accessed using:
```php
<p>@option('footer.copyright')</p>
// or
<p>{{ Page::option('footer')->copyright }}</p>
```
## Contributing
Feel free to suggest changes, ask for new features or fix bugs yourself. We're sure there are still a lot of improvements that could be made and we would be very happy to merge useful pull requests.
Thanks!
## Made with ❤️ for open source
At [Whitecube](https://www.whitecube.be) we use a lot of open source software as part of our daily work.
So when we have an opportunity to give something back, we're super excited!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ public function up()
{
Schema::create('static_pages', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('title');
$table->string('type');
$table->string('name');
$table->string('title')->nullable();
$table->json('attributes');
$table->timestamps();
});
Expand Down
79 changes: 69 additions & 10 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ This package adds basic **flat-file CMS features** to Laravel Nova in a breeze u
composer require whitecube/nova-page
```


If using Laravel >= 5.5, the service providers and aliases will register automatically.

If for some reason you must do it manually, register the package in the `providers` section of the app config file in `app/config/app.php` and also add the facade:
Expand Down Expand Up @@ -48,38 +47,46 @@ public function tools()
You can publish the package's configuration file with the `php artisan vendor:publish` command. This will add the `app/config/novapage.php` file containing the package's default configuration.

### Using the database as the data source

A database source is available if you do not wish to make use of the package's flat-file capabilities.

#### Changing the config
In the config file, change the `default_source` option to `\Whitecube\NovaPage\Sources\Database::class`.

#### Running the migration

You will need to run the following command:
```

```bash
php artisan vendor:publish --tag=nova-page-migrations
```

Doing so will copy the migration to create the `static_pages` table into your project's `database/migrations` directory. Then, simply run:
```

```bash
php artisan migrate
```

#### Customizing the table name
You can customize the table name in the migration file and then update the `table_name` parameter in the `novapage.php` config file, if you wish.

You can customize the table name in the migration file and then update the `table_name` parameter in the `novapage.php` config file, if you wish.

## Templates

In order to assign fields (and even cards!) to a page's edition form, we'll have to create a `Template` class and register this class on one or more routes. You'll see, it's quite easy.

### Creating Templates
### Creating templates

Each Template is defined in an unique class that resembles regular Nova Resources. You can store those classes wherever you want, but the package is configured to use `app/Nova/Templates` by default.

You can use the artisan command to generate the file
You can use the artisan command to generate the file:

```bash
php artisan make:template About
```

Which will result in:

```php
namespace App\Nova\Templates;

Expand Down Expand Up @@ -127,6 +134,27 @@ Route::get('/about-me', 'AboutController@show')

**Important**: Do not forget to name the routes you'll be using with NovaPage templates. Route names are used for retrieving and naming the route's JSON files.

### Option templates

Most websites or applications have repeated content, such as a copyright or contact information. These attributes should not change from page to page, that's why you can define Option "templates". These templates are not bound to a specific route or page and are loaded on request, making it convenient to use them in the app's layouts. You can add as many Option "pages" as you want.

First, create a regular `Template` as described above (e.g.: `php artisan make:template FooterOptions`) and fill the template's `fields()` method with all the wanted Nova fields.

Now, register the template in NovaPage's Manager using the `register(string $type = 'option' | 'route', string $name, string $template)`. A good place to do this is in a ServiceProvider's `boot` method:

```php
use Whitecube\NovaPage\Pages\Manager;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
public function boot(Manager $pages)
{
$pages->register('option', 'footer', \App\Nova\Templates\FooterOptions::class);
}
}
```

## Loading pages for display

### Middleware autoloading, the easiest way
Expand Down Expand Up @@ -220,6 +248,21 @@ Retrieving the page's static values in your application's blade templates is mad
<p>Edited on <time datetime="{{ Page::date('updated_at')->format('c') }}">{{ Page::date('updated_at')->toFormattedDateString() }}</time></p>
<p>{{ Page::get('introduction') }}</p>
<a href="{!! Page::get('cta.href') !!}">{{ Page::get('cta.label') }}</a>
<p>Copyright: {{ Page::option('footer')->copyright }}</p>
@endsection
```

Alternatively, we also added two useful Blade directives, `@get($attribute)` and `@option($key)`, which allow to access static attributes in a shorter way:

```php
@extends('layout')

@section('pageName', Page::name())

@section('content')
<p>@get('introduction')</p>
<a href="@get('cta.href')">@get('cta.label')</a>
<p>Copyright: @option('footer.copyright')</p>
@endsection
```

Expand Down Expand Up @@ -254,20 +297,35 @@ Returns a defined field's value. Optionally, you can provide a callback `Closure

Returns a previously loaded page template.

**`Page::option($name)`**

Loads and/or returns an option template. Can be used to retrieve an option template's attributes (`Page::option('footer')->copyright`).

### Dependency Injection

Alternatively, it's also possible to type-hint the current `Whitecube\NovaPage\Page\Template` in classes resolved by Laravel's [Service Container](https://laravel.com/docs/container), such as controllers. **The page needs to be loaded before** the `Page\Template` is requested, which can be easily achieved using the package's `LoadPageForCurrentRoute` middleware.

```php
use Whitecube\NovaPage\Pages\Manager;
use Whitecube\NovaPage\Pages\Template;

class HomepageController extends Controller
{

public function show(Template $template)
public function show(Template $template, Manager $novapage)
{
// If needed, manipulate $template's attribute before passing it to the view.
return view('pages.home', ['page' => $template]);
// Load other pages or options using
// Manager::load(string $name, string $type = 'route' | 'option', bool $current = true)
$novapage->load('contact', 'route', false);

return view('pages.home', [
// $template contains the loaded template for the current route.
// If needed, manipulate $template's attribute before passing it to the view.
'page' => $template,
// Include other pages or option templates using NovaPage's Manager
'contact' => $novapage->find('contact'),
'footer' => $novapage->option('footer'),
]);
}

}
Expand All @@ -285,10 +343,11 @@ And use it as a regular object in the `pages.home` template:
<p>Edited on <time datetime="{{ $page->getDate('updated_at')->format('c') }}">{{ $page->getDate('updated_at')->toFormattedDateString() }}</time></p>
<p>{{ $page->introduction }}</p>
<a href="{!! $page->cta->href !!}">{{ $page->cta->label }}</a>
<p>Copyright: {{ $footer->copyright }}</p>
@endsection
```

As you can see, for convenience regular attributes (= defined fields) can be directly retrieved as properties of the `Whitecube\NovaPage\Pages\Template` instance.
As you can see, for convenience regular attributes (= defined fields) can be directly retrieved as properties of the `Whitecube\NovaPage\Pages\Template` instances.

## Advanced features

Expand Down
11 changes: 10 additions & 1 deletion resources/views/navigation.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,14 @@
}
}" class="cursor-pointer flex items-center font-normal dim text-white mb-6 text-base no-underline">
<svg class="sidebar-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="var(--sidebar-icon)" d="M6 2h9a1 1 0 0 1 .7.3l4 4a1 1 0 0 1 .3.7v13a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4c0-1.1.9-2 2-2zm9 2.41V7h2.59L15 4.41zM18 9h-3a2 2 0 0 1-2-2V4H6v16h12V9zm-2 7a1 1 0 0 1-1 1H9a1 1 0 0 1 0-2h6a1 1 0 0 1 1 1zm0-4a1 1 0 0 1-1 1H9a1 1 0 0 1 0-2h6a1 1 0 0 1 1 1zm-5-4a1 1 0 0 1-1 1H9a1 1 0 1 1 0-2h1a1 1 0 0 1 1 1z"/></svg>
<span class="sidebar-label">{{ config('novapage.label') }}</span>
<span class="sidebar-label">{{ config('novapage.labels.pages') }}</span>
</router-link>
<router-link tag="h3" :to="{
name: 'index',
params: {
resourceName: 'nova-option'
}
}" class="cursor-pointer flex items-center font-normal dim text-white mb-6 text-base no-underline">
<svg class="sidebar-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="var(--sidebar-icon)" class="heroicon-ui" d="M9 4.58V4c0-1.1.9-2 2-2h2a2 2 0 0 1 2 2v.58a8 8 0 0 1 1.92 1.11l.5-.29a2 2 0 0 1 2.74.73l1 1.74a2 2 0 0 1-.73 2.73l-.5.29a8.06 8.06 0 0 1 0 2.22l.5.3a2 2 0 0 1 .73 2.72l-1 1.74a2 2 0 0 1-2.73.73l-.5-.3A8 8 0 0 1 15 19.43V20a2 2 0 0 1-2 2h-2a2 2 0 0 1-2-2v-.58a8 8 0 0 1-1.92-1.11l-.5.29a2 2 0 0 1-2.74-.73l-1-1.74a2 2 0 0 1 .73-2.73l.5-.29a8.06 8.06 0 0 1 0-2.22l-.5-.3a2 2 0 0 1-.73-2.72l1-1.74a2 2 0 0 1 2.73-.73l.5.3A8 8 0 0 1 9 4.57zM7.88 7.64l-.54.51-1.77-1.02-1 1.74 1.76 1.01-.17.73a6.02 6.02 0 0 0 0 2.78l.17.73-1.76 1.01 1 1.74 1.77-1.02.54.51a6 6 0 0 0 2.4 1.4l.72.2V20h2v-2.04l.71-.2a6 6 0 0 0 2.41-1.4l.54-.51 1.77 1.02 1-1.74-1.76-1.01.17-.73a6.02 6.02 0 0 0 0-2.78l-.17-.73 1.76-1.01-1-1.74-1.77 1.02-.54-.51a6 6 0 0 0-2.4-1.4l-.72-.2V4h-2v2.04l-.71.2a6 6 0 0 0-2.41 1.4zM12 16a4 4 0 1 1 0-8 4 4 0 0 1 0 8zm0-2a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"/></svg>
<span class="sidebar-label">{{ config('novapage.labels.options') }}</span>
</router-link>
23 changes: 17 additions & 6 deletions routes/api.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@
use Whitecube\NovaPage\Http\Controllers\CardController;
use Whitecube\NovaPage\Http\Controllers\FilterController;
use Whitecube\NovaPage\Http\Controllers\LensController;
use Whitecube\NovaPage\Http\Controllers\ResourceIndexController;
use Whitecube\NovaPage\Http\Controllers\ResourceCountController;
use Whitecube\NovaPage\Http\Controllers\ResourceUpdateController;
use Whitecube\NovaPage\Http\Controllers\Page\IndexController as PageResourceIndexController;
use Whitecube\NovaPage\Http\Controllers\Page\CountController as PageResourceCountController;
use Whitecube\NovaPage\Http\Controllers\Page\UpdateController as PageResourceUpdateController;
use Whitecube\NovaPage\Http\Controllers\Option\IndexController as OptionResourceIndexController;
use Whitecube\NovaPage\Http\Controllers\Option\CountController as OptionResourceCountController;
use Whitecube\NovaPage\Http\Controllers\Option\UpdateController as OptionResourceUpdateController;

/*
|--------------------------------------------------------------------------
Expand All @@ -22,17 +25,25 @@

// Actions...
Route::get('/nova-api/nova-page/actions', ActionController::class . '@index');
Route::get('/nova-api/nova-option/actions', ActionController::class . '@index');

// Filters...
Route::get('/nova-api/nova-page/filters', FilterController::class . '@index');
Route::get('/nova-api/nova-option/filters', FilterController::class . '@index');

// Lenses...
Route::get('/nova-api/nova-page/lenses', LensController::class . '@index');
Route::get('/nova-api/nova-option/lenses', LensController::class . '@index');

// Cards / Metrics...
Route::get('/nova-api/nova-page/cards', CardController::class . '@index');
Route::get('/nova-api/nova-option/cards', CardController::class . '@index');

// Resource Management...
Route::get('/nova-api/nova-page', ResourceIndexController::class . '@handle');
Route::get('/nova-api/nova-page/count', ResourceCountController::class . '@show');
Route::put('/nova-api/nova-page/{resourceId}', ResourceUpdateController::class . '@handle');
Route::get('/nova-api/nova-page', PageResourceIndexController::class . '@handle');
Route::get('/nova-api/nova-page/count', PageResourceCountController::class . '@show');
Route::put('/nova-api/nova-page/{resourceId}', PageResourceUpdateController::class . '@handle');

Route::get('/nova-api/nova-option', OptionResourceIndexController::class . '@handle');
Route::get('/nova-api/nova-option/count', OptionResourceCountController::class . '@show');
Route::put('/nova-api/nova-option/{resourceId}', OptionResourceUpdateController::class . '@handle');
23 changes: 23 additions & 0 deletions src/Http/Controllers/Option/CountController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace Whitecube\NovaPage\Http\Controllers\Option;

use Illuminate\Routing\Controller;
use Whitecube\NovaPage\Pages\Manager;
use Laravel\Nova\Http\Requests\ResourceIndexRequest;

class CountController extends Controller
{
/**
* Get the resource count for a given query.
*
* @param \Laravel\Nova\Http\Requests\ResourceIndexRequest $request
* @return \Illuminate\Http\Response
*/
public function show(ResourceIndexRequest $request, Manager $manager)
{
return response()->json([
'count' => $manager->queryResourcesCount($request, 'option')
]);
}
}
30 changes: 30 additions & 0 deletions src/Http/Controllers/Option/IndexController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Whitecube\NovaPage\Http\Controllers\Option;

use Whitecube\NovaPage\Pages\Manager;
use Laravel\Nova\Http\Requests\ResourceIndexRequest;
use Whitecube\NovaPage\Http\Controllers\ResourceIndexController;

class IndexController extends ResourceIndexController
{
/**
* Resource label callback
*
* @return string
*/
protected function resourceLabel() {
return config('novapage.labels.options');
}

/**
* Callback to retrieve the resource index items
*
* @param \Laravel\Nova\Http\Requests\ResourceIndexRequest $request
* @param \Whitecube\NovaPage\Pages\Manager $manager
* @return \Illuminate\Support\Collection
*/
protected function resourceIndexItems(ResourceIndexRequest $request, Manager $manager) {
return $manager->queryIndexResources($request, 'option');
}
}
15 changes: 15 additions & 0 deletions src/Http/Controllers/Option/UpdateController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace Whitecube\NovaPage\Http\Controllers\Option;

use Whitecube\NovaPage\Http\Controllers\ResourceUpdateController;

class UpdateController extends ResourceUpdateController
{
/**
* The queried resource's name
*
* @var string
*/
protected $resourceName = 'nova-option';
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
<?php

namespace Whitecube\NovaPage\Http\Controllers;
namespace Whitecube\NovaPage\Http\Controllers\Page;

use Illuminate\Routing\Controller;
use Whitecube\NovaPage\Pages\Manager;
use Whitecube\NovaPage\Pages\Resource;
use Laravel\Nova\Http\Requests\ResourceIndexRequest;

class ResourceCountController extends Controller
class CountController extends Controller
{
/**
* Get the resource count for a given query.
Expand All @@ -17,6 +16,8 @@ class ResourceCountController extends Controller
*/
public function show(ResourceIndexRequest $request, Manager $manager)
{
return response()->json(['count' => $manager->queryCount($request)]);
return response()->json([
'count' => $manager->queryResourcesCount($request, 'route')
]);
}
}
30 changes: 30 additions & 0 deletions src/Http/Controllers/Page/IndexController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Whitecube\NovaPage\Http\Controllers\Page;

use Whitecube\NovaPage\Pages\Manager;
use Laravel\Nova\Http\Requests\ResourceIndexRequest;
use Whitecube\NovaPage\Http\Controllers\ResourceIndexController;

class IndexController extends ResourceIndexController
{
/**
* Resource label callback
*
* @return string
*/
protected function resourceLabel() {
return config('novapage.labels.pages');
}

/**
* Callback to retrieve the resource index items
*
* @param \Laravel\Nova\Http\Requests\ResourceIndexRequest $request
* @param \Whitecube\NovaPage\Pages\Manager $manager
* @return \Illuminate\Support\Collection
*/
protected function resourceIndexItems(ResourceIndexRequest $request, Manager $manager) {
return $manager->queryIndexResources($request, 'route');
}
}
Loading

0 comments on commit 5707642

Please sign in to comment.