Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix edge case on saving profile attachments #4472

Open
2 tasks
cielf opened this issue Jun 23, 2024 · 33 comments · May be fixed by #4937
Open
2 tasks

Fix edge case on saving profile attachments #4472

cielf opened this issue Jun 23, 2024 · 33 comments · May be fixed by #4937

Comments

@cielf
Copy link
Collaborator

cielf commented Jun 23, 2024

Summary

There is a sequence on editing a profile with an upload that results in the file not being saved

Why fix?

Not saving things the users reasonably expect to be saved is not good... and we have seen the exception noted below in production.

Details

Recreation

Try this sequence:
Sign in as [email protected]
Edit My Organization
Choose a file for IRS Determination Letter
Change the numbers in Area Served so that it no longer adds up to 100
Click Update Information
gets an exception "Cannot get a signed_id for a new record"

What we need

That sequence should not produce an exception. If it is not going to result (after correcting other errors) in the file chosen being saved, we need to include that in the error messaging

Criteria for completion

  • The stated sequence works in a recoverable manner
  • Tests to demonstrate
@McEileen
Copy link
Contributor

Hi, is it all right if I start working on this issue?

@cielf
Copy link
Collaborator Author

cielf commented Nov 28, 2024

Yes, please.

@github-actions github-actions bot removed the Help Wanted Groomed + open to all! label Nov 28, 2024
@McEileen
Copy link
Contributor

McEileen commented Dec 5, 2024

Hi @cielf and team, could I please get some early feedback on my approach to fixing this bug? My plan was to prevent the user from being able to persist invalid changes to the profile. If they attach a document, change the client share to an invalid number, and then click update, they will see an alert at the top of the page. Also, the document won't be attached, and the changes to the client share won't be persisted.

This definitely breaks tests. Here is a compare link, so that you can see the very beginning of what I am suggesting.

What are your thoughts on this approach? Do you support it, or should I take a different tack?

Thanks!

@coalest
Copy link
Collaborator

coalest commented Dec 5, 2024

@McEileen I don't think this is the best approach. If we redirect when the update fails, then we lose all the changes the user made in the form. The partner profile has lots of fields. So it would be possible for the user to fill in a bunch of fields, click save, and then lose all of the new information they put in due to a validation error. Which could be pretty frustrating for users.

Have you seen this open Rail issue? Seems like people solve this issue in one of two ways: ActiveStorage direct uploads or adding a guard clause to make sure attachments have been persisted. Not sure which option the maintainers would prefer. But I think the second option (along with adding a flash message when an attachment failed to be persisted) is the one I would lean towards.

@cielf
Copy link
Collaborator Author

cielf commented Dec 5, 2024

@McEileen --- I am now wondering if work on this this issue might be in conflict with #4821 -- a rework of the profile attachments that @danielabar is working on. Certainly, @danielabar needs to know about this.

As for the technical aspects - I'm afraid I spend very little of my time with the code, so I'm going to ask @awwaiid or @dorner to chime in.

@coalest
Copy link
Collaborator

coalest commented Dec 6, 2024

I was reading a little more about direct uploads here and it mentions:

When a user is uploading a file to your server, instead of directly to storage, it is keeping one off your puma workers busy, and preventing it from serving other requests. If the user has a slow connection, or is uploading a large file, this can take a long time.

If you are running with only a few web servers with low concurrency (say, you are in Heroku, running 2 standard 2x web dynos) you might only have 4 of those workers. If two users are “slow clients”, you just halved your capacity for as long as they are uploading their files. Which means that your other users might take longer to navigate between pages, causing frustration and a bad experience.

So maybe it is worth implementing direct uploads? Only drawback I see is that it would require some CORS configuration in production.

What do you think @dorner?

@McEileen
Copy link
Contributor

McEileen commented Dec 6, 2024

I'm glad I asked for feedback!

@coalest, I hadn't seen that open Rails issue. Thanks for sharing it, it's very helpful. I'm curious what @dorner and @awwaiid think, too.

@cielf Thanks for flagging that work on this issue might be in conflict with #4821. Should I hold off on working on this issue until @danielabar is done with #4821? If so, I am happy to pick up another issue. Just let me know, thanks!

@cielf
Copy link
Collaborator Author

cielf commented Dec 7, 2024

