Commit Graph

9669 Commits

Author SHA1 Message Date
Javi Martín
6f9de94013 Extract stylesheet for social share button styles
This way we can ignore the selector-class-pattern stylelint rule error
due to the `.ssb-whatsapp_app` selector.
2024-06-18 18:27:32 +02:00
Javi Martín
3d5696aff5 Apply no-redeclare ESLint rule
This rule is part of the `eslint:recommended` package. It was the only
rule we weren't following 100% of the time (other than the line length).
2024-06-18 18:27:32 +02:00
Javi Martín
a15ff36a22 Apply Rails/SafeNavigation in officing booth view
In commit 9329e4b6e, `try` was added because there was a case where this
partial was rendered and the `current_booth` method didn't exist.
However, that's no longer the case since commit d5c7858f6. Since then,
this partial is only rendered in the officing section, where the
`current_booth` method is defined.

So we can use the safe navigation operator instead of `try`.
2024-06-18 18:27:32 +02:00
Javi Martín
db274e9a44 Apply Lint/SymbolConversion rule in ERB files 2024-06-18 18:27:32 +02:00
Javi Martín
ca7983baf4 Fix avatar alignment in "my account" and users#show
In commit 35659d441, we started using an <svg> tag instead of an <img>
tag to render avatars. That meant that the `vertical-align: middle` rule
we've got for images was no longer being applied.

So we're adding it back.

The only places where this icon wasn't rendered correctly were "my
account" and the show action in the users controller. The comments were
not affected because we've got a `float: left` rule for the
`comment-avatar svg` selector, which causes the browser to ignore the
value of the `vertical-align` propertly, and the avatars showing author
information were not affected because the `.author-photo` selector
already had a `vertical-align` rule.
2024-06-17 18:19:18 +02:00
Javi Martín
ca8329d5f2 Remove unused association between user and pair answers
The code for Poll::PairAnswer was removed in commit af7c37634.
2024-06-13 19:38:29 +02:00
Javi Martín
5fa6db2226 Rename HTML attributes referencing poll options
Since now poll question answers have been renamed to poll question
options, using HTML IDs, classes and data attributes named `answer` was
confusing.
2024-06-13 19:13:05 +02:00
Javi Martín
8997ed316c Rename variables describing poll options as answers
Since we've renamed the class to `Option`, having variables, methods and
texts refering to it as `answer` was confusing.
2024-06-13 19:13:05 +02:00
Javi Martín
38b38d1fcc Rename Poll::Question::Answer to Poll::Question::Option
Having a class named `Poll::Question::Answer` and another class named
`Poll::Answer` was so confusing that no developer working on the project
has ever been capable of remembering which is which for more than a few
seconds.

Furthermore, we're planning to add open answers to polls, and we might
add a reference from the `poll_answers` table to the
`poll_question_answers` table to property differentiate between open
answers and closed answers. Having yet another thing named answer would
be more than what our brains can handle (we know it because we did this
once in a prototype).

So we're renaming `Poll::Question::Answer` to `Poll::Question::Option`.
Hopefully that'll make it easier to remember. The name is also (more or
less) consistent with the `Legislation::QuestionOption` class, which is
similar.

We aren't changing the table or columns names for now in order to avoid
possible issues when upgrading (old code running with the new database
tables/columns after running the migrations but before deployment has
finished, for instance). We might do it in the future.

I've tried not to change the internationalization keys either so
existing translations would still be valid. However, since we have to
change the keys in `activerecord.yml` so methods like
`human_attribute_name` keep working, I'm also changing them in places
where similar keys were used (like `poll_question_answer` or
`poll/question/answer`).

Note that it isn't clear whether we should use `option` or
`question_option` in some cases. In order to keep things simple, we're
using `option` where we were using `answer` and `question_option` where
we were using `question_answer`.

Also note we're adding tests for the admin menu component, since at
first I forgot to change the `answers` reference there and all tests
passed.
2024-06-13 19:13:01 +02:00
Javi Martín
6188281d33 Don't use instace variables in component views
Just like we do every else (sometimes even on that very same file), we
use the method instead of the instance variable.

We're doing this change now because we're about to modify one of these
files (the poll question answers documents index component).
2024-06-12 15:16:14 +02:00
Javi Martín
bfee1b0ecb Simplify query to get possible answers
We added the code indicating the table in commit 673ec075e because back
then we had a `title` column in both the `poll_question_answers` table
and the `poll_question_answer_translations` table.

