mountainclans / livewire-section-builder
This is my package livewire-section-builder
Installs: 17
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/mountainclans/livewire-section-builder
Requires
- php: ^8.2
- illuminate/contracts: ^10.0||^11.0||^12.0
- livewire/livewire: ^3.0
- mountainclans/laravel-polymorphic-model: ^2.0
- mountainclans/livewire-select: ^1.3
- mountainclans/livewire-ui: ^1.2
- spatie/eloquent-sortable: ^4.4
- spatie/laravel-package-tools: ^1.16
- spatie/laravel-schemaless-attributes: ^2.5
Requires (Dev)
- laravel/pint: ^1.14
- nunomaduro/collision: ^8.1.1||^7.10.0
- orchestra/testbench: ^10.0.0||^9.0.0||^8.22.0
- pestphp/pest: ^2.0||^3.0
- pestphp/pest-plugin-arch: ^2.5||^3.0
- pestphp/pest-plugin-laravel: ^2.0||^3.0
README
Установка
Установите пакет при помощи composer:
composer require mountainclans/livewire-section-builder
Важно! Пакет зависит от других компонентов, в частности, необходимо сразу после установки этого пакета также сконфигурировать для использования пакет mountainclans/livewire-select (инструкции находятся на его странице).
Опубликуйте и примените миграции:
php artisan vendor:publish --tag="livewire-section-builder-migrations"
php artisan migrate
Опубликуйте конфигурационный файл:
php artisan vendor:publish --tag="livewire-section-builder-config"
Конфигурационный массив имеет следующую вложенность:
retyrn [
'sections' => [
[
'key' => 'top_banner',
'title' => 'Top banner',
'model' => EloquentSectionModelClass::class,
'editor' => LivewireEditorComponent::class,
'frontend' => LivewireViewComponent::class,
],
[
'key' => 'advantages',
'title' => 'Advantages',
'model' => EloquentSectionModelClass2::class,
'editor' => LivewireEditorComponent2::class,
'frontend' => LivewireViewComponent2::class,
],
],
'templates' => [
'main_page' => [
'top_banner',
'advantages',
],
],
]
Добавьте в tailwind.config.js в секцию content:
'./vendor/mountainclans/livewire-section-builder/resources/views/**/*.blade.php'
Опционально, Вы можете опубликовать views для их переопределения:
php artisan vendor:publish --tag="livewire-section-builder-views"
Использование
Перед использованием компонентов пакета, пожалуйста, сконфигурируйте используемые классы в конфигурационном файле.
Модель секции
Модель секции должна расширять класс
Структура хранения модели состоит из следующих полей:
- id
- template
- page_id
- type
- order_column
- fields
- created_at
- updated_at
Не рекомендуется менять миграцию, создающую таблицу для секций. Все необходимые поля секции можно сохранить в атрибуте модели fields. Данный атрибут представляет собой schemaless attribute, реализация от Spatie.
Тем не менее, Вы вправе расширять модель секции как Вам необходимо, к примеру, использовать трейты HasTranslations, InteractsWithMedia и другие.
Для того, чтобы одна и та же секция могла быть доступна для разных шаблонов, пожалуйста, используйте уникальные ключи в качестве названий секций.
Админка
В нужном месте страницы используйте компонент редактора:
@if ($pageId && !empty($destination))
<livewire:admin-section-builder :template="BuilderPage::DESTINATION_HOME_PAGE"
:page-id="$pageId"
/>
@endif
Компоненты editor сами занимаются валидацией и сохранением своего состояния, в них может быть любая логика. Удалением, сортировкой, скрытием и показом контента этих компонентов занимается компонент admin-section-builder.
Настоятельно рекомендуется, чтобы компонент взаимодействовал только с соответствующей моделью, указанной в конфиге как model.
Рекомендуется создавать как минимум один публичный метод - saveSection, но в целом реализация никак не регламентирована.
При сохранении компонента рекомендуется выбрасывать событие:
$this->dispatch(AdminSectionBuilder::EVENT_SECTION_UPDATED);
События при редактировании в админке
Вы можете расширить класс компонента AdminSectionBuilder и использовать собственный компонент в админке. В частности, Вы можете подписаться на одно из следующих событий:
- AdminSectionBuilder::EVENT_SECTION_ADDED
- AdminSectionBuilder::EVENT_SECTION_UPDATED
- AdminSectionBuilder::EVENT_SECTION_SORTED
- AdminSectionBuilder::EVENT_SECTION_HIDDEN
- AdminSectionBuilder::EVENT_SECTION_SHOWED
- AdminSectionBuilder::EVENT_SECTION_DELETED
И реализовать, к примеру, отправку уведомлений пользователю.
View-компонент
<livewire:frontend-section-viewer :page-id="$page->id"
:template="BuilderPage::DESTINATION_HOME_PAGE"
/>
Данный компонент выведет все секции с нужным контентом и в нужном порядке.
Повторители
Иногда при создании секции необходимо повторить в ней однотипные данные несколько раз. Сделать это призвана комбинация трейта WithRepeaters и использование blade-компонента admin.repeater-editor.
Создайте модель-наследника BuilderSectionRepeater из пакета. Переопределите метод allowedTypes. Используйте данную модель как базовую, от которой будут наследоваться все повторители секций.
use MountainClans\LivewireSectionBuilder\Models\BuilderSectionRepeater as BaseBuilderSectionRepeater; class BuilderSectionRepeater extends BaseBuilderSectionRepeater { public static function allowedTypes(): array { return [ PropertiesSliderSection::REPEATER_TYPE => PropertiesTabRepeater::class, ]; } }
Унаследуйтесь от этой модели для создания уникальных классов-повторителей. Добавьте в них необходимые трейты (к примеру, HasTranslations, FilledTranslatableFields).
Если модель использует HasTranslations, укажите список переводимых полей.
class AdvantagesOneRepeater extends BuilderSectionRepeater { protected function getInstanceType(): string { return AdvantagesOneSection::REPEATER_TYPE; } public array $translatable = [ 'fields->title', 'fields->description', ]; }
Настройка секции, использующей повторитель
- добавьте в класс секции, использующей repeater, константу
REPEATER_TYPE; - добавьте метод, реализующий связь
repeaters(HasMany):
class AdvantagesOneSection extends BuilderSection { public const REPEATER_TYPE = 'advantages_1_repeater'; public function repeaters(): HasMany { return $this->hasMany(AdvantagesOneRepeater::class, 'section_id'); } }
Редактор
В редакторе секции используйте трейт WithRepeaters.
Обязательно переопределите методы редактора секции getRepeaterModel и getRepeaterFields, как показано в примере.
Опционально вы можете использовать метод getRepeaterDefaults для того, чтобы задать начальные значения полей.
class AdvantagesOneSectionEditor extends Component { // другие трейты use WithRepeaters; // поля компонента public AdvantagesOneSection $section; public function mount(AdvantagesOneSection $section): void { // инициализационная логика $this->setRepeaters(); } public function saveSection(): void { // логика сохранения основного контента $this->saveRepeaters(); // другая логика $this->dispatch(AdminSectionBuilder::EVENT_SECTION_UPDATED); } protected function getRepeaterModel(): string { return AdvantagesOneRepeater::class; } protected function getRepeaterFields(): array { return ['title', 'description']; } // другая логика компонента }
Во view используйте компонент-обёртку для создания редактора контента повторителей. Пример ниже:
{{-- Repeaters --}}
<div class="w-full border-gray-300 dark:border-purple-800 border-2 rounded-lg p-4 mb-6">
<h2 class="dark:text-white font-semibold mb-4">{{ __('Advantages') }}</h2>
@empty($repeaters)
<div class="p-4 text-sm text-gray-800 rounded-lg bg-gray-50 dark:bg-gray-700 dark:text-gray-300"
role="alert">
{{ __('Not exists yet') }}
</div>
@else
@foreach($repeaters as $index => $repeater)
<x-admin.repeater-editor :repeater="$repeater" :index="$index">
<x-ui.translatable>
<div class="grid gap-4 grid-cols-1 lg:grid-cols-5 lg:gap-6">
<div class="col-span-1">
<x-ui.input wire:model="repeaters.{{ $index }}.title"
translatable
:placeholder="__('Title')"
:label="__('Title')"
/>
</div>
<div class="col-span-4">
<x-ui.tiptap wire:model="repeaters.{{ $index }}.description"
translatable
height="70"
placeholder="{{ __('Description') }}"
label="{{ __('Description') }}"
/>
</div>
</div>
</x-ui.translatable>
</x-admin.repeater-editor>
@endforeach
@endempty
</div>
<div class="flex justify-between items-center">
<button wire:click="addRepeater"
type="button"
class="cursor-pointer focus:outline-none text-white bg-purple-700 hover:bg-purple-800 focus:ring-4 focus:ring-purple-300 font-medium rounded-lg text-sm px-5 py-2.5 mb-2 dark:bg-purple-600 dark:hover:bg-purple-700 dark:focus:ring-purple-900"
>{{ __('Add advantage') }}</button>
<x-ui.submit-button>{{ __('Save section') }}</x-ui.submit-button>
</div>
Авторы
Лицензия
The MIT License (MIT). Please see License File for more information.