Now I realize I was thinking this had to do with the "Additional Documents" upload, but it has to do with the IRS Determination Letter. I therefore think it probably doesn't conflict. So do please keep working on this one, if you want to.

@danielabar
Copy link
Collaborator

For the other issue #4821 , the bug occurs if a user saves one document, then comes back later to add another one, the first one disappears. But from the discussion on this ticket, it looks like there could be an unexpected interaction with document uploads and other form validation errors so I'll keep that in mind.

@danielabar
Copy link
Collaborator

There is a potentially simpler solution than direct uploads and CORS, which would prevent the 500 server error and let the user know they need to select the document again. See this comment and commits.

@dorner
Copy link
Collaborator

dorner commented Dec 14, 2024

@cielf should we combine these two issues? I feel like whatever solution we have probably should work for both of them.

I agree that ideally we should be able to keep track of files that were uploaded even when there are form errors and not ask the user to re-select them. @danielabar were you able to figure this out without direct upload?

@danielabar
Copy link
Collaborator

@dorner My solution is an "in between" - I can detect that there was a new doc attempt, but it all gets rolled back with the validation error. So my solution will inform the user via an alert that they need to fix the validation error(s), then re-attach the doc(s). It would look like this:
image

@danielabar
Copy link
Collaborator

@dorner As I wrote the above comment, just realized - given that it's possible to detect a new doc is being uploaded, it may also be possible to save, just that portion of the profile, even if there are validation errors in other fields. I'll investigate further.

@cielf
Copy link
Collaborator Author

cielf commented Dec 15, 2024

@McEileen -- If you haven't made real progress on this, it looks like there might be, not a conflict with, but synergy with just combining it with #4821. So it probably makes sense to have @danielabar work on both after all.

@McEileen
Copy link
Contributor

@cielf That makes sense. I will remove myself from this issue and @danielabar can be assigned to it. I'll look into picking up another issue.

@danielabar
Copy link
Collaborator

danielabar commented Dec 16, 2024

Sorry for long post, there's a few angles to consider. Here is some analysis on the problem and potential solutions.

This is reported specifically here but also affects #4821. More broadly, the problem occurs in any edit form in Rails that:

  • Is using ActiveStorage with default configuration (i.e. server side processing)
  • Contains both a file attachment: has_one_attached and/or has_many_attached
  • Displays the attached file name(s)
  • Contains other form fields that could result in a validation error when the model is saved

If a user uploads a new attachment(s) and fills out other form fields that result in a validation error, the following problems occur:

When the edit form re-renders, it attempts to display the attached file name(s). Since the user attempted an upload, there is an association to a document, however, it's not persisted. This results in the Cannot get a signed_id for a new record from view rendering, and the user gets a 500 Internal Server error page.

Another problem is that the file doesn't get uploaded and associated with the model, because this depends on the model being saved successfully. So the user would have to realize this and attempt their upload again. But they're currently on a 500 Error Page and are completely stuck.

This behaviour is described in the Rails Guide on Active Storage in the section on Form Validation.

Options

1. Avoid Error

The simplest solution to avoid the 500 error is to update the edit view to check if a document is persisted? before attempting to render it. For Partner Profile has_many_attached :documents association, it looks like this:

<% profile.documents.each do |doc| %>
  <% if doc.persisted? %>
    <li><%= link_to doc.blob['filename'], rails_blob_path(doc), class: "font-weight-bold" %></li>
  <% end %>
<% end %>

Note that some of the existing Partner Profile edit view partials are checking for attached?, but this returns true when the document is not persisted so it's insufficient as a safety check to avoid errors.

Pros

  • Technically simple, just a few changes in view form partials
  • User no longer gets blocking error page
  • View renders with validation errors as it usually does, which user can fix and submit again

Cons

  • User is not informed that their attachment(s) didn't go through, so they have to select it again, if they even realize that it didn't get saved

2. Avoid Error + Detection

Make the same view changes as in solution 1 above to avoid the error page.

PLUS

Change the controller update action: In the case of a validation error, check if user was attempting to upload document(s), and if yes, then display an additional alert that the document must be uploaded again.

Specifically for partner profile attached documents association, the updated controller action is:

module Partners
  class ProfilesController < BaseController
    def update
      # === CHECK IF USER IS ATTEMPTING AN UPLOAD ===
      new_document_uploaded = detect_new_documents?(profile_params)
      result = PartnerProfileUpdateService.new(current_partner, partner_params, profile_params).call

      if result.success?
        # Handle success...
      else
        flash.now[:error] = "There is a problem. Try again: %s" % result.error

        # === ALERT IN CASE OF VALIDATION ERROR AND UPLOAD ATTEMPT ===
        flash.now[:alert] = "The file you uploaded was not saved due to validation errors. Please reattach it after fixing the errors." if new_document_uploaded
        # ...
      end
    end

    private

    # === NEW METHOD TO CHECK IF USER WAS TRYING TO UPLOAD DOCS ===
    def detect_new_documents?(profile_params)
      profile_params[:documents].any? { |doc| doc.is_a?(ActionDispatch::Http::UploadedFile) }
    end
  end
end

Pros

  • Avoids the error page
  • Informs user that they need to select their document again
  • Still relatively simple technically

Cons

  • User needs to do additional work to reselect their document(s)
  • In the case of Partners::Profile model, there are a few different attachment fields, have to check them all
  • Controller logic getting cluttered, although maybe some of this could move into a service

3. Avoid Error + Detect + Force Save

Make the same view changes as in solution 1 above to avoid the error page.

PLUS

Change controller update action to forcefully save the uploaded documents if it detects that user was trying to upload, but there are other form validation errors. This is a rough attempt to do server side, what the ActiveStorage Direct Uploads feature is doing.

Here is some very experimental code but it has problems:

module Partners
  class ProfilesController < BaseController
    def update
      # === CHECK IF USER IS ATTEMPTING AN UPLOAD ===
      new_document_uploaded = detect_new_documents?(profile_params)
      result = PartnerProfileUpdateService.new(current_partner, partner_params, profile_params).call

      if result.success?
        # Handle success...
      else
        flash.now[:error] = "There is a problem. Try again: %s" % result.error
        # === TRY TO FORCEFULLY SAVE ===
        save_documents(profile_params) if new_document_uploaded
        # ...
      end
    end

    private

    # === NEW METHOD TO CHECK IF USER WAS TRYING TO UPLOAD DOCS ===
    def detect_new_documents?(profile_params)
      profile_params[:documents].any? { |doc| doc.is_a?(ActionDispatch::Http::UploadedFile) }
    end

    # === TRY TO FORCEFULLY SAVE DOC(S) ===
    def save_documents(profile_params)
      # We have to load the last saved (i.e. valid) profile from the database
      # to perform a save operation because anything based on `profile_params`
      # will contain validation errors.
      current_partner_profile_id = current_partner.profile.id
      temp_profile = Partners::Profile.find(current_partner_profile_id)

      # Grab the documents user was attempting to upload and save them
      documents = profile_params[:documents]
      temp_profile.documents.attach(documents)
      temp_profile.save!

      # Now we have a problem - if we simply return here, then the `current_partner.profile` model
      # will not display the attachment because it still has the old state.
      # So we can reload it so it reflects the fresh state from the database
      # BUT lose the invalid data which user should see to fix other validation errors
      current_partner.profile.reload
    end
  end
end

Pros

  • Avoids the error page
  • Saves the user's docs so they don't need to re-upload

Cons

  • Loses the model values that were invalid - the validation errors will still render, but the user won't see what they entered incorrectly (due to calling reload on the model in the controller update action)
  • Growing complexity in the controller
  • Feels like it's fighting Rails

4. Direct Uploads

UPDATE 2024-12-20: After doing some experimenting, it turns out Direct Upload will not help with associating a file with a model in the case of validation errors..

All of the above solutions involve server side processing. With Direct Uploads, it uses client side JavaScript to directly upload the file from the browser to the server.

Pros

  • Potentially the best user experience because their files should always be saved, independently of form validation errors
  • Potential performance benefits as it doesn't tie up a Puma thread processing slow file uploads
  • This is the "Rails way"

Cons

  • Additional devops work - requires configuring CORS on Azure Storage
  • Should there be any move to AWS S3 or other cloud storage provider, this work would have to be repeated there
  • Requires another cron job to Purge Unattached Uploads
  • Requires additional JavaScript on the edit views to handle various events
  • Unknown unknowns - this isn't used anywhere in Human Essentials currently, so we may discover some edge cases or unexpected interactions - for example user starts an upload, then quickly submits the form before upload is done, and then there's a validation error.