Since that's no longer the case since commit 7a7877656, we can simplify
the code.
2024-06-12 15:16:14 +02:00
Javi Martín
5a0fa28189 Remove no longer needed calls to require_dependency
Not sure about when we stopped needing them, but all usages of
require_dependency definitely become obsolete after we started using
Zeitwerk in commit 5f24ee912.

We're also going to rename `Poll::Question::Answer` to
`Poll::Question::Option`, so the conflict of having two `Answer`
classes, that made us add this code in the first place, will not even
exist.
2024-06-12 15:16:14 +02:00
Javi Martín
eef9f58410 Extract component to render poll geozones
This way we remove a bit of duplication.

These changes also affect the way geozones are rendered in a couple of
minor ways, making them more consistent:

* No empty list of geozones is rendered when there are no geozones
  (before these changes, an empty list was rendered in the index action
  but not in the show action)
* The text clarifying the geozone restriction is always shown (before
  these changes, it was shown in the index action but not in the show
  action)

We've added tests for these cases.
2024-06-10 17:11:30 +02:00
Javi Martín
5dc98929fc Move poll header partial to a component
This way it'll be easier to write tests for it when we change
it.
2024-06-10 16:53:13 +02:00
Javi Martín
bb574db1ea Allow customizing the text to display poll dates
Since we were using `I18n.t`, our monkey-patch of the `t` helper wasn't
being applied.
2024-06-07 16:20:38 +02:00
Javi Martín
d9662164b8 Remove unused code to display polls with no dates
When this code was added, in commit 1a20a3ce4, we had no validation
rules checking the presence of the start and end dates of a poll. Now we
do, so we don't have to check this condition in the view.
2024-06-07 16:19:29 +02:00
Javi Martín
438fe7bd25 Fix inner borders in polls administration tables
The rows in these tables were using the styles from the `.poll`
selector, and the `position: relative` property defined there caused the
inner borders to disappear in some browsers (like Firefox).

So we're adding the `public` class to the selector; this way, it doesn't
affect elements in the admin section.

Even though it's only necessary to add the `.public` prefix to the
`.poll` selector in one place in order to fix this issue, we're doing it
everywhere for consistency.
2024-06-07 16:19:04 +02:00
Javi Martín
7b3b41386e Fix styles for poll dates
We accidentally introduced a typo in commit f497227e3 which caused the
dates to be rendered outside the element where the dates styles are
applied.
2024-06-07 15:52:02 +02:00
Javi Martín
08ca920819 Simplify conditions to render poll status icons
We were using a redundant `elsif` instead of an `else`. We were also
using a negative condition in the main `if`, which made the code a bit
harder to read.

Since we usually use `current_user` instead of `user_signed_in?`, we're
also changing that for consistency.Extract component to render the status of a poll
2024-06-07 15:52:02 +02:00
Javi Martín
765ab758dc Extract component to render a poll in the poll index
This is consistent with the way we've got partials to render debates,
proposals and legislation processes on their index pages.

Note that, while adding the tests for the status icon, we're keeping one
system test because it also tests the process of voting. We're adding a
new, similar component test, where the voter is created in the database,
so all possible statuses are tested in the component.
2024-06-07 15:52:02 +02:00
Javi Martín
2b03e3ebc4 Remove unused CSS to display poll status icons
This code isn't used since commit 5fdbc7b8a.
2024-06-07 15:52:02 +02:00
Javi Martín
ee64efe659 Use the Do Not Track parameter in vimeo videos
With this parameter, Vimeo no longer uses cookies that identifies users
browsing our site.

They do still store some cookies, though; quoting from Vimeo player
parameters overview:

> When DNT is enabled, Vimeo deploys one essential cookie via the
> embeddable player:
> The __cf_bm cookie, which is part of Cloudflare's Bot Management
> service and helps mitigate risk associated with spam and bot traffic.

Not sure whether this counts as essential cookies in our case; they're
essential for Vimeo, but for us, they're third-party cookies, after all.

[1] https://help.vimeo.com/hc/en-us/articles/12426260232977-Player-parameters-overview
2024-06-07 15:28:42 +02:00
Javi Martín
442156b1cc Don't use cookies when embedding youtube videos
When embedding a video in our site YouTube stores cookies in the user's
computer that aren't necessary to watch the video, so we'd have to make
people accept those cookies before letting them watch the video.

Using a URL that doesn't use cookies, like mentioned in YouTube Help
[1], is easier, though, and respects people's privacy without affecting
the user experience.

