Remove images single uploads

This commit is contained in:
Senén Rodero Rodríguez
2017-09-27 10:41:48 +02:00
parent 45f34540ae
commit eef8ad1b73
18 changed files with 16 additions and 510 deletions

View File

@@ -44,28 +44,6 @@
margin-bottom: $line-height;
}
.document-form,
.image-form {
.title{
margin-bottom: $line-height;
}
.document,
.image-form {
.file-name {
margin-top: 0;
}
}
.document,
.image {
.loading-bar.errors {
margin-top: $line-height * 2;
}
}
}
.document,
.image {
@@ -107,12 +85,10 @@
&.complete {
background-color: $success-color;
width: 100%;
}
&.errors {
background-color: $alert-color;
width: 100%;
margin-top: $line-height / 2;
}
}

View File

@@ -251,9 +251,7 @@
.spending-proposal-form,
.document-form,
.topic-new,
.topic-form,
.image-form,
.proposal .image-form {
.topic-form {
.icon-debates,
.icon-proposals,
@@ -306,8 +304,7 @@
.proposal-form,
.topic-form,
.topic-new,
.document-form,
.image-form {
.document-form {
.recommendations li::before {
color: $proposals;
@@ -317,7 +314,6 @@
.budget-investment-new,
.proposal-form,
.proposal-edit,
.image-form,
.document-form,
.new_poll_question,
.edit_poll_question {

View File

@@ -1,24 +1,8 @@
class ImagesController < ApplicationController
before_action :authenticate_user!
before_filter :find_imageable, except: :destroy
before_filter :prepare_new_image, only: [:new]
before_filter :prepare_image_for_creation, only: :create
load_and_authorize_resource
def new
end
def create
if @image.save
flash[:notice] = t "images.actions.create.notice"
redirect_to params[:from]
else
flash[:alert] = t "images.actions.create.alert"
render :new
end
end
def destroy
respond_to do |format|
format.html do
@@ -39,25 +23,4 @@ class ImagesController < ApplicationController
end
end
private
def image_params
params.require(:image).permit(:title, :imageable_type, :imageable_id,
:attachment, :cached_attachment, :user_id)
end
def find_imageable
@imageable = params[:imageable_type].constantize.find_or_initialize_by(id: params[:imageable_id])
end
def prepare_new_image
@image = Image.new(imageable: @imageable)
end
def prepare_image_for_creation
@image = Image.new(image_params)
@image.imageable = @imageable
@image.user = current_user
end
end

View File

@@ -1,9 +1,5 @@
module ImageablesHelper
def can_create_image?(imageable)
can?(:create, Image.new(imageable: imageable))
end
def can_destroy_image?(imageable)
imageable.image.present? && can?(:destroy, imageable.image)
end

View File

@@ -74,7 +74,7 @@ module Abilities
cannot :comment_as_moderator, [::Legislation::Question, Legislation::Annotation]
can [:create, :destroy], Document
can [:create, :destroy], Image
can [:destroy], Image
can [:create, :destroy], DirectUpload
end
end

View File

@@ -39,7 +39,7 @@ module Abilities
can [:create, :destroy, :new], Document, documentable: { author_id: user.id }
can [:create, :destroy, :new], Image, imageable: { author_id: user.id }
can [:destroy], Image, imageable: { author_id: user.id }
can [:create, :destroy], DirectUpload

View File

@@ -10,12 +10,6 @@
class: 'button hollow float-right' %>
<% end %>
<% if can_create_image?(investment) %>
<%= link_to t("images.upload_image"),
new_image_path(imageable_id:investment, imageable_type: investment.class.name, from: request.url),
class: 'button hollow float-right' %>
<% end %>
<% if can_destroy_image?(investment) %>
<%= link_to t("images.remove_image"),
image_path(investment.image, from: request.url),

View File

@@ -1,65 +0,0 @@
<%= form_for @image,
url: images_path(
imageable_type: @image.imageable_type,
imageable_id: @image.imageable_id,
from: params[:from]
),
html: { multipart: true, class: "imageable" } do |f| %>
<%= render 'shared/errors', resource: @image %>
<div class="row image direct-upload">
<%= f.hidden_field :cached_attachment %>
<div class="small-12 column title">
<%= f.text_field :title, placeholder: t("images.new.form.title_placeholder") %>
</div>
<%= render_image(@image, :thumb, false) if @image.attachment.exists? %>
<div class="attachment-actions">
<div class="small-6 column action-add attachment-errors">
<%= f.label :attachment, t("images.form.attachment_label"), class: 'button hollow' %>
<%= f.file_field :attachment,
accept: imageable_accepted_content_types_extensions,
label: false,
class: 'js-image-attachment',
data: {
url: direct_uploads_url("direct_upload[resource_type]": @image.imageable_type,
"direct_upload[resource_id]": @image.imageable_id,
"direct_upload[resource_relation]": "image"),
cached_attachment_input_field: "image_cached_attachment",
title_input_field: "image_title"
} %>
</div>
<div class="small-6 column action-remove text-right">
<% if @image.cached_attachment.present? %>
<%= link_to t('images.form.delete_button'),
direct_upload_destroy_url("direct_upload[resource_type]": @image.imageable_type,
"direct_upload[resource_id]": @image.imageable_id,
"direct_upload[resource_relation]": "image",
"direct_upload[cached_attachment]": @image.cached_attachment),
method: :delete,
remote: true,
class: "delete remove-cached-attachment" %>
<% end %>
</div>
</div>
<div class="small-12 column image-attachment">
<p class="file-name column">
<%= image_attachment_file_name(@image) %>
</p>
</div>
<div class="small-12 column">
<div class="progress-bar-placeholder"><div class="loading-bar"></div></div>
</div>
<div class="actions small-12 medium-6 large-4 end column">
<%= f.submit(t("images.form.submit_button"), class: "button expanded") %>
</div>
</div>
<% end %>

View File

@@ -2,7 +2,8 @@
<figure>
<%= image_tag image.attachment.url(version),
class: image_class(image),
alt: image.title %>
alt: image.title,
title: image.title %>
<% if show_caption %>
<figcaption class="text-right">
<em><%= image.title %></em>

View File

@@ -4,7 +4,7 @@
<%= f.hidden_field :cached_attachment %>
<div class="small-12 column title">
<%= f.text_field :title, placeholder: t("images.new.form.title_placeholder") %>
<%= f.text_field :title, placeholder: t("images.form.title_placeholder") %>
</div>
<%= render_image(f.object, :thumb, false) if f.object.attachment.exists? %>

View File

@@ -1,30 +0,0 @@
<div class="<%= imageable_class(@image.imageable) %>">
<div class="image-form row">
<div class="small-12 medium-9 column">
<%= back_link_to params[:from] %>
<h1><%= t("images.new.title") %></h1>
<p><%= image_note(@image) %></p>
<%= render "form", form_url: images_url %>
</div>
<div class="small-12 medium-3 column">
<span class="icon-image icon-proposals float-right"></span>
<h2><%= t("images.recommendations_title") %></h2>
<ul class="recommendations">
<li>
<%= image_first_recommendation(@image) %>
</li>
<li>
<%= t "images.recommendation_two_html",
accepted_content_types: imageable_humanized_accepted_content_types %>
</li>
<li>
<%= t "images.recommendation_three_html",
max_file_size: imageable_max_file_size %>
</li>
</ul>
</div>
</div>
</div>

View File

@@ -109,7 +109,7 @@
<aside class="small-12 medium-3 column">
<% if can_create_document?(@proposal) || author_of_proposal?(@proposal) || current_editable?(@proposal) ||
can_create_image?(@proposal) || can_destroy_image?(@proposal) %>
can_destroy_image?(@proposal) %>
<div class="sidebar-divider"></div>
<h2><%= t("proposals.show.author") %></h2>
<div class="show-actions-menu">
@@ -129,14 +129,6 @@
<% end %>
<% end %>
<% if can_create_image?(@proposal) %>
<%= link_to new_image_path(imageable_id: @proposal, imageable_type: @proposal.class.name, from: request.url),
class: 'button hollow expanded' do %>
<span class="icon-document"></span>
<%= t("images.upload_image") %>
<% end %>
<% end %>
<% if can_destroy_image?(@proposal) %>
<%= link_to image_path(@proposal.image, from: request.url),
method: :delete,

View File

@@ -1,41 +1,21 @@
en:
images:
upload_image: Upload image
remove_image: Remove image
form:
title: Descriptive image
title_placeholder: Add a descriptive title for the image
attachment_label: Choose image
submit_button: Upload image
delete_button: Remove image
note: "You can upload one image of following content types: %{accepted_content_types}, up to %{max_file_size} MB."
add_new_image: Add image
new:
title: Upload image
budget_investment:
note: 'Add an image to your investment project: %{title}'
proposal:
note: 'Add an image to your proposal: %{title}'
form:
title_placeholder: Add a descriptive title for the image
recommendations_title: File upload tips
proposal:
recommendation_one_html: Proposals with image attract the attention of users more than those that do not have image. This image will be displayed in the list of proposals and on the proposal page.
budget_investment:
recommendation_one_html: Investment project with image attract the attention of users more than those that do not have image. This image will be displayed in the list of project investments and on the project investments page.
recommendation_two_html: "You can upload images in following formats: <strong>%{accepted_content_types}</strong>."
recommendation_three_html: You can upload one image up to <strong>1 MB</strong>.
actions:
create:
notice: Image was created successfully.
alert: Cannot create image. Check form errors and try again.
destroy:
notice: Image was deleted successfully.
alert: Cannot destroy image.
confirm: Are you sure you want to delete the image? This action cannot be undone!
errors:
messages:
in_between: must be in between %{min} and %{max}

View File

@@ -1,41 +1,21 @@
es:
images:
upload_image: Subir imagen
remove_image: Eliminar imagen
form:
title: Imagen descriptiva
attachment_label: Selecciona una imagen
submit_button: Subir imagen
delete_button: Eliminar imagen
note: "Puedes subir una imagen en los formatos: %{accepted_content_types}, y de hasta %{max_file_size} MB por archivo."
add_new_image: Añadir imagen
new:
title: Subir una imagen
budget_investment:
note: 'Añade una imagen la propuesta de inversión: %{title}.'
proposal:
note: 'Añade una imagen a la propuesta: %{title}.'
form:
title_placeholder: Añade un título descriptivo para la imagen
recommendations_title: Consejos para subir imágenes
proposal:
recommendation_one_html: Las propuestas con imagen llaman más la atención de los usuarios que las que no tienen imagen. Esta imagen se mostrará en el listado de propuestas y en la página de la propuesta.
budget_investment:
recommendation_one_html: Las proyectos de inversión con imagen llaman más la atención de los usuarios que las que no tienen imagen. Esta imagen se mostrará en el listado de proyectos de inversión y en la página del proyecto de inversión.
recommendation_two_html: "Sólo puedes subir <strong>imágenes en los formatos: %{accepted_content_types}</strong>."
recommendation_three_html: Puedes subir una imagen de hasta <strong>1 MB</strong>.
actions:
create:
notice: "La imagen se ha creado correctamente."
alert: "La imagen no se ha podido crear. Revise los errores del formulario."
destroy:
notice: "La imagen se ha eliminado correctamente."
alert: "La imagen no se ha podido eliminar."
confirm: "¿Está seguro de que desea eliminar la imagen? Esta acción no se puede deshacer!"
errors:
messages:
in_between: debe estar entre %{min} y %{max}

View File

@@ -36,9 +36,6 @@ Rails.application.routes.draw do
get '/welcome', to: 'welcome#welcome'
get '/cuentasegura', to: 'welcome#verification', as: :cuentasegura
concern :imageable do
resources :images
end
resources :debates do
member do
post :vote
@@ -80,7 +77,7 @@ Rails.application.routes.draw do
resources :budgets, only: [:show, :index] do
resources :groups, controller: "budgets/groups", only: [:show]
resources :investments, controller: "budgets/investments", only: [:index, :new, :create, :show, :destroy], concerns: :imageable do
resources :investments, controller: "budgets/investments", only: [:index, :new, :create, :show, :destroy] do
member do
post :vote
end
@@ -102,7 +99,7 @@ Rails.application.routes.draw do
resources :documents, only: [:new, :create, :destroy]
resources :images, only: [:new, :create, :destroy]
resources :images, only: [:destroy]
resources :direct_uploads, only: [:create]
delete "direct_uploads/destroy", to: "direct_uploads#destroy", as: :direct_upload_destroy
@@ -228,7 +225,7 @@ Rails.application.routes.draw do
end
end
resources :budget_investments, only: [:index, :show, :edit, :update], concerns: :imageable do
resources :budget_investments, only: [:index, :show, :edit, :update] do
resources :budget_investment_milestones
member { patch :toggle_selection }
end

View File

@@ -93,12 +93,7 @@ describe "Abilities::Administrator" do
it { should be_able_to(:create, poll_question_document) }
it { should be_able_to(:destroy, poll_question_document) }
it { should be_able_to(:new, proposal_image) }
it { should be_able_to(:create, proposal_image) }
it { should be_able_to(:destroy, proposal_image) }
it { should be_able_to(:new, budget_investment_image) }
it { should be_able_to(:create, budget_investment_image) }
it { should be_able_to(:destroy, budget_investment_image) }
end

View File

@@ -108,20 +108,10 @@ describe "Abilities::Common" do
it { should_not be_able_to(:create, budget_investment_document) }
it { should_not be_able_to(:destroy, budget_investment_document) }
it { should be_able_to(:new, own_proposal_image) }
it { should be_able_to(:create, own_proposal_image) }
it { should be_able_to(:destroy, own_proposal_image) }
it { should_not be_able_to(:new, proposal_image) }
it { should_not be_able_to(:create, proposal_image) }
it { should_not be_able_to(:destroy, proposal_image) }
it { should be_able_to(:new, own_budget_investment_image) }
it { should be_able_to(:create, own_budget_investment_image) }
it { should be_able_to(:destroy, own_budget_investment_image) }
it { should_not be_able_to(:new, budget_investment_image) }
it { should_not be_able_to(:create, budget_investment_image) }
it { should_not be_able_to(:destroy, budget_investment_image) }
describe 'flagging content' do

View File

@@ -25,7 +25,7 @@ shared_examples "imageable" do |imageable_factory_name, imageable_path, imageabl
visit send(imageable_path, imageable_arguments)
expect(page).to have_css("img[alt='#{image.title}']")
expect(page).to have_css("img[alt='#{image.title}'][title='#{image.title}']")
end
scenario "Show image title when image exists" do
@@ -36,265 +36,6 @@ shared_examples "imageable" do |imageable_factory_name, imageable_path, imageabl
expect(page).to have_content image.title
end
scenario "Should not display upload image button when there is no logged user" do
visit send(imageable_path, imageable_arguments)
within "##{dom_id(imageable)}" do
expect(page).not_to have_link("Upload image")
end
end
scenario "Should not display upload image button when maximum number of images reached " do
create_list(:image, 3, imageable: imageable)
visit send(imageable_path, imageable_arguments)
within "##{dom_id(imageable)}" do
expect(page).not_to have_link("Upload image")
end
end
scenario "Should display upload image button when user is logged in and is imageable owner" do
login_as(user)
visit send(imageable_path, imageable_arguments)
within "##{dom_id(imageable)}" do
expect(page).to have_link("Upload image")
end
end
scenario "Should display upload image button when admin is logged in" do
login_as(administrator)
visit send(imageable_path, imageable_arguments)
within "##{dom_id(imageable)}" do
expect(page).to have_link("Upload image")
end
end
scenario "Should navigate to new image page when click un upload button" do
login_as(user)
visit send(imageable_path, imageable_arguments)
click_link "Upload image"
expect(page).to have_selector("h1", text: "Upload image")
end
end
context "New" do
scenario "Should not be able for unathenticated users" do
visit new_image_path(imageable_type: imageable.class.name,
imageable_id: imageable.id)
expect(page).to have_content("You must sign in or register to continue.")
end
scenario "Should not be able for other users" do
login_as create(:user)
visit new_image_path(imageable_type: imageable.class.name,
imageable_id: imageable.id)
expect(page).to have_content("You do not have permission to carry out the action 'new' on image.")
end
scenario "Should be able to imageable author" do
login_as imageable.author
visit new_image_path(imageable_type: imageable.class.name,
imageable_id: imageable.id)
expect(page).to have_selector("h1", text: "Upload image")
end
scenario "Should show imageable custom recomentations" do
login_as imageable.author
visit new_image_path(imageable_type: imageable.class.name,
imageable_id: imageable.id,
from: send(imageable_path, imageable_arguments))
expect(page).to have_content(image_first_recommendation(Image.new(imageable: imageable)))
expect(page).to have_content "You can upload images in following formats: #{imageable_humanized_accepted_content_types}."
expect(page).to have_content "You can upload one image up to 1 MB."
end
scenario "Should display attachment validation errors after invalid image upload", :js do
login_as imageable.author
visit new_image_path(imageable_type: imageable.class.name,
imageable_id: imageable.id)
attach_image("spec/fixtures/files/logo_header.png", false)
expect(page).to have_css "small.error"
end
scenario "Should display file name after image selection", :js do
login_as imageable.author
visit new_image_path(imageable_type: imageable.class.name,
imageable_id: imageable.id)
attach_file :image_attachment, "spec/fixtures/files/empty.pdf", make_visible: true
expect(page).to have_content "empty.pdf"
end
scenario "Should not display file name after invalid image upload", :js do
login_as imageable.author
visit new_image_path(imageable_type: imageable.class.name,
imageable_id: imageable.id)
attach_image("spec/fixtures/files/logo_header.png", false)
expect(page).not_to have_content "clippy.png"
end
scenario "Should display cached image without caption after valid image upload", :js do
login_as imageable.author
visit new_image_path(imageable_type: imageable.class.name,
imageable_id: imageable.id)
attach_image("spec/fixtures/files/clippy.jpg", true)
expect(page).to have_selector ".loading-bar.complete"
expect(page).to have_css("figure img")
expect(page).not_to have_css("figure figcaption")
end
scenario "Should update loading bar style after valid file upload", :js do
login_as imageable.author
visit new_image_path(imageable_type: imageable.class.name,
imageable_id: imageable.id)
attach_image("spec/fixtures/files/clippy.jpg", true)
expect(page).to have_selector ".loading-bar.complete"
end
scenario "Should update loading bar style after invalid file upload", :js do
login_as imageable.author
visit new_image_path(imageable_type: imageable.class.name,
imageable_id: imageable.id)
attach_image("spec/fixtures/files/logo_header.png", false)
expect(page).to have_selector ".loading-bar.errors"
end
scenario "Should update image title with attachment original file name after valid image upload", :js do
login_as imageable.author
visit new_image_path(imageable_type: imageable.class.name,
imageable_id: imageable.id)
attach_image("spec/fixtures/files/clippy.jpg")
expect(find('input#image_title').value).to eq('clippy.jpg')
end
scenario "Should not update image title with attachment original file name after valid image upload when title already defined by user", :js do
login_as imageable.author
visit new_image_path(imageable_type: imageable.class.name,
imageable_id: imageable.id)
fill_in :image_title, with: "My custom title"
attach_image("spec/fixtures/files/clippy.jpg")
expect(find('input#image_title').value).to eq('My custom title')
end
scenario "Should update image cached_attachment field after valid file upload", :js do
login_as imageable.author
visit new_image_path(imageable_type: imageable.class.name,
imageable_id: imageable.id)
attach_image("spec/fixtures/files/clippy.jpg", true)
expect(page).to have_css("input[name='image[cached_attachment]'][value$='.jpg']", visible: false)
end
scenario "Should not update image cached_attachment field after invalid file upload", :js do
login_as imageable.author
visit new_image_path(imageable_type: imageable.class.name,
imageable_id: imageable.id)
attach_image("spec/fixtures/files/logo_header.png", false)
expect(page).to have_selector ".loading-bar.errors"
expect(find("input[name='image[cached_attachment]']", visible: false).value).to eq("")
end
end
context "Create" do
scenario "Should show validation errors" do
login_as imageable.author
visit new_image_path(imageable_type: imageable.class.name,
imageable_id: imageable.id)
click_on "Upload image"
expect(page).to have_content "3 errors prevented this Image from being saved: "
expect(page).to have_selector "small.error", text: "can't be blank", count: 2
end
scenario "Should show error notice after unsuccessfull image upload" do
login_as imageable.author
visit new_image_path(imageable_type: imageable.class.name,
imageable_id: imageable.id,
from: send(imageable_path, imageable_arguments))
attach_file :image_attachment, "spec/fixtures/files/empty.pdf"
click_on "Upload image"
expect(page).to have_content "Cannot create image. Check form errors and try again."
end
scenario "Should show success notice after successfull image upload" do
login_as imageable.author
visit new_image_path(imageable_type: imageable.class.name,
imageable_id: imageable.id,
from: send(imageable_path, imageable_arguments))
fill_in :image_title, with: "Image title"
attach_file :image_attachment, "spec/fixtures/files/clippy.jpg"
click_on "Upload image"
expect(page).to have_content "Image was created successfully."
end
scenario "Should redirect to imageable path after successfull image upload" do
login_as imageable.author
visit new_image_path(imageable_type: imageable.class.name,
imageable_id: imageable.id,
from: send(imageable_path, imageable_arguments))
fill_in :image_title, with: "Image title"
attach_file :image_attachment, "spec/fixtures/files/clippy.jpg"
click_on "Upload image"
within "##{dom_id(imageable)}" do
expect(page).to have_selector "h1", text: imageable.title
end
end
scenario "Should show new image on imageable images tab after successfull image upload" do
login_as imageable.author
visit new_image_path(imageable_type: imageable.class.name,
imageable_id: imageable.id,
from: send(imageable_path, imageable_arguments))
fill_in :image_title, with: "Image title"
attach_file :image_attachment, "spec/fixtures/files/clippy.jpg"
click_on "Upload image"
expect(page).to have_content "Image title"
end
end
context "Destroy" do