Added the ability to upload pictures in the editor.

This commit is contained in:
2024-07-26 22:04:39 +05:00
parent 4d36821ecc
commit b33362a235
34 changed files with 2007 additions and 40 deletions

View File

@@ -1,23 +1,114 @@
@php
$tinyId = \Illuminate\Support\Str::random(7);
$tinyId = 'form-textarea-wysiwyg-' . $tinyId;
$images = [];
$files = [];
/** @var \App\Dto\View\Volt\Form\WysiwygStorageUpload | null $storageUpload */
if ($storageUpload !== null) {
$storages = old($storageUpload->getRequestInputName(), []);
$images = $storages['content_images'] ?? [];
}
@endphp
<div class="mb-3">
<label for="form-textarea-wysiwyg-{{ $requestName }}">{{ $title }}</label>
<textarea class="form-control {{ $attributes->get('class') }} textarea-tinymce @error($requestName) is-invalid @enderror" name="{{ $name }}" id="form-textarea-wysiwyg-{{ $requestName }}" rows="3">{{ $value }}</textarea>
<label for="{{ $tinyId }}">{{ $title }}</label>
<textarea class="form-control {{ $attributes->get('class') }} textarea-tinymce @error($requestName) is-invalid @enderror" name="{{ $name }}" id="{{ $tinyId }}" rows="3">{{ $value }}</textarea>
@foreach($images as $image)
@continue( empty($image['file']) )
<input type="hidden" value="{{ $image['file'] }}" name="{{ $storageUpload->getInputName() }}[content_images][][file]';">
@endforeach
@error($requestName)
<span class="invalid-feedback">{{ $message }}</span>
<span class="invalid-feedback">{{ $message }}</span>
@enderror
</div>
@pushOnce('scripts')
<script src="{{ asset('/build/tinymce/tinymce.min.js') }}" referrerpolicy="origin"></script>
@include('admin._scripts._tinymce')
@push('scripts')
<script>
document.addEventListener('DOMContentLoaded', () => {
@if($storageUpload !== null)
const textarea = document.querySelector('#{{ $tinyId }}');
if (!textarea) {
return;
}
const storageImageType = '{{ \App\Enums\StorageType::ContentImages->value }}';
const morph = '{{ $storageUpload->getMorph()->value }}';
const storageInputName = '{{ $storageUpload->getInputName() }}';
const imageUpload = (blobInfo, progress) => new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.withCredentials = false;
xhr.open('POST', '{{ route('storage.image_upload_and_resize') }}');
xhr.upload.onprogress = (e) => {
progress(e.loaded / e.total * 100);
};
xhr.onload = () => {
if (xhr.status === 422) {
const json = JSON.parse(xhr.responseText);
let error = 'Error:<br><br>';
for (let key of Object.keys(json.errors)) {
error += json.errors[key] + '<br><br>';
}
reject(error);
return;
}
if (xhr.status === 403) {
reject({ message: 'HTTP Error: ' + xhr.status, remove: true });
return;
}
if (xhr.status < 200 || xhr.status >= 300) {
reject('HTTP Error: ' + xhr.status);
return;
}
const json = JSON.parse(xhr.responseText);
if (!json || typeof json.url != 'string') {
reject('Invalid JSON: ' + xhr.responseText);
return;
}
let input = document.createElement('input');
input.type = 'hidden';
input.name = storageInputName + '[content_images][][file]';
input.value = json.id;
textarea.after(input);
resolve(json.url);
};
xhr.onerror = () => {
reject('Image upload failed due to a XHR Transport error. Code: ' + xhr.status);
};
const formData = new FormData();
formData.append('file', blobInfo.blob(), blobInfo.filename());
formData.append('_token', document.querySelector('meta[name="csrf-token"]').content);
formData.append('storage_type', storageImageType);
formData.append('morph', morph);
xhr.send(formData);
});
@endif
tinymce.init({
selector: '.textarea-tinymce',
selector: '#{{ $tinyId }}',
@if(in_array(app()->getLocale(), ['ru'], true))
language: '{{ app()->getLocale() }}',
@endif
license_key: '{{ $tinymceLicenseKey }}',
plugins: 'advlist code emoticons link lists table codesample',
toolbar: 'bold italic | bullist numlist | link emoticons codesample',
plugins: 'advlist code emoticons link lists table codesample media my-image',
toolbar: 'bold italic | bullist numlist | link image emoticons media codesample',
referrer_policy: 'origin',
@if($storageUpload !== null)
images_upload_handler: imageUpload,
@endif
relative_urls: false,
convert_urls: false,
codesample_global_prismjs: true,
codesample_languages: [
{text: 'HTML/XML', value: 'markup'},
@@ -33,11 +124,11 @@
{text: 'Go', value: 'go'},
{text: 'Nginx', value: 'nginx'},
{text: 'Docker', value: 'docker'},
{text: 'Yaml', value: 'yaml'},
{text: "Treeview", value: "treeview"},
{text: "Diff", value: "diff"},
],
});
});
</script>
@include('_prism')
@endpushonce
@endpush