activeadmin-dropzone 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,16 @@
1
+ class DropzoneController < ApplicationController
2
+
3
+ def upload
4
+ dropzone_class = params[:dropzone_class].constantize
5
+ dropzone_object = dropzone_class.new
6
+ dropzone_object.send "#{ dropzone_class.dropzone_field(:type) }=", params[:dropzonable_class] if dropzone_class.dropzone_field?(:type)
7
+ dropzone_object.send "#{ dropzone_class.dropzone_field(:data) }=", params[:file]
8
+
9
+ if dropzone_object.save
10
+ render json: dropzone_object.to_json
11
+ else
12
+ head :error and return
13
+ end
14
+ end
15
+
16
+ end
@@ -0,0 +1,18 @@
1
+ module ActiveAdmin::ViewsHelper
2
+
3
+ def render_mock_dropzone_files(dropzone_objects)
4
+ dropzone_objects.map do |dropzone_object|
5
+ {
6
+ id: dropzone_object.id,
7
+ name: dropzone_object.send(dropzone_object.class.dropzone_field(:title)),
8
+ size: dropzone_object.send(dropzone_object.class.dropzone_field(:file_size)),
9
+ url: dropzone_object.send(dropzone_object.class.dropzone_field(:url))
10
+ }
11
+ end.map do |hash|
12
+ hash.map{ |(k, v)| "#{ k }: '#{ v }'" }.join(',')
13
+ end.map do |string|
14
+ "{#{ string }}"
15
+ end.join(', ').html_safe
16
+ end
17
+
18
+ end
@@ -0,0 +1,8 @@
1
+ class DropzoneInput
2
+ include Formtastic::Inputs::Base
3
+
4
+ def to_html
5
+ template.render 'dropzone', object: object, options: options, method: method
6
+ end
7
+
8
+ end
@@ -0,0 +1,91 @@
1
+ <div id="dropzone_<%= method %>_<%= cycle(*(1..999).to_a, name: method) %>" class="dropzone">
2
+ <span class="notice"><%=t 'dropzone.drag_or_click' %></span>
3
+ <%= hidden_field_tag "#{ object.class.model_name.singular }[#{ method }_attributes][-1]", "" %>
4
+ <% object.send(method).each_with_index do |dropzone_object, index| %>
5
+ <%= 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)) %>
6
+ <% end %>
7
+ </div>
8
+
9
+ <% unless options[:hint].blank? %>
10
+ <p class="inline-hints dropzone-hint"><%= options[:hint] %></p>
11
+ <% end %>
12
+
13
+ <script>
14
+ (function() {
15
+ Dropzone.autoDiscover = false;
16
+
17
+ var mockFiles = [<%= render_mock_dropzone_files(object.send(method)) %>];
18
+ var dropzone_id = "#dropzone_<%= method %>_<%= current_cycle(method) %>";
19
+ var dropzone = new Dropzone(dropzone_id, {
20
+ url: '<%= upload_dropzone_path(dropzonable_class: object.class, dropzone_class: object.class.send("dropzone_#{ method }_class")) %>',
21
+ addRemoveLinks: true,
22
+ dictCancelUpload: '<%=t "dropzone.cancel" %>',
23
+ dictRemoveFile: '<%=t "dropzone.remove" %>',
24
+ maxFiles: <%= defined?(max_files) ? '1' : 'null' %>,
25
+ sending: function(file, xhr, formData) {
26
+ xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').prop('content'));
27
+ },
28
+ success: function(file, data) {
29
+ $(dropzone_id).append('<input type="hidden" name="<%= object.class.model_name.singular %>[<%= method %>_attributes][' + data.id + '][<%= object.class.send("dropzone_#{ method }_field", :title) %>]" value="" />');
30
+ $(file.previewElement).attr('data-id', data.id);
31
+ $(file.previewElement).attr('data-url', data.url);
32
+ return file.previewElement.classList.add("dz-success");
33
+ },
34
+ removedfile: function(file) {
35
+ $(dropzone_id + ' input[name="<%= object.class.model_name.singular %>[images_attributes][' + file.id + '][<%= object.class.send("dropzone_#{ method }_field", :title) %>]"]').remove();
36
+ $(dropzone_id + ' input[name="<%= object.class.model_name.singular %>[images_attributes][' + file.id + '][<%= object.class.send("dropzone_#{ method }_field", :position) %>]"]').remove();
37
+ $(file.previewElement).remove();
38
+ $(dropzone_id).sortable('refresh');
39
+ }
40
+ });
41
+
42
+ $(dropzone_id).sortable({
43
+ items: '.dz-preview',
44
+ placeholder: 'sortable-placeholder'
45
+ });
46
+
47
+ var func = function(file) {
48
+ if (file.id)
49
+ $(file.previewElement).attr('data-id', file.id);
50
+
51
+ $(file.previewElement).find('.dz-filename, img').on('click', function() {
52
+ var id = $(this).parents('.dz-preview:first').attr('data-id');
53
+ var input = $(dropzone_id + ' input[name="<%= object.class.model_name.singular %>[<%= method %>_attributes][' + id + '][<%= object.class.send("dropzone_#{ method }_field", :title) %>]"]');
54
+ var title = prompt("<%=t 'dropzone.title' %>: ", $(file.previewElement).find('.dz-filename span').text());
55
+ $(file.previewElement).find('.dz-filename span').text(title);
56
+ input.val(title);
57
+ });
58
+ };
59
+
60
+ var generate_dropzone_position_elements = function() {
61
+ var position = 0;
62
+ $(dropzone_id + ' .dz-preview').each(function() {
63
+ var id = $(this).attr('data-id');
64
+ $(dropzone_id).append('<input type="hidden" name="<%= object.class.model_name.singular %>[<%= method %>_attributes][' + id + '][<%= object.class.send("dropzone_#{ method }_field", :position) %>]" value="' + (position++) + '" />');
65
+ });
66
+ };
67
+
68
+ dropzone.on('addedfile', func);
69
+
70
+ for (var i = 0; i < mockFiles.length; i++) {
71
+ var mockFile = mockFiles[i];
72
+ dropzone.options.addedfile.call(dropzone, mockFile);
73
+ func(mockFile);
74
+ if (mockFile.url)
75
+ dropzone.options.thumbnail.call(dropzone, mockFile, mockFile.url);
76
+ $(mockFile.previewElement).attr('data-url', mockFile.url);
77
+ }
78
+
79
+ $('form').submit(function(e) {
80
+ if (dropzone.getQueuedFiles().length > 0 || dropzone.getUploadingFiles().length > 0) {
81
+ if (confirm("<%=t 'dropzone.are_you_sure' %>") == true) {
82
+ generate_dropzone_position_elements();
83
+ } else {
84
+ e.preventDefault();
85
+ }
86
+ } else {
87
+ generate_dropzone_position_elements();
88
+ }
89
+ });
90
+ })();
91
+ </script>
@@ -0,0 +1,7 @@
1
+ en:
2
+ dropzone:
3
+ drag_or_click: 'Drag files here or click to upload'
4
+ cancel: 'Cancel'
5
+ remove: 'Remove'
6
+ title: 'Title'
7
+ are_you_sure: 'Several images have not been uploaded to the server yet. Are you sure to submit form without these images?'
@@ -0,0 +1,7 @@
1
+ ru:
2
+ dropzone:
3
+ drag_or_click: 'Перетащите сюда файлы или нажмите для загрузки'
4
+ cancel: 'Отменить'
5
+ remove: 'Удалить'
6
+ title: 'Название'
7
+ are_you_sure: 'Некоторые файлы еще не загрузились на сервер. Вы действительно хотите сохранить без них?'
data/config/routes.rb ADDED
@@ -0,0 +1,8 @@
1
+ # temporary fix double route error
2
+ unless defined?(Rails.application.routes.url_helpers.upload_dropzone_path)
3
+ Rails.application.routes.draw do
4
+
5
+ post '/dropzone/upload' => 'dropzone#upload', as: :upload_dropzone
6
+
7
+ end
8
+ end
data/lib/.DS_Store ADDED
Binary file
@@ -0,0 +1,2 @@
1
+ require "activeadmin-dropzone/engine"
2
+ require "activeadmin-dropzone/active_record/dropzone"
@@ -0,0 +1,82 @@
1
+ module Activeadmin
2
+ module Dropzone
3
+ extend ActiveSupport::Concern
4
+
5
+ module ClassMethods
6
+ def dropzone(association_name)
7
+ class_eval %Q(
8
+ def self.dropzone_#{ association_name }_class
9
+ self.reflect_on_association(:#{ association_name }).class_name.constantize
10
+ end
11
+
12
+ def #{ association_name }_attributes=(attributes)
13
+ original_collection = self.#{ association_name }.to_a
14
+
15
+ ActiveRecord::Base.transaction do
16
+ 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 })
17
+
18
+ self.#{ association_name }.each do |dropzone_object|
19
+ attribute = attributes[dropzone_object.id.to_s]
20
+ changes = {}
21
+
22
+ title_field = self.class.dropzone_#{ association_name }_class.dropzone_field(:title)
23
+ if dropzone_object.respond_to?(title_field) and dropzone_object.send(title_field) != attribute['title']
24
+ changes[title_field] = attribute['title']
25
+ end
26
+
27
+ position_field = self.class.dropzone_#{ association_name }_class.dropzone_field(:position)
28
+ if dropzone_object.respond_to?(position_field) and dropzone_object.send(position_field) != attribute['position'].to_i
29
+ changes[position_field] = attribute['position']
30
+ end
31
+
32
+ unless changes.empty?
33
+ dropzone_object.update_attributes changes
34
+ end
35
+ end
36
+
37
+ self.update_attribute :#{ association_name }_count, self.#{ association_name }.size if self.respond_to?(:#{ association_name }_count)
38
+
39
+ (original_collection - self.#{ association_name }).each do |object|
40
+ object.destroy
41
+ end
42
+ end
43
+ end
44
+
45
+ def self.dropzone_#{ association_name }_field(key)
46
+ dropzone_#{ association_name }_class.dropzone_field(key)
47
+ end
48
+
49
+ def self.dropzone_#{ association_name }_field?(key)
50
+ dropzone_#{ association_name }_class.dropzone_field?(key)
51
+ end
52
+ )
53
+ end
54
+
55
+ def dropzone_item(options = {})
56
+ options = {
57
+ title: :title,
58
+ position: :position,
59
+ data: :data,
60
+ file_size: :data_file_size,
61
+ url: :data_url
62
+ }.deep_merge(options)
63
+
64
+ class_eval %Q(
65
+ def self.dropzone_field(key)
66
+ #{ options }[key.to_sym]
67
+ end
68
+
69
+ def self.dropzone_field?(key)
70
+ #{ options }.keys.include? key.to_sym
71
+ end
72
+
73
+ def #{ options[:data] }_url
74
+ #{ options[:data] }.url
75
+ end
76
+ )
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ ActiveRecord::Base.send :include, Activeadmin::Dropzone
@@ -0,0 +1,6 @@
1
+ module Activeadmin
2
+ module Dropzone
3
+ class Engine < ::Rails::Engine
4
+ end
5
+ end
6
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+ require 'shoulda'
12
+
13
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
15
+ require 'activeadmin-dropzone'
16
+
17
+ class Test::Unit::TestCase
18
+ end
@@ -0,0 +1,7 @@
1
+ require 'helper'
2
+
3
+ class TestActiveadminDropzone < Test::Unit::TestCase
4
+ should "probably rename this file and start testing for real" do
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: activeadmin-dropzone
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Maxim Gladkov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-02-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: jeweler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: simplecov-rcov
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description:
42
+ email: contact@maximgladkov.com
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files:
46
+ - LICENSE.txt
47
+ - README.md
48
+ files:
49
+ - .DS_Store
50
+ - .document
51
+ - Gemfile
52
+ - Gemfile.lock
53
+ - LICENSE.txt
54
+ - README.md
55
+ - Rakefile
56
+ - VERSION
57
+ - activeadmin-dropzone.gemspec
58
+ - app/.DS_Store
59
+ - app/assets/.DS_Store
60
+ - app/assets/images/.DS_Store
61
+ - app/assets/javascripts/activeadmin-dropzone.js
62
+ - app/assets/javascripts/dropzone.js
63
+ - app/assets/stylesheets/activeadmin-dropzone.css.scss
64
+ - app/assets/stylesheets/dropzone.css
65
+ - app/controllers/dropzone_controller.rb
66
+ - app/helpers/active_admin/views_helper.rb
67
+ - app/inputs/dropzone_input.rb
68
+ - app/views/application/_dropzone.html.erb
69
+ - config/locales/en.yml
70
+ - config/locales/ru.yml
71
+ - config/routes.rb
72
+ - lib/.DS_Store
73
+ - lib/activeadmin-dropzone.rb
74
+ - lib/activeadmin-dropzone/active_record/dropzone.rb
75
+ - lib/activeadmin-dropzone/engine.rb
76
+ - test/helper.rb
77
+ - test/test_activeadmin-dropzone.rb
78
+ homepage: http://maximgladkov.com/blog/activeadmin-dropzone-gem
79
+ licenses:
80
+ - MIT
81
+ metadata: {}
82
+ post_install_message:
83
+ rdoc_options: []
84
+ require_paths:
85
+ - lib
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - '>='
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ requirements: []
97
+ rubyforge_project:
98
+ rubygems_version: 2.0.3
99
+ signing_key:
100
+ specification_version: 4
101
+ summary: Easy to use integration of drag&drop files upload via dropzone.js for ActiveAdmin
102
+ test_files: []