The initialjs-rails gem hasn't been maintained for years, and it
currently requires `railties < 7.0`, meaning we can't upgrade to Rails 7
while we depend on it.
Since the code in the gem is simple, and we were already rewriting its
most complex part (generating a background color), we can implement the
same code, only we're using Ruby instead of JavaScript. This way, the
avatars will be shown on browsers without JavaScript as well. Since
we're adding a component test that checks SVG images are displayed even
without JavaScript, we no longer need the test that checked images were
displayed after AJAX requests.
Now the tests show the user experience better; people don't care about
the internal name used to select the initial (which is what we were
checking); they care about the initial actually displayed.
Note initialjs generated an <img> tag using a `src="data:image/svg+xml;`
attribute. We're generating an <svg> tag instead, because it's easier.
For this reason, we need to change the code slightly, giving the <svg>
tag the `img` role and using `aria-label` so its contents won't be read
aloud by screen readers. We could give it a `presentation` role instead
and forget about `aria-label`, but then screen readers would read the
text anyway (or, at least, some of them would).
These images are always displayed next to a username, meaning people
using screen readers were hearing the same username twice in a row.
Even though we're about to replace the initialjs gem, we're making this
change in case so we've got one more test and we can check everything
keeps working after replacing the gem.
The `use_helpers` method was added in ViewComponent 3.8.0, and it's
included by default in all components since version 3.11.0.
Note we sometimes delegated the `can?` method to the controller instead
of the helpers, for no particularly reason. We're unifying that code as
well.
Most screen readers don't notify when a link is about to open in a new
window [1], so we're indicating it, like we were already doing in most
places with similar links.
We could also add a visual indicator, but since links inside labels
already have accessibility issues, giving more attention to these links
might make matters worse.
[1] https://www.powermapper.com/tests/screen-readers/navigation/a-target-blank/
IMHO the best solution would be to completely remove this checkbox on
forms that require registration. Other than the fact that people have
already agreed with these terms when registering (although I guess these
terms might have changed since then) and that approximately 0% of the
population will read the conditions every time they agree with them,
there's the fact that these links are inside a label and people might
accidentally click on them while trying to click on the label in order
to check the checkbox.
I guess the idea is that these conditions might have changed since the
moment people registered. In a fair world, checking "I agree" would have
no legal meaning because it's unreasonable to expect that people will
read these conditions every time they fill in a form, so whatever we're
trying to do here would be pointless.
But, since I'm not sure about the legal implications of removing this
field in a world where you have to inform people that websites requiring
identification use cookies, for now the field will stay where it is.
Not all the colors initialjs uses by default provide enough contrast
against a white text. The default initialjs colors are:
["#1abc9c", "#16a085", "#f1c40f", "#f39c12", "#2ecc71", "#27ae60",
"#e67e22", "#d35400", "#3498db", "#2980b9", "#e74c3c", "#c0392b",
"#9b59b6", "#8e44ad", "#bdc3c7", "#34495e", "#2c3e50", "#95a5a6",
"#7f8c8d", "#ec87bf", "#d870ad", "#f69785", "#9ba37e", "#b49255",
"#b49255", "#a94136"]
We're replacing them with colors containing less luminosity when
necessary in order to get a 4,5:1 contrast (it could be argued that a
3:1 contrast is enough when the icons are big, but that isn't always the
case and more contrast doesn't hurt):
["#16836d", "#12826c", "#896f06", "#a06608", "#1e8549", "#1e8549",
"#b35e14", "#c75000", "#207ab6", "#2779b0", "#de2f1b", "#c0392b",
"#9b59b6", "#8e44ad", "#6c767f", "#34495e", "#2c3e50", "#66797a",
"#697677", "#d82286", "#c93b8e", "#db310f", "#727755", "#8a6f3d",
"#8a6f3d", "#a94136"]
Since initialjs doesn't provide a way to change these colors using
JavaScript, we're changing them in Ruby, following the same algorithm
used by initialjs.
As far as possible I think the code is clearer if we use CRUD actions
rather than custom actions. This will make it easier to add the action
to remove votes in the next commit.
Note that we are adding this line as we need to validate it that a vote
can be created on a debate by the current user:
```authorize! :create, Vote.new(voter: current_user, votable: @debate)```
We have done it this way and not with the following code as you might
expect, as this way two votes are created instead of one.
```load_and_authorize_resource through: :debate, through_association: :votes_for```
This line tries to load the resource @debate and through the association
"votes_for" it tries to create a new vote associated to that debate.
Therefore a vote is created when trying to authorise the resource and
then another one in the create action, when calling @debate.vote_by (which
is called by @debate.register_vote).
In order to reduce the code used to add styles to the buttons,
we removed the classes that had been added and handled it with
the new aria-pressed attribute
We were already applying these rules in most cases.
Note we aren't enabling the `MultilineArrayLineBreaks` rule because
we've got places with many elements whire it isn't clear whether
having one element per line would make the code more readable.
Previous to this commit the geozone link shown in the
legislation proposal page was pointing to the proposals
process feature instead to the legislation proposals.
Note that in the budgets wizard test we now create district with no
associated geozone, so the text "all city" will appear in the districts
table too, meaning we can't use `within "section", text: "All city" do`
anymore since it would result in an ambiguous match.
Co-Authored-By: Julian Herrero <microweb10@gmail.com>
Co-Authored-By: Javi Martín <javim@elretirao.net>
Using a button for interactive elements is better, as explained in
commit 5311daadf.
Since buttons with "type=button" do nothing by default, we no longer
need to call `preventDefault()` when clicking it.
We were using `map_location` in one place and
`location-map-remove-marker` in another one. We usually use dashes in
HTML class names, we don't say "location map" anywhere else.
We had two different keys with the same text and were passing it as a
parameter. Since the text is the same in any case, we don't need a
parameter for it.
Note we are using the `proposals` i18n key instead of creating a new one
in a `shared` namespace one because creating a new key would mean that
we'd lose the already existing translations in Crowdin.
We were manually generating the IDs in order to pass them as data
attributes in the HTML in a component where we don't have access to the
form which has the inputs.
However, these data attributes only make sense when there's a form
present, so we can pass the form as a parameter and use it to get the
IDs.
We can now define a map as editable when there's an associated form,
which makes sense IMHO.
We were probably setting them separately to avoid having blank data
attributes in the HTML. However, when a data attribute is `nil`, Rails
doesn't write it in the HTML in the first place.
We were using an optional parameter followed by keyword parameters,
which caused a warning with Ruby 2.7:
```
app/components/shared/link_list_component.rb:20: warning: Using the last
argument as keyword parameters is deprecated; maybe ** should be added
to the call
```
I've tried to make `current:` a named parameter as well and then change
all method calls to `link_list`, but was still getting the same warning.
Might have something to do with the fact that we're dealing with arrays
with hashes inside them instead of passing the keyword arguments
directly to the method.
The interface of this method has changed and uses keyword arguments
instead of a hash of options. This change will be particularly
significant when upgrading to Ruby 3.
In commit f374478dd, we enabled the possibility to use HTML in the
search results translations in order to add a <strong> tag to these
results. However, that meant we were also allowing HTML tags inside the
search term itself, and so it was possible to inject HTML on the page.
Stripping the HTML tags solves the issue.
Note the issue wasn't a high severity issue because tags such as
`<script>` weren't allowed since we were using the `sanitize` helper.
We were using very similar code for proposals, debates and investments,
so we might as well share the code between them.
Note we're using the `proposals.index.search_results` key even for
debates and investments. This will still work because the translations
shared the same text, but IMHO we should rename the key to something
like `shared.search_results_summary`. We aren't doing so because we'd
lose all the existing translations.
Defining a behavior on hover means making it different for people using
a keyboard or a touchscreen (most of the population, nowadays).
In this case, we had an accessibility issue where the message wouldn't
disappear once it appeared. That meant that, after tabbing through all
the links and buttons in, for instance, the debates index, the page
would be filled with "participation not allowed" messages, and in order
to see the information about how many people have voted, reloading the
page was required.
For touchscreen users the behavior was similar to what we get on hover,
although we've found some inconsistencies when trying to support several
elements on the same page.
We think in proposals it makes sense to hide the "support" button when
users click on it, and the same applies to the buttonsto support and
vote investment projects. However, we aren't hiding the buttons to
agree/disagree with a debate in order to keep the information about the
current number of people agreeing and disagreeing visible.
Note we're removing some support spec methods because after these
changes the duplication isn't as obvious as it was in the past.
We were using the same logic six times regarding when we should show a
"participation not allowed" message. Since we're going to change the
current behavior, we're unifying the logic in one place so the changes
will be easier.
Using the `flex-with-gap` mixin we avoid the left margin in the second
element when the screen space isn't wide enough to show both buttons.
Setting the margins with CSS also allows as to simplify the view and
makes it easier to customize styles.
Having buttons (previously links) with the text "I agree 75%" is
confusing; people might believe they're saying they only partially agree
with the content. Besides, the results percentages is a different piece
of information which shouldn't be related to whether one person
agrees/disagrees with the content.
This problem might be solved for people using screen readers since we
added the aria-label attribute. However, for sighted keyboard users, the
percentage was being outlined on focus as part of the button, which
might be confusing.
We were using the same code to render links to agree and disagree, so we
can extract a new component for this code.
We're also adding component tests to make it easier to test whether
we're breaking anything while refactoring, although the code is probably
already covered by system tests.
Since the votes mixin was only used in one place, we're removing it and
moving most of its code to a new CSS file for the shared component.
In the moderation section there's no clear indicator as to what the
"Hide" and "Block" buttons do and the difference between them.
Since we're using confirmation dialogs in all moderation actions except
these ones, we're adding them here as well, so the difference will
appear in the dialog.
This isn't a very good solution, though, since the confirmation dialog
comes after clicking the button and users have already been wondering
whether clicking that button will be the right choice. A better solution
would be making the purpose clear before the button is clicked, although
that's something we don't do anywhere in the admin/moderation sections.
This is useful for people using screen readers, since the character used
as a separator won't be read aloud.
Since many screen readers also read content generated via CSS
pseudoelements, we aren't using `content: "|";` or similar but using
elements with a very small width instead.