Оглавление
TinyMCE – это мощный и гибкий редактор для создания и редактирования контента на веб-страницах. Он предлагает широкий набор инструментов и настроек, которые позволяют разработчикам адаптировать его под свои нужды. Здесь мы рассмотрим добавление TinyMCE в панель управления Laravel Orchid.
Laravel Orchid – это современный, быстрый и гибкий фреймворк для разработки панелей управления и административных интерфейсов. Он предоставляет разработчикам множество полезных инструментов и возможностей, среди которых поддержка различных типов полей, система разграничения прав доступа и другое. Интеграция TinyMCE позволит вам расширить функционал панели управления, предоставив пользователям удобный инструмент для работы с контентом.
Подготовка
В первую очередь нам понадобятся скрипты самого редактора. Их можно скачать с официального сайта или через пакетный менеджер. Скачав скрипты, нужно скопировать их в публичную директорию вашего сайта. Я предлагаю разместить их в public/static/tinymce
.
После копирования подключите основной скрипт tinymce.min.js
в админку Orchid. Для этого достаточно добавить ссылку на файл в конфиг config/platform.php
:
return [
// ...
'resource' => [
'stylesheets' => [ ],
'scripts' => [
'/static/tinymce/tinymce.min.js',
],
],
// ...
];
Также нужно настроить сборку пользовательских скриптов админки.
Последние версии Laravel поставляются с настроенным конфигом для сборки фронта с помощью Vite, а Orchid предлагает возможность добавлять пользовательские сборки без необходимости изменять свои шаблоны.
Я предлагаю создать отдельную директорию для файлов админки по пути resources/admin/js
. Здесь можно позже располагать все необходимые для админки скрипты, а сейчас создайте основной файл, который будет служить точкой входа: resources/admin/js/dashboard.js
. Пока его содержимое будет таким:
console.log('My dashboard');
Добавьте этот файл в конфигурацию сборки Vite (файл vite.config.js
).
import laravel from 'laravel-vite-plugin';
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [
laravel({
input : [
'resources/sass/app.scss',
'resources/js/app.js',
// Добавим свой файл для админки
'resources/admin/js/dashboard.js',
],
refresh: true,
}),
],
});
А также в конфиг Orchid (config/platform.php
)
return [
'vite' => [
'resources/admin/js/dashboard.js',
],
];
Выполните в терминале команду
npm run build
и после обновления любой страницы админки, вы увидите в консоли браузера сообщение "My dashboard". Значит всё собралось и подключилось правильно.
Пользовательское поле
Теперь нужно создать пользовательское поле для использования в панели управления. Для этого нам потребуется написать новый php класс, расширяющий класс Orchid\Screen\Field
, blade-шаблон элемента управления и javascript контроллер, инициализирующий TinyMCE.
PHP класс
Чтобы не писать вручную много кода, можно взять уже готовый класс Orchid\Screen\Fields\Quill
и немного изменить его. Создайте новый файл app/Orchid/Fields/TinyMCE.php
и вставьте в него следующее содержимое:
<?php
namespace App\Orchid\Fields;
use Orchid\Screen\Field;
/**
* Class TinyMCE
* @method TinyMCE name(string $value = null)
* @method TinyMCE value($value = true)
* @method TinyMCE help(string $value = null)
* @method TinyMCE title(string $value = null)
*/
class TinyMCE extends Field
{
protected $view = 'orchid.fields.tinymce';
/**
* All attributes that are available to the field.
*/
protected $attributes = [
'value' => null,
'class' => 'textarea-tinymce',
'data-tinymce-target' => 'textarea',
];
/**
* Attributes available for a particular tag.
*/
protected $inlineAttributes = [
'accesskey',
'autofocus',
'cols',
'disabled',
'form',
'maxlength',
'name',
'placeholder',
'readonly',
'required',
'rows',
'tabindex',
'wrap',
];
}
Здесь мы изменили шаблон в свойстве $view
для вывода в админке и набор атрибутов – добавили css-класс и data-атрибут, необходимый для контроллера.
Blade-шаблон
Шаблон для вывода данного элемента, как указано выше, будет располагаться в директории resources/views/orchid/fields
и называться tinymce.blade.php
. Его содержимое также будет на основе шаблона для встроенного редактора Quill:
@component($typeForm, get_defined_vars())
<div
id="tinymce-wrapper-{{ $id }}"
data-controller="tinymce"
data-turbo-temporary
>
<textarea {{ $attributes }}>{{ $value ?? '' }}</textarea>
</div>
@endcomponent
Javascript-контроллер
Фронтэнд панели управления Orchid построен на связке фреймворков Hotwire Turbo и Hotwire Stimulus. Первый предоставляет некое подобие SPA, а второй – компонентный подход и управление элементами на странице. Соответственно, каждый элемент управления в админке управляется контроллером Stimulus. Выше, в коде шаблона, мы указали атрибут data-controller="tinymce"
, указывающий, что наш редактор будет управляться контроллером с именем tinymce
.
Создайте файл resources/admin/js/controllers/tinymce_controller.js
.
export default class extends Controller {
static targets = [
'textarea',
];
connect() {
tinymce.init({
target: this.textareaTarget,
});
}
disconnect() {
tinymce.remove();
}
}
Теперь подключите этот констроллер в файле resources/admin/js/dashboard.js
.
import TinyMCEController from './controllers/tinymce_controller.js';
window.application.register('tinymce', TinyMCEController);
Осталось выполнить сборку npm run build
и новый редактор можно использовать в админке как и любое другое поле.
Пример использования:
Layout::rows([
Input::make('article.title')->title('Заголовок')->required(),
TinyMCE::make('article.content')->title('Содержание'),
]),
Загрузка изображений
По умолчанию TinyMCE сохраняет вставляемые изображения прямо в содержимое в виде base64. Чаще всего такой вариант не годится. Нужно сделать так, чтобы картинки сохранялись в хранилище в виде файлов, используя при этом штатную модель Orchid\Attachment\Models\Attachment
.
Создайте контроллер app/Orchid/Controllers/UploadController.php
, который будет обрабатывать загрузку изображений. Метод загрузки должен возвращать json-объект с ключом location
, содержащий url загруженного файла.
namespace App\Orchid\Controllers;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\UploadedFile;
use Illuminate\Routing\Controller;
use Orchid\Attachment\File;
class UploadController extends Controller
{
public function upload(Request $request): JsonResponse
{
/** @var \Orchid\Attachment\Models\Attachment $attachment */
$attachment = collect($request->allFiles())
->flatten()
->map(fn(UploadedFile $file) => resolve(File::class, [
'file' => $file,
'disk' => 'public',
'group' => 'content',
])->load())
->first();
return response()->json([
'location' => $attachment->url(),
]);
}
}
Теперь нужно определить маршрут, по которому будет осуществляться загрузка. Добавьте в файл routes/platform.php его определение:
use App\Http\Middleware\VerifyCsrfToken;
use App\Orchid\Controllers\UploadController;
Route::post('upload', [UploadController::class, 'upload'])
->name('image.upload')
->withoutMiddleware(VerifyCsrfToken::class);
Для этого маршрута мы отключили проверку csrf-токена, так как не собираемся писать собственный загрузчик, а просто укажем url загрузки в конфигурации TinyMCE. Обновите конфигурацию:
tinymce.init({
target: this.textareaTarget,
plugins: [
'image',
],
toolbar: 'undo redo | styles | bold italic | link image',
relative_urls : false,
remove_script_host: true,
images_upload_url: '/admin/upload',
image_dimensions : false,
images_file_types: 'jpeg,jpg,png,gif,svg,webp',
});
Здесь мы добавили плагин для вставки изображений и соответствующую кнопку на панель редактора, а также указали адрес для сохранения файлов.
Опция relative_urls: false
предписывает генерировать абсолютные url к изображениям, а remove_script_host: true
– удалять из url имя хоста.
Не забудьте пересобрать код для админки.
Решение проблем
В процессе использования выяснилось, что инициализация редактора не происходит, если повторно зайти на страницу, на которой мы уже были. В этом случае вместо редактора отображается простое поле textarea. Для решения этой проблемы нужно добавить атрибут data-turbo-temporary
в шаблон редактора (это уже сделано в коде, представленном выше). А также отключить кэширование в Turbo. Для этого нужно установить параметр platform.turbo.cache
в значение false
.
'turbo' => [
'cache' => false,
],
Вы можете оставить комментарий: