active_admin_multi_upload 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +56 -0
  4. data/Rakefile +32 -0
  5. data/app/assets/stylesheets/active_admin_multi_upload/jquery_upload.scss +1105 -0
  6. data/app/models/concerns/active_admin_multi_upload/uploadable.rb +26 -0
  7. data/app/views/active_admin_multi_upload/_upload_form.html.erb +158 -0
  8. data/config/routes.rb +2 -0
  9. data/lib/active_admin_multi_upload.rb +7 -0
  10. data/lib/active_admin_multi_upload/dsl.rb +49 -0
  11. data/lib/active_admin_multi_upload/engine.rb +5 -0
  12. data/lib/active_admin_multi_upload/version.rb +3 -0
  13. data/lib/generators/active_admin_multi_upload/resource/USAGE +5 -0
  14. data/lib/generators/active_admin_multi_upload/resource/resource_generator.rb +16 -0
  15. data/lib/tasks/active_admin_multi_upload_tasks.rake +4 -0
  16. data/test/active_admin_multi_upload_test.rb +7 -0
  17. data/test/dummy/README.rdoc +28 -0
  18. data/test/dummy/Rakefile +6 -0
  19. data/test/dummy/app/assets/javascripts/application.js +13 -0
  20. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  21. data/test/dummy/app/controllers/application_controller.rb +5 -0
  22. data/test/dummy/app/helpers/application_helper.rb +2 -0
  23. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  24. data/test/dummy/bin/bundle +3 -0
  25. data/test/dummy/bin/rails +4 -0
  26. data/test/dummy/bin/rake +4 -0
  27. data/test/dummy/config.ru +4 -0
  28. data/test/dummy/config/application.rb +28 -0
  29. data/test/dummy/config/boot.rb +5 -0
  30. data/test/dummy/config/environment.rb +5 -0
  31. data/test/dummy/config/environments/development.rb +27 -0
  32. data/test/dummy/config/environments/production.rb +80 -0
  33. data/test/dummy/config/environments/test.rb +36 -0
  34. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  35. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  36. data/test/dummy/config/initializers/inflections.rb +16 -0
  37. data/test/dummy/config/initializers/mime_types.rb +5 -0
  38. data/test/dummy/config/initializers/secret_token.rb +12 -0
  39. data/test/dummy/config/initializers/session_store.rb +3 -0
  40. data/test/dummy/config/initializers/wrap_parameters.rb +9 -0
  41. data/test/dummy/config/locales/en.yml +23 -0
  42. data/test/dummy/config/routes.rb +56 -0
  43. data/test/dummy/public/404.html +58 -0
  44. data/test/dummy/public/422.html +58 -0
  45. data/test/dummy/public/500.html +57 -0
  46. data/test/dummy/public/favicon.ico +0 -0
  47. data/test/integration/navigation_test.rb +9 -0
  48. data/test/test_helper.rb +15 -0
  49. metadata +151 -0
