novius/laravel-nova-visual-composer

A Laravel Nova field to compose blocks.

3.1.0 2022-07-22 08:44 UTC

This package is auto-updated.

Last update: 2024-10-26 11:24:51 UTC


README

Travis Packagist Release Licence

Requirements

  • PHP >= 7.4
  • Laravel Framework >= 8.
  • Nova >= 2.0
  • Imagick PHP extension or GD Library (for Intervention Image)

NOTE: These instructions are for Laravel >= 8. If you are using prior version, please see the previous version's docs.

Installation

composer require novius/laravel-nova-visual-composer

Next, configure Intervention Image package :

Intervention Image configuration instructions

Configuration

Some options that you can override are available.

php artisan vendor:publish --provider="Novius\NovaVisualComposer\NovaVisualComposerServiceProvider" --tag="config"

JS Configuration

Some options (like wysiwyg config) are configurable from JS config file.

You can override it with :

php artisan vendor:publish --provider="Novius\NovaVisualComposer\NovaVisualComposerServiceProvider" --tag="js"

Purge TMP uploaded files

In your app/Console/Kernel.php file, you should register a daily job to purge any stale files :

protected function schedule(Schedule $schedule)
{
    $schedule->command('nova-visual-composer:purge-tmp-files')
        ->daily();
}

By default tmp file is stale considered after 24h. You can override this value in configuration file with seconds_before_purge_tmp_files key.

Usage

Step 1

Create a long text column on your model's table.

$table->longText('content')->nullable();

Configure your model by adding object to the desired column.

use Illuminate\Database\Eloquent\Model;

class Foo extends Model {
    protected $casts = [
        'content' => 'object',
    ];
}

Step 2

Add the field to your Nova resource.

use App\Nova\Resource;
use Novius\NovaVisualComposer\NovaVisualComposer;

class FooResource extends Resource
{       
    public function fields(Request $request)
    {
        return [
            // ..
            NovaVisualComposer::make('Content')
                                ->stacked(),
            // ..
        ];
    }
}

Step 3

Display in your blade template.

@foreach($item->content as $row)
    {!! $row->template::renderFront($row->content) !!}
@endforeach

Create new row templates

Step 1

You have to publish lang and view files.

php artisan vendor:publish --provider="Novius\NovaVisualComposer\NovaVisualComposerServiceProvider" --tag="config"
php artisan vendor:publish --provider="Novius\NovaVisualComposer\NovaVisualComposerServiceProvider" --tag="views"

Step 2

Create your own Row Template and link it into configuration file.

Row Template Class

namespace App\Nova\Templates\Rows;

use Novius\NovaVisualComposer\Templates\RowTemplateAbstract;
use Novius\NovaVisualComposer\Traits\HasImageField;
use Novius\NovaVisualComposer\Traits\HasPrunableFiles;

class ImageText extends RowTemplateAbstract
{
    use HasImageField;
    use HasPrunableFiles;

    public static $name = 'image-text';

    protected static function imageFieldsIndexes(): array
    {
        return [0]; // Because image field is the first field that contains "js-visual-field" class of CRUD view
    }
}

Add it to configuration file

return [

    ...

    'templates' => [
        \Novius\NovaVisualComposer\Templates\Article::class,
        \Novius\NovaVisualComposer\Templates\ImageMultiple::class,
        \Novius\NovaVisualComposer\Templates\ImageSimple::class,
        \Novius\NovaVisualComposer\Templates\Separator::class,
        \Novius\NovaVisualComposer\Templates\Title::class,

        // Custom Template
        \App\Nova\Templates\Rows\ImageText::class,
    ],
];

Step 3

Create template views (CRUD + front views).

resources/views/vendor/nova-visual-composer/templates/ImageText/crud.blade.php

TIPS :

  • Each HTML field that you want to save must contains js-visual-field class.
  • If you want a wysiwyg add js-wysiwyg class to textarea field.
  • If you want an image upload field add js-image-uploader class to file field.
  • If you want a multiple images upload field add js-image-uploader class + multiple attribute to file field.
<div class="shadow-md mb-4 w-full">
    <div class="px-6 py-4">
        <div class="font-bold text-xl mb-4">
            {{ $templateDetails['name_trans'] }}
        </div>
        <div class="flex">
            <div class="w-1/3 pr-3">
                <div class="form-group">
                    <input type="file" class="filepond js-visual-field js-image-uploader">
                </div>
            </div>
            <div class="w-2/3">
                <div class="form-group mb-2">
                    <label class="block text-grey-darker text-sm font-bold mb-2">
                        {{ trans('nova-visual-composer::templates.'.$templateName.'.crud_pre_title') }}
                    </label>
                    <input class="js-visual-field w-full form-control form-input form-input-bordered"
                           type="text"/>
                </div>
                <div class="form-group mb-2">
                    <label class="block text-grey-darker text-sm font-bold mb-2">
                        {{ trans('nova-visual-composer::templates.'.$templateName.'.crud_title') }}
                    </label>
                    <input class="js-visual-field w-full form-control form-input form-input-bordered"
                           type="text"/>
                </div>
                <div class="form-group mb-2">
                    <label class="block text-grey-darker text-sm font-bold mb-2">
                        {{ trans('nova-visual-composer::templates.'.$templateName.'.crud_text') }}
                    </label>
                    <textarea name="content"
                              class="js-visual-field js-wysiwyg w-full form-control form-input-bordered py-2 h-20"></textarea>
                </div>
            </div>
        </div>
    </div>
</div>

resources/views/vendor/nova-visual-composer/templates/ImageText/front.blade.php

@php
    if (empty($content) || !is_array($content)) {
            return;
    }

    list(
        $images,
        $preTitle,
        $title,
        $htmlContent,
    ) = $content;

    $image = is_array($images) ? array_shift($images) : null;
@endphp

<div class="block-image-text">
    @if (!empty($image))
        <img src="{{ asset('storage/'.$image) }}"/>
    @endif
    @if (!empty($preTitle))
        <h5 class="pre-title">
            {{ $preTitle }}
        </h5>
    @endif
    @if (!empty($title))
        <h3 class="title">
            {{ $title }}
        </h3>
    @endif
    @if (!empty($htmlContent))
        <div class="content">
            {!! $htmlContent !!}
        </div>
    @endif
</div>

Step 4

Add your translations to language files.

resources/lang/vendor/nova-visual-composer/fr/templates.php

return [
    ...

    'image-text' => [
        'name' => 'Image / texte',
        'crud_pre_title' => 'Sur-titre',
        'crud_title' => 'Titre',
        'crud_text' => 'Texte',
    ],
];    

Lint

Run php-cs with:

composer run-script lint

Contributing

Contributions are welcome! Leave an issue on Github, or create a Pull Request.

Licence

This package is under GNU Affero General Public License v3 or (at your option) any later version.