refinerycms-imajax 2.0.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +56 -0
- data/app/assets/javascripts/refinery/images.js.coffee.erb +118 -0
- data/app/decorators/controllers/refinery/images_controller_decorator.rb +15 -0
- data/app/views/refinery/admin/images/_form.html.erb +76 -0
- data/config/locales/en.yml +21 -0
- data/config/locales/fr.yml +21 -0
- data/config/routes.rb +5 -0
- data/lib/refinery/imajax.rb +21 -0
- data/lib/refinery/imajax/engine.rb +18 -0
- data/lib/refinerycms-imajax.rb +1 -0
- metadata +78 -0
data/README.md
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# refinerycms-imajax: extension for Refinery CMS.
|
2
|
+
---
|
3
|
+
This is a small and simple extension that replaces the default behavior for image uploading. By default, all images are uploaded on a single form post. That can lead to timeouts on Heroku (to name one) if you upload too many files at once. What refinerycms-imajax does is simply uploading the files one by one. It will only work with modern browsers that supports FileList and FormData (Chrome is one that supports those) but fallbacks to default behavior.
|
4
|
+
|
5
|
+
## Requirements
|
6
|
+
---
|
7
|
+
|
8
|
+
You should have a Rails project with Refinery (>= 2.0.0 but only tested with 2.0.2).
|
9
|
+
|
10
|
+
## Install
|
11
|
+
---
|
12
|
+
Add refinerycms-imajax to your `Gemfile`:
|
13
|
+
|
14
|
+
gem 'refinerycms-imajax', "~> 2.0.0.beta1"
|
15
|
+
|
16
|
+
run
|
17
|
+
|
18
|
+
$ bundle install
|
19
|
+
$ rails s
|
20
|
+
|
21
|
+
It should now work!
|
22
|
+
|
23
|
+
|
24
|
+
## TODO
|
25
|
+
---
|
26
|
+
- Set valid file types based on image model validation (images.js.coffee.erb)
|
27
|
+
- Manage locales and remove hard coded ones
|
28
|
+
- Add a progress bar for each file maybe?
|
29
|
+
- Setup TravisCI to test over multiple Ruby, Rails and Refinery versions
|
30
|
+
- Fix Capybara so that it can test multiple file uploads
|
31
|
+
|
32
|
+
|
33
|
+
## Tests
|
34
|
+
---
|
35
|
+
There is only one request spec actually which is a copy of the refinerycms-images gem. Why? It is not currently possible to test multiple file uploads with Capybara: [https://github.com/jnicklas/capybara/issues/37](https://github.com/jnicklas/capybara/issues/37).
|
36
|
+
|
37
|
+
### Run tests
|
38
|
+
|
39
|
+
1. You need a dummy app first:
|
40
|
+
|
41
|
+
$ bundle exec rake refinery:testing:dummy_app
|
42
|
+
|
43
|
+
2. Run tests:
|
44
|
+
|
45
|
+
$ bundle exec rake
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
### How to build this extension as a gem
|
50
|
+
|
51
|
+
cd [imajax directory]
|
52
|
+
gem build refinerycms-imajax.gemspec
|
53
|
+
gem install refinerycms-imajax.gem
|
54
|
+
|
55
|
+
# Sign up for a http://rubygems.org/ account and publish the gem
|
56
|
+
gem push refinerycms-imajax.gem
|
@@ -0,0 +1,118 @@
|
|
1
|
+
$(document).ready ->
|
2
|
+
images = new Images
|
3
|
+
$("#new_image").submit (e) ->
|
4
|
+
if window.FileList && FormData
|
5
|
+
e.preventDefault()
|
6
|
+
images.upload_all()
|
7
|
+
$("#image_image").change (e) ->
|
8
|
+
images.file_list = e.target.files
|
9
|
+
parent.$(".ui-icon-closethick").click (e) ->
|
10
|
+
e.preventDefault()
|
11
|
+
parent.window.location.href = parent.window.location.href
|
12
|
+
|
13
|
+
|
14
|
+
class Images
|
15
|
+
# TODO:
|
16
|
+
# - add a progress bar for each file maybe?
|
17
|
+
# - refresh images index after closing the dialog box...
|
18
|
+
constructor: ->
|
19
|
+
@authenticity_token = $("meta[name=\"csrf-token\"]").attr("content")
|
20
|
+
@form_action = "/refinery/images/ajax_create"
|
21
|
+
@cache_dom()
|
22
|
+
|
23
|
+
cache_dom: ->
|
24
|
+
@error_list = $("#error_list")
|
25
|
+
@success_list = $("#flash")
|
26
|
+
@error_explanation = $("#errorExplanation")
|
27
|
+
@upload_progress = $("#upload_progress")
|
28
|
+
|
29
|
+
before_upload_all: ->
|
30
|
+
@files = []
|
31
|
+
@errors = []
|
32
|
+
@total_files = @file_list.length
|
33
|
+
@uploaded = 0
|
34
|
+
@error_explanation.hide()
|
35
|
+
|
36
|
+
upload_all: ->
|
37
|
+
@before_upload_all()
|
38
|
+
for file in @file_list
|
39
|
+
@validate(file)
|
40
|
+
@files.push file
|
41
|
+
return @render_errors() if @errors.length > 0
|
42
|
+
$("#submit_button").hide()
|
43
|
+
$(".field").hide()
|
44
|
+
@progress "Uploading..."
|
45
|
+
@upload_next()
|
46
|
+
|
47
|
+
after_upload_all: ->
|
48
|
+
$(".save-loader").hide()
|
49
|
+
@upload_progress.hide()
|
50
|
+
if @errors.length > 0
|
51
|
+
@progress "There was #{@errors.length} error#{(if @errors.length > 1 then "s" else "")}"
|
52
|
+
@render_errors()
|
53
|
+
@success_list.show()
|
54
|
+
|
55
|
+
validate: (file) ->
|
56
|
+
max_file_size = <%= Refinery::Images.max_image_size %>
|
57
|
+
if file.size > max_file_size
|
58
|
+
@errors.push "#{file.name} should be smaller than #{max_file_size} bytes in size"
|
59
|
+
# TODO: set valid file types based on image model validation
|
60
|
+
valid_file_types = ["image/jpeg", "image/png", "image/gif", "image/tiff"]
|
61
|
+
if valid_file_types.indexOf(file.type) == -1
|
62
|
+
@errors.push "#{file.name} should be either a JPG, PNG or GIF"
|
63
|
+
|
64
|
+
upload_next: ->
|
65
|
+
@do_upload(@files[0]) unless @files.length == 0
|
66
|
+
if @total_files > 0 && @files.length == 0
|
67
|
+
@after_upload_all()
|
68
|
+
|
69
|
+
do_upload: (file) =>
|
70
|
+
form = new FormData();
|
71
|
+
form.append "image", file
|
72
|
+
form.append "authenticity_token", @authenticity_token
|
73
|
+
_this = @
|
74
|
+
$.ajax
|
75
|
+
type: 'POST'
|
76
|
+
url: @form_action
|
77
|
+
data: form
|
78
|
+
contentType: false
|
79
|
+
processData: false
|
80
|
+
success: (data) ->
|
81
|
+
_this.post_success(file)
|
82
|
+
error: (data) ->
|
83
|
+
_this.post_error(file, data.responseText)
|
84
|
+
|
85
|
+
after_do_upload: (file) ->
|
86
|
+
@files.remove file
|
87
|
+
@upload_next()
|
88
|
+
|
89
|
+
post_success: (file) ->
|
90
|
+
@progress file.name + " uploaded"
|
91
|
+
@success_list.append("#{file.name} <br />")
|
92
|
+
@update_progress file
|
93
|
+
@after_do_upload file
|
94
|
+
|
95
|
+
post_error: (file, errors) ->
|
96
|
+
errors = JSON.parse(errors).image
|
97
|
+
@update_progress file, errors
|
98
|
+
for e in errors
|
99
|
+
@errors.push "#{file.name}: #{e}"
|
100
|
+
@after_do_upload file
|
101
|
+
|
102
|
+
render_errors: ->
|
103
|
+
$(".save-loader").hide()
|
104
|
+
@error_list.html("")
|
105
|
+
for error in @errors
|
106
|
+
@error_list.append("<li>#{error}</li>")
|
107
|
+
@error_explanation.show()
|
108
|
+
|
109
|
+
update_progress: (file, error = null) ->
|
110
|
+
@uploaded++
|
111
|
+
message = error || "Last upload complete: #{file.name}"
|
112
|
+
@progress "#{@uploaded}/#{@total_files} uploaded | #{message}"
|
113
|
+
|
114
|
+
progress: (text) ->
|
115
|
+
@upload_progress.html(text);
|
116
|
+
|
117
|
+
# adds a remove method to Array
|
118
|
+
Array::remove = (e) -> @[t..t] = [] if (t = @indexOf(e)) > -1
|
@@ -0,0 +1,15 @@
|
|
1
|
+
::Refinery::Admin::ImagesController.class_eval do
|
2
|
+
|
3
|
+
def ajax_create
|
4
|
+
params[:image] = images = {image: params[:image]}
|
5
|
+
params[:image].each do |image|
|
6
|
+
@image = ::Refinery::Image.create(params[:image])
|
7
|
+
end
|
8
|
+
unless @image.errors.any?
|
9
|
+
render :json => { redirect_to: refinery.admin_images_path }
|
10
|
+
else
|
11
|
+
render :json => @image.errors, status: 406
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
<%### imajax specific do %>
|
2
|
+
<% content_for :after_javascript_libraries, javascript_include_tag('refinery/images') %>
|
3
|
+
<%### END imajax specific %>
|
4
|
+
|
5
|
+
<%= form_for @image, :url => (@url_override or @image.persisted? ? refinery.admin_image_path(@image) : refinery.admin_images_path),
|
6
|
+
:html => { :multipart => true } do |f| %>
|
7
|
+
|
8
|
+
<%= render '/refinery/admin/error_messages',
|
9
|
+
:object => @image,
|
10
|
+
:include_object_name => false %>
|
11
|
+
|
12
|
+
<%########################%>
|
13
|
+
<%### imajax specific do %>
|
14
|
+
<% unless @image.errors.any? %>
|
15
|
+
<div id="upload_progress"></div>
|
16
|
+
|
17
|
+
<div class="errorExplanation" id="errorExplanation" style="display:none;">
|
18
|
+
<p><%= t("refinery.admin.error_messages.problems_in_following_fields")%></p>
|
19
|
+
<ul id="error_list">
|
20
|
+
|
21
|
+
</ul>
|
22
|
+
</div>
|
23
|
+
|
24
|
+
<div id="flash_container">
|
25
|
+
<div id="flash" class="flash flash_notice" style="width: auto; display:none;">
|
26
|
+
<h3><%= t("refinery.imajax.uploaded_successfully") %>:</h3>
|
27
|
+
|
28
|
+
</div>
|
29
|
+
</div>
|
30
|
+
<% end %>
|
31
|
+
<%### END imajax specific %>
|
32
|
+
<%########################%>
|
33
|
+
|
34
|
+
<div class='field'>
|
35
|
+
<% if action_name =~ /(edit)|(update)/ %>
|
36
|
+
<p>
|
37
|
+
<%= t('.use_current_image') %>
|
38
|
+
<em><%= t('.or') %></em><%= t('.replace_image') %>
|
39
|
+
</p>
|
40
|
+
<p>
|
41
|
+
<%= f.file_field :image %>
|
42
|
+
</p>
|
43
|
+
<% else %>
|
44
|
+
<% # we must only hint at multiple when it's a new record otherwise update fails. %>
|
45
|
+
<%= f.file_field :image, :multiple => true %>
|
46
|
+
<% end %>
|
47
|
+
</div>
|
48
|
+
|
49
|
+
<div class='field'>
|
50
|
+
<label><%= t('.maximum_image_size', :bytes => number_to_human_size(Refinery::Images.max_image_size)) %></label>
|
51
|
+
</div>
|
52
|
+
|
53
|
+
<input type='hidden' name='wymeditor' value='<%= params[:wymeditor] %>'>
|
54
|
+
|
55
|
+
<%= render '/refinery/admin/form_actions', :f => f,
|
56
|
+
:continue_editing => false,
|
57
|
+
:hide_cancel => (@app_dialog or action_name == "insert" or from_dialog?),
|
58
|
+
:delete_title => t('delete', :scope => 'refinery.admin.images'),
|
59
|
+
:delete_confirmation => t('message', :scope => 'refinery.admin.delete', :title => @image.image_name) -%>
|
60
|
+
|
61
|
+
<% if @app_dialog %>
|
62
|
+
<input type='hidden' name='app_dialog' value='<%= @app_dialog %>' />
|
63
|
+
<input type='hidden' name='field' value='<%= @field %>' />
|
64
|
+
<input type='hidden' name='update_image' value='<%= @update_image %>' />
|
65
|
+
<input type='hidden' name='thumbnail' value='<%= @thumbnail %>' />
|
66
|
+
<input type='hidden' name='callback' value='<%= @callback %>' />
|
67
|
+
<input type='hidden' name='conditions' value='<%= @conditions %>' />
|
68
|
+
<% end %>
|
69
|
+
<% end %>
|
70
|
+
|
71
|
+
<% if action_name =~ /(edit)|(update)/ %>
|
72
|
+
<div id='existing_image'>
|
73
|
+
<label><%=t('.current_image') %></label>
|
74
|
+
<%= image_fu @image, '225x255>', :class => "brown_border" %>
|
75
|
+
</div>
|
76
|
+
<% end %>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
en:
|
2
|
+
refinery:
|
3
|
+
imajax:
|
4
|
+
uploading:
|
5
|
+
"Uploading..."
|
6
|
+
there_was:
|
7
|
+
"There was"
|
8
|
+
error:
|
9
|
+
"error"
|
10
|
+
should_be_smaller:
|
11
|
+
"should be smaller than"
|
12
|
+
bytes_in_size:
|
13
|
+
"bytes in size"
|
14
|
+
image_type:
|
15
|
+
"should be either a JPG, PNG or GIF"
|
16
|
+
uploaded:
|
17
|
+
"uploaded"
|
18
|
+
last_complete:
|
19
|
+
"Last upload complete"
|
20
|
+
uploaded_successfully:
|
21
|
+
"Uploaded successfully"
|
@@ -0,0 +1,21 @@
|
|
1
|
+
fr:
|
2
|
+
refinery:
|
3
|
+
imajax:
|
4
|
+
uploading:
|
5
|
+
"Transfert en cours..."
|
6
|
+
there_was:
|
7
|
+
"Il y a"
|
8
|
+
error:
|
9
|
+
"erreur"
|
10
|
+
should_be_smaller:
|
11
|
+
"devrait être plus petit que"
|
12
|
+
bytes_in_size:
|
13
|
+
"octets"
|
14
|
+
image_type:
|
15
|
+
"devrait être un fichier JPG, PNG ou GIF"
|
16
|
+
uploaded:
|
17
|
+
"transféré"
|
18
|
+
last_complete:
|
19
|
+
"Dernier transfert complété"
|
20
|
+
uploaded_successfully:
|
21
|
+
"Transféré avec succès"
|
data/config/routes.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'refinerycms-core'
|
2
|
+
|
3
|
+
module Refinery
|
4
|
+
autoload :ImajaxGenerator, 'generators/refinery/imajax_generator'
|
5
|
+
|
6
|
+
module Imajax
|
7
|
+
require 'refinery/imajax/engine'
|
8
|
+
|
9
|
+
class << self
|
10
|
+
attr_writer :root
|
11
|
+
|
12
|
+
def root
|
13
|
+
@root ||= Pathname.new(File.expand_path('../../../', __FILE__))
|
14
|
+
end
|
15
|
+
|
16
|
+
def factory_paths
|
17
|
+
@factory_paths ||= [ root.join('spec', 'factories').to_s ]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Refinery
|
2
|
+
module Imajax
|
3
|
+
class Engine < Rails::Engine
|
4
|
+
include Refinery::Engine
|
5
|
+
isolate_namespace Refinery::Imajax
|
6
|
+
|
7
|
+
engine_name :refinery_imajax
|
8
|
+
|
9
|
+
config.to_prepare do
|
10
|
+
#loads the decorators
|
11
|
+
Dir.glob(File.join(File.dirname(__FILE__), "../../../app/decorators/**/*_decorator*.rb")) do |c|
|
12
|
+
Rails.configuration.cache_classes ? require(c) : load(c)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'refinery/imajax'
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: refinerycms-imajax
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.0.0.beta2
|
5
|
+
prerelease: 6
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jean-Philippe Boily | @jipiboily
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-03-18 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: refinerycms-core
|
16
|
+
requirement: &70223676441800 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 2.0.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70223676441800
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: refinerycms-testing
|
27
|
+
requirement: &70223676440380 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 2.0.0
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70223676440380
|
36
|
+
description: Replacing default bulk image uploading with an Ajaxy, one by one, upload
|
37
|
+
method to prevent timeouts
|
38
|
+
email:
|
39
|
+
- j@jipi.ca
|
40
|
+
executables: []
|
41
|
+
extensions: []
|
42
|
+
extra_rdoc_files: []
|
43
|
+
files:
|
44
|
+
- app/assets/javascripts/refinery/images.js.coffee.erb
|
45
|
+
- app/decorators/controllers/refinery/images_controller_decorator.rb
|
46
|
+
- app/views/refinery/admin/images/_form.html.erb
|
47
|
+
- config/locales/en.yml
|
48
|
+
- config/locales/fr.yml
|
49
|
+
- config/routes.rb
|
50
|
+
- lib/refinery/imajax/engine.rb
|
51
|
+
- lib/refinery/imajax.rb
|
52
|
+
- lib/refinerycms-imajax.rb
|
53
|
+
- README.md
|
54
|
+
homepage:
|
55
|
+
licenses: []
|
56
|
+
post_install_message:
|
57
|
+
rdoc_options: []
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ! '>'
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: 1.3.1
|
72
|
+
requirements: []
|
73
|
+
rubyforge_project:
|
74
|
+
rubygems_version: 1.8.17
|
75
|
+
signing_key:
|
76
|
+
specification_version: 3
|
77
|
+
summary: Ajax image uploading for Refinery CMS
|
78
|
+
test_files: []
|