Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ajax image upload #1903

Merged
merged 4 commits into from Aug 27, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.md
Expand Up @@ -4,6 +4,7 @@
* Refactored wysiwyg fields into a partial. [#1796](https://github.com/resolve/refinerycms/pull/1796). [Rob Yurkowski](https://github.com/robyurkowski) * Refactored wysiwyg fields into a partial. [#1796](https://github.com/resolve/refinerycms/pull/1796). [Rob Yurkowski](https://github.com/robyurkowski)
* Shortened all authentication helpers. [#1719](https://github.com/resolve/refinerycms/pull/1719). [Ryan Bigg](https://github.com/radar) * Shortened all authentication helpers. [#1719](https://github.com/resolve/refinerycms/pull/1719). [Ryan Bigg](https://github.com/radar)
* Added canonical page id to body to allow CSS selectors to target specific pages instead of including special CSS files. [#1700](https://github.com/resolve/refinerycms/pull/1700) & [#1828](https://github.com/resolve/refinerycms/pull/1828). [Philip Arndt](https://github.com/parndt) & [Graham Wagener](https://github.com/gwagener/) * Added canonical page id to body to allow CSS selectors to target specific pages instead of including special CSS files. [#1700](https://github.com/resolve/refinerycms/pull/1700) & [#1828](https://github.com/resolve/refinerycms/pull/1828). [Philip Arndt](https://github.com/parndt) & [Graham Wagener](https://github.com/gwagener/)
* Added ajaxy image uploading. [#1739](https://github.com/resolve/refinerycms/pull/1739). [Jean-Philippe Boily](https://github.com/jipiboily)


* [See full list](https://github.com/resolve/refinerycms/compare/2-0-stable...master) * [See full list](https://github.com/resolve/refinerycms/compare/2-0-stable...master)


Expand Down
128 changes: 128 additions & 0 deletions images/app/assets/javascript/refinery/images.js.coffee.erb
@@ -0,0 +1,128 @@
$(document).ready ->
images = new Images
$("#new_image").submit (e) ->
if window.FileList && FormData
e.preventDefault()
images.upload_all()
$("#image_image").change (e) ->
images.file_list = e.target.files


class Images
# TODO:
# - add a progress bar for each file maybe?
# - refresh images index after closing the dialog box...
constructor: ->
@authenticity_token = $("meta[name=\"csrf-token\"]").attr("content")
@form_action = $("#new_image").attr("action")
@cache_dom()

cache_dom: ->
@error_list = $("#error_list")
@success_list = $("#flash")
@error_explanation = $("#errorExplanation")
@upload_progress = $("#upload_progress")

before_upload_all: ->
@files = []
@errors = []
@total_files = @file_list.length
@uploaded = 0
@error_explanation.hide()

upload_all: ->
@before_upload_all()
for file in @file_list
@validate(file)
@files.push file
return @render_errors() if @errors.length > 0
$("#submit_button").hide()
$(".field").hide()
@progress "<%= ::I18n.t("refinery.admin.images.form.uploading")%>"
@upload_next()

after_upload_all: ->
$(".save-loader").hide()
@upload_progress.hide()
@success_list.show()
if @errors.length > 0
@render_errors()
else
if getParameterByName("modal") == "true"
window.parent.document.getElementById("dialog_frame").contentDocument.location.reload(true);
else
window.parent.location.reload(true)

validate: (file) ->
max_file_size = <%= Refinery::Images.max_image_size %>
if file.size > max_file_size
@errors.push "#{file.name} <%= ::I18n.t("refinery.admin.images.form.should_be_smaller")%> #{max_file_size} <%= ::I18n.t("refinery.admin.images.form.bytes_in_size")%>"
# TODO: set valid file types based on image model validation
valid_file_types = ["image/jpeg", "image/png", "image/gif", "image/tiff"]
if valid_file_types.indexOf(file.type) == -1
@errors.push "#{file.name} <%= ::I18n.t("refinery.admin.images.form.image_type")%>"

upload_next: ->
@do_upload(@files[0]) unless @files.length == 0
if @total_files > 0 && @files.length == 0
@after_upload_all()

do_upload: (file) =>
form = new FormData();
form.append "image[image]", file
form.append "authenticity_token", @authenticity_token
_this = @ # save current scope so we can use current object methods within $.ajax
$.ajax
type: 'POST'
url: @form_action
data: form
contentType: false
processData: false
success: (data) ->
_this.post_success(file)
error: (data) ->
_this.post_error(file, data.responseText)

after_do_upload: (file) ->
@files.remove file
@upload_next()

post_success: (file) ->
@progress file.name + " <%= ::I18n.t("refinery.admin.images.form.uploaded")%>"
@update_progress file
@after_do_upload file

post_error: (file, errors) ->
errors = JSON.parse(errors).image
@update_progress file, errors
for e in errors
@errors.push "#{file.name}: #{e}"
@after_do_upload file

render_errors: ->
$(".save-loader").hide()
@error_list.html("")
for error in @errors
@error_list.append("<li>#{error}</li>")
@error_explanation.show()

update_progress: (file, error = null) ->
@uploaded++
message = error || "<%= ::I18n.t("refinery.admin.images.form.last_complete")%>: #{file.name}"
@progress "#{@uploaded}/#{@total_files} <%= ::I18n.t("refinery.admin.images.form.uploaded")%> | #{message}"

progress: (text) ->
@upload_progress.html(text);

# adds a remove method to Array
Array::remove = (e) -> @[t..t] = [] if (t = @indexOf(e)) > -1

getParameterByName = (name) ->
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]")
regexS = "[\\?&]" + name + "=([^&#]*)"
regex = new RegExp(regexS)
results = regex.exec(window.location.search)
unless results?
""
else
decodeURIComponent results[1].replace(/\+/g, " ")
2 changes: 1 addition & 1 deletion images/app/controllers/refinery/admin/images_controller.rb
Expand Up @@ -54,7 +54,7 @@ def create


unless params[:insert] unless params[:insert]
if @images.all?(&:valid?) if @images.all?(&:valid?)
flash.notice = t('created', :scope => 'refinery.crudify', :what => "'#{@images.map(&:title).join("', '")}'") flash.notice = t('uploaded_successfully', :scope => 'refinery.admin.images.form')
if from_dialog? if from_dialog?
@dialog_successful = true @dialog_successful = true
render :nothing => true, :layout => true render :nothing => true, :layout => true
Expand Down
10 changes: 10 additions & 0 deletions images/app/views/refinery/admin/images/_form.html.erb
@@ -1,10 +1,20 @@
<% content_for :after_javascript_libraries, javascript_include_tag('refinery/images') %>
<%= form_for @image, :url => (@url_override or @image.persisted? ? refinery.admin_image_path(@image) : refinery.admin_images_path), <%= form_for @image, :url => (@url_override or @image.persisted? ? refinery.admin_image_path(@image) : refinery.admin_images_path),
:html => { :multipart => true } do |f| %> :html => { :multipart => true } do |f| %>


<%= render '/refinery/admin/error_messages', <%= render '/refinery/admin/error_messages',
:object => @image, :object => @image,
:include_object_name => false %> :include_object_name => false %>


<% if @image.errors.empty? %>
<div id="upload_progress"></div>

<div class="errorExplanation" id="errorExplanation" style="display:none;">
<p><%= t("refinery.admin.error_messages.problems_in_following_fields")%></p>
<ul id="error_list"></ul>
</div>
<% end %>

<div class='field'> <div class='field'>
<% if action_name =~ /(edit)|(update)/ %> <% if action_name =~ /(edit)|(update)/ %>
<p> <p>
Expand Down
9 changes: 9 additions & 0 deletions images/config/locales/en.yml
Expand Up @@ -15,6 +15,15 @@ en:
replace_image: " replace it with this one..." replace_image: " replace it with this one..."
current_image: Current Image current_image: Current Image
maximum_image_size: The maximum image size is %{bytes}. maximum_image_size: The maximum image size is %{bytes}.
uploading: "Uploading..."
there_was: "There was"
error: "error"
should_be_smaller: "should be smaller than"
bytes_in_size: "bytes in size"
image_type: "should be either a JPG, PNG or GIF"
uploaded: "uploaded"
last_complete: "Last upload complete"
uploaded_successfully: "Uploaded successfully"
actions: actions:
create_new_image: Add new image create_new_image: Add new image
records: records:
Expand Down
9 changes: 9 additions & 0 deletions images/config/locales/fr.yml
Expand Up @@ -15,6 +15,15 @@ fr:
replace_image: " la remplacer par celle-ci..." replace_image: " la remplacer par celle-ci..."
current_image: Image actuelle current_image: Image actuelle
maximum_image_size: "La taille de l'image ne doit pas excéder %{bytes}." maximum_image_size: "La taille de l'image ne doit pas excéder %{bytes}."
uploading: "Transfert en cours..."
there_was: "Il y a"
error: "erreur"
should_be_smaller: "devrait être plus petit que"
bytes_in_size: "octets"
image_type: "devrait être un fichier JPG, PNG ou GIF"
uploaded: "transféré"
last_complete: "Dernier transfert complété"
uploaded_successfully: "Transféré avec succès"
actions: actions:
create_new_image: Ajouter une image create_new_image: Ajouter une image
records: records:
Expand Down
4 changes: 2 additions & 2 deletions images/spec/requests/refinery/admin/images_spec.rb
Expand Up @@ -30,8 +30,8 @@ module Refinery
join("spec/fixtures/image-with-dashes.jpg") join("spec/fixtures/image-with-dashes.jpg")
click_button ::I18n.t('save', :scope => 'refinery.admin.form_actions') click_button ::I18n.t('save', :scope => 'refinery.admin.form_actions')
end end

page.should have_content(::I18n.t("uploaded_successfully", :scope => "refinery.admin.images.form"))
page.should have_content(::I18n.t('created', :scope => 'refinery.crudify', :what => "'Image With Dashes'")) page.should have_selector("img[src*='image-with-dashes.jpg']")
Refinery::Image.count.should == 1 Refinery::Image.count.should == 1
end end


Expand Down