Remove documents single uploads

This commit is contained in:
Senén Rodero Rodríguez
2017-09-27 11:04:56 +02:00
parent eef8ad1b73
commit 2993ef8707
11 changed files with 73 additions and 502 deletions

View File

@@ -1,24 +1,8 @@
class DocumentsController < ApplicationController class DocumentsController < ApplicationController
before_action :authenticate_user! before_action :authenticate_user!
before_action :find_documentable, except: :destroy
before_action :prepare_new_document, only: [:new]
before_action :prepare_document_for_creation, only: :create
load_and_authorize_resource load_and_authorize_resource
def new
end
def create
if @document.save
flash[:notice] = t "documents.actions.create.notice"
redirect_to params[:from]
else
flash[:alert] = t "documents.actions.create.alert"
render :new
end
end
def destroy def destroy
respond_to do |format| respond_to do |format|
format.html do format.html do
@@ -39,25 +23,4 @@ class DocumentsController < ApplicationController
end end
end end
private
def document_params
params.require(:document).permit(:title, :documentable_type, :documentable_id,
:attachment, :cached_attachment, :user_id)
end
def find_documentable
@documentable = params[:documentable_type].constantize.find_or_initialize_by(id: params[:documentable_id])
end
def prepare_new_document
@document = Document.new(documentable: @documentable, user_id: current_user.id)
end
def prepare_document_for_creation
@document = Document.new(document_params)
@document.documentable = @documentable
@document.user = current_user
end
end end

View File

@@ -1,9 +1,5 @@
module DocumentablesHelper module DocumentablesHelper
def can_create_document?(documentable)
can?(:create, Document.new(documentable: documentable)) && documentable.documents.size < documentable.class.max_documents_allowed
end
def documentable_class(documentable) def documentable_class(documentable)
documentable.class.name.parameterize('_') documentable.class.name.parameterize('_')
end end

View File

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

View File

@@ -4,12 +4,6 @@
<div class="small-12 medium-9 column"> <div class="small-12 medium-9 column">
<%= back_link_to budget_investments_path(investment.budget, heading_id: investment.heading) %> <%= back_link_to budget_investments_path(investment.budget, heading_id: investment.heading) %>
<% if can_create_document?(investment) %>
<%= link_to t("documents.upload_document"),
new_document_path(documentable_id:investment, documentable_type: investment.class.name, from: request.url),
class: 'button hollow float-right' %>
<% end %>
<% if can_destroy_image?(investment) %> <% if can_destroy_image?(investment) %>
<%= link_to t("images.remove_image"), <%= link_to t("images.remove_image"),
image_path(investment.image, from: request.url), image_path(investment.image, from: request.url),

View File

@@ -1,6 +1,6 @@
<% if documents.any? %> <% if documents.any? %>
<% if documents.size == max_documents_allowed && can?(:create, Document) %> <% if documents.size == max_documents_allowed && can?(:destroy, Document) %>
<div class="row documents-list"> <div class="row documents-list">
<div class="small-12 column"> <div class="small-12 column">
<div class="callout warning text-center"> <div class="callout warning text-center">

View File

@@ -1,63 +0,0 @@
<%= form_for @document,
url: documents_path(
documentable_type: @document.documentable_type,
documentable_id: @document.documentable_id,
from: params[:from]
),
html: { multipart: true, class: "documentable document-form" } do |f| %>
<%= render 'shared/errors', resource: @document %>
<div class="row document direct-upload">
<%= f.hidden_field :cached_attachment %>
<div class="small-12 column title">
<%= f.text_field :title, placeholder: t("documents.new.form.title_placeholder") %>
</div>
<div class="small-12 column attachment-actions">
<div class="small-6 column action-add attachment-errors">
<%= f.label :attachment, t("documents.form.attachment_label"), class: 'button hollow' %>
<%= f.file_field :attachment,
accept: accepted_content_types_extensions(@document.documentable.class),
label: false,
class: 'js-document-attachment',
data: {
url: direct_uploads_url("direct_upload[resource_type]": @document.documentable_type,
"direct_upload[resource_id]": @document.documentable_id,
"direct_upload[resource_relation]": "documents"),
cached_attachment_input_field: "document_cached_attachment",
title_input_field: "document_title"
} %>
</div>
<div class="small-6 column action-remove text-right">
<% if @document.cached_attachment.present? %>
<%= link_to t('documents.form.delete_button'),
direct_upload_destroy_url("direct_upload[resource_type]": @document.documentable_type,
"direct_upload[resource_id]": @document.documentable_id,
"direct_upload[resource_relation]": "documents",
"direct_upload[cached_attachment]": @document.cached_attachment),
method: :delete,
remote: true,
class: "delete remove-cached-attachment" %>
<% end %>
</div>
</div>
<div class="small-12 column">
<p class="file-name">
<%= document_attachment_file_name(@document) %>
</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("documents.form.submit_button"), class: "button expanded") %>
</div>
</div>
<% end %>