That I've found some references saying that youtube does store cookies
once you hit the "play" button even when using the nocookie server [2].
Not sure whether that's an old behavior or I'm doing something wrong,
but I don't see this is the case; even after playing the video, cookies
aren't stored on my browser.

[1] https://support.google.com/youtube/answer/171780#zippy=%2Cturn-on-privacy-enhanced-mode
[2] https://www.cnet.com/news/privacy/youtubes-new-nocookie-feature-continues-to-serve-cookies/
2024-06-06 17:35:27 +02:00
Javi Martín
cc8acdcc87 Make method name consistent in embedded video component
We were using `reg_exp` as the method name, when it returned
`VIMEO_REGEX` or `YOUTUBE_REGEX`.

So using `regex` as the method name is less confusing.
2024-06-06 17:35:27 +02:00
Javi Martín
fee5b8a13c Remove redundant code in embedded video component
When using `<%= `, `nil` is converted to an empty string, so there's no
need to explicitely return an empty string.
2024-06-06 17:35:27 +02:00
Javi Martín
b07132d8d4 Extract methods in embedded video component
No that it's no longer a helper, we can extract method without fearing
they will have the same name as other helper methods.
2024-06-06 17:35:27 +02:00
Javi Martín
579e332cf8 Extract component to render an embedded video 2024-06-06 17:35:27 +02:00
Javi Martín
236b58ab01 Remove duplication in code to validate video URL
We were using the same code, and the same regular expressions, in two
places. To do so, we were including a helper inside a model, which is
something we don't usually do.
2024-06-06 17:35:27 +02:00
Javi Martín
8272b7e9c3 Move shared component stylesheets to shared folder
We had an inconsistency where most stylesheets associated to a component
would have the same relative path as their component, so if we had a
component in `app/components/admin/whatever`, its associated stylesheet
would be in `app/assets/stylesheets/admin/whatever`.

There was one exception to this rule: stylesheets for components in
`app/components/shared/` were placed in `app/assets/stylesheets/`. The
reason was that we thought "well... if they're in the root folder,
they're shared". However, this is confusing because in the root folder
there are also stylesheets that aren't associated to a component.

So we're creating the `app/assets/stylesheets/shared/` folder. This also
means we don't have to manually add every stylesheet in this folder the
the `application.scss` file.

We aren't the same for JavaScript files because with JavaScript we still
don't have a clear association between JavaScript files and components.
Only a couple of them (`advanced_search.js` and `check_all_none.js`)
would be good candidates, and the one for the advanced search form
doesn't even use the `.advanced-search-form` selector that we use in the
CSS file.
2024-06-06 16:28:19 +02:00
Javi Martín
c367f21705 Add buttons to check all/none available languages
Although most Consul Democracy installations will only have a few
available languages using `config.i18n.available_locales`, there's a
chance some installation will keep every language as available and will
enable the desired ones using the admin interface. In these cases,
enabling (or disabling) every language would be tedious, particularly
when casually experimenting in a staging environment or while using the
official Consul Democracy demo.

So we're adding buttons to simplify the process. Since some
installations might have only a couple of available languages, and in
this case these buttons would be pretty much useless, we're only showing
them when there are many languages available.
2024-06-06 16:28:19 +02:00
Javi Martín
a911b0dec7 Extract function in "check all/none" JavaScript file 2024-06-06 16:28:19 +02:00
Javi Martín
15ca47caed Hide "check all/none" buttons when JavaScript isn't available
These buttons only work without JavaScript, so we shouldn't show them in
this case.

I was wondering whether we should use the `hidden` HTML attribute so
these buttons don't show up when stylesheets haven't loaded either. Not
doing so because we already have a stylesheet for the <noscript>
scenario. We might change our minds regarding how to handle these styles
in the future.
2024-06-06 16:28:19 +02:00
Javi Martín
63eacf4579 Move noscript styles to their own stylesheet
This way we can use SCSS syntax here, like we do everywhere else.
2024-06-06 16:28:19 +02:00
Javi Martín
ce1ee861f1 Simplify "check all/none" buttons layout
The float property was removed in commit b71c61e40, but then it was
added again in commit 4a6313fed.