Suggestion

My inclination is for Option 2 (Avoid Error + Detection) as it resolves both issues in a relatively simple way.

Pending user feedback (for example - how often does it occur that user was uploading a doc and also encountered validation error), could add Option 4 as a future enhancement.

@cielf
Copy link
Collaborator Author

cielf commented Dec 16, 2024

Oh -- this definitely requires @dorner's input -- I have different opinions depending on his take on #4.

@dorner
Copy link
Collaborator

dorner commented Dec 18, 2024

I think we can safely say #1 and #3 have too many downsides to consider them.

#4 being "the Rails way" points me more towards it. There are things built into the framework designed to make this work without much effort. I'm not too fussed about the CORS setup, which is something that shouldn't take long to do.

The additional JS is just a couple of lines, so shouldn't matter much.

In general, if there's a general-purpose solution that's used by lots of other projects, I'd much prefer doing it that way. #2 is less work but it results in a less than ideal user experience.

The nice thing about this is that once it's done, we can put it in the application JS and it would work for any other documents we'd ever add. The cron job to purge attachments isn't urgent and can be a followup (we might not really need to do it at all - we probably won't see more than a handful of these every month/year/quarter).

@cielf
Copy link
Collaborator Author

cielf commented Dec 18, 2024

Ok -- since @dorner thinks #4 is workable (that's what I think I read), I would definitely be leaning that way too -- doing "The Rails Way" leads to better maintainability down the road, as people who are new to the project but not to Rails will understand it more readily.

@cielf
Copy link
Collaborator Author

cielf commented Dec 18, 2024

Also noting that we do have another document upload that this will apply to -- one on the partner itself which is meant for documents the bank sees about the partner, that the partner doesn't. I'm pretty sure that'll be the last one. There's a proto-issue in the hopper for that.

@danielabar
Copy link
Collaborator

danielabar commented Dec 20, 2024

Posting some early findings: Here's what happens when direct upload is enabled, and user submits a form with a new file attachment and form inputs that are invalid:

As soon as form submitted, direct upload begins from the browser to the storage service. And this completes successfully. Locally this results in a new file being persisted in the storage service. For example, output of my tree storage:

storage
└── 2y
    └── l4
        └── 2yl4phnzgh9jfvym8rvd7391cqpe

3 directories, 1 file

It also creates a new record in database table active_storage_blobs:

select * from active_storage_blobs;
 id |             key              | filename  |  content_type   | metadata | byte_size |         checksum         |         created_at         | service_name
----+------------------------------+-----------+-----------------+----------+-----------+--------------------------+----------------------------+--------------
  1 | 2yl4phnzgh9jfvym8rvd7391cqpe | dbase.pdf | application/pdf |          |      7171 | PnVMB8Sc/us7Jy4wxuy07w== | 2024-12-20 10:58:45.772687 | local
(1 row)

However, there is no record in active_storage_attachments, which is needed to associate a model with an attachment:

diaper_dev=# select * from active_storage_attachments;
 id | name | record_type | record_id | blob_id | created_at
----+------+-------------+-----------+---------+------------
(0 rows)

In the Rails server output, it starts processing the form update:

Started PATCH "/partners/profile"
...
TRANSACTION (0.9ms)  BEGIN

...
=== PREPARING FOR FILE STORAGE BY FINDING BLOB
ActiveStorage::Blob Load (0.6ms)  SELECT "active_storage_blobs".* FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
...