View File

@@ -108,18 +108,10 @@
</div> </div>
<aside class="small-12 medium-3 column"> <aside class="small-12 medium-3 column">
<% if can_create_document?(@proposal) || author_of_proposal?(@proposal) || current_editable?(@proposal) || <% if author_of_proposal?(@proposal) || current_editable?(@proposal) || can_destroy_image?(@proposal) %>
can_destroy_image?(@proposal) %>
<div class="sidebar-divider"></div> <div class="sidebar-divider"></div>
<h2><%= t("proposals.show.author") %></h2> <h2><%= t("proposals.show.author") %></h2>
<div class="show-actions-menu"> <div class="show-actions-menu">
<% if can_create_document?(@proposal) %>
<%= link_to new_document_path(documentable_id: @proposal, documentable_type: @proposal.class.name, from: request.url),
class: 'button hollow expanded' do %>
<span class="icon-document"></span>
<%= t("documents.upload_document") %>
<% end %>
<% end %>
<% if author_of_proposal?(@proposal) %> <% if author_of_proposal?(@proposal) %>
<%= link_to new_proposal_notification_path(proposal_id: @proposal.id), <%= link_to new_proposal_notification_path(proposal_id: @proposal.id),

View File

@@ -97,7 +97,7 @@ Rails.application.routes.draw do
resources :follows, only: [:create, :destroy] resources :follows, only: [:create, :destroy]
resources :documents, only: [:new, :create, :destroy] resources :documents, only: [:destroy]
resources :images, only: [:destroy] resources :images, only: [:destroy]

View File

@@ -81,16 +81,8 @@ describe "Abilities::Administrator" do
it { should be_able_to(:valuate, create(:budget_investment, budget: create(:budget, phase: 'valuating'))) } it { should be_able_to(:valuate, create(:budget_investment, budget: create(:budget, phase: 'valuating'))) }
it { should be_able_to(:valuate, create(:budget_investment, budget: create(:budget, phase: 'finished'))) } it { should be_able_to(:valuate, create(:budget_investment, budget: create(:budget, phase: 'finished'))) }
it { should be_able_to(:new, proposal_document) }
it { should be_able_to(:create, proposal_document) }
it { should be_able_to(:destroy, proposal_document) } it { should be_able_to(:destroy, proposal_document) }
it { should be_able_to(:new, budget_investment_document) }
it { should be_able_to(:create, budget_investment_document) }
it { should be_able_to(:destroy, budget_investment_document) } it { should be_able_to(:destroy, budget_investment_document) }
it { should be_able_to(:new, poll_question_document) }
it { should be_able_to(:create, poll_question_document) }
it { should be_able_to(:destroy, poll_question_document) } it { should be_able_to(:destroy, poll_question_document) }
it { should be_able_to(:destroy, proposal_image) } it { should be_able_to(:destroy, proposal_image) }

View File

@@ -92,20 +92,10 @@ describe "Abilities::Common" do
it { should_not be_able_to(:create, DirectMessage) } it { should_not be_able_to(:create, DirectMessage) }
it { should_not be_able_to(:show, DirectMessage) } it { should_not be_able_to(:show, DirectMessage) }
it { should be_able_to(:new, own_proposal_document) }
it { should be_able_to(:create, own_proposal_document) }
it { should be_able_to(:destroy, own_proposal_document) } it { should be_able_to(:destroy, own_proposal_document) }
it { should_not be_able_to(:new, proposal_document) }
it { should_not be_able_to(:create, proposal_document) }
it { should_not be_able_to(:destroy, proposal_document) } it { should_not be_able_to(:destroy, proposal_document) }
it { should be_able_to(:new, own_budget_investment_document) }
it { should be_able_to(:create, own_budget_investment_document) }
it { should be_able_to(:destroy, own_budget_investment_document) } it { should be_able_to(:destroy, own_budget_investment_document) }
it { should_not be_able_to(:new, budget_investment_document) }
it { should_not be_able_to(:create, budget_investment_document) }
it { should_not be_able_to(:destroy, budget_investment_document) } it { should_not be_able_to(:destroy, budget_investment_document) }
it { should be_able_to(:destroy, own_proposal_image) } it { should be_able_to(:destroy, own_proposal_image) }

View File

@@ -1,7 +1,5 @@
shared_examples "documentable" do |documentable_factory_name, documentable_path, documentable_path_arguments| shared_examples "documentable" do |documentable_factory_name, documentable_path, documentable_path_arguments|
include ActionView::Helpers include ActionView::Helpers
include DocumentsHelper
include DocumentablesHelper
let!(:administrator) { create(:user) } let!(:administrator) { create(:user) }
let!(:user) { create(:user) } let!(:user) { create(:user) }
@@ -17,55 +15,7 @@ shared_examples "documentable" do |documentable_factory_name, documentable_path,
end end
end end
context "Show" do context "Show documents tab" do
scenario "Should not display upload document button when there is no logged user" do
visit send(documentable_path, arguments)
within "##{dom_id(documentable)}" do
expect(page).not_to have_link("Upload document")
end
end
scenario "Should not display upload document button when maximum number of documents reached " do
create_list(:document, 3, documentable: documentable)
visit send(documentable_path, arguments)
within "##{dom_id(documentable)}" do
expect(page).not_to have_link("Upload document")
end
end
scenario "Should display upload document button when user is logged in and is documentable owner" do
login_as(user)
visit send(documentable_path, arguments)
within "##{dom_id(documentable)}" do
expect(page).to have_link("Upload document")
end
end
scenario "Should display upload document button when admin is logged in" do
login_as(administrator)
visit send(documentable_path, arguments)
within "##{dom_id(documentable)}" do
expect(page).to have_link("Upload document")
end
end
scenario "Should navigate to new document page when click un upload button" do
login_as(user)
visit send(documentable_path, arguments)
click_link "Upload document"
expect(page).to have_selector("h1", text: "Upload document")
end
describe "Documents tab" do
let!(:document) { create(:document, documentable: documentable, user: documentable.author)} let!(:document) { create(:document, documentable: documentable, user: documentable.author)}
@@ -144,249 +94,6 @@ shared_examples "documentable" do |documentable_factory_name, documentable_path,
end end
end
context "New" do
scenario "Should not be able for unathenticated users" do
visit new_document_path(documentable_type: documentable.class.name,
documentable_id: documentable.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_document_path(documentable_type: documentable.class.name,
documentable_id: documentable.id)
expect(page).to have_content("You do not have permission to carry out the action 'new' on document. ")
end
scenario "Should be able to documentable author" do
login_as documentable.author
visit new_document_path(documentable_type: documentable.class.name,
documentable_id: documentable.id)
expect(page).to have_selector("h1", text: "Upload document")
end
scenario "Should display file name after file selection", :js do
login_as documentable.author
visit new_document_path(documentable_type: documentable.class.name,
documentable_id: documentable.id)
attach_file :document_attachment, "spec/fixtures/files/empty.pdf", make_visible: true
expect(page).to have_content "empty.pdf"
end
scenario "Should not display file name after file selection", :js do
login_as documentable.author
visit new_document_path(documentable_type: documentable.class.name,
documentable_id: documentable.id)
attach_document("spec/fixtures/files/logo_header.png", false)
expect(page).not_to have_content "logo_header.jpg"
end
scenario "Should update loading bar style after valid file upload", :js do
login_as documentable.author
visit new_document_path(documentable_type: documentable.class.name,
documentable_id: documentable.id)
attach_document("spec/fixtures/files/empty.pdf", true)
expect(page).to have_selector ".loading-bar.complete"
end
scenario "Should update loading bar style after unvalid file upload", :js do
login_as documentable.author
visit new_document_path(documentable_type: documentable.class.name,
documentable_id: documentable.id)
attach_document("spec/fixtures/files/logo_header.png", false)
expect(page).to have_selector ".loading-bar.errors"
end
scenario "Should update document title with attachment original file name after valid upload if no title defined by user", :js do
login_as documentable.author
visit new_document_path(documentable_type: documentable.class.name,
documentable_id: documentable.id)
attach_document("spec/fixtures/files/empty.pdf", true)
expect(find("input#document_title").value).to eq("empty.pdf")
end
scenario "Should update document title with attachment original file name after invalid upload if no title defined by user", :js do
login_as documentable.author
visit new_document_path(documentable_type: documentable.class.name,
documentable_id: documentable.id)
attach_document("spec/fixtures/files/logo_header.png", false)
expect(find("input#document_title").value).to be_empty
end
scenario "Should not update document title with attachment original file name after file selection when title already defined by user", :js do
login_as documentable.author
visit new_document_path(documentable_type: documentable.class.name,
documentable_id: documentable.id)
fill_in :document_title, with: "My custom title"
attach_document("spec/fixtures/files/empty.pdf", true)
expect(find("input[name='document[title]']").value).to eq("My custom title")
end
scenario "Should update document cached_attachment field after valid file upload", :js do
login_as documentable.author
visit new_document_path(documentable_type: documentable.class.name,
documentable_id: documentable.id)
attach_document("spec/fixtures/files/empty.pdf", true)
expect(page).to have_css("input[name='document[cached_attachment]'][value$='.pdf']", visible: false)
end
scenario "Should not show 'Choose document' button after valid upload", :js do
login_as documentable.author
visit new_document_path(documentable_type: documentable.class.name,
documentable_id: documentable.id)
attach_file :document_attachment, "spec/fixtures/files/empty.pdf", make_visible: true
sleep 1
expect(page).not_to have_content "Choose document"
end
scenario "Should show 'Remove document' button after valid upload", :js do
login_as documentable.author
visit new_document_path(documentable_type: documentable.class.name,
documentable_id: documentable.id)
attach_file :document_attachment, "spec/fixtures/files/empty.pdf", make_visible: true
sleep 1
expect(page).to have_link("Remove document")
end
scenario "Should show 'Choose document' button after remove valid upload", :js do
login_as documentable.author
visit new_document_path(documentable_type: documentable.class.name,
documentable_id: documentable.id)
attach_file :document_attachment, "spec/fixtures/files/empty.pdf", make_visible: true
sleep 1
click_link "Remove document"
sleep 1
expect(page).to have_content "Choose document"
end
scenario "Should not update document cached_attachment field after unvalid file upload", :js do
login_as documentable.author
visit new_document_path(documentable_type: documentable.class.name,
documentable_id: documentable.id)
attach_document("spec/fixtures/files/logo_header.png", false)
expect(find("input[name='document[cached_attachment]']", visible: false).value).to eq("")
end
scenario "Should show documentable custom recomentations" do
login_as documentable.author
visit new_document_path(documentable_type: documentable.class.name,
documentable_id: documentable.id,
from: send(documentable_path, arguments))
expect(page).to have_content "You can upload up to a maximum of #{max_file_size(documentable.class)} documents."
expect(page).to have_content "You can upload #{documentable_humanized_accepted_content_types(documentable.class)} files."
expect(page).to have_content "You can upload files up to #{max_file_size(documentable.class)} MB."
end
end
context "Create" do
scenario "Should show validation errors" do
login_as documentable.author
visit new_document_path(documentable_type: documentable.class.name,
documentable_id: documentable.id)
click_on "Upload document"
expect(page).to have_content "2 errors prevented this Document 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 document upload" do
login_as documentable.author
visit new_document_path(documentable_type: documentable.class.name,
documentable_id: documentable.id,
from: send(documentable_path, arguments))
attach_file :document_attachment, "spec/fixtures/files/empty.pdf"
click_on "Upload document"
expect(page).to have_content "Cannot create document. Check form errors and try again."
end
scenario "Should show success notice after successfull document upload" do
login_as documentable.author
visit new_document_path(documentable_type: documentable.class.name,
documentable_id: documentable.id,
from: send(documentable_path, arguments))
fill_in :document_title, with: "Document title"
attach_file :document_attachment, "spec/fixtures/files/empty.pdf"
click_on "Upload document"
expect(page).to have_content "Document was created successfully."
end
scenario "Should redirect to documentable path after successfull document upload" do
login_as documentable.author
visit new_document_path(documentable_type: documentable.class.name,
documentable_id: documentable.id,
from: send(documentable_path, arguments))
fill_in :document_title, with: "Document title"
attach_file :document_attachment, "spec/fixtures/files/empty.pdf"
click_on "Upload document"
within "##{dom_id(documentable)}" do
expect(page).to have_selector "h1", text: documentable.title
end
end
scenario "Should show new document on documentable documents tab after successfull document upload" do
login_as documentable.author
visit new_document_path(documentable_type: documentable.class.name,
documentable_id: documentable.id,
from: send(documentable_path, arguments))
fill_in :document_title, with: "Document title"
attach_file :document_attachment, "spec/fixtures/files/empty.pdf"
click_on "Upload document"
expect(page).to have_link "Documents (1)"
within "#tab-documents" do
within "#document_#{Document.last.id}" do
expect(page).to have_content "Document title"
expect(page).to have_link "Dowload file"
expect(page).to have_link "Destroy"
end
end
end
end
context "Destroy" do context "Destroy" do
let!(:document) { create(:document, documentable: documentable, user: documentable.author) } let!(:document) { create(:document, documentable: documentable, user: documentable.author) }