Using the `document` or `documents` classes meant styles defined for the
public list of documents conflict with these ones.
So now we're using HTML classes that match the name of the Ruby
component classes, as we usually do.
We were adding <div> tags with the `images` or `documents` HTML class
prettly much every time we rendered a NestedComponent. We're now
including the HTML class inside the component, as we usually do.
We're also rendering the nested components directly, since it's been a
while since the partials were changed to simply render the components.
For the HashAlignment rule, we're using the default `key` style (keys
are aligned and values aren't) instead of the `table` style (both keys
and values are aligned) because, even if we used both in the
application, we used the `key` style a lot more. Furthermore, the
`table` style looks strange in places where there are both very long and
very short keys and sometimes we weren't even consistent with the
`table` style, aligning some keys without aligning other keys.
Ideally we could align hashes to "either key or table", so developers
can decide whether keeping the symmetry of the code is worth it in a
case-per-case basis, but Rubocop doesn't allow this option.
We were using helper methods inside the model; we might as well include
them in the model and use them from anywhere else.
Note we're using a different logic for images and documents methods.
That's because for images the logic was defined in the helper methods,
but for documents the logic is defined in the Documentable concern. In
the past, different documentable classes allowed different content
types, while imageable classes have always allowed the same content
types.
I'm not sure which method is better; for now, I'm leaving it the way it
was (except for the fact that we're removing the helper methods).
Our previous system to delete cached attachments didn't work for
documents because the `custom_hash_data` is different for files created
from a file and files created from cached attachments.
When creating a document attachment, the name of the file is taken into
account to calculate the hash. Let's say the original file name is
"logo.pdf", and the generated hash is "123456". The cached attachment
will be "123456.pdf", so the generated hash using the cached attachment
will be something different, like "28af3". So the file that will be
removed will be "28af3.pdf", and not "123456.pdf", which will still be
present.
Furthermore, there are times where users choose a file and then they
close the browser or go to a different page. In those cases, we weren't
deleting the cached attachments either.
So we're adding a rake task to delete these files once a day. This way
we can simplify the logic we were using to destroy cached attachments.
Note there's related a bug in documents: when editing a record (for
example, a proposal), if the title of the document changes, its hash
changes, and so it will be impossible to generate a link to that
document. Changing the way this hash is generated is not an option
because it would break links to existing files. We'll try to fix it when
moving to Active Storage.
We were hiding the file input and styling the label as a button instead.
Since clicking on a label has the same effect as clicking on the input,
the input worked properly for mouse and touch screen users.
However, hiding the input makes it inaccessible for keyboard users,
since labels don't get keyboard focus, but inputs do.
So we must not hide the input but make it invisible instead. But we
still need to hide the input (alongside the label) after a file has been
attached.
We could add some extra JavaScript to hide the input when we hide the
label. Since the JavaScript is already quite complex and my first few
attempts at changing it failed, I've opted to assume that the input (and
its label) must be hidden whenever there's already a file name, and
implement that rule with CSS.
Note we're using the `:focus-within` pseudoclass to style a label when
focus is on the input. This rule (at the time of writing) is only
supported by 93.5% of the browsers. Keyboard users without a screen
reader and using the other 6.5% of the browsers will still be able to
focus on the field but might not notice the field has received focus.
Since the percentage of affected users will decrease over time and until
now 100% of keyboard users were completely unable to focus on these
fields, for now we think this is a good-enough solution.
This way screen reader users will hear the name of the file before
hearing about the link to destroy it. We were already displaying it this
way visually by having the file name on the left and the destroy link on
the right.
Thanks to this change we can also simplify the code which dynamically
changed the layout.
Using `dom_id` means generating `new_document` as ID for new documents.
Since there might be more than one new document in the form, that means
duplicate IDs, which is invalid HTML.
Even though this issue doesn't affect image fields (because we don't
have many images on the same form), we're removing the ID there as well
for consistency.
These labels weren't associated with any fields, which is invalid HTML.
We're using a legend inside a fieldset instead, which is the natural way
to group form fields together.
We were using long, unique names because these methods used to be helper
methods. Helper methods should have unique names because otherwise one
method would overwrite the other.
Now that we're using components, we can omit the `image_` and
`document_` prefixes.