It might have been necessary to do so back then because we had a
`select` field instead of the links to set the order, but now, instead
of making them float on the left and then make the next element clear
the floats, we can do nothing and obtain the same results.
2024-06-06 16:28:19 +02:00
Javi Martín
673eb1358a Group buttons to check all/none elements
Since they're related, we're making them part of the same list. Instead
of finding a way to have the `Select` prefix they had as a label for the
list, we're including the "prefix" they had inside their texts, so the
text of a button doesn't need any additional context.
2024-06-06 16:28:19 +02:00
Javi Martín
2dab8682d9 Remove unused CSS in legislation
This code using the legislation-categories HTML class was removed in
commits d679c1eb7 and ff66909cd. We've noticed is while dealing with the
`.menu.simple` selectors in the previous commit.
2024-06-06 16:27:56 +02:00
Javi Martín
f47179ff68 Use buttons to check/uncheck all options
People using screen readers usually expect links to take them somewhere
else in the page on to a different page, while they expect buttons to
change something on the page.

Since we're in the latter scenario, using a button is more accessible.
It's also more natural; with a button, we don't need to provide `#` as
the URL or stop the default event when the button is clicked. And,
unlike links, buttons can be activated with either the space or the
enter key. Finally, clicking a link pointing to `#` with the middle
mouse button opens a useless new tab, while buttons do nothing in this
case.

Now that we only have one "All" link on the page, we no longer need to
specify which "All" link we're clicking or which "All" link we are
checking, so we're simplifying the code doing so.
2024-06-06 16:18:33 +02:00
Javi Martín
fdf1fd5f5f Move links to check all/none on RTL languages
Since we don't usually style HTML classes starting with `js-`, we're
renaming it, so it's consistent with the `CheckAllNone` name used in the
`check_all_none.js` file.
2024-06-06 16:09:18 +02:00
Javi Martín
26a43ee0d2 Add a proper title to moderation index pages
Since this is already a component, we can use the `header` method
without much refactoring.
2024-06-06 16:09:18 +02:00
Javi Martín
0c59c2dfb4 Extract model to handle locales settings
This way we can simplify the view, particularly the form. However, we're
still adding some complexity to the form so inputs are inside labels and
so the collection is easier to style with CSS.
2024-06-05 16:10:56 +02:00
Javi Martín
2596b4e78b Use multiple columns to display languages options
When the list of available languages becomes too large, having all of
them in one column makes it harder to select them.

What we're trying to do here is to have multiple columns, with each
column containing between 5 and 10 options, so they can all be easily
seen on the screen at the same time.

For that, there are mainly three options: a flex layout, a grid layout
or a multi-column layout.

Since languages are ordered (more or less) alphabetically, the natural
way to display them is showing the first few ones on the first column,
the following ones on the second column, and so on, as opposed to
displaying the first ones on the first row, the following ones on the
secord row, ... AFAIK this can't be accomplished using a flex layout.

I've tried to do so using a grid layout, and failed. The problem here is
that we don't know how many rows we're going to have.

So we're using a multi-column layout. I haven't found a way to guarantee
a minimum height for the content of each column, so in the end we're
using a hack with the `:has` pseudoclass. Note this pseudoclass is only
supported by about 92%-94% of the browsers (including the last few
versions of all major browsers); people using other browsers will still
see all the options on one column, just like people using small screens
do.
2024-06-05 16:10:56 +02:00
Javi Martín
78bbf430d5 Add a form to edit available locales
We're using different controls depending on the number of available
locales.

When there are only a few locales, the solution is obvious: radio
buttons to select the default language, and checkboxes to select the
available ones are simple and intuitive.

With many languages, showing two consecutive lists of 30 languages could
be confusing, though, particularly on small devices, where scrolling
through both lists could be hard.

So, in this case, we're rendering a <select> to choose the default
language. For selecting the available languages, however, we're sticking
to checkboxes because all the other existing options (like multiple
selects) are hard to use. We think it's OK because the form doesn't have
any additional fields, and there's only one big list of options to
scroll through.

While testing the application, we noticed that if we use the
`admin-fieldset-separator` styles when there's only one fieldset, it's
harder to notice that there's an additional field to select the default
language. So we're only using the `admin-fieldset-separator` styles when
all the fields are grouped in fieldsets.

Regarding the help text for the fieldset, if we leave the help text
outside the <legend> tag, people using screen readers won't hear about
this content. However, if we include it inside the <legend> tag, some
screen readers might read it every time they move to a different
checkbox (or radio button), which can be annoying. Since I don't think
these help messages are really essential, I'm leaving them out of the
<legend> tag. It's also easier to style them if they're outside the
<legend> tag.

Note we're using `display: table` for the labels, for the reasons
mentioned in commit 923c2a7ee.

