diff --git a/app/javascript/controllers/file_input_controller.js b/app/javascript/controllers/file_input_controller.js new file mode 100644 index 0000000000..2264cd4d6d --- /dev/null +++ b/app/javascript/controllers/file_input_controller.js @@ -0,0 +1,48 @@ +import { Controller } from "@hotwired/stimulus"; + +/** + * Stimulus controller to enhance the file input UI for multiple files. + * + * This controller: + * - Listens for file selection on an `` + * - Displays selected file names in a custom list **when multiple files are selected + * - Defaults to the browser’s built-in display for a single file selection + * + * Expected HTML structure should have a placeholder div for the selected file names: + * + * ```erb + *
+ * + *
+ *
+ * ``` + */ +export default class extends Controller { + static targets = ["input", "list"]; + + connect() { + this.inputTarget.addEventListener("change", () => this.updateFileList()); + } + + updateFileList() { + const files = this.inputTarget.files; + this.listTarget.innerHTML = ""; // Clear previous list + + // If no files or only one file is selected, let the native UI handle it + if (files.length <= 1) { + return; + } + + const ul = document.createElement("ul"); + ul.classList.add("list-unstyled", "mt-2"); + + Array.from(files).forEach((file) => { + const li = document.createElement("li"); + li.classList.add("p-1", "rounded", "mb-1"); + li.textContent = file.name; + ul.appendChild(li); + }); + + this.listTarget.appendChild(ul); + } +} diff --git a/app/views/partners/profiles/step/_attached_documents_form.html.erb b/app/views/partners/profiles/step/_attached_documents_form.html.erb index 8b4bd51eb6..3952882c38 100644 --- a/app/views/partners/profiles/step/_attached_documents_form.html.erb +++ b/app/views/partners/profiles/step/_attached_documents_form.html.erb @@ -1,18 +1,24 @@ <%= f.fields_for :profile, profile do |pf| %> -
+
<% if profile.documents.attached? %> Attached files: -
<% end %> diff --git a/spec/system/partners/profile_edit_system_spec.rb b/spec/system/partners/profile_edit_system_spec.rb index 2f575490b4..2267cc6c9c 100644 --- a/spec/system/partners/profile_edit_system_spec.rb +++ b/spec/system/partners/profile_edit_system_spec.rb @@ -100,10 +100,11 @@ end it "preserves previously uploaded documents when adding new attachments" do - # Upload the first document + # Open attached documents section find("button[data-bs-target='#attached_documents']").click expect(page).to have_css("#attached_documents.accordion-collapse.collapse.show", visible: true) + # Upload the first document within "#attached_documents" do attach_file("partner_profile_documents", Rails.root.join("spec/fixtures/files/document1.md"), make_visible: true) end @@ -137,7 +138,47 @@ end end - it "persists file upload when there are validation errors" do + it "allows removal of attached documents" do + # Open attached documents section + find("button[data-bs-target='#attached_documents']").click + expect(page).to have_css("#attached_documents.accordion-collapse.collapse.show", visible: true) + + # Upload two documents - needs to be done individually because Capybara doesn't have attach_files multiple support + # https://github.com/teamcapybara/capybara/issues/37 + within "#attached_documents" do + attach_file("partner_profile_documents", Rails.root.join("spec/fixtures/files/document1.md"), make_visible: true) + end + all("input[type='submit'][value='Save Progress']").last.click + visit edit_partners_profile_path + find("button[data-bs-target='#attached_documents']").click + within "#attached_documents" do + attach_file("partner_profile_documents", Rails.root.join("spec/fixtures/files/document2.md"), make_visible: true) + end + all("input[type='submit'][value='Save Progress']").last.click + + # Remove the first document + visit edit_partners_profile_path + find("button[data-bs-target='#attached_documents']").click + within "#attached_documents" do + document_name = "document1.md" + document_li = find("li.attached-document", text: document_name) + document_li.find("a.btn-danger", text: "Remove").click + expect(page).not_to have_selector("li.attached-document", text: document_name) + end + + # Save Progress + all("input[type='submit'][value='Save Progress']").last.click + expect(page).to have_css(".alert-success", text: "Details were successfully updated.") + + # Verify only one document is listed + visit edit_partners_profile_path + find("button[data-bs-target='#attached_documents']").click + within "#attached_documents" do + expect(page).to have_link("document2.md") + end + end + + it "persists individual file upload when there are validation errors" do # Open up Agency Information section and upload proof-of-status letter find("button[data-bs-target='#agency_information']").click within "#agency_information" do