Development

Вы просматриваете документацию старой версии MoonShine. Рассмотрите возможность обновления вашего проекта до MoonShine 2.x.

MoonShine дает возможности расширения основного функционала и написания собственных пакетов, которые улучшат возможности. В данном разделе мы приведем список таких пакетов, пример с созданием собственного поля и действия.

Если у вас сложности с тем, как должен выглядеть ваш пакет для MoonShine, то мы приготовили для вас готовый шаблон. Шаблон

Следующие сущности могут быть расширены:

  • Fields
  • Filters
  • Decorations
  • Actions
  • Metrics
  • InputExtension
  • FormComponent
  • Resource

# Кастомное поле

Рассмотрим небольшой пример создания собственного поля! Это будет визуальный редактор на основе js плагина CKEditor

Для начала создадим класс, который расширяет MoonShine поля

namespace App\MoonShine\Fields;
 
use MoonShine\Fields\Field;
 
final class CKEditor extends Field
{
protected static string $view = 'fields.ckeditor';
 
protected array $assets = [
'https://cdn.ckeditor.com/ckeditor5/35.3.0/super-build/ckeditor.js'
];
}

И создаем view с реализацией

<x-moonshine::form.textarea
:attributes="$element->attributes()->merge([
'id' => 'ckeditor_' . $item->getKey() . '_' . $element->id(),
'name' => $element->name()
])"
>{!! $element->formViewValue($item) ?? '' !!}</x-moonshine::form.textarea>
 