Also note that, when there's only one available locale, this section is
useless. In this case, we aren't disabling it for now because there's a
chance people see it in the official Consul Democracy demo and then
wonder why it isn't available on their installation. We might disable it
in the future, though.
2024-06-05 16:10:56 +02:00
Javi Martín
6de4737b70 Allow different default locales per tenant
Note that, for everything to work consistently, we need to make sure
that the default locale is one of the available locales.

Also note that we aren't overwriting the `#save ` method set by
globalize. I didn't feel too comfortable changing a monkey-patch which
ideally shouldn't be there in the first place, I haven't found a case
where `Globalize.locale` is `nil` (since it defaults to `I18n.locale`,
which should never be `nil`), so using `I18n.default_locale` probably
doesn't affect us.
2024-06-05 16:10:56 +02:00
Javi Martín
722e50a669 Simplify code to find a content block
We're only calling the `block_for` method from one place: the
`content_block` helper, and we're never passing the locale parameter to
that helper, which means we're always calling `block_for` using
`I18n.locale`.

So I'm not sure why we were doing the `locale ||=` assignment, since
`I18n.locale` doesn't return nil.

In any case, since this was added in commit c1de2dced, Ruby has added
support for arguments forwarding, so we can use it here to simplify the
code a little bit.
2024-06-05 16:10:56 +02:00
Javi Martín
647121d13e Allow different locales per tenant
Note that, currently, we take these settings from the database but we
don't provide a way to edit them through the admin interface, so the
locales must be manually introduced through a Rails console.

While we did consider using a comma-separated list, we're using spaces
in order to be consistent with the way we store the allowed content
types settings.

The `enabled_locales` nomenclature, which contrasts with
`available_locales`, is probably subconsciously based on similar
patterns like the one Nginx uses to enable sites.

Note that we aren't using `Setting.enabled_locales` in the globalize
initializer when setting the fallbacks. This means the following test
(which we could add to the shared globalizable examples) would fail:

```
it "Falls back to an enabled locale if the fallback is not enabled" do
  Setting["locales.default"] = "en"
  Setting["locales.enabled"] = "fr en"
  allow(I18n.fallbacks).to receive(:[]).and_return([:fr, :es])
  Globalize.set_fallbacks_to_all_available_locales

  I18n.with_locale(:fr) do
    expect(record.send(attribute)).to eq "In English"
  end
end
```

The reason is that the code making this test pass could be:

```
def Globalize.set_fallbacks_to_all_available_locales
  Globalize.fallbacks = I18n.available_locales.index_with do |locale|
    ((I18n.fallbacks[locale] & Setting.enabled_locales) + Setting.enabled_locales).uniq
  end
end
```

However, this would make it impossible to run `rake db:migrate` on new
applications because the initializer would try to load the `Setting`
model but the `settings` table wouldn't exist at that point.

Besides, this is a really rare case that IMHO we don't need to support.
For this scenario, an installation would have to enable a locale, create
records with contents in that locale, then disable that locale and have
that locale as a fallback for a language where content for that record
wasn't created. If that happened, it would be solved by creating content
for that record in every enabled language.
2024-06-05 16:10:56 +02:00
Javi Martín
790d515afc Remove unused code in globalizable concern
This code was added in commit 041abe904, but it was never used.
2024-06-05 16:10:56 +02:00
Javi Martín
c11780880c Move form builders to their own folder
We were defining one builder in the `app/lib/` folder and another one
inside a helper module.

So now we're grouping them together. This way we're following the "one
class per file" convention that we follow most of the time. And, by
extracting the `TranslatableFormBuilder` class to its own file, it'll be
easier to add tests for it.

Note that, for consistency, we're renaming the
`TranslationsFieldsBuilder` class so it ends in `FormBuilder`.
2024-06-05 16:10:56 +02:00
Javi Martín
26b48e527a Move information texts form partial to a component
This way it'll be easierto write tests for it when we change it.
2024-06-05 16:10:56 +02:00
Javi Martín
2a5edbb5dd Move content blocks forms partials to components
This way we can simplify the controller a little bit, and it'll be
easier to write tests for them when we change the code.
2024-06-05 16:10:56 +02:00
Javi Martín
1898bdec56 Remove redundant conditions in content blocks controller
In the case of the `edit` action, we're using
`load_and_authorize_resource`, which will always return a
`SiteCustomization::ContentBlock`. In the case of
`edit_heading_content_block`, we're using `Budget::ContentBlock.find`,
which always returns a `Budget::ContentBlock` (or raises an exception).

So, in both cases, the condition to assign `@selected_content_block` can
be removed.
2024-06-05 16:10:56 +02:00