@@ -0,0 +1,26 @@
1
+ module ActiveAdminMultiUpload::Uploadable
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ include Rails.application.routes.url_helpers
6
+ end
7
+
8
+ module ClassMethods
9
+ def allows_upload(name)
10
+ code = <<-eoruby
11
+ def to_jq_upload
12
+ {
13
+ "name" => read_attribute(#{name}),
14
+ "size" => image.size,
15
+ "url" => image.url,
16
+ "thumbnail_url" => image.thumb.url,
17
+ "delete_url" => destroy_upload_admin_#{self.name.downcase}_url(self, only_path: true),
18
+ "id" => id,
19
+ "delete_type" => "DELETE"
20
+ }
21
+ end
22
+ eoruby
23
+ class_eval(code)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,158 @@
1
+ <%= stylesheet_link_tag "active_admin_multi_upload/jquery_upload" %>
2
+
3
+
4
+ <% options = options ||= {}
5
+ uploaded_ids_form_input_name = options[:uploaded_ids_form_input_name] ||= "#{resource.class.name.downcase}[#{association.singularize}_ids][]"
6
+ existing_uploads = options[:existing_uploads] ||= resource.send(association.to_sym)
7
+ input_id_prefix = options[:input_id_prefix] ||= "#{resource.class.name.downcase}_#{association.singularize}_ids_"
8
+ post_url = options[:post_url] ||= "/admin/#{association}/create_upload"
9
+ input_name = options[:input_name] ||= "#{association.singularize}[#{attribute}]"
10
+
11
+ %>
12
+
13
+ <div id="uploader">
14
+ <!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload -->
15
+ <div class="row fileupload-buttonbar">
16
+ <div class="span7">
17
+ <!-- The fileinput-button span is used to style the file input field as button -->
18
+ <span class="btn btn-success fileinput-button">
19
+ <i class="icon-plus icon-white"></i>
20
+ <span>Add files...</span>
21
+ <input id="fileupload" type="file" name="<%= input_name %>" multiple>
22
+ </span>
23
+ <button type="reset" class="btn btn-warning cancel">
24
+ <i class="icon-ban-circle icon-white"></i>
25
+ <span>Cancel upload</span>
26
+ </button>
27
+ <button type="button" class="btn btn-danger delete">
28
+ <i class="icon-trash icon-white"></i>
29
+ <span>Delete</span>
30
+ </button>
31
+ <input type="checkbox" class="toggle">
32
+ </div>
33
+ </div>
34
+ <!-- The loading indicator is shown during image processing -->
35
+ <div class="fileupload-process"></div>
36
+ <br>
37
+ <!-- The table listing the files available for upload/download -->
38
+ <table class="table table-striped"><tbody class="files" id="files-container" data-toggle="modal-gallery" data-target="#modal-gallery"></tbody></table>
39
+ </div>
40
+
41
+
42
+ <script>
43
+ var fileUploadErrors = {
44
+ maxFileSize: 'File is too big',
45
+ minFileSize: 'File is too small',
46
+ acceptFileTypes: 'Filetype not allowed',
47
+ maxNumberOfFiles: 'Max number of files exceeded',
48
+ uploadedBytes: 'Uploaded bytes exceed file size',
49
+ emptyResult: 'Empty file upload result'
50
+ };
51
+ </script>
52
+
53
+ <!-- The template to display files available for upload -->
54
+ <script id="template-upload" type="text/x-tmpl">
55
+ {% for (var i=0, file; file=o.files[i]; i++) { %}
56
+ <tr class="template-upload fade">
57
+ <td class="preview"><span class="fade"></span></td>
58
+ <td class="name"><span>{%=file.name%}</span></td>
59
+ <td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td>
60
+ {% if (file.error) { %}
61
+ <td class="error" colspan="2"><span class="label label-important">{%=locale.fileupload.error%}</span> {%=locale.fileupload.errors[file.error] || file.error%}</td>
62
+ {% } else if (o.files.valid && !i) { %}
63
+ <td>
64
+ <div class="progress progress-striped active" role="progressbar" ><div class="progress-bar bar progress-bar-success" style="width:0%;"></div></div>
65
+ </td>
66
+ <td class="start">{% if (!o.options.autoUpload) { %}
67
+ <button class="btn btn-primary">
68
+ <i class="icon-upload icon-white"></i>
69
+ <span>{%=locale.fileupload.start%}</span>
70
+ </button>
71
+ {% } %}</td>
72
+ {% } else { %}
73
+ <td colspan="2"></td>
74
+ {% } %}
75
+ <td class="cancel">{% if (!i) { %}
76
+ <button class="btn btn-warning">
77
+ <i class="icon-ban-circle icon-white"></i>
78
+ <span>{%=locale.fileupload.cancel%}</span>
79
+ </button>
80
+ {% } %}</td>
81
+ </tr>
82
+ {% } %}
83
+ </script>
84
+
85
+ <!-- The template to display files available for download -->
86
+ <script id="template-download" type="text/x-tmpl">
87
+ {% for (var i=0, file; file=o.files[i]; i++) { %}
88
+ <tr class="template-download fade">
89
+ {% if (file.error) { %}
90
+ <td></td>
91
+ <td class="name"><span>{%=file.name%}</span></td>
92
+ <td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td>
93
+ <td class="error" colspan="2"><span class="label label-important">{%=locale.fileupload.error%}</span> {%=locale.fileupload.errors[file.error] || file.error%}</td>
94
+ {% } else { %}
95
+ <td class="preview">{% if (file.thumbnail_url) { %}
96
+ <a href="{%=file.url%}" title="{%=file.name%}" rel="gallery" download="{%=file.name%}"><img src="{%=file.thumbnail_url%}"></a>
97
+ {% } %}</td>
98
+ <td class="name" id="upload_{%=file.id%}">
99
+ <a href="{%=file.url%}" title="{%=file.name%}" rel="{%=file.thumbnail_url&&'gallery'%}" download="{%=file.name%}">{%=file.name%}</a>
100
+ </td>
101
+ <td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td>
102
+ <td colspan="2"></td>
103
+ {% } %}
104
+ <td class="delete">
105
+ <button class="btn btn-danger" data-type="{%=file.delete_type%}" data-url="{%=file.delete_url%}">
106
+ <i class="icon-trash icon-white"></i>
107
+ <span>{%=locale.fileupload.destroy%}</span>
108
+ </button>
109
+ <input type="checkbox" name="delete" value="1">
110
+ </td>
111
+ </tr>
112
+ {% } %}
113
+ </script>
114
+
115
+
116
+ <script type="text/javascript" charset="utf-8">
117
+ $(function () {
118
+ // Initialize the jQuery File Upload widget:
119
+ $('#uploader').fileupload({
120
+ url: "<%= post_url %>",
121
+ autoUpload: true,
122
+ formData: {},
123
+ sequentialUploads: true,
124
+ fileInput: $("#fileupload"),
125
+ filesContainer: "#files-container"
126
+ }).on('fileuploadcompleted', function(e, data) {
127
+ insertUploadInputs(data.result.files);
128
+ }).bind('fileuploaddestroy', function(e, data) {
129
+ removeUploadInputs([data]);
130
+ });
131
+ });
132
+ </script>
133
+
134
+
135
+ <script type="text/javascript">
136
+ var insertUploadInputs = function(files) {
137
+ $.each(files, function(index, file) {
138
+ var input = $("<input type='hidden' class='file-upload' name='<%= uploaded_ids_form_input_name %>' id='<%= input_id_prefix %>" + file.id + "' value='" + file.id + "' />");
139
+ input.insertAfter($("#upload_" + file.id));
140
+ });
141
+ };
142
+
143
+ var removeUploadInputs = function(files) {
144
+ $.each(files, function(index, file) {
145
+ var id = file.url.split("/").pop();
146
+ $("#<%= input_id_prefix %>" + id).remove();
147
+ });
148
+ };
149
+
150
+ $(function () {
151
+ var files = <%= existing_uploads.map(&:to_jq_upload).to_json.html_safe %>;
152
+ var uploader = $("#uploader").data("blueimpFileupload");
153
+ var template = uploader._renderDownload(files)['appendTo'](uploader.options.filesContainer);
154
+ uploader._transition(template);
155
+ insertUploadInputs(files);
156
+ });
157
+
158
+ </script>
data/config/routes.rb ADDED
@@ -0,0 +1,2 @@
1
+ Rails.application.routes.draw do
2
+ end
@@ -0,0 +1,7 @@
1
+ require "active_admin_multi_upload/engine"
2
+ require "active_admin_multi_upload/dsl"
3
+
4
+ module ActiveAdminMultiUpload
5
+ end
6
+
7
+ ::ActiveAdmin::DSL.send(:include, ActiveAdminMultiUpload::DSL)
@@ -0,0 +1,49 @@
1
+ module ActiveAdminMultiUpload
2
+ module DSL
3
+
4
+ def allows_multi_upload(options={})
5
+
6
+ config.resource_class.send(:include, ::ActiveAdminMultiUpload::Uploadable)
7
+ uploader = options[:mounted_uploader] ||= :image
8
+ config.resource_class.send(:allows_upload, uploader)
9
+
10
+ collection_action :create_upload, method: :post do
11
+ @upload_model = options[:model] ||= active_admin_config.resource_class
12
+ @model = @upload_model.new(upload_resource_params)
13
+ if @model.save
14
+ respond_to do |format|
15
+ format.html {
16
+ render :json => [@model.to_jq_upload].to_json,
17
+ :content_type => 'text/html',
18
+ :layout => false
19
+ }
20
+ format.json {
21
+ render :json => { files: [@model.to_jq_upload] }, status: :created
22
+ }
23
+ end
24
+ else
25
+ render :json => [{:error => "custom_failure"}], :status => 304
26
+ end
27
+ end
28
+
29
+ member_action :destroy_upload, method: :delete do
30
+ @upload_model = options[:model] ||= active_admin_config.resource_class
31
+ @model = @upload_model.find(params[:id])
32
+ @model.destroy
33
+ render :json => true
34
+ end
35
+
36
+ controller do
37
+ # Rails 4 Strong Parameters compatibility and backwards compatibility.
38
+ def upload_resource_params
39
+ # I don't think this will work any more.
40
+ if respond_to?(:permitted_params)
41
+ permitted_params[active_admin_config.resource_class.name.underscore]
42
+ else
43
+ params[active_admin_config.resource_class.name.underscore]
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,5 @@
1
+ module ActiveAdminMultiUpload
2
+ class Engine < ::Rails::Engine
3
+ require 'jquery-fileupload-rails'
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ module ActiveAdminMultiUpload
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,5 @@
1
+ Description:
2
+ Adds the ability to upload multiple files to a Model that has a Carrierwave uploader mounted to it within Active Admin
3
+
4
+ Example:
5
+ rails g active_admin_multi_upload:resource YourModel
@@ -0,0 +1,16 @@
1
+ module ActiveAdminMultiUpload
2
+ class ResourceGenerator < Rails::Generators::NamedBase
3
+ source_root File.expand_path('../templates', __FILE__)
4
+
5
+ def add_js_assets
6
+ append_file "app/assets/javascripts/active_admin.js.coffee", "#= require jquery-fileupload\n"
7
+ append_file "app/assets/javascripts/active_admin.js.coffee", "#= require jquery-fileupload/vendor/tmpl\n"
8
+ end
9
+
10
+ def add_css_assets
11
+ append_file "app/assets/stylesheets/active_admin.css.scss", '@import "jquery.fileupload-ui";'
12
+ end
13
+
14
+ private
15
+ end
16
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :active_admin_multi_upload do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,7 @@
1
+ require 'test_helper'
2
+
3
+ class ActiveAdminMultiUploadTest < ActiveSupport::TestCase
4
+ test "truth" do
5
+ assert_kind_of Module, ActiveAdminMultiUpload
6
+ end
7
+ end
@@ -0,0 +1,28 @@
1
+ == README
2
+
3
+ This README would normally document whatever steps are necessary to get the
4
+ application up and running.
5
+
6
+ Things you may want to cover:
7
+
8
+ * Ruby version
9
+
10
+ * System dependencies
11
+
12
+ * Configuration
13
+
14
+ * Database creation
15
+
16
+ * Database initialization
17
+
18
+ * How to run the test suite
19
+
20
+ * Services (job queues, cache servers, search engines, etc.)
21
+
22
+ * Deployment instructions
23
+
24
+ * ...
25
+
26
+
27
+ Please feel free to use a different markup language if you do not plan to run
28
+ <tt>rake doc:app</tt>.
@@ -0,0 +1,6 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require File.expand_path('../config/application', __FILE__)
5
+
6
+ Dummy::Application.load_tasks
@@ -0,0 +1,13 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file.
9
+ //
10
+ // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require_tree .
@@ -0,0 +1,13 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
9
+ * compiled file, but it's generally better to create a new file per style scope.
10
+ *
11
+ *= require_self
12
+ *= require_tree .
13
+ */
@@ -0,0 +1,5 @@
1
+ class ApplicationController < ActionController::Base
2
+ # Prevent CSRF attacks by raising an exception.
3
+ # For APIs, you may want to use :null_session instead.
4
+ protect_from_forgery with: :exception
5
+ end
@@ -0,0 +1,2 @@
1
+ module ApplicationHelper
2
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Dummy</title>
5
+ <%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
6
+ <%= javascript_include_tag "application", "data-turbolinks-track" => true %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
3
+ load Gem.bin_path('bundler', 'bundle')
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
3
+ require_relative '../config/boot'
4
+ require 'rails/commands'
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require_relative '../config/boot'
3
+ require 'rake'
4
+ Rake.application.run
@@ -0,0 +1,4 @@
1
+ # This file is used by Rack-based servers to start the application.
2
+
3
+ require ::File.expand_path('../config/environment', __FILE__)
4
+ run Rails.application
@@ -0,0 +1,28 @@
1
+ require File.expand_path('../boot', __FILE__)
2
+
3
+ # Pick the frameworks you want:
4
+ # require "active_record/railtie"
5
+ require "action_controller/railtie"
6
+ require "action_mailer/railtie"
7
+ require "sprockets/railtie"
8
+ require "rails/test_unit/railtie"
9
+
10
+ Bundler.require(*Rails.groups)
11
+ require "active_admin_multi_upload"
12
+
13
+ module Dummy
14
+ class Application < Rails::Application
15
+ # Settings in config/environments/* take precedence over those specified here.
16
+ # Application configuration should go into files in config/initializers
17
+ # -- all .rb files in that directory are automatically loaded.
18
+
19
+ # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
20
+ # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
21
+ # config.time_zone = 'Central Time (US & Canada)'
22
+
23
+ # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
24
+ # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
25
+ # config.i18n.default_locale = :de
26
+ end
27
+ end
28
+