Merge pull request #4586 from consul/attach_with_keyboard

Allow attaching files using the keyboard
This commit is contained in:
Javi Martín
2021-07-15 00:19:27 +02:00
committed by GitHub
40 changed files with 324 additions and 450 deletions

View File

@@ -57,7 +57,7 @@
<% if feature?(:allow_images) %>
<div class="images small-12 column">
<%= render "images/nested_image", imageable: @phase, f: f %>
<%= render "images/nested_image", f: f %>
<p class="help-text"><%= t("admin.budget_phases.edit.image_description") %></p>
</div>
<% end %>

View File

@@ -41,7 +41,7 @@
<% if feature?(:allow_images) %>
<div class="images small-12 column">
<%= render "/images/nested_image", imageable: budget, f: f %>
<%= render "/images/nested_image", f: f %>
<p class="help-text"><%= t("admin.budgets.edit.image_description") %></p>
</div>
<% end %>

View File

@@ -38,13 +38,13 @@
<% if feature?(:allow_images) %>
<div class="images">
<%= render "images/nested_image", imageable: investment, f: f %>
<%= render "images/nested_image", f: f %>
</div>
<% end %>
<% if feature?(:allow_attached_documents) %>
<div class="documents">
<%= render "documents/nested_documents", documentable: investment, f: f %>
<%= render "documents/nested_documents", f: f %>
</div>
<% end %>

View File

@@ -0,0 +1,28 @@
<div class="document direct-upload document-fields nested-fields">
<%= f.hidden_field :id %>
<%= f.hidden_field :user_id, value: current_user.id %>
<%= f.hidden_field :cached_attachment %>
<div class="small-12 column title">
<%= f.text_field :title, placeholder: t("documents.form.title_placeholder") %>
</div>
<div class="small-12 column attachment-actions">
<p class="file-name small-9 column"><%= file_name %></p>
<div class="small-9 column action-add attachment-errors document-attachment">
<%= file_field %>
</div>
<div class="small-3 column action-remove text-right">
<%= destroy_link %>
</div>
</div>
<div class="small-12 column">
<div class="progress-bar-placeholder"><div class="loading-bar"></div></div>
</div>
<hr>
</div>

View File

@@ -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

View File

@@ -0,0 +1,24 @@
<fieldset class="documents-list">
<legend><%= t("documents.form.title") %></legend>
<p class="help-text"><%= note %></p>
<div id="nested-documents" data-max-documents-allowed="<%= max_documents_allowed %>">
<%= f.fields_for :documents do |documents_builder| %>
<%= render Documents::FieldsComponent.new(documents_builder) %>
<% end %>
</div>
<%= 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"
} %>
<div id="max-documents-notice" class="max-documents-notice callout primary text-center <%= "hide" unless max_documents_allowed? %>">
<%= sanitize(t("documents.max_documents_allowed_reached")) %>
</div>
</fieldset>

View File

@@ -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

View File

@@ -0,0 +1,29 @@
<div class="image direct-upload nested-fields">
<%= f.hidden_field :id %>
<%= f.hidden_field :user_id, value: current_user.id %>
<%= f.hidden_field :cached_attachment %>
<div class="small-12 margin-top title">
<%= f.text_field :title, placeholder: t("images.form.title_placeholder") %>
</div>
<%= render_image(image, :thumb, false) if image.attachment.exists? %>
<div class="small-12 column attachment-actions">
<p class="file-name small-9 column"><%= file_name %></p>
<div class="small-9 column action-add attachment-errors image-attachment">
<%= file_field %>
</div>
<div class="small-3 column action-remove text-right">
<%= destroy_link %>
</div>
</div>
<div class="small-12 column">
<div class="progress-bar-placeholder"><div class="loading-bar"></div></div>
</div>
<hr>
</div>

View File

@@ -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

View File

@@ -0,0 +1,24 @@
<fieldset>
<legend><%= t("images.form.title") %></legend>
<p class="help-text"><%= note %></p>
<div id="nested-image">
<%= f.fields_for image_fields do |image_builder| %>
<%= render Images::FieldsComponent.new(image_builder, imageable: imageable) %>
<% end %>
</div>
<%= 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"
} %>
</fieldset>

View File

@@ -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

View File

@@ -39,13 +39,13 @@
<% if feature?(:allow_images) %>
<div class="images">
<%= render "images/nested_image", imageable: proposal, f: f %>
<%= render "images/nested_image", f: f %>
</div>
<% end %>
<% if feature?(:allow_attached_documents) %>
<div class="documents">
<%= render "documents/nested_documents", documentable: proposal, f: f %>
<%= render "documents/nested_documents", f: f %>
</div>
<% end %>