User new direct uploads controllers action on imageable.

This commit is contained in:
Senén Rodero Rodríguez
2017-09-19 12:00:59 +02:00
parent 824dd26d5a
commit 966ff4dc03
19 changed files with 225 additions and 135 deletions

View File

@@ -63,7 +63,7 @@
//= require followable //= require followable
//= require flaggable //= require flaggable
//= require documentable //= require documentable
// require imageable //= require imageable
//= require tree_navigator //= require tree_navigator
//= require custom //= require custom
//= require tag_autocomplete //= require tag_autocomplete

View File

@@ -28,7 +28,7 @@ App.Documentable =
change: (e, data) -> change: (e, data) ->
$.each data.files, (index, file) -> $.each data.files, (index, file) ->
App.Documentable.setFilename(data, file) App.Documentable.setFilename(inputData, file)
fail: (e, data) -> fail: (e, data) ->
$(data.cachedAttachmentField).val("") $(data.cachedAttachmentField).val("")
@@ -47,9 +47,9 @@ App.Documentable =
App.Documentable.clearInputErrors(data) App.Documentable.clearInputErrors(data)
$(data.addAttachmentLabel).hide() $(data.addAttachmentLabel).hide()
$(data.destroyAttachmentLinkContainer).html(data.result.destroy_link) destroyAttachmentLink = $(data.result.destroy_link)
data.destroyAttachmentLinkContainer = $(data.wrapper).find('.action-remove .remove-cached-attachment') $(data.destroyAttachmentLinkContainer).html(destroyAttachmentLink)
$(data.destroyAttachmentLinkContainer).on 'click', (e) -> $(destroyAttachmentLink).on 'click', (e) ->
e.preventDefault() e.preventDefault()
e.stopPropagation() e.stopPropagation()
App.Documentable.doDeleteCachedAttachmentRequest(this.href, data) App.Documentable.doDeleteCachedAttachmentRequest(this.href, data)

View File

