feature: add image uploads to MD editor

This commit is contained in:
Ryan Chandler
2021-03-20 23:24:46 +00:00
parent 210e892774
commit adbd9ff2af
7 changed files with 145 additions and 65 deletions
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1,4 +1,4 @@
{
"/js/filament.js": "/js/filament.js?id=f6f25b9e29038b97ab02",
"/css/filament.css": "/css/filament.css?id=4bd4d738e31deebdabd8"
"/css/filament.css": "/css/filament.css?id=c2cefa20cf3b7ab5aca0"
}
@@ -11,12 +11,21 @@
@pushonce('filament-scripts:markdown-editor-component')
<script type="module" src="https://cdn.jsdelivr.net/npm/@github/markdown-toolbar-element@1.4.0/dist/index.min.js"></script>
<script type="module" src="https://unpkg.com/@github/file-attachment-element@1.x/dist/index.js"></script>
<script src="https://cdn.jsdelivr.net/npm/mdhl@0.0.6/dist/mdhl.umd.js"></script>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<script>
function markdownEditor(config) {
return {
attachmentDirectory: config.attachmentDirectory,
attachmentDisk: config.attachmentDisk,
attachmentUploadUrl: config.attachmentUploadUrl,
csrfToken: config.csrfToken,
overlay: null,
preview: '',
@@ -43,6 +52,47 @@
this.$el.style.height = this.$refs.textarea.style.height
this.overlay = mdhl.highlight(this.value = this.$refs.textarea.value)
},
uploadAttachments: function ($event) {
const attachment = $event.detail?.attachments?.[0]
if (! attachment || ! attachment.file) return
let formData = new FormData()
formData.append('directory', this.attachmentDirectory)
formData.append('disk', this.attachmentDisk)
formData.append('file', attachment.file)
fetch(this.attachmentUploadUrl, {
body: formData,
credentials: 'same-origin',
headers: {
'X-CSRF-TOKEN': this.csrfToken,
},
method: 'POST',
})
.then(response => response.text())
.then(url => {
this.$refs.textarea.value += "\n\n"
this.$refs.imageTrigger.click()
const urlStart = this.$refs.textarea.selectionStart + 2
const urlEnd = urlStart + 3
this.$refs.textarea.value = [
this.$refs.textarea.value.substring(0, urlStart),
url,
this.$refs.textarea.value.substring(urlEnd)
].join('')
this.$refs.textarea.selectionStart = urlStart - 2
this.$refs.textarea.selectionEnd = urlStart - 2
this.resize()
})
}
}
}
@@ -61,6 +111,10 @@
<div
x-data="markdownEditor({
tab: '{{ $formComponent->isDisabled() ? 'preview' : 'write' }}',
attachmentDirectory: {{ json_encode($formComponent->getAttachmentDirectory()) }},
attachmentDisk: {{ json_encode($formComponent->getAttachmentDiskName()) }},
attachmentUploadUrl: {{ json_encode($formComponent->getAttachmentUploadUrl()) }},
csrfToken: {{ json_encode(csrf_token()) }},
})"
x-init="init"
wire:ignore
@@ -109,7 +163,7 @@
@if ($formComponent->hasToolbarButton('attachFiles'))
<x-filament::button size="small" class="text-base" title="{{ __('forms::fields.markdownEditor.toolbarButtons.attachFiles') }}">
<md-image class="w-full h-full">
<md-image class="w-full h-full" x-ref="imageTrigger">
<x-heroicon-o-photograph class="w-4" />
</md-image>
</x-filament::button>
@@ -173,18 +227,21 @@
@endunless
<div x-show="tab === 'write'" class="relative w-full h-full" style="min-height: 150px;">
<textarea
{!! $formComponent->isAutofocused() ? 'autofocus' : null !!}
{!! $formComponent->getId() ? "id=\"{$formComponent->getId()}\"" : null !!}
{!! $formComponent->getName() ? "{$formComponent->getBindingAttribute()}=\"{$formComponent->getName()}\"" : null !!}
{!! $formComponent->getPlaceholder() ? "placeholder=\"{$formComponent->getPlaceholder()}\"" : null !!}
{!! $formComponent->isRequired() ? 'required' : null !!}
@input="resize"
class="absolute bg-transparent top-0 left-0 block z-1 w-full h-full min-h-full rounded resize-none shadow-sm placeholder-gray-400 focus:placeholder-gray-500 placeholder-opacity-100 focus:border-blue-300 focus:ring focus:ring-blue-200 focus:ring-opacity-50 {{ $errors->has($formComponent->getName()) ? 'border-danger-600 motion-safe:animate-shake' : 'border-gray-300' }}"
x-ref="textarea"
></textarea>
<file-attachment directory>
<textarea
{!! $formComponent->isAutofocused() ? 'autofocus' : null !!}
{!! $formComponent->getId() ? "id=\"{$formComponent->getId()}\"" : null !!}
{!! $formComponent->getName() ? "{$formComponent->getBindingAttribute()}=\"{$formComponent->getName()}\"" : null !!}
{!! $formComponent->getPlaceholder() ? "placeholder=\"{$formComponent->getPlaceholder()}\"" : null !!}
{!! $formComponent->isRequired() ? 'required' : null !!}
@input="resize"
@file-attachment-accepted.window="uploadAttachments"
class="absolute bg-transparent top-0 left-0 block z-1 w-full h-full min-h-full rounded resize-none shadow-sm placeholder-gray-400 focus:placeholder-gray-500 placeholder-opacity-100 focus:border-blue-300 focus:ring focus:ring-blue-200 focus:ring-opacity-50 {{ $errors->has($formComponent->getName()) ? 'border-danger-600 motion-safe:animate-shake' : 'border-gray-300' }}"
x-ref="textarea"
></textarea>
</file-attachment>
<div class="w-full h-full text-black" x-ref="overlay" x-html="overlay"></div>
<div class="w-full h-full text-black break-words" x-ref="overlay" x-html="overlay"></div>
</div>
<div class="block w-full h-full min-h-full px-6 py-4 border border-gray-300 rounded shadow-sm focus:border-blue-300" x-show="tab === 'preview'" style="min-height: 150px;">
@@ -0,0 +1,59 @@
<?php
namespace Filament\Forms\Components\Concerns;
trait HasAttachments
{
protected $attachmentDirectory = 'attachments';
protected $attachmentDiskName;
protected $attachmentUploadUrl;
public function attachmentDirectory($directory)
{
$this->configure(function () use ($directory) {
$this->attachmentDirectory = $directory;
});
return $this;
}
public function attachmentDisk($disk)
{
$this->configure(function () use ($disk) {
$this->attachmentDiskName = $disk;
});
return $this;
}
public function enableAttachments($url)
{
$this->configure(function () use ($url) {
$this->attachmentUploadUrl = $url;
if (method_exists($this, 'enableToolbarButtons')) {
$this->enableToolbarButtons(['attachFiles']);
}
});
return $this;
}
public function getAttachmentDirectory()
{
return $this->attachmentDirectory;
}
public function getAttachmentDiskName()
{
return $this->attachmentDiskName;
}
public function getAttachmentUploadUrl()
{
return $this->attachmentUploadUrl;
}
}
@@ -8,6 +8,7 @@ class MarkdownEditor extends Field
use Concerns\CanBeCompared;
use Concerns\CanBeUnique;
use Concerns\HasPlaceholder;
use Concerns\HasAttachments;
protected $toolbarButtons = [
'attachFiles',
@@ -22,6 +23,17 @@ class MarkdownEditor extends Field
'write',
];
protected function setUp()
{
$this->attachmentDisk(config('forms.default_filesystem_disk'));
$attachmentUploadUrl = config('forms.rich_editor.default_attachment_upload_url');
if ($attachmentUploadUrl) {
$this->enableAttachments($attachmentUploadUrl);
}
}
public function disableAllToolbarButtons()
{
$this->configure(function () {
+2 -50
View File
@@ -8,12 +8,7 @@ class RichEditor extends Field
use Concerns\CanBeCompared;
use Concerns\CanBeUnique;
use Concerns\HasPlaceholder;
protected $attachmentDirectory = 'attachments';
protected $attachmentDiskName;
protected $attachmentUploadUrl;
use Concerns\HasAttachments;
protected $toolbarButtons = [
'bold',
@@ -35,29 +30,12 @@ class RichEditor extends Field
$this->attachmentDisk(config('forms.default_filesystem_disk'));
$attachmentUploadUrl = config('forms.rich_editor.default_attachment_upload_url');
if ($attachmentUploadUrl) {
$this->enableAttachments($attachmentUploadUrl);
}
}
public function attachmentDirectory($directory)
{
$this->configure(function () use ($directory) {
$this->attachmentDirectory = $directory;
});
return $this;
}
public function attachmentDisk($disk)
{
$this->configure(function () use ($disk) {
$this->attachmentDiskName = $disk;
});
return $this;
}
public function disableAllToolbarButtons()
{
$this->configure(function () {
@@ -82,17 +60,6 @@ class RichEditor extends Field
return $this;
}
public function enableAttachments($url)
{
$this->configure(function () use ($url) {
$this->attachmentUploadUrl = $url;
$this->enableToolbarButtons(['attachFiles']);
});
return $this;
}
public function enableToolbarButtons($buttonsToEnable)
{
$this->configure(function () use ($buttonsToEnable) {
@@ -106,21 +73,6 @@ class RichEditor extends Field
return $this;
}
public function getAttachmentDirectory()
{
return $this->attachmentDirectory;
}
public function getAttachmentDiskName()
{
return $this->attachmentDiskName;
}
public function getAttachmentUploadUrl()
{
return $this->attachmentUploadUrl;
}
public function getToolbarButtons()
{
return $this->toolbarButtons;