4 Коммитов

Автор SHA1 Сообщение Дата
Mattia Roccoberton
c0d37ad94e v0.2.10 2020-09-05 16:08:46 +02:00
Mattia Roccoberton
96c70106a4 Add a new example: upload plugin using Active Storage 2020-09-05 16:07:19 +02:00
Mattia Roccoberton
4ec6e80760 Editor default options refactoring + include imageUploader plugin
In order to use imageUploader plugin:
- js/css files must included in the app;
- an upload method must be provided in Active Admin entity;
- the image_uploader server_url field option needs to be set.
2020-09-04 10:53:29 +02:00
Mattia Roccoberton
707f4a5cc7 README improvements 2020-09-04 09:14:18 +02:00
9 изменённых файлов: 210 добавлений и 18 удалений

Просмотреть файл

@@ -47,8 +47,31 @@ Why 2 separated scripts/styles? In this way you can include a different version
f.input :description, as: :quill_editor, input_html: { data: { options: { modules: { toolbar: [['bold', 'italic', 'underline'], ['link']] }, placeholder: 'Type something...', theme: 'snow' } } }
```
## Notes
- Upload features (images/documents/files): not tested yet.
### ImageUploader plugin
This plugin allows to upload images to the server (instead of storing them in *base64* by default), reference [here](https://github.com/NoelOConnell/quill-image-uploader).
```ruby
# Upload method (to be included in the admin entity configuration)
member_action :upload, method: [:post] do
result = { success: resource.images.attach(params[:file_upload]) }
result[:url] = url_for(resource.images.last) if result[:success]
render json: result
end
```
```ruby
# Form field
unless object.new_record?
plugin_opts = { image_uploader: { server_url: upload_admin_post_path(object.id), field_name: 'file_upload' } }
f.input :description, as: :quill_editor, input_html: { data: { plugins: plugin_opts } }
end
```
For the relevant files of the upload example see [here](examples/upload_plugin_using_activestorage/).
Consider that this is just a basic example: images are uploaded as soon as they are attached to the
editor (regardless of the form submit), it shows the editor only for an existing record (because of
the *upload_admin_post_path*) and it doesn't provide a way to remove images (just deleting them from
the editor will not destroy them, you'll need to implement a purge logic for that).
## Do you like it? Star it!
If you use this component just star it. A developer is more motivated to improve a project when there is some interest.

1
app/assets/javascripts/activeadmin/quill.imageUploader.min.js поставляемый Обычный файл

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@@ -1,25 +1,40 @@
// --- functions ---------------------------------------------------------------
function initQuillEditors() {
var default_theme = 'snow';
var default_toolbar = [
['bold', 'italic', 'underline'],
['link', 'blockquote', 'code-block'],
[{ 'script': 'sub'}, { 'script': 'super' }],
[{ 'align': [] }, { list: 'ordered' }, { list: 'bullet' }],
[{ 'color': [] }, { 'background': [] }],
['image'],
['clean'],
];
var editors = document.querySelectorAll('.quill-editor');
var default_options = {
modules: {
toolbar: [
['bold', 'italic', 'underline'],
['link', 'blockquote', 'code-block'],
[{ 'script': 'sub'}, { 'script': 'super' }],
[{ 'align': [] }, { list: 'ordered' }, { list: 'bullet' }],
[{ 'color': [] }, { 'background': [] }],
['clean'],
]
},
placeholder: '',
theme: 'snow'
};
var registered_plugins = {};
for(var i = 0; i < editors.length; i++) {
var content = editors[i].querySelector('.quill-editor-content');
var isActive = editors[i].classList.contains('quill-editor--active');
if(content && !isActive) {
var options = editors[i].getAttribute('data-options') ? JSON.parse(editors[i].getAttribute('data-options')) : default_options;
// Setup editor options
var options = editors[i].getAttribute('data-options') ? JSON.parse(editors[i].getAttribute('data-options')) : {};
if(!options.theme) options.theme = default_theme;
if(!options.modules) options.modules = {};
if(!options.modules.toolbar) options.modules.toolbar = default_toolbar;
// Setup plugin options
var plugin_options = editors[i].getAttribute('data-plugins') ? JSON.parse(editors[i].getAttribute('data-plugins')) : {};
if(plugin_options.image_uploader && plugin_options.image_uploader.server_url) {
if(!registered_plugins.image_uploader) {
Quill.register('modules/imageUploader', ImageUploader);
registered_plugins.image_uploader = true;
}
var opts = plugin_options.image_uploader;
options.modules.imageUploader = setupImageUploader(opts.server_url, opts.field_name);
}
// Init editor
editors[i]['_quill-editor'] = new Quill(content, options);
editors[i].classList += ' quill-editor--active';
}
@@ -40,6 +55,33 @@ function initQuillEditors() {
}
}
function setupImageUploader(server_url, field_name) {
return {
upload: file => {
return new Promise((resolve, reject) => {
const formData = new FormData();
formData.append(field_name || 'file_upload', file);
fetch(server_url, {
body: formData,
headers: {
'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
},
method: 'POST'
}).then(response => response.json())
.then(result => {
resolve(result.url);
})
.catch(error => {
reject('Upload failed');
console.error('Error: ', error);
});
});
}
}
}
// --- events ------------------------------------------------------------------
$(document).ready( function() {
initQuillEditors();
});

33
app/assets/stylesheets/activeadmin/quill.imageUploader.min.css поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,33 @@
.image-uploading {
position: relative;
display: inline-block;
}
.image-uploading img {
max-width: 98% !important;
filter: blur(5px);
opacity: 0.3;
}
.image-uploading::before {
content: "";
box-sizing: border-box;
position: absolute;
top: 50%;
left: 50%;
width: 30px;
height: 30px;
margin-top: -15px;
margin-left: -15px;
border-radius: 50%;
border: 3px solid #ccc;
border-top-color: #1e986c;
z-index: 1;
animation: spinner 0.6s linear infinite;
}
@keyframes spinner {
to {
transform: rotate(360deg);
}
}

Просмотреть файл

@@ -0,0 +1,73 @@
# frozen_string_literal: true
ActiveAdmin.register Post do
permit_params :author_id,
:title,
:description,
:category,
:dt,
:position,
:published,
tag_ids: []
member_action :upload, method: [:post] do
result = { success: resource.images.attach(params[:file_upload]) }
result[:url] = url_for(resource.images.last) if result[:success]
render json: result
end
index do
selectable_column
id_column
column :title
column :author
column :published
column :created_at
actions
end
show do
attributes_table do
row :author
row :title
row :description
row :category
row :dt
row :position
row :published
row :tags
row :created_at
row :updated_at
row :images do |resurce|
resurce.images.each do |image|
div do
link_to image.filename, image, target: '_blank'
end
end
nil
end
end
active_admin_comments
end
form do |f|
f.inputs 'Post' do
f.input :author
f.input :title
unless object.new_record?
plugin_opts = { image_uploader: { server_url: upload_admin_post_path(object.id), field_name: 'file_upload' } }
f.input :description, as: :quill_editor, input_html: { data: { plugins: plugin_opts } }
end
f.input :category
f.input :dt
f.input :position
f.input :published
end
f.inputs 'Tags' do
f.input :tags
end
f.actions
end
end

Просмотреть файл

@@ -0,0 +1,6 @@
//= require active_admin/base
//= require activeadmin/quill_editor/quill
//= require activeadmin/quill_editor_input
//= require activeadmin/quill.imageUploader.min

Просмотреть файл

@@ -0,0 +1,7 @@
@import 'active_admin/mixins';
@import 'active_admin/base';
@import 'activeadmin/quill_editor/quill.snow';
@import 'activeadmin/quill_editor_input';
@import 'activeadmin/quill.imageUploader.min';

Просмотреть файл

@@ -0,0 +1,7 @@
# frozen_string_literal: true
class Post < ApplicationRecord
has_many_attached :images
validates :title, allow_blank: false, presence: true
end

Просмотреть файл

@@ -2,6 +2,6 @@
module ActiveAdmin
module QuillEditor
VERSION = '0.2.9'
VERSION = '0.2.10'
end
end