@@ -1,45 +1,173 @@
App.Imageable = App.Imageable =
initialize: -> initialize: ->
console.log 'App.Imageable initialize' inputFiles = $('input.direct_upload_image_attachment[type=file]')
input_files = $('input.direct_upload_attachment[type=file]')
$.each input_files, (index, file) -> $.each inputFiles, (index, input) ->
wrapper = $(file).closest(".direct-upload") App.Imageable.initializeDirectUploadInput(input)
App.Imageable.watchRemoveImagebutton(wrapper)
$("#new_image_link").on 'click', -> $("#new_image_link").on 'click', -> $(this).hide()
$(this).hide()
initializeDirectUploadInput: (input) ->
inputData = @buildData([], input)
@initializeRemoveImageLink(input)
@initializeRemoveCachedImageLink(input, inputData)
$(input).fileupload
paramName: "attachment"
formData: null
add: (e, data) ->
data = App.Imageable.buildFileUploadData(e, data)
App.Imageable.clearProgressBar(data)
App.Imageable.setProgressBar(data, 'uploading')
data.submit()
change: (e, data) ->
$.each data.files, (index, file) ->
App.Imageable.setFilename(inputData, file.name)
fail: (e, data) ->
$(data.cachedAttachmentField).val("")
App.Imageable.clearFilename(data)
App.Imageable.setProgressBar(data, 'errors')
App.Imageable.clearInputErrors(data)
App.Imageable.setInputErrors(data)
App.Imageable.clearPreview(data)
$(data.destroyAttachmentLinkContainer).find("a.delete:not(.remove-nested)").remove()
$(data.addAttachmentLabel).show()
done: (e, data) ->
$(data.cachedAttachmentField).val(data.result.cached_attachment)
App.Imageable.setTitleFromFile(data, data.result.filename)
App.Imageable.setProgressBar(data, 'complete')
App.Imageable.setFilename(data, data.result.filename)
App.Imageable.clearInputErrors(data)
$(data.addAttachmentLabel).hide()
App.Imageable.setPreview(data)
destroyAttachmentLink = $(data.result.destroy_link)
$(data.destroyAttachmentLinkContainer).html(destroyAttachmentLink)
$(destroyAttachmentLink).on 'click', (e) ->
e.preventDefault()
e.stopPropagation()
App.Imageable.doDeleteCachedAttachmentRequest(this.href, data)
progress: (e, data) ->
progress = parseInt(data.loaded / data.total * 100, 10)
$(data.progressBar).find('.loading-bar').css 'width', progress + '%'
return
buildFileUploadData: (e, data) ->
data = @buildData(data, e.target)
return data
buildData: (data, input) ->
wrapper = $(input).closest('.direct-upload')
data.input = input
data.wrapper = wrapper
data.progressBar = $(wrapper).find('.progress-bar-placeholder')
data.preview = $(wrapper).find('.image-preview')
data.errorContainer = $(wrapper).find('.attachment-errors')
data.fileNameContainer = $(wrapper).find('p.file-name')
data.destroyAttachmentLinkContainer = $(wrapper).find('.action-remove')
data.addAttachmentLabel = $(wrapper).find('.action-add label')
data.cachedAttachmentField = $(wrapper).find("#" + $(input).data('cached-attachment-input-field'))
data.titleField = $(wrapper).find("#" + $(input).data('title-input-field'))
$(wrapper).find('.progress-bar-placeholder').css('display', 'block')
return data
clearFilename: (data) ->
$(data.fileNameContainer).text('')
$(data.fileNameContainer).hide()
clearInputErrors: (data) ->
$(data.errorContainer).find('small.error').remove()
clearProgressBar: (data) ->
$(data.progressBar).find('.loading-bar').removeClass('complete errors uploading').css('width', "0px")
clearPreview: (data) ->
$(data.wrapper).find('.image-preview').remove()
setFilename: (data, file_name) ->
$(data.fileNameContainer).text(file_name)
$(data.fileNameContainer).show()
setProgressBar: (data, klass) ->
$(data.progressBar).find('.loading-bar').addClass(klass)
setTitleFromFile: (data, title) ->
if $(data.titleField).val() == ""
$(data.titleField).val(title)
setInputErrors: (data) ->
errors = '<small class="error">' + data.jqXHR.responseJSON.errors + '</small>'
$(data.errorContainer).append(errors)
setPreview: (data) ->
image_preview = '<div class="small-12 column text-center image-preview"><figure><img src="' + data.result.attachment_url + '" class="cached-image"/></figure></div>'
if $(data.preview).length > 0
$(data.preview).replaceWith(image_preview)
else
$(image_preview).insertBefore($(data.wrapper).find(".attachment-actions"))
data.preview = $(data.wrapper).find('.image-preview')
watchRemoveImagebutton: (wrapper) -> watchRemoveImagebutton: (wrapper) ->
console.log 'App.Imageable watchRemoveDocumentbutton'
remove_image_button = $(wrapper).find('a.delete[href="#"]') remove_image_button = $(wrapper).find('a.delete[href="#"]')
$(remove_image_button).on 'click', (e) -> $(remove_image_button).on 'click', (e) ->
e.preventDefault() e.preventDefault()
$(wrapper).remove() $(wrapper).remove()
$('#new_image_link').show() $('#new_image_link').show()
uploadNestedImage: (id, nested_image, result) -> doDeleteCachedAttachmentRequest: (url, data) ->
$('#' + id).replaceWith(nested_image) $.ajax
@updateLoadingBar(id, result) type: "POST"
@initialize() url: url
dataType: "json"
data: { "_method": "delete" }
complete: ->
$(data.cachedAttachmentField).val("")
$(data.addAttachmentLabel).show()
uploadPlainImage: (id, nested_image, result) -> App.Imageable.clearFilename(data)
$('#' + id).replaceWith(nested_image) App.Imageable.clearInputErrors(data)
@updateLoadingBar(id, result) App.Imageable.clearProgressBar(data)
@initialize() App.Imageable.clearPreview(data)
updateLoadingBar: (id, result) -> if $(data.input).data('nested-image') == true
if result $(data.wrapper).remove()
$('#' + id).find('.loading-bar').addClass 'complete' $('#new_image_link').show()
else else
$('#' + id).find('.loading-bar').addClass 'errors' $(data.destroyAttachmentLinkContainer).find('a.delete').remove()
$('#' + id).find('.progress-bar-placeholder').css('display','block')
new: (nested_fields) -> initializeRemoveImageLink: (input) ->
$(".images-list").append(nested_fields) wrapper = $(input).closest(".direct-upload")
remove_image_link = $(wrapper).find('a.remove-nested-field')
$(remove_image_link).on 'click', (e) ->
e.preventDefault()
$(wrapper).remove()
$('#new_image_link').show()
initializeRemoveCachedImageLink: (input, data) ->
wrapper = $(input).closest(".direct-upload")
remove_image_link = $(wrapper).find('a.remove-cached-attachment')
$(remove_image_link).on 'click', (e) ->
e.preventDefault()
e.stopPropagation()
App.Imageable.doDeleteCachedAttachmentRequest(this.href, data)
new: (nested_field) ->
nested_field = $(nested_field)
$(".images-list").append(nested_field)
input = nested_field.find("input[type='file']")
@initializeDirectUploadInput(input)
$("#new_image_link").hide() $("#new_image_link").hide()
@initialize()
destroyNestedImage: (id, notice) -> destroyNestedImage: (id, notice) ->
$('#' + id).remove() $('#' + id).remove()

