Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 25 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

Easy to use integration of drag&drop files upload via [dropzone.js](http://www.dropzonejs.com) for [ActiveAdmin](http://www.activeadmin.info).

## History

* 28.09.2015 - change model association: delete self-writed association, add `accepts_nested_attributes_for`.

## Requirements

* [ActiveAdmin](http://www.activeadmin.info);
Expand All @@ -13,20 +17,32 @@ Easy to use integration of drag&drop files upload via [dropzone.js](http://www.d

Add line to your Gemfile:

gem 'activeadmin-dropzone', '~> 0.2.1'
gem 'activeadmin-dropzone', github: 'farpostdesign/activeadmin-dropzone'

Add `dropzone` to your file container's class:
Add `dropzone_item` to your file's class:

class Post
dropzone :images
class Image
dropzone_item container_id: :page_id
end

Add `dropzone_item` to your file's class:
Add method `title` in the model if there is no such attribute:

class Image
dropzone_item
has_attached_file :file

def title
file_file_name
end
end

Add permitions to `permit_params` method for your Active Admin file, for example:

permit_params :title,
:annotation,
:description,
...,
images_attributes: [:id, :title, :position, :_destroy] # for model Image

Add `input` to your ActiveAdmin form:

f.input :images, as: :dropzone
Expand All @@ -43,7 +59,9 @@ You can customize columns used for upload by passing `Hash` to the `dropzone_ite
position: :position,
data: :data,
file_size: :data_file_size,
url: :data_url
url: :data_url,
container_type: :page_type, # only for polymorphic associations!
container_id: :page_id, # required!

## Contributing to activeadmin-dropzone

Expand Down
5 changes: 3 additions & 2 deletions app/helpers/active_admin/view_helpers/dropzone_helper.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
module ActiveAdmin::ViewHelpers::DropzoneHelper

def render_mock_dropzone_files(dropzone_objects)
dropzone_objects.map do |dropzone_object|
dropzone_objects.map.with_index do |dropzone_object, index|
{
id: dropzone_object.id,
name: dropzone_object.send(dropzone_object.class.dropzone_field(:title)).squish,
size: dropzone_object.send(dropzone_object.class.dropzone_field(:file_size)),
url: dropzone_object.send(dropzone_object.class.dropzone_field(:url))
url: dropzone_object.send(dropzone_object.class.dropzone_field(:url)),
index: index,
}
end.to_json.html_safe
end
Expand Down
24 changes: 13 additions & 11 deletions app/views/application/_dropzone.html.erb
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
<div id="dropzone_<%= method %>_<%= cycle(*(1..999).to_a, name: method) %>" class="dropzone">
<span class="notice"><%=t 'dropzone.drag_or_click' %></span>
<%= hidden_field_tag "#{ object.class.model_name.singular }[#{ method }_attributes][-1]", "" %>
<% object.send(method).each_with_index do |dropzone_object, index| %>
<%= hidden_field_tag "#{ object.class.model_name.singular }[#{ method }_attributes][#{ dropzone_object.id }][#{ object.class.send("dropzone_#{ method }_field", :title) }]", dropzone_object.send(object.class.send("dropzone_#{ method }_field", :title)) %>
<%= hidden_field_tag "#{ object.class.model_name.singular }[#{ method }_attributes][#{ index }][id]", dropzone_object.id %>
<% end %>
</div>

Expand All @@ -15,9 +14,10 @@
Dropzone.autoDiscover = false;

var mockFiles = <%= render_mock_dropzone_files(object.send(method)) %>;
var mockFilesCount = mockFiles.length;
var dropzone_id = "#dropzone_<%= method %>_<%= current_cycle(method) %>";
var dropzone = new Dropzone(dropzone_id, {
url: '<%= raw upload_dropzone_path(dropzonable_id: (object.new_record? ? nil : object.id), dropzonable_class: object.class, dropzone_class: object.class.send("dropzone_#{ method }_class")) %>',
url: '<%= raw upload_dropzone_path(dropzonable_id: (object.new_record? ? nil : object.id), dropzonable_class: object.class, dropzone_class: object.send(method).klass.to_s) %>',
addRemoveLinks: true,
dictCancelUpload: '<%=t "dropzone.cancel" %>',
dictRemoveFile: '<%=t "dropzone.remove" %>',
Expand All @@ -26,15 +26,15 @@
xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').prop('content'));
},
success: function(file, data) {
$(dropzone_id).append('<input type="hidden" name="<%= object.class.model_name.singular %>[<%= method %>_attributes][' + data.id + '][<%= object.class.send("dropzone_#{ method }_field", :title) %>]" value="' + data.title + '" />');
$(dropzone_id).append('<input type="hidden" name="<%= object.class.model_name.singular %>[<%= method %>_attributes][' + mockFilesCount + '][id]" value="' + data.id + '" />');
$(file.previewElement).attr('data-id', data.id);
$(file.previewElement).attr('data-url', data.url);
$(file.previewElement).attr('data-index', mockFilesCount++);
$(file.previewElement).find('.dz-filename span').text(data.title);
return file.previewElement.classList.add("dz-success");
},
removedfile: function(file) {
$(dropzone_id + ' input[name="<%= object.class.model_name.singular %>[<%= method %>_attributes][' + file.id + '][<%= object.class.send("dropzone_#{ method }_field", :title) %>]"]').remove();
$(dropzone_id + ' input[name="<%= object.class.model_name.singular %>[<%= method %>_attributes][' + file.id + '][<%= object.class.send("dropzone_#{ method }_field", :position) %>]"]').remove();
$(dropzone_id).append('<input type="hidden" name="<%= object.class.model_name.singular %>[<%= method %>_attributes][' + file.index + '][_destroy]" value="1" />');
$(file.previewElement).remove();
$(dropzone_id).sortable('refresh');
}
Expand All @@ -46,12 +46,14 @@
});

var func = function(file) {
if (file.id)
if (file.id) {
$(file.previewElement).attr('data-id', file.id);
$(file.previewElement).attr('data-index', file.index);
}

$(file.previewElement).find('.dz-filename, img').on('click', function() {
var id = $(this).parents('.dz-preview:first').attr('data-id');
var input = $(dropzone_id + ' input[name="<%= object.class.model_name.singular %>[<%= method %>_attributes][' + id + '][<%= object.class.send("dropzone_#{ method }_field", :title) %>]"]');
var index = $(this).parents('.dz-preview:first').attr('data-index');
var input = $(dropzone_id + ' input[name="<%= object.class.model_name.singular %>[<%= method %>_attributes][' + index + '][id]"]');
var title = prompt("<%=t 'dropzone.title' %>: ", $(file.previewElement).find('.dz-filename span').text());
$(file.previewElement).find('.dz-filename span').text(title);
input.val(title);
Expand All @@ -61,8 +63,8 @@
var generate_dropzone_position_elements = function() {
var position = 0;
$(dropzone_id + ' .dz-preview').each(function() {
var id = $(this).attr('data-id');
$(dropzone_id).append('<input type="hidden" name="<%= object.class.model_name.singular %>[<%= method %>_attributes][' + id + '][<%= object.class.send("dropzone_#{ method }_field", :position) %>]" value="' + (position++) + '" />');
var index = $(this).attr('data-index');
$(dropzone_id).append('<input type="hidden" name="<%= object.class.model_name.singular %>[<%= method %>_attributes][' + index + '][<%= object.send(method).klass.send("dropzone_field", :position) %>]" value="' + (position++) + '" />');
});
};

Expand Down
54 changes: 3 additions & 51 deletions lib/activeadmin-dropzone/active_record/dropzone.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,62 +3,13 @@ module Dropzone
extend ActiveSupport::Concern

module ClassMethods
def dropzone(association_name)
class_eval %Q(
def self.dropzone_#{ association_name }_class
self.reflect_on_association(:#{ association_name }).class_name.constantize
end

def #{ association_name }_attributes=(attributes)
original_collection = self.#{ association_name }.to_a

ActiveRecord::Base.transaction do
self.#{ association_name } = self.class.dropzone_#{ association_name }_class.find(attributes.select{ |id, hash| !id.blank? and id != '-1' }.map{ |id, hash| id.to_i })

self.#{ association_name }.each do |dropzone_object|
attribute = attributes[dropzone_object.id.to_s]
changes = {}

title_field = self.class.dropzone_#{ association_name }_class.dropzone_field(:title)
if dropzone_object.respond_to?(title_field) and dropzone_object.send(title_field) != attribute['title']
changes[title_field] = attribute['title']
end

position_field = self.class.dropzone_#{ association_name }_class.dropzone_field(:position)
if dropzone_object.respond_to?(position_field) and dropzone_object.send(position_field) != attribute['position'].to_i
changes[position_field] = attribute['position']
end

unless changes.empty?
dropzone_object.update_attributes changes
end
end

self.update_attribute :#{ association_name }_count, self.#{ association_name }.count if self.respond_to?(:#{ association_name }_count)

(original_collection - self.#{ association_name }).each do |object|
object.destroy
end
end
end

def self.dropzone_#{ association_name }_field(key)
dropzone_#{ association_name }_class.dropzone_field(key)
end

def self.dropzone_#{ association_name }_field?(key)
dropzone_#{ association_name }_class.dropzone_field?(key)
end
)
end

def dropzone_item(options = {})
options = {
title: :title,
position: :position,
data: :data,
file_size: :data_file_size,
url: :data_url
url: :data_url,
}.deep_merge(options)

class_eval %Q(
Expand All @@ -76,7 +27,8 @@ def data_url

def as_json(options = { })
super(options).merge({
url: data_url
url: data_url,
title: title
})
end
)
Expand Down