We're continuing to replace links with buttons, for the reasons
explained in commit 5311daadf.
Since we're using the admin action component, we can also simplify the
logic handling the confirmation message.
In order to avoid duplicate IDs when generating buttons to block the
same author more than once in a page, we're including the record dom_id
in the ID of the button to block an author.
Note that in proposal notifications we're writing the call to
render the component in the same line as the <div class="reply">
definition in order to be able to use the `:empty` selector when the
component renders nothing. No browser matches whitespace with the
`:empty` selector, so we can't add newline characters inside the tag. A
more elegant solution would be extracting the proposal notification
actions to a component and only rendering it if the moderation actions
component is rendered.
In this PR (https://github.com/consul/consul/pull/4683) a new syntax was introduced
in the component specs to check that the component was not rendering.
It seems interesting to add this syntax to the rest of the cases and thus unify the way
we check that a component is not rendering.
As mentioned in commit bc0f04075, a <select> field which submits its
form on change causes many accessibility and usability issues. In this
case there was also an incompatibility with the advanced search filter
which caused a bug solved in commit 541a5fa89.
So the question is where to position the filters and how to display
them. One factor to take into the account is how relevant these filters
are, particularly compared to the links to select the prefered order,
since we don't usually give users the choice of both filters and orders.
Our filters don't really make sense until the valuation phase starts,
since before that phase investments aren't selected nor their
feasibility is decided.
After that phase, the only phase where citizens are really involved
is the final voting; the rest of the phases are done by valuators and
administrators. In the final voting, citizens can only vote on selected
projects, and that's the default filter during that phase.
So these filters are mainly there for information purposes, and not to
help citizens in the phases where they're actually involved (accepting
projects, selecting projects and balloting).
Orders, on the other hand, play a crucial role during the final voting
phase. Since citizens might have already voted for a few projects and
have, let's say, 100,000€ left, ordering by price allows them to find
which projects are within their remaining budget.
In conclusion, orders are more important than filters, and so they
should have a more prominent place.
For consistency with the proposals section, where we've got some links
in the sidebar (bottom part of the page on small screens) providing a
similar funcionality, like accessing selected proposals or archived or
retired proposals, we're moving the investments filters to the sidebar
(bottom part of the page on small screens) as well.
Since we're simplifying the main method, we can use a view file instead
of the `call` method. This way we make the code more consistent with the
rest of our components, since we always use a separate file.
Doing so generates an extra newline at the end of the generated HTML, so
we need to change a couple of tests a little bit.
This way it's easier to refactor it and/or change it.
Back in commit c156621a4 I wrote:
> Generally speaking, I'm not a big fan of helpers, but there are
> methods which IMHO qualify as helpers when (...) many Rails helpers,
> like `tag`, follow these principles.
It's time to modify these criteria a little bit. In some situations,
it's great to have a helper method so it can be easily used in view
(like `link_to`). However, from the maintenance point of view, helper
methods are usually messy because extracting methods requires making
sure there isn't another helper method with that name.
So we can use the best part of these worlds and provide a helper so it
can be easily called from the view, but internally make that helper
render a component and enjoy the advantages associated with using an
isolated Ruby class.
Since forms are landmarks, screen reader users might navigate to the
form. But then they were going to find an empty form with no way to
toggle it.
Moving the button inside the form means screen reader users navigating
to the form will find the button to toggle it.
It also helps us simplifying the code; there's no need to use
data-attributes to communicate whether the form should be visible since
now we can easily use the button `aria-expanded` attribute.
We could further simplify the JavaScript if we used a CSS rule to
show/hide the form fields based on the toggle button `aria-expanded`
attribute. However, implementing the "slide" animation we use when
toggling the form with CSS is difficult and unreliable.
We were using the form and then showing it with JavaScript when advanced
search terms were present. Now we hide it with JavaScript when no
advanced search are present. This means users without JavaScript
(including users with JavaScript enabled but bad internet connections
preventing the JavaScript to load) can now access the form.
The other main difference between the two versions is the way the form
flashes while JavaScript is loading.
Previously, the form would always be hidden when no terms had been
introduced. However, when these terms were present, after submitting the
form it would briefly be hidden and then shown again.
Now the opposite happens. When advanced search terms are present, the
form is shown at all times. However, when they aren't, the form is
briefly shown before it disappears.
Here the previous behavior is arguably better because most of the time
these terms will not be present.
So basically we're significantly improving the experience of some users
at the cost of slightly worsen the experience of other users.
We're also hiding the button to show the form when JavaScript is
disabled, since in this scenario it's useless. We're using the `hidden`
attribute so hidden buttons can be detected in CSS.
Checking the `style` attribute fails in JavaScript tests because the
browser converts colors to the `rgb()` format.
So we're testing the generated HTML in a component test while
simplifying the system test.
Now it's easier to change the investments filter. Previously we had to
go back to the budget index page, change the filter there, and then
select one heading.
Now the links to change the current filter in the budget index page
aren't needed anymore.
Now the banner component accepts either a banner or a section and loads
the banner if it's a section, so we don't have to add the `@banners`
variable in several controllers.