View File

@@ -28,8 +28,8 @@
background-color: $light-gray; background-color: $light-gray;
} }
.js-document-attachment, input.direct_upload_image_attachment[type=file],
input.direct_upload_image_attachment[type=file] { .js-document-attachment{
display: none; display: none;
} }

View File

@@ -30,8 +30,7 @@
} }
input.direct_upload_image_attachment[type=file], input.direct_upload_image_attachment[type=file],
input.direct_upload_document_attachment[type=file], input.direct_upload_document_attachment[type=file] {
input.direct_upload_attachment[type=file] {
display: none; display: none;
} }
@@ -55,7 +54,6 @@
&.errors { &.errors {
background-color: $alert-color; background-color: $alert-color;
width: 100%;
margin-top: $line-height / 2; margin-top: $line-height / 2;
} }
} }

View File

@@ -18,8 +18,7 @@ class DirectUploadsController < ApplicationController
render json: { cached_attachment: @direct_upload.relation.cached_attachment, render json: { cached_attachment: @direct_upload.relation.cached_attachment,
filename: @direct_upload.relation.attachment.original_filename, filename: @direct_upload.relation.attachment.original_filename,
destroy_link: render_destroy_upload_link(@direct_upload).html_safe, destroy_link: render_destroy_upload_link(@direct_upload).html_safe,
attachment_url: @direct_upload.relation.attachment.url, attachment_url: @direct_upload.relation.attachment.url
is_image: Image::ACCEPTED_CONTENT_TYPE.include?(@direct_upload.relation.attachment_content_type)
} }
else else
@direct_upload.destroy_attachment @direct_upload.destroy_attachment

View File

@@ -3,10 +3,8 @@ class ImagesController < ApplicationController
before_filter :find_imageable, except: :destroy before_filter :find_imageable, except: :destroy
before_filter :prepare_new_image, only: [:new, :new_nested] before_filter :prepare_new_image, only: [:new, :new_nested]
before_filter :prepare_image_for_creation, only: :create before_filter :prepare_image_for_creation, only: :create
before_filter :find_image, only: :destroy
load_and_authorize_resource except: :upload load_and_authorize_resource
skip_authorization_check only: :upload
def new def new
end end
@@ -46,32 +44,6 @@ class ImagesController < ApplicationController
end end
end end
def destroy_upload
@image = Image.new(cached_attachment: params[:path])
@image.set_attachment_from_cached_attachment
@image.cached_attachment = nil
@image.imageable = @imageable
if @image.attachment.destroy
flash.now[:notice] = t "images.actions.destroy.notice"
else
flash.now[:alert] = t "images.actions.destroy.alert"
end
render :destroy
end
def upload
@image = Image.new(image_params.merge(user: current_user))
@image.imageable = @imageable
if @image.valid?
@image.attachment.save
@image.set_cached_attachment_from_attachment(URI(request.url))
else
@image.attachment.destroy
end
end
private private
def image_params def image_params
@@ -83,10 +55,6 @@ class ImagesController < ApplicationController
@imageable = params[:imageable_type].constantize.find_or_initialize_by(id: params[:imageable_id]) @imageable = params[:imageable_type].constantize.find_or_initialize_by(id: params[:imageable_id])
end end
def find_image
@image = Image.find(params[:id])
end
def prepare_new_image def prepare_new_image
@image = Image.new(imageable: @imageable) @image = Image.new(imageable: @imageable)
end end

View File

@@ -1,7 +1,8 @@
module DirectUploadsHelper module DirectUploadsHelper
def render_destroy_upload_link(direct_upload) def render_destroy_upload_link(direct_upload)
link_to t('documents.form.delete_button'), label = direct_upload.resource_relation == "image" ? "images" : "documents"
link_to t("#{label}.form.delete_button"),
direct_upload_destroy_url("direct_upload[resource_type]": direct_upload.resource_type, direct_upload_destroy_url("direct_upload[resource_type]": direct_upload.resource_type,
"direct_upload[resource_id]": direct_upload.resource_id, "direct_upload[resource_id]": direct_upload.resource_id,
"direct_upload[resource_relation]": direct_upload.resource_relation, "direct_upload[resource_relation]": direct_upload.resource_relation,

View File

@@ -56,7 +56,7 @@ module ImagesHelper
method: :delete, method: :delete,
remote: true, remote: true,
data: { confirm: t('images.actions.destroy.confirm') }, data: { confirm: t('images.actions.destroy.confirm') },
class: "delete float-right" class: "delete remove-image"
elsif !image.persisted? && image.cached_attachment.present? elsif !image.persisted? && image.cached_attachment.present?
link_to t('images.form.delete_button'), link_to t('images.form.delete_button'),
destroy_upload_images_path(path: image.cached_attachment, destroy_upload_images_path(path: image.cached_attachment,
@@ -65,18 +65,18 @@ module ImagesHelper
imageable_id: image.imageable_id), imageable_id: image.imageable_id),
method: :delete, method: :delete,
remote: true, remote: true,
class: "delete float-right" class: "delete remove-cached-attachment"
else else
link_to t('images.form.delete_button'), link_to t('images.form.delete_button'),
"#", "#",
class: "delete float-right remove-nested" class: "delete remove-nested"
end end
end end
def render_image_attachment(image) def render_image_attachment(image)
html = file_field_tag :attachment, html = file_field_tag :attachment,
accept: imageable_accepted_content_types_extensions, accept: imageable_accepted_content_types_extensions,
class: 'direct_upload_attachment', class: 'direct_upload_image_attachment',
data: { data: {
url: image_direct_upload_url(image), url: image_direct_upload_url(image),
cached_attachment_input_field: image_nested_field_id(image, :cached_attachment), cached_attachment_input_field: image_nested_field_id(image, :cached_attachment),

View File

@@ -13,10 +13,10 @@
<%= f.hidden_field :cached_attachment %> <%= f.hidden_field :cached_attachment %>
<div class="small-12 column"> <div class="small-12 column">
<%= f.text_field :title %> <%= f.text_field :title, placeholder: t("documents.new.form.title_placeholder") %>
</div> </div>
<div class="small-12 column actions"> <div class="small-12 column attachment-actions">
<div class="small-6 column action-add attachment-errors"> <div class="small-6 column action-add attachment-errors">
<%= f.label :attachment, t("documents.form.attachment_label"), class: 'button hollow' %> <%= f.label :attachment, t("documents.form.attachment_label"), class: 'button hollow' %>
<%= f.file_field :attachment, <%= f.file_field :attachment,

View File

@@ -16,7 +16,8 @@
<%= label_tag :title, t("activerecord.attributes.document.title") %> <%= label_tag :title, t("activerecord.attributes.document.title") %>
<%= text_field_tag :title, <%= text_field_tag :title,
document.errors.has_key?(:attachment) ? "" : document.title, document.title,
placeholder: t("documents.new.form.title_placeholder"),
name: document_nested_field_name(document, index, :title), name: document_nested_field_name(document, index, :title),
id: document_nested_field_id(document, index, :title), id: document_nested_field_id(document, index, :title),
class: "document-title" %> class: "document-title" %>

View File

@@ -30,11 +30,10 @@
"direct_upload[resource_id]": @image.imageable_id, "direct_upload[resource_id]": @image.imageable_id,
"direct_upload[resource_relation]": "image"), "direct_upload[resource_relation]": "image"),
cached_attachment_input_field: "image_cached_attachment", cached_attachment_input_field: "image_cached_attachment",
title_input_field: "image_title", title_input_field: "image_title"
multiple: false
} %> } %>
</div> </div>
<div class="small-6 column action-remove"> <div class="small-6 column action-remove text-right">
<% if @image.cached_attachment.present? %> <% if @image.cached_attachment.present? %>
<%= link_to t('images.form.delete_button'), <%= link_to t('images.form.delete_button'),
direct_upload_destroy_url("direct_upload[resource_type]": @image.imageable_type, direct_upload_destroy_url("direct_upload[resource_type]": @image.imageable_type,
@@ -43,7 +42,7 @@
"direct_upload[cached_attachment]": @image.cached_attachment), "direct_upload[cached_attachment]": @image.cached_attachment),
method: :delete, method: :delete,
remote: true, remote: true,
class: "delete float-right" %> class: "delete remove-cached-attachment" %>
<% end %> <% end %>
</div> </div>
</div> </div>

View File

@@ -14,6 +14,7 @@
<div class="small-12 column"> <div class="small-12 column">
<%= label_tag :title, t("activerecord.attributes.image.title") %> <%= label_tag :title, t("activerecord.attributes.image.title") %>
<%= text_field_tag :title, <%= text_field_tag :title,
image.title, image.title,
placeholder: t("images.new.form.title_placeholder"), placeholder: t("images.new.form.title_placeholder"),
@@ -31,7 +32,7 @@
<div class="small-6 column action-add attachment-errors"> <div class="small-6 column action-add attachment-errors">
<%= render_image_attachment(image) %> <%= render_image_attachment(image) %>
</div> </div>
<div class="small-6 column action-remove"> <div class="small-6 column action-remove text-right">
<%= render_destroy_image_link(image) %> <%= render_destroy_image_link(image) %>
</div> </div>
</div> </div>

View File

@@ -1,17 +1,7 @@
<% if params[:nested_image] == "true" %> App.Imageable.destroyNestedImage("<%= image_nested_field_wrapper_id %>", "<%= j render('layouts/flash') %>")
<% new_image_link = link_to t("images.form.add_new_image"),
App.Imageable.destroyNestedImage("<%= image_nested_field_wrapper_id %>", "<%= j render('layouts/flash') %>")
<% new_image_link = link_to t("images.form.add_new_image"),
new_nested_images_path(imageable_type: @image.imageable_type), new_nested_images_path(imageable_type: @image.imageable_type),
remote: true, remote: true,
id: "new_image_link", id: "new_image_link",
class: "button hollow" %> class: "button hollow" %>
App.Imageable.updateNewImageButton("<%= j new_image_link %>") App.Imageable.updateNewImageButton("<%= j new_image_link %>")
<% else %>
App.Imageable.replacePlainImage("plain_image_fields",
"<%= j render('layouts/flash') %>",
"<%= j render('plain_fields', image: @image) %>")
<% end %>

View File