<script>
CKEDITOR.ClassicEditor.create(document.getElementById("ckeditor_{{ $item->getKey() }}_{{ $element->id() }}"), {
// https://ckeditor.com/docs/ckeditor5/latest/features/toolbar/toolbar.html#extended-toolbar-configuration-format
toolbar: {
items: [
'heading', '|',
'bold', 'italic', 'strikethrough', 'underline', 'code', 'subscript', 'superscript', 'removeFormat', '|',
'bulletedList', 'numberedList', 'todoList',
'outdent', 'indent', '|',
'undo', 'redo',
'-',
'exportPDF','exportWord', '|',
'findAndReplace', '|',
'fontSize', 'fontColor', 'fontBackgroundColor',
'alignment', '|',
'link', 'insertImage', 'blockQuote', 'insertTable', 'mediaEmbed', 'codeBlock', 'htmlEmbed', '|',
'specialCharacters', 'horizontalLine', 'sourceEditing'
],
shouldNotGroupWhenFull: true
},
// Changing the language of the interface requires loading the language file using the <script> tag.
// language: 'es',
list: {
properties: {
styles: true,
startIndex: true,
reversed: true
}
},
// https://ckeditor.com/docs/ckeditor5/latest/features/headings.html#configuration
heading: {
options: [
{ model: 'paragraph', title: 'Paragraph', class: 'ck-heading_paragraph' },
{ model: 'heading1', view: 'h1', title: 'Heading 1', class: 'ck-heading_heading1' },
{ model: 'heading2', view: 'h2', title: 'Heading 2', class: 'ck-heading_heading2' },
{ model: 'heading3', view: 'h3', title: 'Heading 3', class: 'ck-heading_heading3' },
{ model: 'heading4', view: 'h4', title: 'Heading 4', class: 'ck-heading_heading4' },
{ model: 'heading5', view: 'h5', title: 'Heading 5', class: 'ck-heading_heading5' },
{ model: 'heading6', view: 'h6', title: 'Heading 6', class: 'ck-heading_heading6' }
]
},
// https://ckeditor.com/docs/ckeditor5/latest/features/editor-placeholder.html#using-the-editor-configuration
placeholder: 'Welcome to CKEditor 5!',
// https://ckeditor.com/docs/ckeditor5/latest/features/font.html#configuring-the-font-family-feature
fontFamily: {
options: [
'default',
'Arial, Helvetica, sans-serif',
'Courier New, Courier, monospace',
'Georgia, serif',
'Lucida Sans Unicode, Lucida Grande, sans-serif',
'Tahoma, Geneva, sans-serif',
'Times New Roman, Times, serif',
'Trebuchet MS, Helvetica, sans-serif',
'Verdana, Geneva, sans-serif'
],
supportAllValues: true
},
// https://ckeditor.com/docs/ckeditor5/latest/features/font.html#configuring-the-font-size-feature
fontSize: {
options: [ 10, 12, 14, 'default', 18, 20, 22 ],
supportAllValues: true
},
// Be careful with the setting below. It instructs CKEditor to accept ALL HTML markup.
// https://ckeditor.com/docs/ckeditor5/latest/features/general-html-support.html#enabling-all-html-features
htmlSupport: {
allow: [
{
name: /.*/,
attributes: true,
classes: true,
styles: true
}
]
},
codeBlock: {
languages: [
{ language: 'php', label: 'Php' },
{ language: 'js', label: 'Js' }
]
},
// Be careful with enabling previews
// https://ckeditor.com/docs/ckeditor5/latest/features/html-embed.html#content-previews
htmlEmbed: {
showPreviews: true
},
// https://ckeditor.com/docs/ckeditor5/latest/features/link.html#custom-link-attributes-decorators
link: {
decorators: {
addTargetToExternalLinks: true,
defaultProtocol: 'https://',
toggleDownloadable: {
mode: 'manual',
label: 'Downloadable',
attributes: {
download: 'file'
}
}
}
},
// https://ckeditor.com/docs/ckeditor5/latest/features/mentions.html#configuration
mention: {
feeds: [
{
marker: '@',
feed: [
'@apple', '@bears', '@brownie', '@cake', '@cake', '@candy', '@canes', '@chocolate', '@cookie', '@cotton', '@cream',
'@cupcake', '@danish', '@donut', '@dragée', '@fruitcake', '@gingerbread', '@gummi', '@ice', '@jelly-o',
'@liquorice', '@macaroon', '@marzipan', '@oat', '@pie', '@plum', '@pudding', '@sesame', '@snaps', '@soufflé',
'@sugar', '@sweet', '@topping', '@wafer'
],
minimumCharacters: 1
}
]
},
simpleUpload: {
// The URL that the images are uploaded to.
uploadUrl: '{{ route('moonshine.attachments') }}',
},
// The "super-build" contains more premium features that require additional configuration, disable them below.
// Do not turn them on unless you read the documentation and know how to configure them and setup the editor.
removePlugins: [
// These two are commercial, but you can try them out without registering to a trial.
// 'ExportPdf',
// 'ExportWord',
'CKBox',
'CKFinder',
//'EasyImage',
// This sample uses the Base64UploadAdapter to handle image uploads as it requires no configuration.
// https://ckeditor.com/docs/ckeditor5/latest/features/images/image-upload/base64-upload-adapter.html
// Storing images as Base64 is usually a very bad idea.
// Replace it on production website with other solutions:
// https://ckeditor.com/docs/ckeditor5/latest/features/images/image-upload/image-upload.html
// 'Base64UploadAdapter',
'RealTimeCollaborativeComments',
'RealTimeCollaborativeTrackChanges',
'RealTimeCollaborativeRevisionHistory',
'PresenceList',
'Comments',
'TrackChanges',
'TrackChangesData',
'RevisionHistory',
'Pagination',
'WProofreader',
// Careful, with the Mathtype plugin CKEditor will not load when loading this sample
// from a local file system (file://) - load this site via HTTP server if you enable MathType
'MathType'
]
});
</script>
 
<style>
.ck-editor__editable {
max-height: 400px;
background-color: white!important;
color: black!important;
}
</style>

Вот и все!

# Кастомное действие

В MoonShine уже есть несколько встроенных действий, таких как Экспорт и Импорт , но вы также можете создавать свои собственные действия.

Для этого вам нужно создать класс, который расширяет класс действия MoonShine и определить метод handle.

namespace App\MoonShine\Actions;
 
use MoonShine\Actions\Action;
 
class CustomAction extends Action
{
public function handle(): mixed
{
// Код с логикой обработчика
}
}

Этого уже достаточно, чтобы отобразить наше действие на странице ресурса. Однако, давайте рассмотрим, что еще можно определить в нашем классе действия.

class CustomAction extends Action
{
protected static string $view = 'view.custom'; // Собственное blade отображение
 
protected bool $withQuery = true; // Если необходимо передавать в url действия, весь текущий getQuery
 
protected bool $inDropdown = false; // Отображать кнопку вне выпадающего списка
 
protected ?string $icon = 'heroicons.outline.table-cells'; // Иконка для кнопки
}

Затем зарегистрируйте действие в методе actions ресурса, в котором вы хотите отобразить его.

public function actions(): array
{
return [
CustomAction::make('Кастомное действие'),
];
}

Готово!