=== DETECTS VALIDATION ERROR
TRANSACTION (0.6ms)  ROLLBACK
05:58:46 web.1    |   ↳ app/services/partner_profile_update_service.rb:29:in `perform_profile_service'
05:58:46 web.1    | [!] PartnerProfileUpdateService failed to update profile for...

So even though the file has been uploaded successfully, Rails still won't associate the model with it due to the validation error.

And this leaves an orphan file in storage, which must be why the Rails Guides mention to have a cron job to periodically clean up.

Still Hope?

I found this blog post: https://justin.searls.co/posts/drive-by-active-storage-advice/

And if you do enable direct upload, you should realize that if validation fails when persisting the model after a form submission, the uploaded file will be orphaned by default upon re-render. This is bad. So to avoid it, you can do this weird thing I hacked together to render a hidden input and a file input with the exact same name.

I can attempt the hack mentioned in the blog post, but it would appear that there is no entirely Rails-way to solve this. This is also the kind of thing to keep an eye on if it would still work on future Rails upgrades.

@danielabar
Copy link
Collaborator

Related to above, just found this mention of a hidden field together with direct uploads in Rails Guide on ActiveStorage so maybe it's not a hack after all? https://guides.rubyonrails.org/v7.1/active_storage_overview.html#form-validation

Will investigate further.

@danielabar
Copy link
Collaborator

Doing some more experimenting with direct uploads, and hidden field to maintain the upload in case of form validation errors:

NOTE: direct upload only starts when user submits the form.

When the form renders with validation error, the blob has been uploaded to file storage and saved in the database. And the model current_partner.profile.proof_of_partner_status has in-memory an association to the file blob (the association is not persisted at this point, but it is in memory).

This means it can be rendered something like this:

<label class="control-label col-md-3">501(c)(3) IRS Determination Letter</label>
    === EXISTING SUCCESS CASE WHEN FILE IS FULLY ATTACHED AND PERSISTED ===
    <% if profile.proof_of_partner_status.persisted? %>
      <div class="col-md-8">
        Attached file: <%= link_to profile.proof_of_partner_status.blob['filename'], rails_blob_path(profile.proof_of_partner_status), class: "font-weight-bold" %>
        <%= pf.file_field :proof_of_partner_status, direct_upload: true, class: "form-control-file" %>
      </div>
    <% else %>
      <div class="col-md-8">

        === NEW LOGIC: SUBMIT HIDDEN FIELD WITH SIGNED_ID BECAUSE IT IS THERE IN MEMORY ===
        === ALSO SHOW USER A "DON'T WORRY" MESSAGE WITH THE FILE NAME ===
        <% if profile.proof_of_partner_status.attached? %>
          <%= pf.hidden_field :proof_of_partner_status, value: profile.proof_of_partner_status.signed_id %>
          Don't worry we haven't lost your upload of <span class="font-mono"><%= profile.proof_of_partner_status.blob.filename %></span>, you don't need to to upload it again
        <% end %>

        <div class="col-md-8">
        <%= pf.file_field :proof_of_partner_status, direct_upload: true, class: "form-control-file" %>
      </div>
    <% end %>

This works for the first time user is uploading the IRS letter, or if they already had one saved, and want to switch to another one.

Since there are multiple of these files, I could look into extracting that logic to a partial.

The has_many_attached for other documents requires further research because that also requires hidden fields just to maintain the existing ones if user is uploading one more.

NOTE: They still have to fix the validation errors and submit the form again successfully, in order for the file attachment to actually get associated with the model. i.e. if they abandon the form at this point, the file will not be associated with the profile.

@cielf Does this sound like a reasonable interaction to solve this issue?

@cielf
Copy link
Collaborator Author

cielf commented Dec 21, 2024

I'm not immediately getting why we can't show them the information where they would expect it.

@McEileen McEileen removed their assignment Dec 21, 2024
@danielabar
Copy link
Collaborator

danielabar commented Dec 22, 2024

The interaction would look like this:

  1. User arrives at edit profile and they haven't yet selected IRS letter - in this case, the file input shows "No file chosen" (default browser implementation of file input):
    image

  2. User clicks Choose File, then selects a file - now it shows the selected file name beside the Choose File button, again this is part of default browser implementation of file input:
    image

  3. User opens some other accordion section and fills it out invalid, eg: leaving all media fields empty and not selecting No Social Media Presence:
    image

  4. User clicks Save Progress (today, this results in the Error Page) - on my branch, it now shows the validation error about social media presence, and opens the Media information section so user can correct their error:
    image

  5. By default, Rails Active Storage (whether server processed or direct upload) will not associate the file to the profile model in this case because it hasn't been saved successfully. However, on my branch I've added a hidden field and some logic to maintain it, but it will look different than the browser default rendering of file input. Should the user happen to re-open Agency Info section, they see this:
    image

  6. User fixes validation error by specifying a Website:
    image

  7. After clicking Save Progress, the form, including Website field AND file they selected previously are saved:
    image

All of this is committed on my branch if you want to try it out: https://github.com/danielabar/human-essentials/tree/4472-partner-profile-files-direct-upload

@cielf
Copy link
Collaborator Author

cielf commented Jan 5, 2025

I'm not clear on why we can't show the name of the file in the intervening bit.

@cielf
Copy link
Collaborator Author

cielf commented Jan 5, 2025

Hrm - I tried it out and it wasn't preserving the file information if you change the attached file, then have an error, then fix the error.

@danielabar
Copy link
Collaborator

@cielf

I'm not clear on why we can't show the name of the file in the intervening bit.

We can, but not (easily) in the default browser's rendering of the file input type. In this case, the file name the user selected when they submitted the form with a validation error is displayed in the "don't worry, we still have your file" message:
image

However, since this project uses Bootstrap and Simpleform gem, it might be possible to replace the look (and behaviour) of the default browser file input with something custom. When it's custom, it may be possible to control it to look as if the user has selected a file even when they haven't (in that rendering).

Some experimental work on my branch:
image

image image

Let me know if that's on the right track? If yes, I can work on extracting a partial so the same logic can work on the other files. (Although the multiple case will be a different complexity, there's another issue for that one, also assigned to me).

I tried it out and it wasn't preserving the file information if you change the attached file, then have an error, then fix the error.

For me it does save the file when the form is submitted with the validation error fixed. Can you list the steps in a little more detail to reproduce?

@cielf
Copy link
Collaborator Author

cielf commented Jan 13, 2025

Sorry for taking so long to get to this.

I think we might be barking up the wrong tree a bit (and as usual, it's on me).

The simplest thing to do might be to just say "Attached file:", instead of all the "Don't worry..." which I think might actually make the partners worry more when they weren't worrying before?

Yes -- technically it's not actually attached yet. But it will be if they successfully save, and none of the other information they have entered will be saved unless they save successfully, so it is still consistent.

@cielf
Copy link
Collaborator Author

cielf commented Jan 13, 2025

In the whole keeping things consistent vein, though -- please also look at how we are handling the file uploads on the partner (as opposed to the profile). This is just as input into your work -- In an ideal world, we should be doing the same sort of thing across the board.

@cielf
Copy link
Collaborator Author

cielf commented Jan 13, 2025

And yeah -- what you have now does seem to handling showing the file with error properly.

@danielabar
Copy link
Collaborator

danielabar commented Jan 18, 2025

@cielf I've removed the "don't worry" message.

I'm currently work-in-progress on a re-usable solution for the custom file input. Features will include:

  • Boostrap look & feel to match existing forms
  • Ability to display/save user's previously selected file in case they submitted the form with a validation error

This could eventually be used to replace all file inputs, but might want to limit this to Partner Profile to limit the scope. The work here will include:

  • Single file attachments for Partner Profile
    • 501(c)(3) IRS Determination Letter
    • Form 990 Filed
  • Handle both step-wise and legacy form editing (has step-wise feature been turned on in production? maybe we could get rid of the old legacy all-in-one form as a follow-on?)
  • Enhance system tests for step-wise and legacy profile editing wrt file uploads under success and error conditions

NOTE: This will handle single file attachments. The multiple case has other complexities, there's a different issue to deal with that: #4821

@cielf
Copy link
Collaborator Author

cielf commented Jan 18, 2025

Yes, Step wise has been turned on in prod. And yes, we will be getting rid of the old legacy form as a follow-on. I'll talk with the planning group about timing on that tomorrow.

danielabar added a commit to danielabar/human-essentials that referenced this issue Jan 20, 2025
Ensure Active Storage direct uploads retain selected files during form
resubmissions when validation errors occur. This improves the user
experience by avoiding the need to re-select files.

- Add a custom file input partial styled with Bootstrap to display
  file names for new and previously uploaded files.
- Include a hidden field with the signed ID of uploaded files for
  re-association after successful submission.
- Create a Stimulus controller (`file-input-label`) to dynamically
  update labels with the selected file name or default text.
- Update forms in `Partners::Profiles` to use the shared file upload
  partial.
- Add a system test to validate the persistence of file uploads
  through validation errors and final submission.
danielabar added a commit to danielabar/human-essentials that referenced this issue Jan 22, 2025
Static error pages were previously loading the entire app's JavaScript,
including components like ActiveStorage, which aren't needed on these
pages. This was causing JavaScript console errors in system tests due to
missing importmap references for ActiveStorage. Instead of adding
unnecessary imports, this commit removes the JavaScript from the
static error pages.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants