diff --git a/app/assets/javascripts/documentable.js b/app/assets/javascripts/documentable.js index b6b85ba8c..7aa9e1b29 100644 --- a/app/assets/javascripts/documentable.js +++ b/app/assets/javascripts/documentable.js @@ -17,11 +17,11 @@ App.Documentable.lockUploads(); } }); + App.Documentable.initializeRemoveCachedDocumentLinks(); }, initializeDirectUploadInput: function(input) { var inputData; inputData = this.buildData([], input); - this.initializeRemoveCachedDocumentLink(input, inputData); $(input).fileupload({ paramName: "attachment", formData: null, @@ -45,7 +45,6 @@ App.Documentable.setInputErrors(data); $(data.destroyAttachmentLinkContainer).find("a.delete:not(.remove-nested)").remove(); $(data.addAttachmentLabel).addClass("error"); - $(data.addAttachmentLabel).show(); }, done: function(e, data) { var destroyAttachmentLink; @@ -54,16 +53,8 @@ App.Documentable.setProgressBar(data, "complete"); App.Documentable.setFilename(data, data.result.filename); App.Documentable.clearInputErrors(data); - $(data.addAttachmentLabel).hide(); - $(data.wrapper).find(".attachment-actions").removeClass("small-12").addClass("small-6 float-right"); - $(data.wrapper).find(".attachment-actions .action-remove").removeClass("small-3").addClass("small-12"); destroyAttachmentLink = $(data.result.destroy_link); $(data.destroyAttachmentLinkContainer).html(destroyAttachmentLink); - $(destroyAttachmentLink).on("click", function(event) { - event.preventDefault(); - event.stopPropagation(); - App.Documentable.doDeleteCachedAttachmentRequest(this.href, data); - }); if (input.lockUpload) { App.Documentable.showNotice(); } @@ -78,8 +69,6 @@ buildData: function(data, input) { var wrapper; wrapper = $(input).closest(".direct-upload"); - data.input = input; - data.wrapper = wrapper; data.progressBar = $(wrapper).find(".progress-bar-placeholder"); data.errorContainer = $(wrapper).find(".attachment-errors"); data.fileNameContainer = $(wrapper).find("p.file-name"); @@ -92,7 +81,6 @@ }, clearFilename: function(data) { $(data.fileNameContainer).text(""); - $(data.fileNameContainer).hide(); }, clearInputErrors: function(data) { $(data.errorContainer).find("small.error").remove(); @@ -102,7 +90,6 @@ }, setFilename: function(data, file_name) { $(data.fileNameContainer).text(file_name); - $(data.fileNameContainer).show(); }, setProgressBar: function(data, klass) { $(data.progressBar).find(".loading-bar").addClass(klass); @@ -127,39 +114,10 @@ showNotice: function() { $("#max-documents-notice").removeClass("hide"); }, - doDeleteCachedAttachmentRequest: function(url, data) { - $.ajax({ - type: "POST", - url: url, - dataType: "json", - data: { - "_method": "delete" - }, - complete: function() { - $(data.cachedAttachmentField).val(""); - $(data.addAttachmentLabel).show(); - App.Documentable.clearFilename(data); - App.Documentable.clearInputErrors(data); - App.Documentable.clearProgressBar(data); - App.Documentable.unlockUploads(); - $(data.wrapper).find(".attachment-actions").addClass("small-12").removeClass("small-6 float-right"); - $(data.wrapper).find(".attachment-actions .action-remove").addClass("small-3").removeClass("small-12"); - if ($(data.input).data("nested-document") === true) { - $(data.wrapper).remove(); - } else { - $(data.wrapper).find("a.remove-cached-attachment").remove(); - } - } - }); - }, - initializeRemoveCachedDocumentLink: function(input, data) { - var remove_document_link, wrapper; - wrapper = $(input).closest(".direct-upload"); - remove_document_link = $(wrapper).find("a.remove-cached-attachment"); - $(remove_document_link).on("click", function(e) { - e.preventDefault(); - e.stopPropagation(); - App.Documentable.doDeleteCachedAttachmentRequest(this.href, data); + initializeRemoveCachedDocumentLinks: function() { + $("#nested-documents").on("ajax:complete", "a.remove-cached-attachment", function() { + App.Documentable.unlockUploads(); + $(this).closest(".direct-upload").remove(); }); }, removeDocument: function(id) { diff --git a/app/assets/javascripts/imageable.js b/app/assets/javascripts/imageable.js index 7f0773907..c2ee3e882 100644 --- a/app/assets/javascripts/imageable.js +++ b/app/assets/javascripts/imageable.js @@ -8,20 +8,17 @@ $("#nested-image").on("cocoon:after-remove", function() { $("#new_image_link").removeClass("hide"); }); - $("#nested-image").on("cocoon:before-insert", function() { - $(".js-image-attachment").closest(".image").remove(); - }); $("#nested-image").on("cocoon:after-insert", function(e, nested_image) { var input; $("#new_image_link").addClass("hide"); input = $(nested_image).find(".js-image-attachment"); App.Imageable.initializeDirectUploadInput(input); }); + App.Imageable.initializeRemoveCachedImageLinks(); }, initializeDirectUploadInput: function(input) { var inputData; inputData = this.buildData([], input); - this.initializeRemoveCachedImageLink(input, inputData); $(input).fileupload({ paramName: "attachment", formData: null, @@ -46,7 +43,6 @@ App.Imageable.clearPreview(data); $(data.destroyAttachmentLinkContainer).find("a.delete:not(.remove-nested)").remove(); $(data.addAttachmentLabel).addClass("error"); - $(data.addAttachmentLabel).show(); }, done: function(e, data) { var destroyAttachmentLink; @@ -55,17 +51,9 @@ App.Imageable.setProgressBar(data, "complete"); App.Imageable.setFilename(data, data.result.filename); App.Imageable.clearInputErrors(data); - $(data.addAttachmentLabel).hide(); - $(data.wrapper).find(".attachment-actions").removeClass("small-12").addClass("small-6 float-right"); - $(data.wrapper).find(".attachment-actions .action-remove").removeClass("small-3").addClass("small-12"); App.Imageable.setPreview(data); destroyAttachmentLink = $(data.result.destroy_link); $(data.destroyAttachmentLinkContainer).html(destroyAttachmentLink); - $(destroyAttachmentLink).on("click", function(event) { - event.preventDefault(); - event.stopPropagation(); - App.Imageable.doDeleteCachedAttachmentRequest(this.href, data); - }); }, progress: function(e, data) { var progress; @@ -77,7 +65,6 @@ buildData: function(data, input) { var wrapper; wrapper = $(input).closest(".direct-upload"); - data.input = input; data.wrapper = wrapper; data.progressBar = $(wrapper).find(".progress-bar-placeholder"); data.preview = $(wrapper).find(".image-preview"); @@ -92,7 +79,6 @@ }, clearFilename: function(data) { $(data.fileNameContainer).text(""); - $(data.fileNameContainer).hide(); }, clearInputErrors: function(data) { $(data.errorContainer).find("small.error").remove(); @@ -105,7 +91,6 @@ }, setFilename: function(data, file_name) { $(data.fileNameContainer).text(file_name); - $(data.fileNameContainer).show(); }, setProgressBar: function(data, klass) { $(data.progressBar).find(".loading-bar").addClass(klass); @@ -130,40 +115,10 @@ data.preview = $(data.wrapper).find(".image-preview"); } }, - doDeleteCachedAttachmentRequest: function(url, data) { - $.ajax({ - type: "POST", - url: url, - dataType: "json", - data: { - "_method": "delete" - }, - complete: function() { - $(data.cachedAttachmentField).val(""); - $(data.addAttachmentLabel).show(); - App.Imageable.clearFilename(data); - App.Imageable.clearInputErrors(data); - App.Imageable.clearProgressBar(data); - App.Imageable.clearPreview(data); - $("#new_image_link").removeClass("hide"); - $(data.wrapper).find(".attachment-actions").addClass("small-12").removeClass("small-6 float-right"); - $(data.wrapper).find(".attachment-actions .action-remove").addClass("small-3").removeClass("small-12"); - if ($(data.input).data("nested-image") === true) { - $(data.wrapper).remove(); - } else { - $(data.wrapper).find("a.remove-cached-attachment").remove(); - } - } - }); - }, - initializeRemoveCachedImageLink: function(input, data) { - var remove_image_link, wrapper; - wrapper = $(input).closest(".direct-upload"); - remove_image_link = $(wrapper).find("a.remove-cached-attachment"); - $(remove_image_link).on("click", function(e) { - e.preventDefault(); - e.stopPropagation(); - App.Imageable.doDeleteCachedAttachmentRequest(this.href, data); + initializeRemoveCachedImageLinks: function() { + $("#nested-image").on("ajax:complete", "a.remove-cached-attachment", function() { + $("#new_image_link").removeClass("hide"); + $(this).closest(".direct-upload").remove(); }); }, removeImage: function(id) { diff --git a/app/assets/stylesheets/mixins/uploads.scss b/app/assets/stylesheets/mixins/uploads.scss index f7fd718fc..570b65326 100644 --- a/app/assets/stylesheets/mixins/uploads.scss +++ b/app/assets/stylesheets/mixins/uploads.scss @@ -20,13 +20,17 @@ p { margin-bottom: 0; } + + &:focus-within label { + outline: $outline-focus; + } } .attachment-errors { > .js-image-attachment, > .js-document-attachment { - display: none; + @include element-invisible; ~ .error { display: inline-block; @@ -41,7 +45,17 @@ } .file-name { + padding-left: 0; margin-top: 0; + + &:empty { + display: none; + } + + &:not(:empty) + .document-attachment, + &:not(:empty) + .image-attachment { + display: none; + } } .loading-bar { diff --git a/app/components/admin/budget_phases/form_component.html.erb b/app/components/admin/budget_phases/form_component.html.erb index 3fcaab81c..45e8b65d4 100644 --- a/app/components/admin/budget_phases/form_component.html.erb +++ b/app/components/admin/budget_phases/form_component.html.erb @@ -57,7 +57,7 @@ <% if feature?(:allow_images) %>
- <%= render "images/nested_image", imageable: @phase, f: f %> + <%= render "images/nested_image", f: f %>

<%= t("admin.budget_phases.edit.image_description") %>

<% end %> diff --git a/app/components/admin/budgets/form_component.html.erb b/app/components/admin/budgets/form_component.html.erb index 6000b586d..ae286844e 100644 --- a/app/components/admin/budgets/form_component.html.erb +++ b/app/components/admin/budgets/form_component.html.erb @@ -41,7 +41,7 @@ <% if feature?(:allow_images) %>
- <%= render "/images/nested_image", imageable: budget, f: f %> + <%= render "/images/nested_image", f: f %>

<%= t("admin.budgets.edit.image_description") %>

<% end %> diff --git a/app/components/budgets/investments/form_component.html.erb b/app/components/budgets/investments/form_component.html.erb index 34283dbd8..3705bc10e 100644 --- a/app/components/budgets/investments/form_component.html.erb +++ b/app/components/budgets/investments/form_component.html.erb @@ -38,13 +38,13 @@ <% if feature?(:allow_images) %>
- <%= render "images/nested_image", imageable: investment, f: f %> + <%= render "images/nested_image", f: f %>
<% end %> <% if feature?(:allow_attached_documents) %>
- <%= render "documents/nested_documents", documentable: investment, f: f %> + <%= render "documents/nested_documents", f: f %>
<% end %> diff --git a/app/components/documents/fields_component.html.erb b/app/components/documents/fields_component.html.erb new file mode 100644 index 000000000..5822f89ba --- /dev/null +++ b/app/components/documents/fields_component.html.erb @@ -0,0 +1,28 @@ +
+ <%= f.hidden_field :id %> + <%= f.hidden_field :user_id, value: current_user.id %> + <%= f.hidden_field :cached_attachment %> + +
+ <%= f.text_field :title, placeholder: t("documents.form.title_placeholder") %> +
+ +
+

<%= file_name %>

+ +
+ <%= file_field %> +
+ +
+ <%= destroy_link %> +
+
+ +
+
+
+ +
+ +
diff --git a/app/components/documents/fields_component.rb b/app/components/documents/fields_component.rb new file mode 100644 index 000000000..3aa0126bf --- /dev/null +++ b/app/components/documents/fields_component.rb @@ -0,0 +1,54 @@ +class Documents::FieldsComponent < ApplicationComponent + attr_reader :f + delegate :current_user, to: :helpers + + def initialize(f) + @f = f + end + + private + + def document + f.object + end + + def file_name + document.attachment_file_name + end + + def destroy_link + if !document.persisted? && document.cached_attachment.present? + link_to t("documents.form.delete_button"), + direct_upload_destroy_path( + "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" + else + link_to_remove_association document.new_record? ? t("documents.form.cancel_button") : t("documents.form.delete_button"), f, class: "delete remove-document" + end + end + + def file_field + klass = document.persisted? || document.cached_attachment.present? ? " hide" : "" + f.file_field :attachment, + label_options: { class: "button hollow #{klass}" }, + accept: accepted_content_types_extensions, + class: "js-document-attachment", + data: { url: direct_upload_path } + end + + def direct_upload_path + direct_uploads_path("direct_upload[resource_type]": document.documentable_type, + "direct_upload[resource_id]": document.documentable_id, + "direct_upload[resource_relation]": "documents") + end + + def accepted_content_types_extensions + Setting.accepted_content_types_for("documents").map { |content_type| ".#{content_type}" }.join(",") + end +end diff --git a/app/components/documents/nested_component.html.erb b/app/components/documents/nested_component.html.erb new file mode 100644 index 000000000..743cd7be3 --- /dev/null +++ b/app/components/documents/nested_component.html.erb @@ -0,0 +1,24 @@ +
+ <%= t("documents.form.title") %> +

<%= note %>

+ +
+ <%= f.fields_for :documents do |documents_builder| %> + <%= render Documents::FieldsComponent.new(documents_builder) %> + <% end %> +
+ + <%= link_to_add_association t("documents.form.add_new_document"), f, :documents, + partial: "documents/document_fields", + id: "new_document_link", + class: "button upload-document + #{"hide" if max_documents_allowed?}", + data: { + association_insertion_node: "#nested-documents", + association_insertion_method: "append" + } %> + +
"> + <%= sanitize(t("documents.max_documents_allowed_reached")) %> +
+
diff --git a/app/components/documents/nested_component.rb b/app/components/documents/nested_component.rb new file mode 100644 index 000000000..a37587e81 --- /dev/null +++ b/app/components/documents/nested_component.rb @@ -0,0 +1,28 @@ +class Documents::NestedComponent < ApplicationComponent + attr_reader :f + delegate :documentable_humanized_accepted_content_types, :max_file_size, to: :helpers + + def initialize(f) + @f = f + end + + private + + def documentable + f.object + end + + def max_documents_allowed + documentable.class.max_documents_allowed + end + + def note + t "documents.form.note", max_documents_allowed: max_documents_allowed, + accepted_content_types: documentable_humanized_accepted_content_types(documentable.class), + max_file_size: max_file_size(documentable.class) + end + + def max_documents_allowed? + documentable.documents.count >= max_documents_allowed + end +end diff --git a/app/components/images/fields_component.html.erb b/app/components/images/fields_component.html.erb new file mode 100644 index 000000000..49d8f1fd8 --- /dev/null +++ b/app/components/images/fields_component.html.erb @@ -0,0 +1,29 @@ +
+ <%= f.hidden_field :id %> + <%= f.hidden_field :user_id, value: current_user.id %> + <%= f.hidden_field :cached_attachment %> + +
+ <%= f.text_field :title, placeholder: t("images.form.title_placeholder") %> +
+ + <%= render_image(image, :thumb, false) if image.attachment.exists? %> + +
+

<%= file_name %>

+ +
+ <%= file_field %> +
+ +
+ <%= destroy_link %> +
+
+ +
+
+
+ +
+
diff --git a/app/components/images/fields_component.rb b/app/components/images/fields_component.rb new file mode 100644 index 000000000..9b6ceb80d --- /dev/null +++ b/app/components/images/fields_component.rb @@ -0,0 +1,61 @@ +class Images::FieldsComponent < ApplicationComponent + attr_reader :f, :imageable + delegate :current_user, :render_image, to: :helpers + + def initialize(f, imageable:) + @f = f + @imageable = imageable + end + + private + + def image + f.object + end + + def file_name + image.attachment_file_name + end + + def destroy_link + if !image.persisted? && image.cached_attachment.present? + link_to t("images.form.delete_button"), + direct_upload_destroy_path( + "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" + else + link_to_remove_association t("images.form.delete_button"), f, class: "delete remove-image" + end + end + + def file_field + klass = image.persisted? || image.cached_attachment.present? ? " hide" : "" + f.file_field :attachment, + label_options: { class: "button hollow #{klass}" }, + accept: accepted_content_types_extensions, + class: "js-image-attachment", + data: { url: direct_upload_path } + end + + def direct_upload_path + direct_uploads_path("direct_upload[resource_type]": imageable.class.name, + "direct_upload[resource_id]": imageable.id, + "direct_upload[resource_relation]": "image") + end + + def accepted_content_types_extensions + Setting.accepted_content_types_for("images").map do |content_type| + if content_type == "jpg" + ".jpg,.jpeg" + else + ".#{content_type}" + end + end.join(",") + end +end diff --git a/app/components/images/nested_component.html.erb b/app/components/images/nested_component.html.erb new file mode 100644 index 000000000..0505ea4de --- /dev/null +++ b/app/components/images/nested_component.html.erb @@ -0,0 +1,24 @@ +
+ <%= t("images.form.title") %> +

<%= note %>

+ +
+ <%= f.fields_for image_fields do |image_builder| %> + <%= render Images::FieldsComponent.new(image_builder, imageable: imageable) %> + <% end %> +
+ + <%= link_to_add_association t("images.form.add_new_image"), f, image_fields, + force_non_association_create: true, + partial: "images/image_fields", + id: "new_image_link", + class: "button upload-image + #{"hide" if image_fields == :image && imageable.image.present?}", + render_options: { + locals: { imageable: imageable } + }, + data: { + association_insertion_node: "#nested-image", + association_insertion_method: "append" + } %> +
diff --git a/app/components/images/nested_component.rb b/app/components/images/nested_component.rb new file mode 100644 index 000000000..61087bcff --- /dev/null +++ b/app/components/images/nested_component.rb @@ -0,0 +1,20 @@ +class Images::NestedComponent < ApplicationComponent + attr_reader :f, :image_fields + delegate :imageable_humanized_accepted_content_types, :imageable_max_file_size, to: :helpers + + def initialize(f, image_fields: :image) + @f = f + @image_fields = image_fields + end + + private + + def imageable + f.object + end + + def note + t "images.form.note", accepted_content_types: imageable_humanized_accepted_content_types, + max_file_size: imageable_max_file_size + end +end diff --git a/app/components/proposals/form_component.html.erb b/app/components/proposals/form_component.html.erb index f1af97081..566391e58 100644 --- a/app/components/proposals/form_component.html.erb +++ b/app/components/proposals/form_component.html.erb @@ -39,13 +39,13 @@ <% if feature?(:allow_images) %>
- <%= render "images/nested_image", imageable: proposal, f: f %> + <%= render "images/nested_image", f: f %>
<% end %> <% if feature?(:allow_attached_documents) %>
- <%= render "documents/nested_documents", documentable: proposal, f: f %> + <%= render "documents/nested_documents", f: f %>
<% end %> diff --git a/app/controllers/admin/poll/questions/answers/images_controller.rb b/app/controllers/admin/poll/questions/answers/images_controller.rb index 37e4cfcc8..e39a8bc66 100644 --- a/app/controllers/admin/poll/questions/answers/images_controller.rb +++ b/app/controllers/admin/poll/questions/answers/images_controller.rb @@ -7,11 +7,9 @@ class Admin::Poll::Questions::Answers::ImagesController < Admin::Poll::BaseContr end def new - @answer = ::Poll::Question::Answer.find(params[:answer_id]) end def create - @answer = ::Poll::Question::Answer.find(params[:answer_id]) @answer.attributes = images_params if @answer.save diff --git a/app/helpers/documentables_helper.rb b/app/helpers/documentables_helper.rb index 74d7ccf0d..5dcffacb3 100644 --- a/app/helpers/documentables_helper.rb +++ b/app/helpers/documentables_helper.rb @@ -1,12 +1,4 @@ module DocumentablesHelper - def documentable_class(documentable) - documentable.class.name.parameterize(separator: "_") - end - - def max_documents_allowed(documentable) - documentable.class.max_documents_allowed - end - def max_file_size(documentable_class) documentable_class.max_file_size / Numeric::MEGABYTE end @@ -15,21 +7,7 @@ module DocumentablesHelper documentable_class.accepted_content_types end - def accepted_content_types_extensions(documentable_class) - Setting.accepted_content_types_for("documents").map { |content_type| ".#{content_type}" }.join(",") - end - def documentable_humanized_accepted_content_types(documentable_class) Setting.accepted_content_types_for("documents").join(", ") end - - def documentables_note(documentable) - t "documents.form.note", max_documents_allowed: max_documents_allowed(documentable), - accepted_content_types: documentable_humanized_accepted_content_types(documentable.class), - max_file_size: max_file_size(documentable.class) - end - - def max_documents_allowed?(documentable) - documentable.documents.count >= documentable.class.max_documents_allowed - end end diff --git a/app/helpers/documents_helper.rb b/app/helpers/documents_helper.rb index 574e971b9..3ff564a03 100644 --- a/app/helpers/documents_helper.rb +++ b/app/helpers/documents_helper.rb @@ -1,47 +1,4 @@ module DocumentsHelper - def document_attachment_file_name(document) - document.attachment_file_name - end - - def document_errors_on_attachment(document) - document.errors[:attachment].join(", ") if document.errors.key?(:attachment) - end - - def render_destroy_document_link(builder, document) - if !document.persisted? && document.cached_attachment.present? - link_to t("documents.form.delete_button"), - direct_upload_destroy_path( - "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" - else - link_to_remove_association document.new_record? ? t("documents.form.cancel_button") : t("documents.form.delete_button"), builder, class: "delete remove-document" - end - end - - def render_attachment(builder, document) - klass = document.persisted? || document.cached_attachment.present? ? " hide" : "" - builder.file_field :attachment, - label_options: { class: "button hollow #{klass}" }, - accept: accepted_content_types_extensions(document.documentable_type.constantize), - class: "js-document-attachment", - data: { - url: document_direct_upload_path(document), - nested_document: true - } - end - - def document_direct_upload_path(document) - direct_uploads_path("direct_upload[resource_type]": document.documentable_type, - "direct_upload[resource_id]": document.documentable_id, - "direct_upload[resource_relation]": "documents") - end - def document_item_link(document) info_text = "#{document.humanized_content_type} | #{number_to_human_size(document.attachment_file_size)}" diff --git a/app/helpers/imageables_helper.rb b/app/helpers/imageables_helper.rb index 16b49caf9..c0e4c4893 100644 --- a/app/helpers/imageables_helper.rb +++ b/app/helpers/imageables_helper.rb @@ -11,22 +11,7 @@ module ImageablesHelper Setting["uploads.images.content_types"]&.split(" ") || ["image/jpeg"] end - def imageable_accepted_content_types_extensions - Setting.accepted_content_types_for("images").map do |content_type| - if content_type == "jpg" - ".jpg,.jpeg" - else - ".#{content_type}" - end - end.join(",") - end - def imageable_humanized_accepted_content_types Setting.accepted_content_types_for("images").join(", ") end - - def imageables_note(_imageable) - t "images.form.note", accepted_content_types: imageable_humanized_accepted_content_types, - max_file_size: imageable_max_file_size - end end diff --git a/app/helpers/images_helper.rb b/app/helpers/images_helper.rb index b265e10ad..5f992a6b5 100644 --- a/app/helpers/images_helper.rb +++ b/app/helpers/images_helper.rb @@ -9,57 +9,14 @@ module ImagesHelper end end - def image_attachment_file_name(image) - image.attachment_file_name - end - - def image_errors_on_attachment(image) - image.errors[:attachment].join(", ") if image.errors.key?(:attachment) - end - def image_class(image) image.persisted? ? "persisted-image" : "cached-image" end - def render_destroy_image_link(builder, image) - if !image.persisted? && image.cached_attachment.present? - link_to t("images.form.delete_button"), - direct_upload_destroy_path( - "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" - else - link_to_remove_association t("images.form.delete_button"), builder, class: "delete remove-image" - end - end - - def render_image_attachment(builder, imageable, image) - klass = image.persisted? || image.cached_attachment.present? ? " hide" : "" - builder.file_field :attachment, - label_options: { class: "button hollow #{klass}" }, - accept: imageable_accepted_content_types_extensions, - class: "js-image-attachment", - data: { - url: image_direct_upload_path(imageable), - nested_image: true - } - end - def render_image(image, version, show_caption = true) version = image.persisted? ? version : :original render "images/image", image: image, version: version, show_caption: show_caption end - - def image_direct_upload_path(imageable) - direct_uploads_path("direct_upload[resource_type]": imageable.class.name, - "direct_upload[resource_id]": imageable.id, - "direct_upload[resource_relation]": "image") - end end diff --git a/app/views/admin/dashboard/actions/_form.html.erb b/app/views/admin/dashboard/actions/_form.html.erb index 810726868..178fe0596 100644 --- a/app/views/admin/dashboard/actions/_form.html.erb +++ b/app/views/admin/dashboard/actions/_form.html.erb @@ -62,7 +62,7 @@ <% if feature?(:allow_attached_documents) %>

- <%= render "documents/nested_documents", documentable: dashboard_action, f: f %> + <%= render "documents/nested_documents", f: f %>
<% end %> diff --git a/app/views/admin/legislation/processes/_form.html.erb b/app/views/admin/legislation/processes/_form.html.erb index 98ab0e51c..3094d4ccd 100644 --- a/app/views/admin/legislation/processes/_form.html.erb +++ b/app/views/admin/legislation/processes/_form.html.erb @@ -110,7 +110,7 @@
- <%= render "documents/nested_documents", documentable: @process, f: f %> + <%= render "documents/nested_documents", f: f %>
@@ -118,7 +118,7 @@
- <%= render "images/nested_image", imageable: @process, f: f %> + <%= render "images/nested_image", f: f %>
diff --git a/app/views/admin/milestones/_form.html.erb b/app/views/admin/milestones/_form.html.erb index 07fe07e8b..23314333f 100644 --- a/app/views/admin/milestones/_form.html.erb +++ b/app/views/admin/milestones/_form.html.erb @@ -27,10 +27,10 @@
<%= f.date_field :publication_date %> - <%= render "images/admin_image", imageable: @milestone, f: f %> + <%= render "images/nested_image", f: f %>
- <%= render "documents/nested_documents", documentable: @milestone, f: f %> + <%= render "documents/nested_documents", f: f %>
<%= f.submit nil, class: "button success" %> diff --git a/app/views/admin/poll/polls/_form.html.erb b/app/views/admin/poll/polls/_form.html.erb index b3ce9eaf3..926a98ce4 100644 --- a/app/views/admin/poll/polls/_form.html.erb +++ b/app/views/admin/poll/polls/_form.html.erb @@ -32,8 +32,8 @@
-
- <%= render "images/admin_image", imageable: @poll, f: f %> +
+ <%= render "images/nested_image", f: f %>
diff --git a/app/views/admin/poll/questions/answers/documents.html.erb b/app/views/admin/poll/questions/answers/documents.html.erb index 786c38cd9..71d6baeb5 100644 --- a/app/views/admin/poll/questions/answers/documents.html.erb +++ b/app/views/admin/poll/questions/answers/documents.html.erb @@ -15,7 +15,7 @@ <%= render "shared/errors", resource: @answer %>
- <%= render "documents/nested_documents", documentable: @answer, f: f %> + <%= render "documents/nested_documents", f: f %>
diff --git a/app/views/admin/poll/questions/answers/images/new.html.erb b/app/views/admin/poll/questions/answers/images/new.html.erb index a6e401047..fa373fbc1 100644 --- a/app/views/admin/poll/questions/answers/images/new.html.erb +++ b/app/views/admin/poll/questions/answers/images/new.html.erb @@ -5,7 +5,7 @@ <%= render "shared/errors", resource: @answer %>
- <%= render "images/nested_image", imageable: @answer, f: f, image_fields: :images %> + <%= render Images::NestedComponent.new(f, image_fields: :images) %>
<%= f.submit t("admin.questions.answers.images.save_image"), class: "button success" %> diff --git a/app/views/admin/widget/cards/_form.html.erb b/app/views/admin/widget/cards/_form.html.erb index 37676354b..606697f4d 100644 --- a/app/views/admin/widget/cards/_form.html.erb +++ b/app/views/admin/widget/cards/_form.html.erb @@ -45,7 +45,7 @@
- <%= render "images/nested_image", imageable: card, f: f %> + <%= render "images/nested_image", f: f %>
diff --git a/app/views/documents/_document_fields.html.erb b/app/views/documents/_document_fields.html.erb index 8f532c71b..6e452d9b2 100644 --- a/app/views/documents/_document_fields.html.erb +++ b/app/views/documents/_document_fields.html.erb @@ -1,31 +1 @@ -
- <%= f.hidden_field :id %> - <%= f.hidden_field :user_id, value: current_user.id %> - <%= f.hidden_field :cached_attachment %> - -
- <%= f.text_field :title, placeholder: t("documents.form.title_placeholder") %> -
- -
-
- <%= render_attachment(f, f.object) %> -
-
- <%= render_destroy_document_link(f, f.object) %> -
-
- -
-

- <%= document_attachment_file_name(f.object) %> -

-
- -
-
-
- -
- -
+<%= render Documents::FieldsComponent.new(f) %> diff --git a/app/views/documents/_nested_documents.html.erb b/app/views/documents/_nested_documents.html.erb index d4f80dd8e..229840e83 100644 --- a/app/views/documents/_nested_documents.html.erb +++ b/app/views/documents/_nested_documents.html.erb @@ -1,24 +1 @@ -
- <%= f.label :documents, t("documents.form.title") %> -

<%= documentables_note(documentable) %>

- -
- <%= f.fields_for :documents do |documents_builder| %> - <%= render "documents/document_fields", f: documents_builder %> - <% end %> -
- - <%= link_to_add_association t("documents.form.add_new_document"), f, :documents, - partial: "documents/document_fields", - id: "new_document_link", - class: "button upload-document - #{"hide" if max_documents_allowed?(documentable)}", - data: { - association_insertion_node: "#nested-documents", - association_insertion_method: "append" - } %> - -
"> - <%= sanitize(t("documents.max_documents_allowed_reached")) %> -
-
+<%= render Documents::NestedComponent.new(f) %> diff --git a/app/views/images/_admin_image.html.erb b/app/views/images/_admin_image.html.erb deleted file mode 100644 index 95ce0c752..000000000 --- a/app/views/images/_admin_image.html.erb +++ /dev/null @@ -1,40 +0,0 @@ -
-
- <%= f.label :image, t("images.form.admin_title") %> - - <%= link_to_add_association t("images.form.add_new_image"), f, :image, - force_non_association_create: true, - partial: "images/image_fields", - id: "new_image_link", - class: "button hollow", - render_options: { - locals: { imageable: imageable } - }, - data: { - association_insertion_node: "#nested-image", - association_insertion_method: "append" - } %> - - <%= render_image(f.object.image, :thumb, false) if f.object.image %> - -
- <%= f.fields_for :image do |image_builder| %> - -
- <%= image_builder.hidden_field :id %> - <%= image_builder.hidden_field :user_id, value: current_user.id %> - <%= image_builder.hidden_field :cached_attachment %> - - <%= image_builder.text_field :title, placeholder: t("images.form.title_placeholder"), label: "#{t("images.form.admin_alt_text")}" %> - -
-
- <%= render_image_attachment(image_builder, imageable, image_builder.object) %> -
-
-
- - <% end %> -
-
-
diff --git a/app/views/images/_image_fields.html.erb b/app/views/images/_image_fields.html.erb index 7fbfb0f01..0c3134c2a 100644 --- a/app/views/images/_image_fields.html.erb +++ b/app/views/images/_image_fields.html.erb @@ -1,32 +1 @@ -
- <%= f.hidden_field :id %> - <%= f.hidden_field :user_id, value: current_user.id %> - <%= f.hidden_field :cached_attachment %> - -
- <%= f.text_field :title, placeholder: t("images.form.title_placeholder") %> -
- - <%= render_image(f.object, :thumb, false) if f.object.attachment.exists? %> - -
-
- <%= render_image_attachment(f, imageable, f.object) %> -
-
- <%= render_destroy_image_link(f, f.object) %> -
-
- -
-

- <%= image_attachment_file_name(f.object) %> -

-
- -
-
-
- -
-
+<%= render Images::FieldsComponent.new(f, imageable: imageable) %> diff --git a/app/views/images/_nested_image.html.erb b/app/views/images/_nested_image.html.erb index fc8e6cc62..c55ccaa56 100644 --- a/app/views/images/_nested_image.html.erb +++ b/app/views/images/_nested_image.html.erb @@ -1,24 +1 @@ -<% image_fields ||= :image %> - -<%= f.label image_fields, t("images.form.title") %> -

<%= imageables_note(imageable) %>

- -
- <%= f.fields_for image_fields do |image_builder| %> - <%= render "images/image_fields", f: image_builder, imageable: imageable %> - <% end %> -
- -<%= link_to_add_association t("images.form.add_new_image"), f, image_fields, - force_non_association_create: true, - partial: "images/image_fields", - id: "new_image_link", - class: "button upload-image - #{"hide" if image_fields == :image && imageable.image.present?}", - render_options: { - locals: { imageable: imageable } - }, - data: { - association_insertion_node: "#nested-image", - association_insertion_method: "append" - } %> +<%= render Images::NestedComponent.new(f) %> diff --git a/app/views/legislation/proposals/_form.html.erb b/app/views/legislation/proposals/_form.html.erb index f1f8aef59..6e65c5ff1 100644 --- a/app/views/legislation/proposals/_form.html.erb +++ b/app/views/legislation/proposals/_form.html.erb @@ -28,12 +28,12 @@ <% if feature?(:allow_images) %>
- <%= render "images/nested_image", imageable: @proposal, f: f %> + <%= render "images/nested_image", f: f %>
<% end %>
- <%= render "documents/nested_documents", documentable: @proposal, f: f %> + <%= render "documents/nested_documents", f: f %>
diff --git a/config/locales/en/images.yml b/config/locales/en/images.yml index 480b3e232..02ee8d843 100644 --- a/config/locales/en/images.yml +++ b/config/locales/en/images.yml @@ -8,8 +8,6 @@ en: note: "You can upload one image of following content types: %{accepted_content_types}, up to %{max_file_size} MB." add_new_image: Add image title_placeholder: Add a descriptive title for the image - admin_title: "Image" - admin_alt_text: "Alternative text for the image" actions: destroy: notice: Image was deleted successfully. diff --git a/config/locales/es/images.yml b/config/locales/es/images.yml index edc299e1e..ed197fa7d 100644 --- a/config/locales/es/images.yml +++ b/config/locales/es/images.yml @@ -7,8 +7,6 @@ es: 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 - admin_title: "Imagen" - admin_alt_text: "Texto alternativo para la imagen" actions: destroy: notice: La imagen se ha eliminado correctamente. diff --git a/spec/shared/system/documentable.rb b/spec/shared/system/documentable.rb index 062d978c0..296da2bda 100644 --- a/spec/shared/system/documentable.rb +++ b/spec/shared/system/documentable.rb @@ -134,12 +134,3 @@ shared_examples "documentable" do |documentable_factory_name, documentable_path, end end end - -def attach_document(path, success = true) - attach_file :document_attachment, path, make_visible: true - if success - expect(page).to have_css ".loading-bar.complete" - else - expect(page).to have_css ".loading-bar.errors" - end -end diff --git a/spec/shared/system/imageable.rb b/spec/shared/system/imageable.rb index 6b39c17ea..59e08af32 100644 --- a/spec/shared/system/imageable.rb +++ b/spec/shared/system/imageable.rb @@ -30,14 +30,3 @@ shared_examples "imageable" do |imageable_factory_name, imageable_path, imageabl end end end - -def attach_image(path, success = true) - image = find(".image") - image_input = image.find("input[type=file]", visible: false) - attach_file image_input[:id], path, make_visible: true - if success - expect(page).to have_css ".loading-bar.complete" - else - expect(page).to have_css ".loading-bar.errors" - end -end diff --git a/spec/shared/system/nested_documentable.rb b/spec/shared/system/nested_documentable.rb index b6b1175a6..315eda144 100644 --- a/spec/shared/system/nested_documentable.rb +++ b/spec/shared/system/nested_documentable.rb @@ -77,12 +77,7 @@ shared_examples "nested documentable" do |login_as_name, documentable_factory_na click_link "Add new document" within "#nested-documents" do - document = find(".document input[type=file]", visible: :hidden) - attach_file( - document[:id], - Rails.root.join("spec/fixtures/files/empty.pdf"), - make_visible: true - ) + attach_file "Choose document", Rails.root.join("spec/fixtures/files/empty.pdf") expect(page).to have_css ".loading-bar.complete" end @@ -109,12 +104,7 @@ shared_examples "nested documentable" do |login_as_name, documentable_factory_na within "#nested-documents" do input = find("input[name$='[title]']") fill_in input[:id], with: "My Title" - document_input = find("input[type=file]", visible: :hidden) - attach_file( - document_input[:id], - Rails.root.join("spec/fixtures/files/empty.pdf"), - make_visible: true - ) + attach_file "Choose document", Rails.root.join("spec/fixtures/files/empty.pdf") expect(page).to have_css ".loading-bar.complete" end @@ -320,9 +310,8 @@ end def documentable_attach_new_file(path, success = true) click_link "Add new document" - document = all("#new_document").last - document_input = document.find("input[type=file]", visible: :hidden) - attach_file(document_input[:id], path, make_visible: true) + document = all(".document").last + attach_file "Choose document", path within document do if success diff --git a/spec/shared/system/nested_imageable.rb b/spec/shared/system/nested_imageable.rb index eddc3bab2..1560db273 100644 --- a/spec/shared/system/nested_imageable.rb +++ b/spec/shared/system/nested_imageable.rb @@ -38,12 +38,7 @@ shared_examples "nested imageable" do |imageable_factory_name, path, imageable_p visit send(path, arguments) click_link "Add image" - image_input = find(".image").find("input[type=file]", visible: :hidden) - attach_file( - image_input[:id], - Rails.root.join("spec/fixtures/files/clippy.jpg"), - make_visible: true - ) + attach_file "Choose image", Rails.root.join("spec/fixtures/files/clippy.jpg") expect(page).to have_selector ".file-name", text: "clippy.jpg" end @@ -67,12 +62,7 @@ shared_examples "nested imageable" do |imageable_factory_name, path, imageable_p click_link "Add image" input_title = find(".image input[name$='[title]']") fill_in input_title[:id], with: "Title" - image_input = find(".image").find("input[type=file]", visible: :hidden) - attach_file( - image_input[:id], - Rails.root.join("spec/fixtures/files/clippy.jpg"), - make_visible: true - ) + attach_file "Choose image", Rails.root.join("spec/fixtures/files/clippy.jpg") if has_many_images expect(find("input[id$='_title']").value).to eq "Title" @@ -271,8 +261,7 @@ def imageable_attach_new_file(_imageable_factory_name, path, success = true) click_link "Add image" within "#nested-image" do image = find(".image") - image_input = image.find("input[type=file]", visible: :hidden) - attach_file(image_input[:id], path, make_visible: true) + attach_file "Choose image", path within image do if success expect(page).to have_css(".loading-bar.complete") diff --git a/spec/system/admin/widgets/cards_spec.rb b/spec/system/admin/widgets/cards_spec.rb index dac6a03a7..9258e12e5 100644 --- a/spec/system/admin/widgets/cards_spec.rb +++ b/spec/system/admin/widgets/cards_spec.rb @@ -252,11 +252,8 @@ describe "Cards", :admin do def attach_image_to_card click_link "Add image" - image_input = all(".image").last.find("input[type=file]", visible: false) - attach_file( - image_input[:id], - Rails.root.join("spec/fixtures/files/clippy.jpg"), - make_visible: true) + attach_file "Choose image", Rails.root.join("spec/fixtures/files/clippy.jpg") + expect(page).to have_field("widget_card_image_attributes_title", with: "clippy.jpg") end end