@@ -19,6 +19,9 @@ en:
note: 'Add new document to your investment project: %{title}' note: 'Add new document to your investment project: %{title}'
proposal: proposal:
note: 'Add new document to your proposal: %{title}' note: 'Add new document to your proposal: %{title}'
form:
title_placeholder: Add a descriptive title for the document
recommendations_title: File upload tips recommendations_title: File upload tips
recommendation_one_html: You can upload up to a <strong>maximum of %{max_documents_allowed} documents</strong>. recommendation_one_html: You can upload up to a <strong>maximum of %{max_documents_allowed} documents</strong>.
recommendation_two_html: You can upload <strong>%{accepted_content_types}</strong> files. recommendation_two_html: You can upload <strong>%{accepted_content_types}</strong> files.

View File

@@ -19,6 +19,9 @@ es:
note: 'Añade un documento la propuesta de inversión: %{title}.' note: 'Añade un documento la propuesta de inversión: %{title}.'
proposal: proposal:
note: 'Añade un documento a la propuesta: %{title}.' note: 'Añade un documento a la propuesta: %{title}.'
form:
title_placeholder: Añade un título descriptivo para el documento
recommendations_title: Consejos para subir archivos recommendations_title: Consejos para subir archivos
recommendation_one_html: Puedes subir hasta un máximo de <strong>%{max_documents_allowed} documentos</strong> recommendation_one_html: Puedes subir hasta un máximo de <strong>%{max_documents_allowed} documentos</strong>
recommendation_two_html: Sólo puedes subir <strong>archivos %{accepted_content_types}</strong>. recommendation_two_html: Sólo puedes subir <strong>archivos %{accepted_content_types}</strong>.

View File

@@ -1290,6 +1290,8 @@ feature 'Proposals' do
it_behaves_like "followable", "proposal", "proposal_path", { "id": "id" } it_behaves_like "followable", "proposal", "proposal_path", { "id": "id" }
describe "my specs group" do
it_behaves_like "imageable", "proposal", "proposal_path", { "id": "id" } it_behaves_like "imageable", "proposal", "proposal_path", { "id": "id" }
it_behaves_like "nested imageable", it_behaves_like "nested imageable",
@@ -1325,7 +1327,7 @@ feature 'Proposals' do
nil, nil,
"Save changes", "Save changes",
"Proposal updated successfully" "Proposal updated successfully"
end
scenario 'Erased author' do scenario 'Erased author' do
user = create(:user) user = create(:user)
proposal = create(:proposal, author: user) proposal = create(:proposal, author: user)

View File

@@ -243,8 +243,6 @@ def documentable_attach_new_file(documentable_factory_name, index, path, success
expect(page).to have_css ".loading-bar.errors" expect(page).to have_css ".loading-bar.errors"
end end
end end
end end
def documentable_fill_new_valid_proposal def documentable_fill_new_valid_proposal

View File

@@ -45,7 +45,7 @@ shared_examples "nested imageable" do |imageable_factory_name, path, imageable_p
imageable_attach_new_file(imageable_factory_name, "spec/fixtures/files/clippy.jpg") imageable_attach_new_file(imageable_factory_name, "spec/fixtures/files/clippy.jpg")
expect(page).to have_css("##{imageable_factory_name}_image_attributes_title[value$='clippy.jpg']") expect(find("##{imageable_factory_name}_image_attributes_title").value).to eq("clippy.jpg")
end end
scenario "Should not update nested image file title with file name after choosing a file when title already defined", :js do scenario "Should not update nested image file title with file name after choosing a file when title already defined", :js do
@@ -98,7 +98,6 @@ shared_examples "nested imageable" do |imageable_factory_name, path, imageable_p
end end
scenario "Should show nested image errors after unvalid form submit", :js do scenario "Should show nested image errors after unvalid form submit", :js do
page.driver.resize_window 1200, 2000
login_as user login_as user
visit send(path, arguments) visit send(path, arguments)
@@ -130,7 +129,7 @@ shared_examples "nested imageable" do |imageable_factory_name, path, imageable_p
click_link "Remove image" click_link "Remove image"
end end
expect(page).to have_content "Image was deleted successfully." expect(page).not_to have_css "#nested_image"
end end
scenario "Should show successful notice when resource filled correctly without any nested images", :js do scenario "Should show successful notice when resource filled correctly without any nested images", :js do