Skip to content

LLM translations - #6068

Merged
taitus merged 5 commits into
consuldemocracy:masterfrom
danesjenovdan:ai
Nov 20, 2025
Merged

LLM translations#6068
taitus merged 5 commits into
consuldemocracy:masterfrom
danesjenovdan:ai

Conversation

@stirkac

@stirkac stirkac commented Aug 21, 2025

Copy link
Copy Markdown
Collaborator

LLM Translations

Objectives

AI based / LLM translations enable a new way to translate user generated content without relying on Microsoft's services.

Using RubyLLM approach, it means that a variety of LLM providers and their models can be used, from paid services to local instances.

Leverage the existing Remote translations framework by providing an alternate LLM based translation, instead of Microsoft service currently in place.

Visual Changes

Introduced a new Settings panel - LLM Settings. Enables Consul admins to configure LLM Settings - LLM provider, model and choosing to use LLM for remote translations
Consul LLM Settings

Usage and configuration

1. Setting LLM Provider Credentials

Enter LLM credentials to your secrets.yml file, as shown in secrets.yml.example
To find the exact names of required fields to configure your chosen provider, reference Ruby LLM documentation.

2. Enabling remote translations in Admin

Select the provider, model and turn on the "Content Translation" switch in Admin > Global Settings > LLM Settings

  • Switching on LLM Settings takes precedence over Microsoft services, if they are previously configured. If you want to use Microsoft translations, do not turn on "Content Translation" switch in LLM Settings.

3. Configuring LLM prompt

Use config/llm_prompts.yml and edit remote_translation_prompt to set up your own translation prompt. Ensure that the prompt returns the resulting translation as it's expected to be viewed by the end user.

@stirkac
stirkac force-pushed the ai branch 11 times, most recently from 5334f69 to 9231f7e Compare September 10, 2025 10:52
@stirkac stirkac changed the title AI translations LLM translations Sep 11, 2025
@stirkac
stirkac force-pushed the ai branch 3 times, most recently from 2f0923f to f7d255c Compare September 16, 2025 08:49
@javierm
javierm marked this pull request as ready for review September 16, 2025 13:16
@taitus taitus self-assigned this Sep 22, 2025

@taitus taitus left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stirkac Thank you so much for this pull request! 🎉
I’ve left a few comments. Let me know what you think!

For the components under app/components/admin/settings, there’s also a patch attached in the comment of llm_configuration_tab_component.html.erb.
It might make sense to start the review there, since the rest of the feedback builds on that.

Thanks again for the work and for including tests and documentation — much appreciated! 🙌

Comment thread app/components/admin/settings/llm_configuration_tab_component.html.erb Outdated
Comment on lines +1 to +19
.admin .dropdown-settings-form {
label {
display: table;
}

select {
width: auto;
}

.help-text {
display: block;
}

[type="submit"] {
@include regular-button;
display: block;
margin-top: $line-height;
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we apply the patch suggested in app/components/admin/settings/llm_configuration_tab_component.html.erb, we should review which of the styles in app/assets/stylesheets/admin/settings/dropdown_settings.scss are still needed. At minimum, we should rename the file to dropdown_form.scss to match the new component name.

One specific concern: @include regular-button; on the submit button is overriding the "button hollow expanded" classes used by Admin::Settings::DropdownFormComponent. That means the hollow style won’t take effect.

Comment thread app/lib/remote_translations/caller.rb Outdated
Comment thread app/lib/remote_translations/caller.rb Outdated
Comment thread app/lib/remote_translations/llm/client.rb
Comment thread config/locales/en/admin.yml
Comment thread config/locales/en/admin.yml Outdated
Comment thread spec/components/layout/remote_translations_button_component_spec.rb Outdated
Comment thread spec/lib/remote_translations/caller_selection_spec.rb Outdated
Comment thread spec/system/admin/llm/llm_settings_spec.rb Outdated

@taitus taitus left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @stirkac

Thanks for making the suggested changes in the review. Since I wasn't sure whether we'd end up modifying the logic and components, I left the specs for last.

Here I've added a few comments about conventions and some adjustments to the tests.

As I won't be able to continue the review until next week, I'm sending you the suggestions I have so far, along with what's still pending. For example, adding a test to check how providers are loaded across different tenants depending on their secrets, using the stub_secrets helper. Something similar to this code:

stub_secrets(
  llm: {
    openai_api_key: "1234",
    deepseek_api_key: "4321"
  },
  tenants: {
    new_tenant_name: {
      llm: {
        openai_api_key: "2222",
        deepseek_api_key: "4444"
      }
    }
  }
)

I'd also like to review and update spec/shared/system/remotely_translatable.rb to align it as much as possible with the LLM setup.

Of course, feel free to ping me if you have any questions.

Comment thread spec/components/layout/remote_translations_button_component_spec.rb Outdated
Comment thread spec/lib/remote_translations/caller_selection_spec.rb Outdated
Comment thread spec/lib/remote_translations/caller_spec.rb Outdated
Comment thread spec/lib/remote_translations/caller_spec.rb Outdated
Comment thread spec/system/admin/settings_spec.rb Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can take care of updating the docs/es/features/user_content_translations.md file.
I'm leaving this comment here so we don't forget.

Comment thread config/locales/en/settings.yml Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could add a new spec file at
spec/components/admin/settings/dropdown_form_component_spec.rb
to cover this component with component specs (similar to the existing FeaturedSettingsFormComponent tests).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could add a few more specs in the FeaturedSettingsFormComponent tests to cover the recent changes in this component.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could add a new spec file at
spec/components/admin/settings/llm_configuration_tab_component_spec.rb
to cover this component with component specs. The most interesting part to test here would probably be the disabled states depending on the component's configuration.

stirkac added a commit to danesjenovdan/consul that referenced this pull request Nov 4, 2025
Addressed comments about conventions and some adjustments to the tests from the pull request consuldemocracy#6068
stirkac added a commit to danesjenovdan/consul that referenced this pull request Nov 6, 2025
Addressed comments about conventions and some adjustments to the tests from the pull request consuldemocracy#6068

@taitus taitus left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @stirkac

Thanks again for applying all the changes to this PR!

In addition to the three small comments you'll see in the review, I'm sharing a couple of patches that you can apply if they make sense to you:

docs-and-es-translations.patch

  • Includes the Spanish documentation update and a small structural tweak in the English version (no text changes).
  • Since we now have a Spanish version, both guides reference separate images (display-llm-translations-en.png and display-llm-translations-es.png).
    You’ll just need to rename the original image from display-llm-translations.png to display-llm-translations-en.png and add the Spanish one.
  • I'd also suggest adding a "Pricing" subsection under Using LLM Translation (same level as Configuration), with a short generic explanation about how costs vary by provider/model 🤔

specs-changes.patch

  • Contains the adjustments we discussed for the tests related to spec/shared/system/remotely_translatable.rb, along with a few simplifications and some alignment with our component conventions.
    For the remotely translatable changes, I opted to allow a new provider and make one call for :microsoft and another for :llm. Since the Microsoft option will likely be deprecated in upcoming releases, we can revisit and optimize those tests later on.

They're all small tweaks, that's why I preferred to share them as patches rather than add tiny inline comments in the review.

If anything doesn't quite fit or you'd rather approach it differently, just let me know and we'll figure it out together.

Thanks again! 🙌

Comment thread app/lib/remote_translations/llm/client.rb Outdated
Comment thread config/locales/en/settings.yml Outdated
Comment thread app/components/admin/settings/llm_configuration_tab_component.rb Outdated
@stirkac
stirkac force-pushed the ai branch 2 times, most recently from f727c06 to c3eb99b Compare November 13, 2025 15:45
Create a reusable DropdownFormComponent for admin settings that
standardizes dropdown form inputs. The component follows the same
pattern as FeaturedSettingsFormComponent and integrates with the
existing RowComponent structure.

Also add disabled parameter support to both DropdownFormComponent
and FeaturedSettingsFormComponent, allowing settings to be disabled
based on configuration state. Update RowComponent to support dropdown
type settings and pass through disabled and options parameters.
Introduce the new LLM Settings section in the admin interface,
allowing administrators to select the LLM provider, choose a model, and
enable or disable LLM based remote translations.

Add ruby_llm as a dependency.
Expand the existing RemoteTranslations framework by adding support for
LLM-based translations as an alternative to the Microsoft service.

The caller now selects between Microsoft and LLM providers based on the
admin configuration, with LLM taking precedence when enabled.
Update remotely_translatable shared examples to support both
Microsoft and LLM translation providers. This allows testing
translation feature with either provider while maintaining
backward compatibility with existing Microsoft based tests.

Note: Since the Microsoft option will likely be deprecated in
upcoming releases, we can revisit and optimize those tests later on.

@taitus taitus left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stirkac Thanks a lot for all the work on this! 🙌

Approved! 🚀

We'll merge it as soon as we confirm that the new 2.4.1 release is behaving as expected, just to be sure we don't need to issue a follow-up fix. 😊

@taitus
taitus merged commit 5691bb1 into consuldemocracy:master Nov 20, 2025
15 checks passed
@github-project-automation github-project-automation Bot moved this from Reviewing to Release 2.5.0 in Consul Democracy Nov 20, 2025
@javierm javierm added the AI label Nov 20, 2025
stirkac added a commit to danesjenovdan/consul that referenced this pull request Dec 6, 2025
commit 009d5953be123c5c7826fd703a43a2c2a9fd4420
Author: Sebastjan Stojnsek <stirkac@users.noreply.github.com>
Date:   Sat Dec 6 16:16:50 2025 +0100

    make image suggestions togglable with a switch

commit 9193ddf12a736927e21ecc6cd28f4b4f542c9cbe
Author: Sebastjan Stojnsek <stirkac@users.noreply.github.com>
Date:   Sat Dec 6 11:25:28 2025 +0100

    wip image suggestions

commit 577f79b084ebf2fd48d09c47af701b6d82cf6168
Merge: 1ddef04bfb 6afe59a9e4
Author: Javi Martín <35156+javierm@users.noreply.github.com>
Date:   Wed Dec 3 14:53:00 2025 +0100

    Merge pull request #6158 from consuldemocracy/css_in_info_separators

    Use CSS to style separators in author/date/comments info

commit 6afe59a9e442383e311918631c2351f089d23ca1
Author: Javi Martín <javim@elretirao.net>
Date:   Sat Nov 22 01:08:59 2025 +0100

    Use CSS to style separators in detailed info component

    Just like we did to the basic info component a few commits ago. We're
    extracting a mixin to shared the CSS between these two components.

    Now we've reduced the amount of reported hard coded strings by ERB Lint
    to 39.

commit 22f6f20f8d3e1916e04630f8fab144f0eea489e7
Author: Javi Martín <javim@elretirao.net>
Date:   Sat Nov 22 15:26:50 2025 +0100

    Move author info partial to a component

    Since we've already using a component for the basic author info, we're
    doing the same for consistency. We're also renaming it to
    `DetailedAuthorInfo` for consistency with the `DetailedInfo` component.

commit 040438fe02721dcdeaa09ec107fe6eeff872fa3c
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 24 14:32:22 2025 +0100

    Use a <time> tag to display the detailed info date

    Just like we did with the basic info date a few commits ago.

commit 6c4dc5e4b15cbe22d18d664f24f3a8012d339f46
Author: Javi Martín <javim@elretirao.net>
Date:   Sat Nov 22 01:02:12 2025 +0100

    Use a shared component to render detailed information

    We were using the same code in six different places.

    Note we're changing the conditition to render the flag/unflag actions
    from `if current_user` to `if can?(:flag, record)`. The latter is more
    reliable, and it works with topics (that can't be flagged even if
    there's a current user).

commit 3f8df7ad4969da603b0088e1206105d7c050704c
Author: Javi Martín <javim@elretirao.net>
Date:   Sun Nov 23 02:36:35 2025 +0100

    Move investment detail partial to a component

    This way it'll be easier to manage the `preview` parameter.

commit 460e91e373dc2709a32e7080584f668ad06e2a86
Author: Javi Martín <javim@elretirao.net>
Date:   Sat Nov 22 15:22:09 2025 +0100

    Remove unused code in author info

    The `association_name` attribute (which is about real-life associations
    or organizations, and not about active record associations) was only
    ever used in spending proposals.

commit 435e69a55a389e75dcfb1ef71ab1e112f72d72f6
Author: Javi Martín <javim@elretirao.net>
Date:   Sat Nov 22 15:00:06 2025 +0100

    Show link to comments for selected proposals

    This link was hidden in commit 1a0f0215a in order to simplify the
    information shown in selected proposals. However, we're still showing
    the comments on that page, so having a link to the comments section is
    useful. It might also be confusing for people to see this information in
    some cases but not in other cases, for reasons they probably won't be
    able to understand.

    We aren't 100% this is the best option, but we're choosing the one that
    keeps things simple, and that is using the same interface for every
    proposal. This will also help when refactoring this code.

commit 186164be0491b1ecc678afb559b6b69a3bb440eb
Author: Javi Martín <javim@elretirao.net>
Date:   Fri Nov 21 16:40:17 2025 +0100

    Use CSS to style separators in basic info component

    Using CSS instead of HTML entities is what we've been doing during the
    last few years.

    We're getting some false positives when checking for hard coded strings
    with ERB Lint. With these changes and the refactorings done in the
    previous commits, we've reduced the amount of reported hard coded
    strings from 87 to 59.

    Note we're using `::after` pseudoelements because, in the case of
    comments, the `::before` element is used for the comments icon. Also
    note we're using `position: absolute` for the separator; if we didn't,
    in elements with a background like the "collective" tag for
    organizations or official position labels, the separator would be inside
    the area with a different background, which isn't what we want.

commit 55dfe21c7cbcf0967688485403661af33a4b1a10
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 24 16:24:41 2025 +0100

    Use a shared component to render basic content

    We were using similar code for debates, investments, proposals and
    legislation proposals.

commit 57675d40f6f2f54c0b3cf3895b84aa8e4e5da211
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 24 02:18:46 2025 +0100

    Use a <time> tag to display the basic info date

    This is what <time> tags are for, and using a tag makes styling this
    element easier.

commit a9516a3995c27b310620290bc3a961d8f1640523
Author: Javi Martín <javim@elretirao.net>
Date:   Fri Nov 21 16:34:39 2025 +0100

    Use a shared component to render basic info

    We were using the same code in five different places.

    Note we're adding a `management_polymorphic_path` which is quite a hack
    as it makes an exception for budget investments. The reason is that in
    admin and valuation routes we define:

    ```
    resources :budgets
      # (...)
      resources :budget_investments
    ```

    While in management routes we define:

    ```
    resources :budgets
      # (...)
      resources :investments
    ```

    Furthermore, in the admin section, we use the
    `Admin::BudgetInvestmentsController`, while in the management section we
    use the `Management::Budgets::InvestmentsController`.

    Long story short: we can't use the same code to calculate a management
    polymorphic route and an admin polymorphic route for budget investments.
    So we're directly calling the `management_budget_investment_path` method
    instead in `management_polymorphic_path` when the resource is an
    investment.

    Also note we're replacing the `topic-info` HTML class with `basic-info`
    in both dashboard comments info and community poll info. We're doing so
    because they display very basic information, even if they're inside an
    element with a `topic-show` class. This change slightly affects the
    styles, but nothing significant; the margins are now a bit different.

commit 911fbcdf974c166da171ce670e89a4d0d01d8072
Author: Javi Martín <javim@elretirao.net>
Date:   Sat Nov 22 14:08:38 2025 +0100

    Remove unused selector in investment show page

    This selector isn't used since commit d0b8fef6b.

commit eb6ac1460275b96b037ecb2d83bedd549188e077
Author: Javi Martín <javim@elretirao.net>
Date:   Sat Nov 22 14:08:13 2025 +0100

    Fix typo in budget investment info CSS

    Due to this undetected typo, the styles defined here weren't applied to
    the `.budget-investment-show .budget-investment-info` selector. To apply
    these styles, as a workaround we were adding `.budget-investment-show`
    to the list of selectors that are used in `index` actions. And then we
    were also adding a `<br>` tag because this meant the bottom margin was
    too small.

    By fixing the typo, we can remove the workarounds.

commit 120b74c3247a32d2c1a87fbfc52bc970d5803d3e
Author: Javi Martín <javim@elretirao.net>
Date:   Sat Nov 22 13:51:48 2025 +0100

    Remove unused CSS for debate-info

    This code isn't used since commit d679c1eb7.

commit 0b7b216b9d4a77d1ab602d806058cfdf9f14752c
Author: Javi Martín <javim@elretirao.net>
Date:   Thu Nov 20 20:07:06 2025 +0100

    Remove unused CSS in debate/proposal show

    There are no `.debate-show .debate-description` or `.proposal-show
    .proposal-description` selectors in any page. As far as I know, these
    selectors have never existed because `.debate-description` and
    `.proposal-description` are only used in pages showing a list of
    debates/proposals.

commit 4d87e8587b055c90fbea5056f821f2ff0f7c54f7
Author: Javi Martín <javim@elretirao.net>
Date:   Thu Nov 20 19:52:05 2025 +0100

    Simplify styles for minimal content

    This way it'll be easier to change the other places where we use
    debate-content and other similar classes. After all, none of the styles
    we added to those classes were applied to the minimal content.

commit 56b72b4b8c9062a24e91519ada9ea5b4ba8e6ab0
Author: Javi Martín <javim@elretirao.net>
Date:   Thu Nov 20 18:47:47 2025 +0100

    Use a shared component to render basic author info

    We were using the same code in six different places.

    The only change we're doing is that the author information shown in the
    list of investements was slightly different and now is the same as
    everywhere else. We believe it was a typo due to code duplication and
    that there was no real intention behind the changes in the official
    level and organization logic for investments.

    For example, the `official?` condition on investments was added in
    commit be6d7a1d3 on June 3, 2016, copied from proposals and debates.
    However, by the time it was finally merged in commit 14bb9eef8, the
    logic in proposals and debates had changed to
    `display_official_position_badge?` (commit 9e910a834).

    Not sure why the organization was shown in debates, proposals and
    legislation proposals but not in investments, though, but it was
    probably another typo.

    Note we're adding `Basic` to the component name because there's already
    a `shared/_author_info` partial.

    Also note that, in featured proposals and proposals summary, we're still
    hiding the organization information. Not sure whether this information
    should be displayed in these cases; we're doing it to keep the existing
    behavior, since the information displayed in those sections is different
    than the one displayed in other places.

commit 8a9e2043f7b9329e1c89fcd1cda5399a419fa6c5
Author: Javi Martín <javim@elretirao.net>
Date:   Thu Nov 20 18:42:08 2025 +0100

    Extract components to render featured proposals

commit cf3efd9006f8795432549dddaff7bee6d2075dd7
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 24 16:34:10 2025 +0100

    Move proposals summary view to a component

commit 0d97b205b6441b1d8fe7ad2034aa0a189564eb49
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 24 16:23:44 2025 +0100

    Fix typo in proposals summary

    So now the styles for `proposal-content` are applied here as well.

commit 9c48db61c321146fb69ddab81d8604de473f3fb4
Author: Javi Martín <javim@elretirao.net>
Date:   Thu Nov 20 18:42:08 2025 +0100

    Use the shared translation key for author_deleted

    We were defining the same translation in four places, one of them being
    a shared one.

    So now we're using the shared one everywhere.

commit 1ddef04bfb532e80c202ee0da483b2aa677b7d9a
Merge: 5691bb13c8 182bd3cb12
Author: Javi Martín <35156+javierm@users.noreply.github.com>
Date:   Thu Nov 27 15:21:22 2025 +0100

    Merge pull request #5922 from consuldemocracy/rails7.2

    Upgrade to Rails 7.2

commit 182bd3cb1289006f119fdbf651b5fb9eb73ae4cd
Author: Javi Martín <javim@elretirao.net>
Date:   Fri Nov 21 14:29:41 2025 +0100

    Use rails defaults for puma and database threads

    Back in commit 1e32455cd, we used puma's default values for threads.
    This was a mistake, though; for Rails application, the maximum number of
    threads should be at most the number defined in the database pool. The
    Rails-generated puma configuration says:

    > Any libraries that use a connection pool or another resource pool
    > should be configured to provide at least as many connections as the
    > number of threads. This includes Active Record's `pool` parameter in
    > `database.yml`.

    So we now set the number of threads to 3 and the size of the database
    poll to 5 by default, which is what Rails 7.2 does. Note that
    overwriting `RAILS_MAX_THREADS` would result in the database pool having
    the same size as the number of threads. In my humble opinion, this is a
    bit confusing, and there's currently debate about what Rails should do
    in the future [1].

    [1] Pull request 55687 in https://github.com/rails/rails

commit ef5b0cdb582f43c8ca02b71170c4856efd6cd28a
Author: Javi Martín <javim@elretirao.net>
Date:   Wed Nov 19 16:01:36 2025 +0100

    Remove reference to initializer no longer in Rails

    We forgot to do so in commit d8c866c5e.

commit 1954c830b63d0f336c13fa2bb3d84a31a43f8c0e
Author: Javi Martín <javim@elretirao.net>
Date:   Tue Nov 18 19:27:10 2025 +0100

    Remove initializer to disable PDF auto previews

    This code is already included in Rails 7.2, so we can now safely remove
    it.

commit ac71e438865f0a7785ea4a80f41c40e19cb242b9
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Mar 10 05:16:23 2025 +0100

    Use Rails 7.2 defaults and overwrite them

    For the `active_job.enqueue_after_transaction_commit` configuration
    option, we're keeping the value that was used in Rails 7.1 because it's
    the default value again in Rails 8.0 and the option will be removed in
    Rails 8.1 [1]. Instead, we're changing the `after_*` model callbacks
    that were running jobs inside a transaction so now they run these jobs
    after the transaction is completed.

    For YJIT, we're only enabling it on production environments since it
    doesn't seem to work so well on development and test environments [2].

    [1] See pull request 52675 in https://github.com/rails/rails
    [2] See pull request 53746 in https://github.com/rails/rails

commit 9c71aa62c20b733444c41412f1feb82bdce54134
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Mar 10 05:07:39 2025 +0100

    Return Date objects when selecting dates with raw SQL

    I don't think this change affects us at all, so we're going with the new
    default in Rails 7.2. Out of our dependencies, groupdate seems to be the
    only one that could be affected, and it looks like it keeps working as
    expected.

commit adb7bcc80df27b9d0c41dd4d7bc6676993c24227
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Mar 10 05:02:57 2025 +0100

    Validate migration timestamps

    This is the default in Rails 7.2 and, since we don't write migrations
    with timestamps in the future, we can safely enable it.

commit d120a221721d3b3dffce5e4753c4708bb4bc988a
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Mar 10 04:57:35 2025 +0100

    Allow WebP images in Active Storage

    Currently we don't use them in the application, but we intend to use
    them in the future, so we're using the default value in Rails 7.2.

commit ab271c6ad6cdb2b73f1fc6fb3a399593cb4ad817
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Mar 10 02:13:29 2025 +0100

    Upgrade to Rails 7.2

    Note we're removing the `secret_key_base` key from the test and
    development secrets, since it's ignored in these environments. Quoting
    from the Rails documentation [1]:

    > In development and test, this is randomly generated and stored in a
    > temporary file in <tt>tmp/local_secret.txt</tt>.

    Due to this, in **development**, existing cookies won't be used after
    upgrading. If this is important for you (for example, if you're
    constantly switching branches with Consul Democracy 2.4 and Consul
    Democracy 2.5 in order to change the upgrade), **on your local
    machine**, delete your `secret_key_base` references for the
    **development** environment in your `config/secrets.yml`.

    Other minor modifications from the code the `rails app:update` generates
    include removing the `APP_NAME` and puma-dev references in `bin/setup`
    (they were added in Rails 7.2 but removed once again in Rails 8.0) and
    commenting the `config.autoload_lib` option (we don't autoload the
    `lib/` folder but use `app/lib/` instead).

    [1] https://api.rubyonrails.org/v7.2.0/classes/Rails/Application.html#method-i-secret_key_base

commit d532d3886978ff40cd4a60378003fdf2d98979d6
Author: Javi Martín <javim@elretirao.net>
Date:   Thu Nov 20 16:37:59 2025 +0100

    Make the `secrets` method compatible with Rails 7.2

    We're about to upgrade to Rails 7.2, and in this version the `secrets`
    method has been removed. Since we don't plan to start using credentials
    in the foreseeable future, we're using a simplified version of the
    `secrets` method found in Rails 7.1.

    We also need to overwrite the `secret_key_base` method so it reads the
    one in `config/secrets.yml`. However, doing so is tricky since this
    method contains a few conditionals related to the current environment
    and to certain environment variables. Currently the logic of this method
    (extracted from the source code of Rails 7.2) is:

    ```
    if ENV["SECRET_KEY_BASE_DUMMY"]
      generate_local_secret
    else
      ENV["SECRET_KEY_BASE"] ||
        Rails.application.credentials.secret_key_base ||
        (Rails.env.local? && generate_local_secret)
    end
    ```

    Instead, we're overwriting the `credentials` method so it returns
    secrets instead; since the `secret_key_base` method calls
    `credentials.secret_key_base` when running the application on
    production, overwriting the `credentials` method will cause the
    application to get the secret key base from the `config/secrets.yml`
    file. Since we don't use credentials at all, this change doesn't affect
    the rest of the application.

    To avoid confusion, we're changing the Devise initializer so it doesn't
    reference the `secrets.secret_key_base` method but uses
    `application.secret_key_base` instead.

commit f61ba9ff213535061ff66ba32edfb35c17150e8b
Author: Javi Martín <javim@elretirao.net>
Date:   Tue Nov 18 16:56:50 2025 +0100

    Move active storage service config to environments

    This is the default behavior. We used to have environment files for
    staging and preproduction, so we added it to `config/application.rb`.
    However, now that we've got rid of staging and preproduction, having it
    in `config/environments/` is more convenient because that's what we get
    every time we upgrade to a new version of Rails and run `rails
    app:upgrade`.

commit d5bb1fef5fe4f3704409f286b5da40bf11d40734
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Mar 10 04:18:12 2025 +0100

    Only use `excluding` to replace `where.not(id:`

    We were getting an error in some places when upgrading to Rails 7.2. For
    instance, when searching proposals, we got a query like:

    ```
    "SELECT \"proposals\".\"id\" FROM \"proposals\" LEFT OUTER JOIN
    \"taggings\" ON \"taggings\".\"taggable_type\" = $1 AND
    \"taggings\".\"context\" = $2 AND \"taggings\".\"taggable_id\" =
    \"proposals\".\"id\" LEFT OUTER JOIN \"tags\" ON \"tags\".\"id\" =
    \"taggings\".\"tag_id\" INNER JOIN (SELECT \"proposals\".\"id\" AS
    pg_search_id, ((ts_rank((\"proposals\".\"tsv\"), (to_tsquery('english',
    ''' ' || unaccent('Economía') || ' ''' || ':*')), 0))) AS rank FROM
    \"proposals\" WHERE ((\"proposals\".\"tsv\") @@ (to_tsquery('english',
    ''' ' || unaccent('Economía') || ' ''' || ':*')))) AS
    pg_search_c0cbf0fbcaf64c0b201506 ON \"proposals\".\"id\" =
    pg_search_c0cbf0fbcaf64c0b201506.pg_search_id WHERE
    \"proposals\".\"hidden_at\" IS NULL AND \"proposals\".\"published_at\"
    IS NOT NULL AND \"proposals\".\"created_at\" >= $3 AND
    \"proposals\".\"retired_at\" IS NOT NULL AND (1=0) GROUP BY
    \"proposals\".\"id\" ORDER BY pg_search_c0cbf0fbcaf64c0b201506.rank
    DESC, proposals.cached_votes_up DESC"
    ```

    This resulted in an error:

    ```
    ActiveRecord::StatementInvalid:
    PG::GroupingError: ERROR: column "pg_search_c0cbf0fbcaf64c0b201506.rank"
    must appear in the GROUP BY clause or be used in an aggregate function
    LINE 1: ...NULL AND (1=0) GROUP BY "proposals"."id" ORDER BY pg_search_
    ```

    So now we're only using `excluding` in places where we used to use
    `where.not(id:`. This way we keep the exact same behavior we had before
    we started to use `excluding`. According to the Rails documentation [1]:

    > Post.excluding(post) (...) Post.excluding(post_one, post_two) (...) is
    > short-hand for `.where.not(id: post.id)` and
    > `.where.not(id: [post_one.id,` post_two.id])`.

    This reverts part of commit 38ad65605.

    [1] https://api.rubyonrails.org/v7.2/classes/ActiveRecord/QueryMethods.html#method-i-excluding

commit 45878654cca9fa94da21ba3381f5d8760cde2bd0
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Mar 10 02:57:17 2025 +0100

    Update references to customization documentation

    The old references haven't worked for years. Since we're about to change
    the `application.rb` file as part of the upgrade to Rails 7.2, we're
    updating this comment.

commit 5691bb13c804203ffd3e8261bf658cec17f5d43e
Merge: 2b86ff875e 8fcba5460d
Author: Sebastia <sebastia.roig@gmail.com>
Date:   Thu Nov 20 15:05:10 2025 +0100

    Merge pull request #6068 from danesjenovdan/ai

    LLM translations

commit 2b86ff875e65c244d98c332523d554ca5fcd3f45
Merge: 43daf609d8 3671dcabeb
Author: Javi Martín <35156+javierm@users.noreply.github.com>
Date:   Wed Nov 19 18:26:33 2025 +0100

    Merge pull request #6153 from bfabio/patch-1

    Add landingURL to publiccode.yml

commit 43daf609d802a06d3e53d9f115a69d23bbd3a380
Merge: 9bf5ff6546 9b337487ab
Author: Javi Martín <35156+javierm@users.noreply.github.com>
Date:   Wed Nov 19 13:41:04 2025 +0100

    Merge pull request #6151 from consuldemocracy/use_rails7.1_methods

    Use Rails 7.1 methods to simplify code

commit 9b337487ab740d1a47b824f7ebccc514c26f7e98
Author: Javi Martín <javim@elretirao.net>
Date:   Tue Nov 18 04:05:33 2025 +0100

    Extract method in executions image component

    This makes the code more readable.

commit a5460704dd1c919ae109452efcf5fcec4d992295
Author: Javi Martín <javim@elretirao.net>
Date:   Tue Nov 18 03:56:57 2025 +0100

    Use where.associated to simplify code

    This method was actually introduced in Rails 7.0, but since we didn't
    start using it back then, we're starting now.

commit 0010ea96e2a4029fff884b59343fed80ff437863
Author: Javi Martín <javim@elretirao.net>
Date:   Thu Apr 18 03:21:38 2024 +0200

    Use Object#with to simplify setups in tests

    This method was introduced in Rails 7.1 and is very useful in this kind
    of situations.

commit 2a4e84095b15c098e509b2acec250dfb181c1554
Author: Javi Martín <javim@elretirao.net>
Date:   Tue Nov 18 02:43:26 2025 +0100

    Merge Sanitizable and Taggable concerns

    The Sanitizable concern only makes sense for Taggable models since
    commit 7bf4e4d61. Having two different concerns led to some
    inconsitencies. The `Legislation::Process` class was including Taggable
    but not Sanitizable (making it the only class where tags weren't
    sanitized). On the other hand, the `Budget::Phase` class still included
    the `Sanitizable` concern even if it doesn't have tags, meaning
    including it was useless.

    We came up with this refactoring while trying to find places where we
    could simplify code using the `normalizes` method included in Rails 7.1.
    While doing so here turned out not to be trivial, we've decided to keep
    this refactoring as part of this pull request.

commit 3671dcabebabeb76f2b0b221e68c0d029aaa72cd
Author: Fabio Bonelli <fbonelli@gmail.com>
Date:   Wed Nov 19 09:22:50 2025 +0100

    Add landingURL to publiccode.yml

    Add landing URL so that the EU OSS Catalog can have a nice
    link to the project page.

commit 8fcba5460d003cbf36eee8040b16d1aafc053741
Author: Sebastjan Stojnsek <stirkac@users.noreply.github.com>
Date:   Tue Nov 18 10:26:17 2025 +0100

    Update system tests for LLM translation support

    Update remotely_translatable shared examples to support both
    Microsoft and LLM translation providers. This allows testing
    translation feature with either provider while maintaining
    backward compatibility with existing Microsoft based tests.

    Note: Since the Microsoft option will likely be deprecated in
    upcoming releases, we can revisit and optimize those tests later on.

commit 3f0a235a01f5d6c81d1cd2935ace52b3f165a230
Author: Sebastjan Stojnsek <stirkac@users.noreply.github.com>
Date:   Tue Nov 18 10:25:57 2025 +0100

    Add documentation for LLM translation feature

commit b8be4ff31315333fafc4df97afa1e2e2e5a25646
Author: Sebastjan Stojnsek <stirkac@users.noreply.github.com>
Date:   Tue Nov 18 10:25:41 2025 +0100

    Integrate LLM translations into RemoteTranslations

    Expand the existing RemoteTranslations framework by adding support for
    LLM-based translations as an alternative to the Microsoft service.

    The caller now selects between Microsoft and LLM providers based on the
    admin configuration, with LLM taking precedence when enabled.

commit 4beb391f3e9a9255aa985658643ff034877596b0
Author: Sebastjan Stojnsek <stirkac@users.noreply.github.com>
Date:   Tue Nov 18 10:24:26 2025 +0100

    Add LLM settings panel to Admin configuration

    Introduce the new LLM Settings section in the admin interface,
    allowing administrators to select the LLM provider, choose a model, and
    enable or disable LLM based remote translations.

    Add ruby_llm as a dependency.

commit 412da9b4b5ef694a677fc3a8a097c6d140fce880
Author: Sebastjan Stojnsek <stirkac@users.noreply.github.com>
Date:   Tue Nov 18 10:16:03 2025 +0100

    Add reusable DropdownFormComponent for admin settings

    Create a reusable DropdownFormComponent for admin settings that
    standardizes dropdown form inputs. The component follows the same
    pattern as FeaturedSettingsFormComponent and integrates with the
    existing RowComponent structure.

    Also add disabled parameter support to both DropdownFormComponent
    and FeaturedSettingsFormComponent, allowing settings to be disabled
    based on configuration state. Update RowComponent to support dropdown
    type settings and pass through disabled and options parameters.

commit adbadc1d99b03517ef4e22cf52a981526d37e646
Author: Javi Martín <javim@elretirao.net>
Date:   Tue Nov 18 03:24:33 2025 +0100

    Use `normalizes` to clean document numbers

    Since we no longer have to wait for validation to normalize this
    attribute, we can simplify the tests a little bit.

    Note that in Rails 7.1 the `normalizes` method isn't available in
    ActiveModel. That means we can't use it in `Officing::Residence` and
    `Verification::Residence`. For that, we'll have to wait for Rails 8.1.

    Note that there's still some duplication and we could certainly extract
    the regular expression to a shared class. We'll do so (unless we forget)
    when we upgrade to Rails 8.1 and start using ActiveModel normalizations.

commit 39b8e8fc86d28e54372f794e15aedd606dc11341
Author: Javi Martín <javim@elretirao.net>
Date:   Thu Apr 18 02:41:53 2024 +0200

    Use `normalizes` on local census text attributes

    This way we don't have to wait for validation in order to get the
    normalized value.

commit 59b0386d677a22c1e868c4cdd47a989cab3ab955
Author: Javi Martín <javim@elretirao.net>
Date:   Thu Apr 18 02:23:58 2024 +0200

    Use env.local? where possible

    This is a very convenient method in some cases.

commit 0177deb4d9f4a06b1c16c4a9473b492c5a6e30dd
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 20:32:20 2025 +0100

    Remove unused verification/email#new route

    We added it in commit 01a5a0387, but never used it.

commit eb60fb0e143f4c2031cfef2c3ecaa348c667480c
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 20:28:43 2025 +0100

    Remove unused moderation/administrator_tasks routes

    We don't use these routes since commit f9a085a40.

commit b242fd0f282f07206d954a32cc86cc3350437de1
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 20:18:41 2025 +0100

    Remove unused admin/poll/officers#new route

    We accidentally didn't do so in commit 3670859fa, where we deleted the
    unused `show` and `edit` actions.

commit dd8982ef1ea352096023655d9698b5c171ad7a23
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 19:48:33 2025 +0100

    Remove unused admin/poll/officer_assignments routes

    We don't use them since commit 9181610de. We're also removing methods
    that were only used before the no longer existing `create` action.

commit 20785f29bc6dc0f8c114d01e3c72b35f823db86f
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 19:46:15 2025 +0100

    Remove unused admin/users routes and permissions

    We added both the `show` route and the `:search` permission in commit
    b61621060. However, we've never used them; `show` was probably a typo,
    and we use a filter in the `index` action to search users.

commit 1b9ea63922cc5d4ce30b2e686fd325b4ac4f30f1
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 19:43:11 2025 +0100

    Remove unused admin/tags#update route

    We don't use this route since commit e60ffa3c0.

commit 81783f5f6c663c30f1cfc37798e195674ff66fe3
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 19:36:18 2025 +0100

    Remove unused admin/newsletters#users route

    We don't use this route since commit cb15a2e25.

commit 550697bf72902ada8ab2399d866398074443686e
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 19:34:03 2025 +0100

    Remove unused admin/valuators#summary route

    We don't use this route since commit 24dde9c35.

commit f5075d1e5f534e97af9c41eb74618bb954c2ceb4
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 19:30:56 2025 +0100

    Remove unused admin/banners#search route

    We added this route in commit 3b2bfc46c, but never used it.

commit cd2cde27eb2c2650899e874d0e4ed5190d73f6c0
Author: Javi Martín <javim@elretirao.net>
Date:   Thu Apr 18 02:26:13 2024 +0200

    Remove unused accounts#erase route

    We added this route in commit 9cc158540, but never used it. The
    `delete_form` path was used instead.

commit 9bf5ff654647b10666893609d3c77008ce8d0f3f
Merge: 17e7a6fa36 c0624cd19b
Author: Javi Martín <35156+javierm@users.noreply.github.com>
Date:   Mon Nov 17 18:17:58 2025 +0100

    Merge pull request #6146 from consuldemocracy/release_2.4.1

    Release version 2.4.1

commit c0624cd19b2196aca6eb3e7b5e7a6540f774d546
Author: Javi Martín <javim@elretirao.net>
Date:   Thu Nov 13 16:34:53 2025 +0100

    Release version 2.4.1

commit 17e7a6fa365fd72fa76409f17e6c4a43f21c1161
Merge: 5e70cbdc1c b4b66f0382
Author: Javi Martín <35156+javierm@users.noreply.github.com>
Date:   Mon Nov 17 18:02:21 2025 +0100

    Merge pull request #6149 from consuldemocracy/bump_js_yaml

    Bump js-yaml from 4.1.0 to 4.1.1

commit b4b66f03827690de422f4bde1af940a88629dcfc
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 17:26:38 2025 +0100

    Bump js-yaml from 4.1.0 to 4.1.1

    We're getting a Dependabot alert because of this [1], but currently
    Dependabot is unable to open the pull request fixing it [2].

    Code generated by running `npm audit fix`.

    [1] https://github.com/advisories/GHSA-mh29-5h37-fv8m
    [2] Issue 13551 in https://github.com/dependabot/dependabot-core

commit 5e70cbdc1c064bb952fce1c651e683dbbddb7d25
Merge: dd2fb6469f 5a432da498
Author: Javi Martín <35156+javierm@users.noreply.github.com>
Date:   Mon Nov 17 16:43:12 2025 +0100

    Merge pull request #6148 from consuldemocracy/add_label_to_edit_form_map_markers

    Add ARIA labels to admin settings map marker

commit 5a432da4986b490fe4f984edeea297627da4a3fb
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 03:19:31 2025 +0100

    Update old usages of investments JSON data

    We aren't using these properties since commit 3fa3c90db. An old test was
    failing when checking for Axe accessibility issues because of this.

commit 288f62cdd2041af28ba17904987d26877979c153
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 04:24:08 2025 +0100

    Use coordinates as marker labels when there's only one mappable

    When editing/showing a proposal or an investment, the most relevant
    information regarding the marker are the coordinates. The title of the
    proposal or investment is redundant because we already know the marker
    is about that proposal/investment.

    There's one problem with this approach, though: when editing a proposal
    or an investment, the aria-label of the marker isn't updated
    automatically when we move the marker to a different place. This
    behaviour will only affect people who use both a screen reader and a
    mouse, since keyboard users can't change the position of the marker in
    the first place. We'll deal with this issue when we make it possible to
    change the position of a marker using the keyboard.

commit 99696cb302535933babc8bbcc45343e08845bc77
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 01:08:22 2025 +0100

    Add aria-label to markers in admin map settings

    We forgot to do so in commit b896fc4bb. Back then, we said:

    > Note that we aren't providing a proper aria-label for markers on the
    > map we use in the form to create a proposal or an investment. Adding
    > one isn't trivial given the current code, and keyboard users can't add
    > a marker in the first place. We'll have to revisit this issue when we
    > add keyboard support for this.

    However, in the admin section, the marker is already there, so it should
    have a label. In this case, we're using the coordinates as label because
    it's the most relevant text for the marker in the context of a form. We
    could also use "Default map location" instead, but that information is
    already present on the page.

    Axe was reporting the same accessibility error we mentioned in commit
    b896fc4bb in this situation.

commit 1693aa5d9cfda3079889f40f3b01a5eefaf2143f
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 00:44:51 2025 +0100

    Use render_map to render the admin settings map

    This way we remove duplication.

    Note that to check whether to render the button to remove a marker,
    we're checking whether the map location belongs to a mappable. This
    means we're changing the code that renders the map in the "new proposal"
    and "new investment" forms so the map location belongs to a proposal or
    investment. We're association the map location to a new record because
    writing something like:

    ```
    def map_location
      proposal.map_location || MapLocation.new(proposal: proposal)
    end
    ```

    Would change the `proposal` object because of the way Rails treats
    non-persisted `has_one` associations. Although probably safe in this
    case, changing an object when rendering a view could have side effects.

    Also note that we're changing the HTML ID of the map element from
    `admin-map` to `new_map_location` (the latter is returned by the
    `dom_id` method).  We were only using this ID in tests since commit
    289426c1c, so changing it doesn't really affect us.

commit 8a575ae83c66111166c5f55015541e67f302621d
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 02:21:52 2025 +0100

    Remove duplicate map location translations

    We were using the same texts twice. For the remove marker label text,
    however, we were using the text defined in proposals for both proposals
    and investments.

    Ideally the translation keys for these texts would go in another
    namespace, since they no longer refer to just proposals. However,
    renaming the translation keys would mean losing the existing
    translations in every language we manage through Crowdin. So we aren't
    doing so.

commit b9adef481a9ff34df4a61c845997f4a1033f4b89
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 00:43:09 2025 +0100

    Simplify variable name in map location fields

    The `m_l` prefix isn't really necessary when we're talking about map
    locations, and sometimes when searching the project I think `m_l_`
    stands for "machine learning" and get confused.

commit 29e5adc233a09b0430151a399eb343eab60a8cbf
Author: Javi Martín <javim@elretirao.net>
Date:   Sun Nov 16 23:57:46 2025 +0100

    Move map location fields partial to a component

    This way it'll be easier to test it and refactor it.

commit 67e00654bd56ef91b635b41b275e40c594c9b8e4
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 02:11:14 2025 +0100

    Extract methods to get map location in form components

    This way changing them will be easier.

commit 8b3ac5ac971cc188d6a685141aa34450d2cd8d51
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 00:18:19 2025 +0100

    Use a legend instead of a label in map location fields

    The label was invalid HTML since it wasn't referencing any existing
    element.

commit 86a12b23ad0a4c99f947cbeb7956a22fdd77038f
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 01:59:17 2025 +0100

    Test admin map settings from the user's point of view

    People using these settings don't know about the hidden fields, but they
    do know about the fields that are actually displayed on the page. So we
    check that these fields are updated when the marker is updated.

commit a6908f201755c2594214baff05c5cf8aa5384b16
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 00:31:44 2025 +0100

    Group similar map tests together

    We're about to change some of these tests, and we usually group similar
    system tests in order to make the test suite a bit faster.

commit 2d85bd5351ac7dee88c976a1a9995561fe83cf2e
Author: Javi Martín <javim@elretirao.net>
Date:   Sun Nov 16 23:53:26 2025 +0100

    Remove duplication rendering map location fields

    We're going to move the partial to a component, and this makes it
    easier.

commit 0ec7c65b9bbd374263812a701f4b73e2c6113338
Author: Javi Martín <javim@elretirao.net>
Date:   Sun Nov 16 23:45:56 2025 +0100

    Don't pass unused parameter to map location fields partial

    We don't use this parameter since commit c34aa5412.

commit d0b57868af3b9d3fe40b074de4d753267b09e391
Author: Javi Martín <javim@elretirao.net>
Date:   Sat Nov 15 05:37:59 2025 +0100

    Move settings map inside the form

    That's what we usually do, and it makes sense since clicking on the map
    changes the content of hidden fields in the form.

commit dd2fb6469f234ba6c02061769fc2a992a5d39a3a
Merge: ebac669fd0 9a898495ac
Author: Javi Martín <35156+javierm@users.noreply.github.com>
Date:   Fri Nov 14 15:49:51 2025 +0100

    Merge pull request #6144 from consuldemocracy/serious_accessibility_issues

    Fix most Axe serious accessibility issues

commit ebac669fd0a357333439ad18a6f36ab2f9ca67c2
Merge: 2e4a05f6b9 4e455578d1
Author: Sebastia <sebastia.roig@gmail.com>
Date:   Fri Nov 14 15:38:25 2025 +0100

    Merge pull request #6125 from consuldemocracy/remove-obsolete-scopes

    Add missing investments filter on admin activity page

commit 2e4a05f6b90bfed7d01edee534c3777a0cd22593
Merge: 4aa650325a 873968ee0a
Author: Sebastia <sebastia.roig@gmail.com>
Date:   Fri Nov 14 15:38:08 2025 +0100

    Merge pull request #6040 from consuldemocracy/remove-redundant-tests

    Remove redundant tests

commit 873968ee0aebdfd018654c82a8de7e80eaf35953
Author: taitus <sebastia.roig@gmail.com>
Date:   Wed Jul 9 14:27:27 2025 +0200

    Unify related tests in wizard phases spec

commit 3dc0de34bc2e3e1aeeb05c79d5788053fd9d48b5
Author: taitus <sebastia.roig@gmail.com>
Date:   Wed Jul 9 14:26:59 2025 +0200

    Unify related tests in wizard headings spec

commit d43654be42fadcbfcbfcad9f643286b3b606dc90
Author: taitus <sebastia.roig@gmail.com>
Date:   Wed Jul 9 14:26:35 2025 +0200

    Unify related tests in wizard groups spec

commit 42ef5b65bdcff17dffa017dcab45a11af9f27b9f
Author: taitus <sebastia.roig@gmail.com>
Date:   Wed Jul 9 14:23:44 2025 +0200

    Unify similar tests in wizard budgets spec

    We are unifying the test "Create budget - Knapsack voting (default)" with
    "A new budget is always created in draft mode" because they are almost the same.

    On the other hand, we also merged the test "update budget" with "submit the
    form with errors and then without errors". Just like in the previous case, there
    were two ways to access the edit page, so we removed the one that is already
    tested in other specs.

commit 4e455578d1c8ff69d14bba832c2507e3e1bc68a7
Author: taitus <sebastia.roig@gmail.com>
Date:   Fri Nov 14 11:46:11 2025 +0100

    Rename User.by_authors to with_ids

    The "by_authors" scope was the last remaining name from the removed
    family of `by_author` scopes. It no longer reflects its purpose: it
    simply loads users by IDs.

commit a9129158c12fc68f9c33f0942a811217522cf6ee
Author: taitus <sebastia.roig@gmail.com>
Date:   Fri Nov 14 13:41:37 2025 +0100

    Make moderation tests easier to read

    - reuse aria-labels instead of DOM selectors when checking moderation checkboxes
    - drop redundant 'first' in the within

commit a3a44f527b7439e09f1c03035e14d82348bf1ab5
Author: taitus <sebastia.roig@gmail.com>
Date:   Fri Oct 24 09:47:52 2025 +0200

    Give purpose to previously unused on_budget_investments scope

    The "on_budget_investments" scope in Activity has never been used
    anywhere in the codebase. It was introduced in commit d9d38482b34
    ("extends Activity to include Investment valuations") but no references
    were ever added.

    Instead of removing it, we make use of the scope by adding the missing
    "Budget investments" filter to the admin Activity section. This aligns
    it with the rest of the activity filters and gives the scope the purpose
    it was originally intended for.

commit 0332160627ad05792cc5218a5b7c0251b1222e46
Author: taitus <sebastia.roig@gmail.com>
Date:   Fri Oct 24 14:23:19 2025 +0200

    Remove unused by_official_level scope from Proposal

    The "by_official_level" scope in Proposal is no longer used anywhere in
    the code. Its last use was removed in commit 9f1f912d84 ("Remove
    official level filter from advanced search").

commit 41837344681d01ccc18a06e734243ac4c0bd8571
Author: taitus <sebastia.roig@gmail.com>
Date:   Fri Oct 24 14:10:47 2025 +0200

    Remove unused sort_by_most_commented scope from Debate

    The "sort_by_most_commented" scope in Debate is no longer used anywhere in
    the code. Its last use was removed in commit b89f39bfef ("Removes
    unused orders from debates controller")

commit 8938b781c3cef50922f28096a6f7d3fdb003618a
Author: taitus <sebastia.roig@gmail.com>
Date:   Fri Oct 24 13:59:49 2025 +0200

    Remove unused created_by scope from Proposal

    The "created_by" scope in Proposal is no longer used anywhere in the code.
    It was introduced in 77dd604 and its last usage was dropped in commit 64258baf977
    ("Refactor getting the public activity information").

commit 29f4edd466ac6a07df8f45daff13eeda9755e379
Author: taitus <sebastia.roig@gmail.com>
Date:   Fri Oct 24 10:50:36 2025 +0200

    Remove unused scopes from Legislation::Proposal

    The "for_render", "sort_by_hot_score" and "sort_by_most_commented"
    scopes in Legislation::Proposal are no longer used
    anywhere in the code. They were all introduced in commit 335399e571
    ("Created Legislation Proposals model") and have never been
    referenced since.

commit c4368b077a2f55b2a02d3d8885124c7e98914d1c
Author: taitus <sebastia.roig@gmail.com>
Date:   Fri Oct 24 10:38:50 2025 +0200

    Remove unused by_geozone_id scope from Poll

    The "by_geozone_id" scope in Poll is no longer used anywhere in the code.
    It was first introduced in commit 20cb0440150e ("adds search and filter
    for poll questions") and later moved to the Poll model in commit
    d02450596048 ("moves geozones from poll question to poll in models"),
    but has never been referenced since.

commit 151b12bd35d5d36cc75f63ec6829aa60c7e04359
Author: taitus <sebastia.roig@gmail.com>
Date:   Fri Oct 24 10:23:38 2025 +0200

    Remove unused by_email scope from VerifiedUser

    The "by_email" scope in VerifiedUser is no longer used anywhere in the
    code. Its last occurrence was removed in commit 76daee1fb04 ("removes
    unmasked emails and phones in forms").

commit 9a898495ac7df39de920e8d3ed3abe5c731f4bc3
Author: Javi Martín <javim@elretirao.net>
Date:   Fri Nov 7 15:31:26 2025 +0100

    Add menuitem role to sign out button

    Back in commit c6f0a3761, we replaced the link to sign out with a
    button. However, this button is a child of a data-responsive-menu
    dropdown element. Since Foundation adds the `menubar` role to responsive
    menus, its children are supposed to have a `menuitem` role. So we're
    adding it.

    Note we're adding the role with JavaScript because, when JavaScript is
    disabled, Foundation won't change the `responsive-menu` role to
    `menubar`. So we can't have a `menuitem` in this case.

    Axe was reporting the following issue:

    ```
    Found 1 accessibility violation:

    1) aria-required-children: Certain ARIA roles must contain
       particular children (critical)
        https://dequeuniversity.com/rules/axe/4.11/aria-required-children?application=axeAPI
        The following 1 node violate this rule:

            Selector: .account-menu
            HTML: <ul class="account-menu menu dropdown"
                      data-responsive-menu="medium-dropdown" role="menubar"
                      data-dropdown-menu="cabp3q-dropdown-menu"
                      data-mutate="ph8tvp-responsive-menu">
            Fix any of the following:
            - Element has children which are not allowed: button[tabindex]
    ```

commit b896fc4bba509452510b2e71c24ef9af13055eae
Author: Javi Martín <javim@elretirao.net>
Date:   Wed Feb 26 16:12:45 2025 +0100

    Add aria-label to map markers

    Axe was reporting an accessibility error:

    ```
    Found 1 accessibility violation:

    1) aria-command-name: ARIA commands must have an accessible name
       (serious)
       https://dequeuniversity.com/rules/axe/4.11/aria-command-name?application=axeAPI
       The following 1 node violate this rule:

         Selector: .leaflet-marker-icon
         HTML: <div class="leaflet-marker-icon map-marker
                           leaflet-zoom-animated leaflet-interactive"
                    tabindex="0" role="button">
                    <div class="map-icon"></div>
               </div>
         Fix any of the following:
         - Element does not have text that is visible to screen readers
         - aria-label attribute does not exist or is empty
         - aria-labelledby attribute does not exist, references elements
           that do not exist or references elements that are empty
         - Element has no title attribute
    ```

    Using the title of the proposal/investment as the text of the marker is
    definitely a good solution when there are several markers on the map.
    Not sure whether there's a better option when there's only one marker,
    though.

    Note that we aren't providing a proper aria-label for markers on the map
    we use in the form to create a proposal or an investment. Adding one
    isn't trivial given the current code, and keyboard users can't add a
    marker in the first place. We'll have to revisit this issue when we add
    keyboard support for this.

    We're also changing a test to make sure that titles with quotes in their
    names don't break the markup due to an invalid aria-label attribute.

commit b5d939565b368601f0930c044ba87ef2f905f3f3
Author: Javi Martín <javim@elretirao.net>
Date:   Fri Nov 7 13:10:40 2025 +0100

    Make fullscreen editor preview focusable

    This part of the page can be scrolled independently with the mouse, and
    so the same should be possible with a keyboard.

    Axe was reporting this error:

    ```
    1) scrollable-region-focusable: Scrollable region must have
       keyboard access (serious)
        https://dequeuniversity.com/rules/axe/4.11/scrollable-region-focusable?application=axeAPI
        The following 1 node violate this rule:

          Selector: .fullscreen > .markdown-preview.medium-6.small-12
          HTML: <div class="small-12 medium-6 column markdown-preview">
          Fix any of the following:
          - Element should have focusable content
          - Element should be focusable
    ```

commit 4aa650325ac1d04450c19402ce1e7decee42aef8
Merge: 82c6e2c8dc b6a2ff2cd6
Author: Javi Martín <35156+javierm@users.noreply.github.com>
Date:   Thu Nov 6 15:54:48 2025 +0100

    Merge pull request #6050 from consuldemocracy/dependabot/npm_and_yarn/stylistic/stylelint-plugin-4.0.0

    Bump @stylistic/stylelint-plugin from 3.1.2 to 4.0.0

commit b6a2ff2cd6ca4f0dfc7b07c0c58504b339ce84b7
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Thu Nov 6 13:39:21 2025 +0000

    Bump @stylistic/stylelint-plugin from 3.1.2 to 4.0.0

    Bumps [@stylistic/stylelint-plugin](https://github.com/stylelint-stylistic/stylelint-stylistic) from 3.1.2 to 4.0.0.
    - [Release notes](https://github.com/stylelint-stylistic/stylelint-stylistic/releases)
    - [Changelog](https://github.com/stylelint-stylistic/stylelint-stylistic/blob/main/CHANGELOG.md)
    - [Commits](https://github.com/stylelint-stylistic/stylelint-stylistic/compare/v3.1.2...v4.0.0)

    ---
    updated-dependencies:
    - dependency-name: "@stylistic/stylelint-plugin"
      dependency-version: 4.0.0
      dependency-type: direct:development
      update-type: version-update:semver-major
    ...

    Signed-off-by: dependabot[bot] <support@github.com>

commit 82c6e2c8dc7d3db13e125729f4f86aaae36d0e34
Merge: 2c74f9f35b c6da88f3fa
Author: Javi Martín <35156+javierm@users.noreply.github.com>
Date:   Thu Nov 6 14:37:15 2025 +0100

    Merge pull request #6140 from consuldemocracy/bump_rails_to_7.1.6

    Bump rails from 7.1.5.2 to 7.1.6

commit c6da88f3fab89c11efb3e9b5d0e3a7f4b8061bc8
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 3 12:30:23 2025 +0100

    Bump rails from 7.1.5.2 to 7.1.6

    This is the latest security release in the Rails 7.1.x series.

commit 2c74f9f35b73d733451cf7c1e5fe8962075e89ba
Merge: a563108a03 ad654949ab
Author: Javi Martín <35156+javierm@users.noreply.github.com>
Date:   Thu Nov 6 13:25:39 2025 +0100

    Merge pull request #6123 from consuldemocracy/max_empty_lines

    Add and apply stylistic/max-empty-lines rule

commit a563108a03619dd8a538ce90074d34dceedf4c44
Merge: 2927fd4a05 8d7deef413
Author: Javi Martín <35156+javierm@users.noreply.github.com>
Date:   Thu Nov 6 13:25:00 2025 +0100

    Merge pull request #6124 from consuldemocracy/menu_button_flashing

    Don't flash the menu button on desktop screens

commit 2927fd4a05483f6cd1357a909b1c0c9aa8292f96
Merge: 3e1276510c 3584ab048c
Author: Javi Martín <35156+javierm@users.noreply.github.com>
Date:   Thu Nov 6 13:23:38 2025 +0100

    Merge pull request #6134 from consuldemocracy/dependabot/npm_and_yarn/stylelint-16.25.0

    Bump stylelint from 16.20.0 to 16.25.0

commit 3584ab048c7bd04b853fef56a425aa55e6294777
Author: Javi Martín <javim@elretirao.net>
Date:   Wed Nov 5 19:51:05 2025 +0100

    Replace word-break: break-word with overflow-wrap

    According to W3C documentation [1]:

    > For compatibility with legacy content, the word-break property also
    > supports a deprecated break-word keyword. When specified, this has the
    > same effect as word-break: normal and overflow-wrap: anywhere,
    > regardless of the actual value of the overflow-wrap property.

    This is currently *not* detected by the `property-no-deprecated`
    stylelint rule. However, since this rule detects other places where we
    should use `overflow-wrap`, we're changing it as part of the same pull
    request.

    Note that, as of November 2025, 98.22% of the browsers support
    `overflow-wrap: anywhere`. We're still making this change because we
    only use this property in two specific places and it isn't very likely
    that long words will really be a problem with the remaining 1.78%.

    By the way, I'm not sure why we use this property in the budget
    invesment show paragraphs and not in other similar places. It was
    introduced in commit e3878ff43, alongside other changes which don't seem
    to be related. When in doubt, we leave things as they were, so we're
    doing the same thing here.

    [1] https://www.w3.org/TR/css-text-3/#word-break-property
    [2] https://caniuse.com/mdn-css_properties_overflow-wrap_anywhere

commit d063475769c8494e7f67ec33a9eb2dc2029b6bd8
Author: Javi Martín <javim@elretirao.net>
Date:   Wed Nov 5 19:02:58 2025 +0100

    Use CSS instead of utility classes in options table

    This way we make it easier to customize this component. In this specific
    case, ideally we'd remove some of the CSS as well. For now we're leaving
    it as it was for compatibility reasons.

commit 2d72144048b664a25feed7909386eca861629533
Author: Javi Martín <javim@elretirao.net>
Date:   Wed Nov 5 18:39:19 2025 +0100

    Extract component to render question options table

    This way it's easier to know that the styles for the `break` HTML class
    and the JavaScript for sortable elements (which we shouldn't use, by the
    way, because of its accessibility issues) are only used here.

commit d6f6b94ae457491da7f38cf92d67224e74f5f9a2
Author: Javi Martín <javim@elretirao.net>
Date:   Wed Nov 5 19:16:52 2025 +0100

    Fix wrong selector for sortable tables

    We renamed the HTML class to `table-sortable` in commit 99f8bb449. It
    was incorrectly being applied to the question options table.

commit a5e788dde4b32c4eb627f2715c96c7b163f039c9
Author: Javi Martín <javim@elretirao.net>
Date:   Tue Nov 4 15:39:51 2025 +0100

    Add and apply property-no-deprecated stylelint rule

    This rule was introduced in stylelint 16.23. Out of the deprecated
    properties it detects, we were only using `word-wrap`.

    According to the CSS Working Group [1]:

    > For legacy reasons, UAs must treat word-wrap as a legacy name alias of
    > the overflow-wrap property.

    Since there's universal browser support for `overflow-wrap: break-word`
    [2], we can safely replace `word-wrap` with `overflow-wrap`.

    [1] https://drafts.csswg.org/css-text/#overflow-wrap-property
    [2] https://caniuse.com/mdn-css_properties_overflow-wrap_break-word

commit 917c9e6ac4fdd5af350a19d2becec900185a8886
Author: Javi Martín <javim@elretirao.net>
Date:   Tue Nov 4 13:19:44 2025 +0100

    Add no-invalid-position-declaration stylelint rule

    This rule was introduced in stylelint 16.23. We were always following
    it, and it's unlikely that we miss it before opening a pull request, but
    it might be useful during development.

commit f9f718543fa633da5d3b9c0345c55b65c84b33db
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Nov 4 12:19:13 2025 +0000

    Bump stylelint from 16.20.0 to 16.25.0

    Bumps [stylelint](https://github.com/stylelint/stylelint) from 16.20.0 to 16.25.0.
    - [Release notes](https://github.com/stylelint/stylelint/releases)
    - [Changelog](https://github.com/stylelint/stylelint/blob/main/CHANGELOG.md)
    - [Commits](https://github.com/stylelint/stylelint/compare/16.20.0...16.25.0)

    ---
    updated-dependencies:
    - dependency-name: stylelint
      dependency-version: 16.25.0
      dependency-type: direct:development
      update-type: version-update:semver-minor
    ...

    Signed-off-by: dependabot[bot] <support@github.com>

commit 3e1276510c4d43b1251954032b2919645af35550
Merge: 520f0c42d4 8e6a5eac78
Author: Javi Martín <35156+javierm@users.noreply.github.com>
Date:   Wed Nov 5 18:21:26 2025 +0100

    Merge pull request #6093 from consuldemocracy/dependabot/bundler/rubocop-1.81.1

    Bump rubocop from 1.76.1 to 1.81.7

commit ad654949abf084ad5486bef631425004aed2ed93
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Oct 13 11:59:37 2025 +0200

    Add and apply stylistic/max-empty-lines rule

    We were already using a similar rule in Ruby files.

commit 8d7deef41360b1cdf6800775ce0a0977b4beac11
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Sep 12 04:34:36 2022 +0200

    Don't flash the menu button on desktop screens

    The button flashed briefly when loading the page. This was even more
    obvious when using devices with slow internet connections.

    Using CSS instead of JavaScript to hide the menu solves the issue, since
    styles are loaded before scripts.

commit 618fc4b2c08b52f04244ad126cb28811ba7212c6
Author: Javi Martín <javim@elretirao.net>
Date:   Sun Apr 14 01:59:23 2024 +0200

    Move responsive menu styles to its proper file

    We forgot to do so in commit 49cb6e010.

commit 8e6a5eac7836ae26dbdfe08feb44ec29ac7792fd
Author: Javi Martín <javim@elretirao.net>
Date:   Fri Oct 31 14:44:06 2025 +0100

    Add Style/ArrayIntersectWithSingleElement rule

    This rule was introduced in rubocop 1.81. Even though it doesn't
    currently affect us, it makes sense.

commit d18c627392c1d628cd949020d7989bd0dbf71a03
Author: Javi Martín <javim@elretirao.net>
Date:   Fri Oct 31 14:40:32 2025 +0100

    Add and apply Layout/EmptyLinesAfterModuleInclusion rule

    This rule was added in rubocop 1.79. We were inconsistent about it, so
    we're adding it to get more consistency.

commit 7f749bb9bb8eefa5113c0c44f9211bfb7f386a16
Author: Javi Martín <javim@elretirao.net>
Date:   Fri Oct 31 14:31:35 2025 +0100

    Add and apply Style/CollectionQuerying rubocop rule

    This rule was added in rubocop 1.77. We were following it most of the
    time. It makes the code more readable in my humble opinion.

commit 1fa3cf8ce7e479aabb29d0746773fa40a6559dd1
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Fri Oct 31 13:26:52 2025 +0000

    Bump rubocop from 1.76.1 to 1.81.1

    This release includes some updates in the Style/RedundantParentheses and
    Naming/PredicateMethod rules. We're changing the code accordingly.

    Bumps [rubocop](https://github.com/rubocop/rubocop) from 1.76.1 to 1.81.1.
    - [Release notes](https://github.com/rubocop/rubocop/releases)
    - [Changelog](https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md)
    - [Commits](https://github.com/rubocop/rubocop/compare/v1.76.1...v1.81.1)

    ---
    updated-dependencies:
    - dependency-name: rubocop
      dependency-version: 1.81.1
      dependency-type: direct:development
      update-type: version-update:semver-minor
    ...

    Signed-off-by: dependabot[bot] <support@github.com>

commit 413d0ed9beffe7ff8ce62c37edd9e1224e18c8d6
Author: Javi Martín <javim@elretirao.net>
Date:   Fri Oct 31 15:31:20 2025 +0100

    Return the persisted line in add_investment

    This method was returning a boolean value and caused a
    `Naming/PredicateMethod` when upgrading rubocop.

    So, instead, we're returning the created line when it was successfully
    created, and `nil` when it wasn't.

    Having said that, I'm not sure why we added the `.persisted?` back in
    commit 3eb22ab7b since as far as I can tell we don't use the return
    value for anything. The test added in commit da43e9e2e for this change
    passes if we simply return `lines.create(investment: investment)`.

    For now I'm leaving the `persisted?` check just in case, but removing it
    might be fine.

commit 15f7632f3d3e9cb9edf4fdcada7b8bb68d3451ff
Author: Javi Martín <javim@elretirao.net>
Date:   Fri Oct 31 15:11:22 2025 +0100

    Refactor notifiable_available? method

    This method was calling `check_availability`, which returned a boolean
    value and caused a `Naming/PredicateMethod` when upgrading rubocop.

    So we're changing the logic a little bit to remove the
    `check_availability` method and merge the tests of `check_availability`
    and `notifiable_available?` (which were almost identical) together.

commit 2fdfefe55dc7cba1cc76026f04bba131b080f1bc
Author: Javi Martín <javim@elretirao.net>
Date:   Fri Oct 31 14:56:57 2025 +0100

    Use Verification::Email.valid_token? instead of .find

    This way it's more obvious that the method is supposed to return a
    boolean. When upgrading rubocop, we get a `Naming/PredicateMethod` error
    due to `.find` returning a boolean.

commit 520f0c42d488ea8b142ab3e09f63c17abced9d79
Merge: ec6252cc41 cc9f7904ac
Author: Javi Martín <35156+javierm@users.noreply.github.com>
Date:   Wed Nov 5 14:26:38 2025 +0100

    Merge pull request #6142 from consuldemocracy/dependabot/bundler/rubocop-rspec_rails-2.31.0

    Bump rubocop-rspec_rails from 2.30.0 to 2.31.0

commit cc9f7904acc77b95786663bb56795a58d422de57
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Wed Nov 5 13:11:50 2025 +0000

    Bump rubocop-rspec_rails from 2.30.0 to 2.31.0

    We're changing the `.rubocop.yml` file because we were getting a
    warning:

    ```
    rubocop-rspec_rails extension supports plugin, specify `plugins:
    rubocop-rspec_rails` instead of `require: rubocop-rspec_rails` in
    .rubocop.yml.  For more information, see
    https://docs.rubocop.org/rubocop/plugin_migration_guide.html.
    ```

    Bumps [rubocop-rspec_rails](https://github.com/rubocop/rubocop-rspec_rails) from 2.30.0 to 2.31.0.
    - [Release notes](https://github.com/rubocop/rubocop-rspec_rails/releases)
    - [Changelog](https://github.com/rubocop/rubocop-rspec_rails/blob/master/CHANGELOG.md)
    - [Commits](https://github.com/rubocop/rubocop-rspec_rails/compare/v2.30.0...v2.31.0)

    ---
    updated-dependencies:
    - dependency-name: rubocop-rspec_rails
      dependency-version: 2.31.0
      dependency-type: direct:development
      update-type: version-update:semver-minor
    ...

    Signed-off-by: dependabot[bot] <support@github.com>

commit ec6252cc416cfc980b4e44ba2e37b0805fa58516
Merge: c3f34030fe 0ca94e5443
Author: Javi Martín <35156+javierm@users.noreply.github.com>
Date:   Wed Nov 5 14:06:09 2025 +0100

    Merge pull request #6106 from consuldemocracy/dependabot/bundler/rubocop-rails-2.33.4

    Bump rubocop-rails from 2.29.1 to 2.33.4

commit 0ca94e54437bef65d38148c9e243f8871b10273f
Author: Javi Martín <javim@elretirao.net>
Date:   Fri Oct 31 13:10:20 2025 +0100

    Add and apply Rails/FindByOrAssignmentMemoization rule

    This rule was added in rubocop-rails 2.33.

    At first, I wasn't very fond of this rule. It made the code less
    readable even if it improved performace in some cases.

    Then I realized that in the `Admin::MachineLearning::SettingComponent`
    we were using `find_by` when we should be using `find_by!` instead, and
    we detected that thanks to this rule.

    So, only for that reason, I'm adding this rule, but I'm fine if we
    remove it.

commit 048bdb2e9ef5ad22bd9937f47ad01823a44f09f0
Author: Javi Martín <javim@elretirao.net>
Date:   Fri Oct 31 13:02:09 2025 +0100

    Add and apply Rails/OrderArguments rubocop rule

    This rule was introduced in rubocop-rails 2.33. We were following it
    most of the time.

commit 0c5dc24cc23f23f270f9a294257e7bffd854d56e
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Fri Oct 31 11:01:51 2025 +0000

    Bump rubocop-rails from 2.29.1 to 2.33.4

    We're changing the `.rubocop.yml` file because we were getting a
    warning:

    ```
    rubocop-rails extension supports plugin, specify `plugins:
    rubocop-rails` instead of `require: rubocop-rails` in .rubocop.yml. For
    more information, see
    https://docs.rubocop.org/rubocop/plugin_migration_guide.html.
    ```

    Bumps [rubocop-rails](https://github.com/rubocop/rubocop-rails) from 2.29.1 to 2.33.4.
    - [Release notes](https://github.com/rubocop/rubocop-rails/releases)
    - [Changelog](https://github.com/rubocop/rubocop-rails/blob/master/CHANGELOG.md)
    - [Commits](https://github.com/rubocop/rubocop-rails/compare/v2.29.1...v2.33.4)

    ---
    updated-dependencies:
    - dependency-name: rubocop-rails
      dependency-version: 2.33.4
      dependency-type: direct:development
      update-type: version-update:semver-minor
    ...

    Signed-off-by: dependabot[bot] <support@github.com>

commit c3f34030fe0f59b4f59a70243d74f43f69dd7629
Merge: a72d137fac a3c25b5a2b
Author: Javi Martín <35156+javierm@users.noreply.github.com>
Date:   Wed Nov 5 11:51:04 2025 +0100

    Merge pull request #6090 from consuldemocracy/dependabot/bundler/rubocop-performance-1.26.0

    Bump rubocop-performance from 1.23.1 to 1.26.1

commit a3c25b5a2b2faffdceedc7b724dc4d2c14578e30
Author: Javi Martín <javim@elretirao.net>
Date:   Fri Oct 31 12:29:03 2025 +0100

    Add Performance/ZipWithoutBlock rubocop rule

    This rule was added in rubocop-performance 1.24.

    We currently don't have code where it'd be relevant, but it's a nice
    rule to have if we ever write `something.map { |element| [element] }`.

commit 42378285acc095cde080e6e9aaf1097d23e475c1
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Fri Oct 31 10:57:42 2025 +0000

    Bump rubocop-performance …
stirkac added a commit to danesjenovdan/consul that referenced this pull request Dec 22, 2025
commit 4141a2116dc6fa08967b88225a3328bb39dac782
Author: Sebastjan Stojnsek <stirkac@users.noreply.github.com>
Date:   Sat Dec 6 11:25:28 2025 +0100

    Image suggestions with LLM

    This commit introduces image suggestions next to the upload image button, to present stock images from Pexels service.

    Under the hood that uses LLM to extract context from title and description fields of the newly created resource, and then uses this to look up stock photos through Pexels API.

    Such selected image is treated as user-uploaded image, and is saved through the local server when selected by the user.

commit 92f46e0092bcc7cd2145905e4025f275c2b05de3
Merge: 6ee9c3a5cd 9c7b16a68b
Author: Sebastia <sebastia.roig@gmail.com>
Date:   Thu Dec 18 16:51:13 2025 +0100

    Merge pull request #6187 from consuldemocracy/update-customization-docs

    update gems.md documentation with conflict resolution suggestion

commit 9c7b16a68be906407e9b42fa0e2472def7686fe3
Author: Lucía Luzuriaga <luzuriaga.lucia@gmail.com>
Date:   Tue Dec 16 12:49:48 2025 -0300

    update gems.md documentation with conflict resolution suggestion

commit 6ee9c3a5cd41606e492a383acbb1c00f6f9afc0d
Author: Alejandro Vera <alejandro.vera1988@gmail.com>
Date:   Mon Dec 15 13:34:10 2025 +0000

    Add Valencian SDG images (Merge pull request #6145)

    The Valencian SDG images included in this PR are sourced
    from the Generalitat Valenciana’s official CONSUL participation platform:
    https://gvaparticipa.gva.es/sdg/goals?locale=val

commit 577f79b084ebf2fd48d09c47af701b6d82cf6168
Merge: 1ddef04bfb 6afe59a9e4
Author: Javi Martín <35156+javierm@users.noreply.github.com>
Date:   Wed Dec 3 14:53:00 2025 +0100

    Merge pull request #6158 from consuldemocracy/css_in_info_separators

    Use CSS to style separators in author/date/comments info

commit 6afe59a9e442383e311918631c2351f089d23ca1
Author: Javi Martín <javim@elretirao.net>
Date:   Sat Nov 22 01:08:59 2025 +0100

    Use CSS to style separators in detailed info component

    Just like we did to the basic info component a few commits ago. We're
    extracting a mixin to shared the CSS between these two components.

    Now we've reduced the amount of reported hard coded strings by ERB Lint
    to 39.

commit 22f6f20f8d3e1916e04630f8fab144f0eea489e7
Author: Javi Martín <javim@elretirao.net>
Date:   Sat Nov 22 15:26:50 2025 +0100

    Move author info partial to a component

    Since we've already using a component for the basic author info, we're
    doing the same for consistency. We're also renaming it to
    `DetailedAuthorInfo` for consistency with the `DetailedInfo` component.

commit 040438fe02721dcdeaa09ec107fe6eeff872fa3c
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 24 14:32:22 2025 +0100

    Use a <time> tag to display the detailed info date

    Just like we did with the basic info date a few commits ago.

commit 6c4dc5e4b15cbe22d18d664f24f3a8012d339f46
Author: Javi Martín <javim@elretirao.net>
Date:   Sat Nov 22 01:02:12 2025 +0100

    Use a shared component to render detailed information

    We were using the same code in six different places.

    Note we're changing the conditition to render the flag/unflag actions
    from `if current_user` to `if can?(:flag, record)`. The latter is more
    reliable, and it works with topics (that can't be flagged even if
    there's a current user).

commit 3f8df7ad4969da603b0088e1206105d7c050704c
Author: Javi Martín <javim@elretirao.net>
Date:   Sun Nov 23 02:36:35 2025 +0100

    Move investment detail partial to a component

    This way it'll be easier to manage the `preview` parameter.

commit 460e91e373dc2709a32e7080584f668ad06e2a86
Author: Javi Martín <javim@elretirao.net>
Date:   Sat Nov 22 15:22:09 2025 +0100

    Remove unused code in author info

    The `association_name` attribute (which is about real-life associations
    or organizations, and not about active record associations) was only
    ever used in spending proposals.

commit 435e69a55a389e75dcfb1ef71ab1e112f72d72f6
Author: Javi Martín <javim@elretirao.net>
Date:   Sat Nov 22 15:00:06 2025 +0100

    Show link to comments for selected proposals

    This link was hidden in commit 1a0f0215a in order to simplify the
    information shown in selected proposals. However, we're still showing
    the comments on that page, so having a link to the comments section is
    useful. It might also be confusing for people to see this information in
    some cases but not in other cases, for reasons they probably won't be
    able to understand.

    We aren't 100% this is the best option, but we're choosing the one that
    keeps things simple, and that is using the same interface for every
    proposal. This will also help when refactoring this code.

commit 186164be0491b1ecc678afb559b6b69a3bb440eb
Author: Javi Martín <javim@elretirao.net>
Date:   Fri Nov 21 16:40:17 2025 +0100

    Use CSS to style separators in basic info component

    Using CSS instead of HTML entities is what we've been doing during the
    last few years.

    We're getting some false positives when checking for hard coded strings
    with ERB Lint. With these changes and the refactorings done in the
    previous commits, we've reduced the amount of reported hard coded
    strings from 87 to 59.

    Note we're using `::after` pseudoelements because, in the case of
    comments, the `::before` element is used for the comments icon. Also
    note we're using `position: absolute` for the separator; if we didn't,
    in elements with a background like the "collective" tag for
    organizations or official position labels, the separator would be inside
    the area with a different background, which isn't what we want.

commit 55dfe21c7cbcf0967688485403661af33a4b1a10
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 24 16:24:41 2025 +0100

    Use a shared component to render basic content

    We were using similar code for debates, investments, proposals and
    legislation proposals.

commit 57675d40f6f2f54c0b3cf3895b84aa8e4e5da211
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 24 02:18:46 2025 +0100

    Use a <time> tag to display the basic info date

    This is what <time> tags are for, and using a tag makes styling this
    element easier.

commit a9516a3995c27b310620290bc3a961d8f1640523
Author: Javi Martín <javim@elretirao.net>
Date:   Fri Nov 21 16:34:39 2025 +0100

    Use a shared component to render basic info

    We were using the same code in five different places.

    Note we're adding a `management_polymorphic_path` which is quite a hack
    as it makes an exception for budget investments. The reason is that in
    admin and valuation routes we define:

    ```
    resources :budgets
      # (...)
      resources :budget_investments
    ```

    While in management routes we define:

    ```
    resources :budgets
      # (...)
      resources :investments
    ```

    Furthermore, in the admin section, we use the
    `Admin::BudgetInvestmentsController`, while in the management section we
    use the `Management::Budgets::InvestmentsController`.

    Long story short: we can't use the same code to calculate a management
    polymorphic route and an admin polymorphic route for budget investments.
    So we're directly calling the `management_budget_investment_path` method
    instead in `management_polymorphic_path` when the resource is an
    investment.

    Also note we're replacing the `topic-info` HTML class with `basic-info`
    in both dashboard comments info and community poll info. We're doing so
    because they display very basic information, even if they're inside an
    element with a `topic-show` class. This change slightly affects the
    styles, but nothing significant; the margins are now a bit different.

commit 911fbcdf974c166da171ce670e89a4d0d01d8072
Author: Javi Martín <javim@elretirao.net>
Date:   Sat Nov 22 14:08:38 2025 +0100

    Remove unused selector in investment show page

    This selector isn't used since commit d0b8fef6b.

commit eb6ac1460275b96b037ecb2d83bedd549188e077
Author: Javi Martín <javim@elretirao.net>
Date:   Sat Nov 22 14:08:13 2025 +0100

    Fix typo in budget investment info CSS

    Due to this undetected typo, the styles defined here weren't applied to
    the `.budget-investment-show .budget-investment-info` selector. To apply
    these styles, as a workaround we were adding `.budget-investment-show`
    to the list of selectors that are used in `index` actions. And then we
    were also adding a `<br>` tag because this meant the bottom margin was
    too small.

    By fixing the typo, we can remove the workarounds.

commit 120b74c3247a32d2c1a87fbfc52bc970d5803d3e
Author: Javi Martín <javim@elretirao.net>
Date:   Sat Nov 22 13:51:48 2025 +0100

    Remove unused CSS for debate-info

    This code isn't used since commit d679c1eb7.

commit 0b7b216b9d4a77d1ab602d806058cfdf9f14752c
Author: Javi Martín <javim@elretirao.net>
Date:   Thu Nov 20 20:07:06 2025 +0100

    Remove unused CSS in debate/proposal show

    There are no `.debate-show .debate-description` or `.proposal-show
    .proposal-description` selectors in any page. As far as I know, these
    selectors have never existed because `.debate-description` and
    `.proposal-description` are only used in pages showing a list of
    debates/proposals.

commit 4d87e8587b055c90fbea5056f821f2ff0f7c54f7
Author: Javi Martín <javim@elretirao.net>
Date:   Thu Nov 20 19:52:05 2025 +0100

    Simplify styles for minimal content

    This way it'll be easier to change the other places where we use
    debate-content and other similar classes. After all, none of the styles
    we added to those classes were applied to the minimal content.

commit 56b72b4b8c9062a24e91519ada9ea5b4ba8e6ab0
Author: Javi Martín <javim@elretirao.net>
Date:   Thu Nov 20 18:47:47 2025 +0100

    Use a shared component to render basic author info

    We were using the same code in six different places.

    The only change we're doing is that the author information shown in the
    list of investements was slightly different and now is the same as
    everywhere else. We believe it was a typo due to code duplication and
    that there was no real intention behind the changes in the official
    level and organization logic for investments.

    For example, the `official?` condition on investments was added in
    commit be6d7a1d3 on June 3, 2016, copied from proposals and debates.
    However, by the time it was finally merged in commit 14bb9eef8, the
    logic in proposals and debates had changed to
    `display_official_position_badge?` (commit 9e910a834).

    Not sure why the organization was shown in debates, proposals and
    legislation proposals but not in investments, though, but it was
    probably another typo.

    Note we're adding `Basic` to the component name because there's already
    a `shared/_author_info` partial.

    Also note that, in featured proposals and proposals summary, we're still
    hiding the organization information. Not sure whether this information
    should be displayed in these cases; we're doing it to keep the existing
    behavior, since the information displayed in those sections is different
    than the one displayed in other places.

commit 8a9e2043f7b9329e1c89fcd1cda5399a419fa6c5
Author: Javi Martín <javim@elretirao.net>
Date:   Thu Nov 20 18:42:08 2025 +0100

    Extract components to render featured proposals

commit cf3efd9006f8795432549dddaff7bee6d2075dd7
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 24 16:34:10 2025 +0100

    Move proposals summary view to a component

commit 0d97b205b6441b1d8fe7ad2034aa0a189564eb49
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 24 16:23:44 2025 +0100

    Fix typo in proposals summary

    So now the styles for `proposal-content` are applied here as well.

commit 9c48db61c321146fb69ddab81d8604de473f3fb4
Author: Javi Martín <javim@elretirao.net>
Date:   Thu Nov 20 18:42:08 2025 +0100

    Use the shared translation key for author_deleted

    We were defining the same translation in four places, one of them being
    a shared one.

    So now we're using the shared one everywhere.

commit 1ddef04bfb532e80c202ee0da483b2aa677b7d9a
Merge: 5691bb13c8 182bd3cb12
Author: Javi Martín <35156+javierm@users.noreply.github.com>
Date:   Thu Nov 27 15:21:22 2025 +0100

    Merge pull request #5922 from consuldemocracy/rails7.2

    Upgrade to Rails 7.2

commit 182bd3cb1289006f119fdbf651b5fb9eb73ae4cd
Author: Javi Martín <javim@elretirao.net>
Date:   Fri Nov 21 14:29:41 2025 +0100

    Use rails defaults for puma and database threads

    Back in commit 1e32455cd, we used puma's default values for threads.
    This was a mistake, though; for Rails application, the maximum number of
    threads should be at most the number defined in the database pool. The
    Rails-generated puma configuration says:

    > Any libraries that use a connection pool or another resource pool
    > should be configured to provide at least as many connections as the
    > number of threads. This includes Active Record's `pool` parameter in
    > `database.yml`.

    So we now set the number of threads to 3 and the size of the database
    poll to 5 by default, which is what Rails 7.2 does. Note that
    overwriting `RAILS_MAX_THREADS` would result in the database pool having
    the same size as the number of threads. In my humble opinion, this is a
    bit confusing, and there's currently debate about what Rails should do
    in the future [1].

    [1] Pull request 55687 in https://github.com/rails/rails

commit ef5b0cdb582f43c8ca02b71170c4856efd6cd28a
Author: Javi Martín <javim@elretirao.net>
Date:   Wed Nov 19 16:01:36 2025 +0100

    Remove reference to initializer no longer in Rails

    We forgot to do so in commit d8c866c5e.

commit 1954c830b63d0f336c13fa2bb3d84a31a43f8c0e
Author: Javi Martín <javim@elretirao.net>
Date:   Tue Nov 18 19:27:10 2025 +0100

    Remove initializer to disable PDF auto previews

    This code is already included in Rails 7.2, so we can now safely remove
    it.

commit ac71e438865f0a7785ea4a80f41c40e19cb242b9
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Mar 10 05:16:23 2025 +0100

    Use Rails 7.2 defaults and overwrite them

    For the `active_job.enqueue_after_transaction_commit` configuration
    option, we're keeping the value that was used in Rails 7.1 because it's
    the default value again in Rails 8.0 and the option will be removed in
    Rails 8.1 [1]. Instead, we're changing the `after_*` model callbacks
    that were running jobs inside a transaction so now they run these jobs
    after the transaction is completed.

    For YJIT, we're only enabling it on production environments since it
    doesn't seem to work so well on development and test environments [2].

    [1] See pull request 52675 in https://github.com/rails/rails
    [2] See pull request 53746 in https://github.com/rails/rails

commit 9c71aa62c20b733444c41412f1feb82bdce54134
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Mar 10 05:07:39 2025 +0100

    Return Date objects when selecting dates with raw SQL

    I don't think this change affects us at all, so we're going with the new
    default in Rails 7.2. Out of our dependencies, groupdate seems to be the
    only one that could be affected, and it looks like it keeps working as
    expected.

commit adb7bcc80df27b9d0c41dd4d7bc6676993c24227
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Mar 10 05:02:57 2025 +0100

    Validate migration timestamps

    This is the default in Rails 7.2 and, since we don't write migrations
    with timestamps in the future, we can safely enable it.

commit d120a221721d3b3dffce5e4753c4708bb4bc988a
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Mar 10 04:57:35 2025 +0100

    Allow WebP images in Active Storage

    Currently we don't use them in the application, but we intend to use
    them in the future, so we're using the default value in Rails 7.2.

commit ab271c6ad6cdb2b73f1fc6fb3a399593cb4ad817
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Mar 10 02:13:29 2025 +0100

    Upgrade to Rails 7.2

    Note we're removing the `secret_key_base` key from the test and
    development secrets, since it's ignored in these environments. Quoting
    from the Rails documentation [1]:

    > In development and test, this is randomly generated and stored in a
    > temporary file in <tt>tmp/local_secret.txt</tt>.

    Due to this, in **development**, existing cookies won't be used after
    upgrading. If this is important for you (for example, if you're
    constantly switching branches with Consul Democracy 2.4 and Consul
    Democracy 2.5 in order to change the upgrade), **on your local
    machine**, delete your `secret_key_base` references for the
    **development** environment in your `config/secrets.yml`.

    Other minor modifications from the code the `rails app:update` generates
    include removing the `APP_NAME` and puma-dev references in `bin/setup`
    (they were added in Rails 7.2 but removed once again in Rails 8.0) and
    commenting the `config.autoload_lib` option (we don't autoload the
    `lib/` folder but use `app/lib/` instead).

    [1] https://api.rubyonrails.org/v7.2.0/classes/Rails/Application.html#method-i-secret_key_base

commit d532d3886978ff40cd4a60378003fdf2d98979d6
Author: Javi Martín <javim@elretirao.net>
Date:   Thu Nov 20 16:37:59 2025 +0100

    Make the `secrets` method compatible with Rails 7.2

    We're about to upgrade to Rails 7.2, and in this version the `secrets`
    method has been removed. Since we don't plan to start using credentials
    in the foreseeable future, we're using a simplified version of the
    `secrets` method found in Rails 7.1.

    We also need to overwrite the `secret_key_base` method so it reads the
    one in `config/secrets.yml`. However, doing so is tricky since this
    method contains a few conditionals related to the current environment
    and to certain environment variables. Currently the logic of this method
    (extracted from the source code of Rails 7.2) is:

    ```
    if ENV["SECRET_KEY_BASE_DUMMY"]
      generate_local_secret
    else
      ENV["SECRET_KEY_BASE"] ||
        Rails.application.credentials.secret_key_base ||
        (Rails.env.local? && generate_local_secret)
    end
    ```

    Instead, we're overwriting the `credentials` method so it returns
    secrets instead; since the `secret_key_base` method calls
    `credentials.secret_key_base` when running the application on
    production, overwriting the `credentials` method will cause the
    application to get the secret key base from the `config/secrets.yml`
    file. Since we don't use credentials at all, this change doesn't affect
    the rest of the application.

    To avoid confusion, we're changing the Devise initializer so it doesn't
    reference the `secrets.secret_key_base` method but uses
    `application.secret_key_base` instead.

commit f61ba9ff213535061ff66ba32edfb35c17150e8b
Author: Javi Martín <javim@elretirao.net>
Date:   Tue Nov 18 16:56:50 2025 +0100

    Move active storage service config to environments

    This is the default behavior. We used to have environment files for
    staging and preproduction, so we added it to `config/application.rb`.
    However, now that we've got rid of staging and preproduction, having it
    in `config/environments/` is more convenient because that's what we get
    every time we upgrade to a new version of Rails and run `rails
    app:upgrade`.

commit d5bb1fef5fe4f3704409f286b5da40bf11d40734
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Mar 10 04:18:12 2025 +0100

    Only use `excluding` to replace `where.not(id:`

    We were getting an error in some places when upgrading to Rails 7.2. For
    instance, when searching proposals, we got a query like:

    ```
    "SELECT \"proposals\".\"id\" FROM \"proposals\" LEFT OUTER JOIN
    \"taggings\" ON \"taggings\".\"taggable_type\" = $1 AND
    \"taggings\".\"context\" = $2 AND \"taggings\".\"taggable_id\" =
    \"proposals\".\"id\" LEFT OUTER JOIN \"tags\" ON \"tags\".\"id\" =
    \"taggings\".\"tag_id\" INNER JOIN (SELECT \"proposals\".\"id\" AS
    pg_search_id, ((ts_rank((\"proposals\".\"tsv\"), (to_tsquery('english',
    ''' ' || unaccent('Economía') || ' ''' || ':*')), 0))) AS rank FROM
    \"proposals\" WHERE ((\"proposals\".\"tsv\") @@ (to_tsquery('english',
    ''' ' || unaccent('Economía') || ' ''' || ':*')))) AS
    pg_search_c0cbf0fbcaf64c0b201506 ON \"proposals\".\"id\" =
    pg_search_c0cbf0fbcaf64c0b201506.pg_search_id WHERE
    \"proposals\".\"hidden_at\" IS NULL AND \"proposals\".\"published_at\"
    IS NOT NULL AND \"proposals\".\"created_at\" >= $3 AND
    \"proposals\".\"retired_at\" IS NOT NULL AND (1=0) GROUP BY
    \"proposals\".\"id\" ORDER BY pg_search_c0cbf0fbcaf64c0b201506.rank
    DESC, proposals.cached_votes_up DESC"
    ```

    This resulted in an error:

    ```
    ActiveRecord::StatementInvalid:
    PG::GroupingError: ERROR: column "pg_search_c0cbf0fbcaf64c0b201506.rank"
    must appear in the GROUP BY clause or be used in an aggregate function
    LINE 1: ...NULL AND (1=0) GROUP BY "proposals"."id" ORDER BY pg_search_
    ```

    So now we're only using `excluding` in places where we used to use
    `where.not(id:`. This way we keep the exact same behavior we had before
    we started to use `excluding`. According to the Rails documentation [1]:

    > Post.excluding(post) (...) Post.excluding(post_one, post_two) (...) is
    > short-hand for `.where.not(id: post.id)` and
    > `.where.not(id: [post_one.id,` post_two.id])`.

    This reverts part of commit 38ad65605.

    [1] https://api.rubyonrails.org/v7.2/classes/ActiveRecord/QueryMethods.html#method-i-excluding

commit 45878654cca9fa94da21ba3381f5d8760cde2bd0
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Mar 10 02:57:17 2025 +0100

    Update references to customization documentation

    The old references haven't worked for years. Since we're about to change
    the `application.rb` file as part of the upgrade to Rails 7.2, we're
    updating this comment.

commit 5691bb13c804203ffd3e8261bf658cec17f5d43e
Merge: 2b86ff875e 8fcba5460d
Author: Sebastia <sebastia.roig@gmail.com>
Date:   Thu Nov 20 15:05:10 2025 +0100

    Merge pull request #6068 from danesjenovdan/ai

    LLM translations

commit 2b86ff875e65c244d98c332523d554ca5fcd3f45
Merge: 43daf609d8 3671dcabeb
Author: Javi Martín <35156+javierm@users.noreply.github.com>
Date:   Wed Nov 19 18:26:33 2025 +0100

    Merge pull request #6153 from bfabio/patch-1

    Add landingURL to publiccode.yml

commit 43daf609d802a06d3e53d9f115a69d23bbd3a380
Merge: 9bf5ff6546 9b337487ab
Author: Javi Martín <35156+javierm@users.noreply.github.com>
Date:   Wed Nov 19 13:41:04 2025 +0100

    Merge pull request #6151 from consuldemocracy/use_rails7.1_methods

    Use Rails 7.1 methods to simplify code

commit 9b337487ab740d1a47b824f7ebccc514c26f7e98
Author: Javi Martín <javim@elretirao.net>
Date:   Tue Nov 18 04:05:33 2025 +0100

    Extract method in executions image component

    This makes the code more readable.

commit a5460704dd1c919ae109452efcf5fcec4d992295
Author: Javi Martín <javim@elretirao.net>
Date:   Tue Nov 18 03:56:57 2025 +0100

    Use where.associated to simplify code

    This method was actually introduced in Rails 7.0, but since we didn't
    start using it back then, we're starting now.

commit 0010ea96e2a4029fff884b59343fed80ff437863
Author: Javi Martín <javim@elretirao.net>
Date:   Thu Apr 18 03:21:38 2024 +0200

    Use Object#with to simplify setups in tests

    This method was introduced in Rails 7.1 and is very useful in this kind
    of situations.

commit 2a4e84095b15c098e509b2acec250dfb181c1554
Author: Javi Martín <javim@elretirao.net>
Date:   Tue Nov 18 02:43:26 2025 +0100

    Merge Sanitizable and Taggable concerns

    The Sanitizable concern only makes sense for Taggable models since
    commit 7bf4e4d61. Having two different concerns led to some
    inconsitencies. The `Legislation::Process` class was including Taggable
    but not Sanitizable (making it the only class where tags weren't
    sanitized). On the other hand, the `Budget::Phase` class still included
    the `Sanitizable` concern even if it doesn't have tags, meaning
    including it was useless.

    We came up with this refactoring while trying to find places where we
    could simplify code using the `normalizes` method included in Rails 7.1.
    While doing so here turned out not to be trivial, we've decided to keep
    this refactoring as part of this pull request.

commit 3671dcabebabeb76f2b0b221e68c0d029aaa72cd
Author: Fabio Bonelli <fbonelli@gmail.com>
Date:   Wed Nov 19 09:22:50 2025 +0100

    Add landingURL to publiccode.yml

    Add landing URL so that the EU OSS Catalog can have a nice
    link to the project page.

commit 8fcba5460d003cbf36eee8040b16d1aafc053741
Author: Sebastjan Stojnsek <stirkac@users.noreply.github.com>
Date:   Tue Nov 18 10:26:17 2025 +0100

    Update system tests for LLM translation support

    Update remotely_translatable shared examples to support both
    Microsoft and LLM translation providers. This allows testing
    translation feature with either provider while maintaining
    backward compatibility with existing Microsoft based tests.

    Note: Since the Microsoft option will likely be deprecated in
    upcoming releases, we can revisit and optimize those tests later on.

commit 3f0a235a01f5d6c81d1cd2935ace52b3f165a230
Author: Sebastjan Stojnsek <stirkac@users.noreply.github.com>
Date:   Tue Nov 18 10:25:57 2025 +0100

    Add documentation for LLM translation feature

commit b8be4ff31315333fafc4df97afa1e2e2e5a25646
Author: Sebastjan Stojnsek <stirkac@users.noreply.github.com>
Date:   Tue Nov 18 10:25:41 2025 +0100

    Integrate LLM translations into RemoteTranslations

    Expand the existing RemoteTranslations framework by adding support for
    LLM-based translations as an alternative to the Microsoft service.

    The caller now selects between Microsoft and LLM providers based on the
    admin configuration, with LLM taking precedence when enabled.

commit 4beb391f3e9a9255aa985658643ff034877596b0
Author: Sebastjan Stojnsek <stirkac@users.noreply.github.com>
Date:   Tue Nov 18 10:24:26 2025 +0100

    Add LLM settings panel to Admin configuration

    Introduce the new LLM Settings section in the admin interface,
    allowing administrators to select the LLM provider, choose a model, and
    enable or disable LLM based remote translations.

    Add ruby_llm as a dependency.

commit 412da9b4b5ef694a677fc3a8a097c6d140fce880
Author: Sebastjan Stojnsek <stirkac@users.noreply.github.com>
Date:   Tue Nov 18 10:16:03 2025 +0100

    Add reusable DropdownFormComponent for admin settings

    Create a reusable DropdownFormComponent for admin settings that
    standardizes dropdown form inputs. The component follows the same
    pattern as FeaturedSettingsFormComponent and integrates with the
    existing RowComponent structure.

    Also add disabled parameter support to both DropdownFormComponent
    and FeaturedSettingsFormComponent, allowing settings to be disabled
    based on configuration state. Update RowComponent to support dropdown
    type settings and pass through disabled and options parameters.

commit adbadc1d99b03517ef4e22cf52a981526d37e646
Author: Javi Martín <javim@elretirao.net>
Date:   Tue Nov 18 03:24:33 2025 +0100

    Use `normalizes` to clean document numbers

    Since we no longer have to wait for validation to normalize this
    attribute, we can simplify the tests a little bit.

    Note that in Rails 7.1 the `normalizes` method isn't available in
    ActiveModel. That means we can't use it in `Officing::Residence` and
    `Verification::Residence`. For that, we'll have to wait for Rails 8.1.

    Note that there's still some duplication and we could certainly extract
    the regular expression to a shared class. We'll do so (unless we forget)
    when we upgrade to Rails 8.1 and start using ActiveModel normalizations.

commit 39b8e8fc86d28e54372f794e15aedd606dc11341
Author: Javi Martín <javim@elretirao.net>
Date:   Thu Apr 18 02:41:53 2024 +0200

    Use `normalizes` on local census text attributes

    This way we don't have to wait for validation in order to get the
    normalized value.

commit 59b0386d677a22c1e868c4cdd47a989cab3ab955
Author: Javi Martín <javim@elretirao.net>
Date:   Thu Apr 18 02:23:58 2024 +0200

    Use env.local? where possible

    This is a very convenient method in some cases.

commit 0177deb4d9f4a06b1c16c4a9473b492c5a6e30dd
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 20:32:20 2025 +0100

    Remove unused verification/email#new route

    We added it in commit 01a5a0387, but never used it.

commit eb60fb0e143f4c2031cfef2c3ecaa348c667480c
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 20:28:43 2025 +0100

    Remove unused moderation/administrator_tasks routes

    We don't use these routes since commit f9a085a40.

commit b242fd0f282f07206d954a32cc86cc3350437de1
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 20:18:41 2025 +0100

    Remove unused admin/poll/officers#new route

    We accidentally didn't do so in commit 3670859fa, where we deleted the
    unused `show` and `edit` actions.

commit dd8982ef1ea352096023655d9698b5c171ad7a23
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 19:48:33 2025 +0100

    Remove unused admin/poll/officer_assignments routes

    We don't use them since commit 9181610de. We're also removing methods
    that were only used before the no longer existing `create` action.

commit 20785f29bc6dc0f8c114d01e3c72b35f823db86f
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 19:46:15 2025 +0100

    Remove unused admin/users routes and permissions

    We added both the `show` route and the `:search` permission in commit
    b61621060. However, we've never used them; `show` was probably a typo,
    and we use a filter in the `index` action to search users.

commit 1b9ea63922cc5d4ce30b2e686fd325b4ac4f30f1
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 19:43:11 2025 +0100

    Remove unused admin/tags#update route

    We don't use this route since commit e60ffa3c0.

commit 81783f5f6c663c30f1cfc37798e195674ff66fe3
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 19:36:18 2025 +0100

    Remove unused admin/newsletters#users route

    We don't use this route since commit cb15a2e25.

commit 550697bf72902ada8ab2399d866398074443686e
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 19:34:03 2025 +0100

    Remove unused admin/valuators#summary route

    We don't use this route since commit 24dde9c35.

commit f5075d1e5f534e97af9c41eb74618bb954c2ceb4
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 19:30:56 2025 +0100

    Remove unused admin/banners#search route

    We added this route in commit 3b2bfc46c, but never used it.

commit cd2cde27eb2c2650899e874d0e4ed5190d73f6c0
Author: Javi Martín <javim@elretirao.net>
Date:   Thu Apr 18 02:26:13 2024 +0200

    Remove unused accounts#erase route

    We added this route in commit 9cc158540, but never used it. The
    `delete_form` path was used instead.

commit 9bf5ff654647b10666893609d3c77008ce8d0f3f
Merge: 17e7a6fa36 c0624cd19b
Author: Javi Martín <35156+javierm@users.noreply.github.com>
Date:   Mon Nov 17 18:17:58 2025 +0100

    Merge pull request #6146 from consuldemocracy/release_2.4.1

    Release version 2.4.1

commit c0624cd19b2196aca6eb3e7b5e7a6540f774d546
Author: Javi Martín <javim@elretirao.net>
Date:   Thu Nov 13 16:34:53 2025 +0100

    Release version 2.4.1

commit 17e7a6fa365fd72fa76409f17e6c4a43f21c1161
Merge: 5e70cbdc1c b4b66f0382
Author: Javi Martín <35156+javierm@users.noreply.github.com>
Date:   Mon Nov 17 18:02:21 2025 +0100

    Merge pull request #6149 from consuldemocracy/bump_js_yaml

    Bump js-yaml from 4.1.0 to 4.1.1

commit b4b66f03827690de422f4bde1af940a88629dcfc
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 17:26:38 2025 +0100

    Bump js-yaml from 4.1.0 to 4.1.1

    We're getting a Dependabot alert because of this [1], but currently
    Dependabot is unable to open the pull request fixing it [2].

    Code generated by running `npm audit fix`.

    [1] https://github.com/advisories/GHSA-mh29-5h37-fv8m
    [2] Issue 13551 in https://github.com/dependabot/dependabot-core

commit 5e70cbdc1c064bb952fce1c651e683dbbddb7d25
Merge: dd2fb6469f 5a432da498
Author: Javi Martín <35156+javierm@users.noreply.github.com>
Date:   Mon Nov 17 16:43:12 2025 +0100

    Merge pull request #6148 from consuldemocracy/add_label_to_edit_form_map_markers

    Add ARIA labels to admin settings map marker

commit 5a432da4986b490fe4f984edeea297627da4a3fb
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 03:19:31 2025 +0100

    Update old usages of investments JSON data

    We aren't using these properties since commit 3fa3c90db. An old test was
    failing when checking for Axe accessibility issues because of this.

commit 288f62cdd2041af28ba17904987d26877979c153
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 04:24:08 2025 +0100

    Use coordinates as marker labels when there's only one mappable

    When editing/showing a proposal or an investment, the most relevant
    information regarding the marker are the coordinates. The title of the
    proposal or investment is redundant because we already know the marker
    is about that proposal/investment.

    There's one problem with this approach, though: when editing a proposal
    or an investment, the aria-label of the marker isn't updated
    automatically when we move the marker to a different place. This
    behaviour will only affect people who use both a screen reader and a
    mouse, since keyboard users can't change the position of the marker in
    the first place. We'll deal with this issue when we make it possible to
    change the position of a marker using the keyboard.

commit 99696cb302535933babc8bbcc45343e08845bc77
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 01:08:22 2025 +0100

    Add aria-label to markers in admin map settings

    We forgot to do so in commit b896fc4bb. Back then, we said:

    > Note that we aren't providing a proper aria-label for markers on the
    > map we use in the form to create a proposal or an investment. Adding
    > one isn't trivial given the current code, and keyboard users can't add
    > a marker in the first place. We'll have to revisit this issue when we
    > add keyboard support for this.

    However, in the admin section, the marker is already there, so it should
    have a label. In this case, we're using the coordinates as label because
    it's the most relevant text for the marker in the context of a form. We
    could also use "Default map location" instead, but that information is
    already present on the page.

    Axe was reporting the same accessibility error we mentioned in commit
    b896fc4bb in this situation.

commit 1693aa5d9cfda3079889f40f3b01a5eefaf2143f
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 00:44:51 2025 +0100

    Use render_map to render the admin settings map

    This way we remove duplication.

    Note that to check whether to render the button to remove a marker,
    we're checking whether the map location belongs to a mappable. This
    means we're changing the code that renders the map in the "new proposal"
    and "new investment" forms so the map location belongs to a proposal or
    investment. We're association the map location to a new record because
    writing something like:

    ```
    def map_location
      proposal.map_location || MapLocation.new(proposal: proposal)
    end
    ```

    Would change the `proposal` object because of the way Rails treats
    non-persisted `has_one` associations. Although probably safe in this
    case, changing an object when rendering a view could have side effects.

    Also note that we're changing the HTML ID of the map element from
    `admin-map` to `new_map_location` (the latter is returned by the
    `dom_id` method).  We were only using this ID in tests since commit
    289426c1c, so changing it doesn't really affect us.

commit 8a575ae83c66111166c5f55015541e67f302621d
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 02:21:52 2025 +0100

    Remove duplicate map location translations

    We were using the same texts twice. For the remove marker label text,
    however, we were using the text defined in proposals for both proposals
    and investments.

    Ideally the translation keys for these texts would go in another
    namespace, since they no longer refer to just proposals. However,
    renaming the translation keys would mean losing the existing
    translations in every language we manage through Crowdin. So we aren't
    doing so.

commit b9adef481a9ff34df4a61c845997f4a1033f4b89
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 00:43:09 2025 +0100

    Simplify variable name in map location fields

    The `m_l` prefix isn't really necessary when we're talking about map
    locations, and sometimes when searching the project I think `m_l_`
    stands for "machine learning" and get confused.

commit 29e5adc233a09b0430151a399eb343eab60a8cbf
Author: Javi Martín <javim@elretirao.net>
Date:   Sun Nov 16 23:57:46 2025 +0100

    Move map location fields partial to a component

    This way it'll be easier to test it and refactor it.

commit 67e00654bd56ef91b635b41b275e40c594c9b8e4
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 02:11:14 2025 +0100

    Extract methods to get map location in form components

    This way changing them will be easier.

commit 8b3ac5ac971cc188d6a685141aa34450d2cd8d51
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 00:18:19 2025 +0100

    Use a legend instead of a label in map location fields

    The label was invalid HTML since it wasn't referencing any existing
    element.

commit 86a12b23ad0a4c99f947cbeb7956a22fdd77038f
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 01:59:17 2025 +0100

    Test admin map settings from the user's point of view

    People using these settings don't know about the hidden fields, but they
    do know about the fields that are actually displayed on the page. So we
    check that these fields are updated when the marker is updated.

commit a6908f201755c2594214baff05c5cf8aa5384b16
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 17 00:31:44 2025 +0100

    Group similar map tests together

    We're about to change some of these tests, and we usually group similar
    system tests in order to make the test suite a bit faster.

commit 2d85bd5351ac7dee88c976a1a9995561fe83cf2e
Author: Javi Martín <javim@elretirao.net>
Date:   Sun Nov 16 23:53:26 2025 +0100

    Remove duplication rendering map location fields

    We're going to move the partial to a component, and this makes it
    easier.

commit 0ec7c65b9bbd374263812a701f4b73e2c6113338
Author: Javi Martín <javim@elretirao.net>
Date:   Sun Nov 16 23:45:56 2025 +0100

    Don't pass unused parameter to map location fields partial

    We don't use this parameter since commit c34aa5412.

commit d0b57868af3b9d3fe40b074de4d753267b09e391
Author: Javi Martín <javim@elretirao.net>
Date:   Sat Nov 15 05:37:59 2025 +0100

    Move settings map inside the form

    That's what we usually do, and it makes sense since clicking on the map
    changes the content of hidden fields in the form.

commit dd2fb6469f234ba6c02061769fc2a992a5d39a3a
Merge: ebac669fd0 9a898495ac
Author: Javi Martín <35156+javierm@users.noreply.github.com>
Date:   Fri Nov 14 15:49:51 2025 +0100

    Merge pull request #6144 from consuldemocracy/serious_accessibility_issues

    Fix most Axe serious accessibility issues

commit ebac669fd0a357333439ad18a6f36ab2f9ca67c2
Merge: 2e4a05f6b9 4e455578d1
Author: Sebastia <sebastia.roig@gmail.com>
Date:   Fri Nov 14 15:38:25 2025 +0100

    Merge pull request #6125 from consuldemocracy/remove-obsolete-scopes

    Add missing investments filter on admin activity page

commit 2e4a05f6b90bfed7d01edee534c3777a0cd22593
Merge: 4aa650325a 873968ee0a
Author: Sebastia <sebastia.roig@gmail.com>
Date:   Fri Nov 14 15:38:08 2025 +0100

    Merge pull request #6040 from consuldemocracy/remove-redundant-tests

    Remove redundant tests

commit 873968ee0aebdfd018654c82a8de7e80eaf35953
Author: taitus <sebastia.roig@gmail.com>
Date:   Wed Jul 9 14:27:27 2025 +0200

    Unify related tests in wizard phases spec

commit 3dc0de34bc2e3e1aeeb05c79d5788053fd9d48b5
Author: taitus <sebastia.roig@gmail.com>
Date:   Wed Jul 9 14:26:59 2025 +0200

    Unify related tests in wizard headings spec

commit d43654be42fadcbfcbfcad9f643286b3b606dc90
Author: taitus <sebastia.roig@gmail.com>
Date:   Wed Jul 9 14:26:35 2025 +0200

    Unify related tests in wizard groups spec

commit 42ef5b65bdcff17dffa017dcab45a11af9f27b9f
Author: taitus <sebastia.roig@gmail.com>
Date:   Wed Jul 9 14:23:44 2025 +0200

    Unify similar tests in wizard budgets spec

    We are unifying the test "Create budget - Knapsack voting (default)" with
    "A new budget is always created in draft mode" because they are almost the same.

    On the other hand, we also merged the test "update budget" with "submit the
    form with errors and then without errors". Just like in the previous case, there
    were two ways to access the edit page, so we removed the one that is already
    tested in other specs.

commit 4e455578d1c8ff69d14bba832c2507e3e1bc68a7
Author: taitus <sebastia.roig@gmail.com>
Date:   Fri Nov 14 11:46:11 2025 +0100

    Rename User.by_authors to with_ids

    The "by_authors" scope was the last remaining name from the removed
    family of `by_author` scopes. It no longer reflects its purpose: it
    simply loads users by IDs.

commit a9129158c12fc68f9c33f0942a811217522cf6ee
Author: taitus <sebastia.roig@gmail.com>
Date:   Fri Nov 14 13:41:37 2025 +0100

    Make moderation tests easier to read

    - reuse aria-labels instead of DOM selectors when checking moderation checkboxes
    - drop redundant 'first' in the within

commit a3a44f527b7439e09f1c03035e14d82348bf1ab5
Author: taitus <sebastia.roig@gmail.com>
Date:   Fri Oct 24 09:47:52 2025 +0200

    Give purpose to previously unused on_budget_investments scope

    The "on_budget_investments" scope in Activity has never been used
    anywhere in the codebase. It was introduced in commit d9d38482b34
    ("extends Activity to include Investment valuations") but no references
    were ever added.

    Instead of removing it, we make use of the scope by adding the missing
    "Budget investments" filter to the admin Activity section. This aligns
    it with the rest of the activity filters and gives the scope the purpose
    it was originally intended for.

commit 0332160627ad05792cc5218a5b7c0251b1222e46
Author: taitus <sebastia.roig@gmail.com>
Date:   Fri Oct 24 14:23:19 2025 +0200

    Remove unused by_official_level scope from Proposal

    The "by_official_level" scope in Proposal is no longer used anywhere in
    the code. Its last use was removed in commit 9f1f912d84 ("Remove
    official level filter from advanced search").

commit 41837344681d01ccc18a06e734243ac4c0bd8571
Author: taitus <sebastia.roig@gmail.com>
Date:   Fri Oct 24 14:10:47 2025 +0200

    Remove unused sort_by_most_commented scope from Debate

    The "sort_by_most_commented" scope in Debate is no longer used anywhere in
    the code. Its last use was removed in commit b89f39bfef ("Removes
    unused orders from debates controller")

commit 8938b781c3cef50922f28096a6f7d3fdb003618a
Author: taitus <sebastia.roig@gmail.com>
Date:   Fri Oct 24 13:59:49 2025 +0200

    Remove unused created_by scope from Proposal

    The "created_by" scope in Proposal is no longer used anywhere in the code.
    It was introduced in 77dd604 and its last usage was dropped in commit 64258baf977
    ("Refactor getting the public activity information").

commit 29f4edd466ac6a07df8f45daff13eeda9755e379
Author: taitus <sebastia.roig@gmail.com>
Date:   Fri Oct 24 10:50:36 2025 +0200

    Remove unused scopes from Legislation::Proposal

    The "for_render", "sort_by_hot_score" and "sort_by_most_commented"
    scopes in Legislation::Proposal are no longer used
    anywhere in the code. They were all introduced in commit 335399e571
    ("Created Legislation Proposals model") and have never been
    referenced since.

commit c4368b077a2f55b2a02d3d8885124c7e98914d1c
Author: taitus <sebastia.roig@gmail.com>
Date:   Fri Oct 24 10:38:50 2025 +0200

    Remove unused by_geozone_id scope from Poll

    The "by_geozone_id" scope in Poll is no longer used anywhere in the code.
    It was first introduced in commit 20cb0440150e ("adds search and filter
    for poll questions") and later moved to the Poll model in commit
    d02450596048 ("moves geozones from poll question to poll in models"),
    but has never been referenced since.

commit 151b12bd35d5d36cc75f63ec6829aa60c7e04359
Author: taitus <sebastia.roig@gmail.com>
Date:   Fri Oct 24 10:23:38 2025 +0200

    Remove unused by_email scope from VerifiedUser

    The "by_email" scope in VerifiedUser is no longer used anywhere in the
    code. Its last occurrence was removed in commit 76daee1fb04 ("removes
    unmasked emails and phones in forms").

commit 9a898495ac7df39de920e8d3ed3abe5c731f4bc3
Author: Javi Martín <javim@elretirao.net>
Date:   Fri Nov 7 15:31:26 2025 +0100

    Add menuitem role to sign out button

    Back in commit c6f0a3761, we replaced the link to sign out with a
    button. However, this button is a child of a data-responsive-menu
    dropdown element. Since Foundation adds the `menubar` role to responsive
    menus, its children are supposed to have a `menuitem` role. So we're
    adding it.

    Note we're adding the role with JavaScript because, when JavaScript is
    disabled, Foundation won't change the `responsive-menu` role to
    `menubar`. So we can't have a `menuitem` in this case.

    Axe was reporting the following issue:

    ```
    Found 1 accessibility violation:

    1) aria-required-children: Certain ARIA roles must contain
       particular children (critical)
        https://dequeuniversity.com/rules/axe/4.11/aria-required-children?application=axeAPI
        The following 1 node violate this rule:

            Selector: .account-menu
            HTML: <ul class="account-menu menu dropdown"
                      data-responsive-menu="medium-dropdown" role="menubar"
                      data-dropdown-menu="cabp3q-dropdown-menu"
                      data-mutate="ph8tvp-responsive-menu">
            Fix any of the following:
            - Element has children which are not allowed: button[tabindex]
    ```

commit b896fc4bba509452510b2e71c24ef9af13055eae
Author: Javi Martín <javim@elretirao.net>
Date:   Wed Feb 26 16:12:45 2025 +0100

    Add aria-label to map markers

    Axe was reporting an accessibility error:

    ```
    Found 1 accessibility violation:

    1) aria-command-name: ARIA commands must have an accessible name
       (serious)
       https://dequeuniversity.com/rules/axe/4.11/aria-command-name?application=axeAPI
       The following 1 node violate this rule:

         Selector: .leaflet-marker-icon
         HTML: <div class="leaflet-marker-icon map-marker
                           leaflet-zoom-animated leaflet-interactive"
                    tabindex="0" role="button">
                    <div class="map-icon"></div>
               </div>
         Fix any of the following:
         - Element does not have text that is visible to screen readers
         - aria-label attribute does not exist or is empty
         - aria-labelledby attribute does not exist, references elements
           that do not exist or references elements that are empty
         - Element has no title attribute
    ```

    Using the title of the proposal/investment as the text of the marker is
    definitely a good solution when there are several markers on the map.
    Not sure whether there's a better option when there's only one marker,
    though.

    Note that we aren't providing a proper aria-label for markers on the map
    we use in the form to create a proposal or an investment. Adding one
    isn't trivial given the current code, and keyboard users can't add a
    marker in the first place. We'll have to revisit this issue when we add
    keyboard support for this.

    We're also changing a test to make sure that titles with quotes in their
    names don't break the markup due to an invalid aria-label attribute.

commit b5d939565b368601f0930c044ba87ef2f905f3f3
Author: Javi Martín <javim@elretirao.net>
Date:   Fri Nov 7 13:10:40 2025 +0100

    Make fullscreen editor preview focusable

    This part of the page can be scrolled independently with the mouse, and
    so the same should be possible with a keyboard.

    Axe was reporting this error:

    ```
    1) scrollable-region-focusable: Scrollable region must have
       keyboard access (serious)
        https://dequeuniversity.com/rules/axe/4.11/scrollable-region-focusable?application=axeAPI
        The following 1 node violate this rule:

          Selector: .fullscreen > .markdown-preview.medium-6.small-12
          HTML: <div class="small-12 medium-6 column markdown-preview">
          Fix any of the following:
          - Element should have focusable content
          - Element should be focusable
    ```

commit 4aa650325ac1d04450c19402ce1e7decee42aef8
Merge: 82c6e2c8dc b6a2ff2cd6
Author: Javi Martín <35156+javierm@users.noreply.github.com>
Date:   Thu Nov 6 15:54:48 2025 +0100

    Merge pull request #6050 from consuldemocracy/dependabot/npm_and_yarn/stylistic/stylelint-plugin-4.0.0

    Bump @stylistic/stylelint-plugin from 3.1.2 to 4.0.0

commit b6a2ff2cd6ca4f0dfc7b07c0c58504b339ce84b7
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Thu Nov 6 13:39:21 2025 +0000

    Bump @stylistic/stylelint-plugin from 3.1.2 to 4.0.0

    Bumps [@stylistic/stylelint-plugin](https://github.com/stylelint-stylistic/stylelint-stylistic) from 3.1.2 to 4.0.0.
    - [Release notes](https://github.com/stylelint-stylistic/stylelint-stylistic/releases)
    - [Changelog](https://github.com/stylelint-stylistic/stylelint-stylistic/blob/main/CHANGELOG.md)
    - [Commits](https://github.com/stylelint-stylistic/stylelint-stylistic/compare/v3.1.2...v4.0.0)

    ---
    updated-dependencies:
    - dependency-name: "@stylistic/stylelint-plugin"
      dependency-version: 4.0.0
      dependency-type: direct:development
      update-type: version-update:semver-major
    ...

    Signed-off-by: dependabot[bot] <support@github.com>

commit 82c6e2c8dc7d3db13e125729f4f86aaae36d0e34
Merge: 2c74f9f35b c6da88f3fa
Author: Javi Martín <35156+javierm@users.noreply.github.com>
Date:   Thu Nov 6 14:37:15 2025 +0100

    Merge pull request #6140 from consuldemocracy/bump_rails_to_7.1.6

    Bump rails from 7.1.5.2 to 7.1.6

commit c6da88f3fab89c11efb3e9b5d0e3a7f4b8061bc8
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Nov 3 12:30:23 2025 +0100

    Bump rails from 7.1.5.2 to 7.1.6

    This is the latest security release in the Rails 7.1.x series.

commit 2c74f9f35b73d733451cf7c1e5fe8962075e89ba
Merge: a563108a03 ad654949ab
Author: Javi Martín <35156+javierm@users.noreply.github.com>
Date:   Thu Nov 6 13:25:39 2025 +0100

    Merge pull request #6123 from consuldemocracy/max_empty_lines

    Add and apply stylistic/max-empty-lines rule

commit a563108a03619dd8a538ce90074d34dceedf4c44
Merge: 2927fd4a05 8d7deef413
Author: Javi Martín <35156+javierm@users.noreply.github.com>
Date:   Thu Nov 6 13:25:00 2025 +0100

    Merge pull request #6124 from consuldemocracy/menu_button_flashing

    Don't flash the menu button on desktop screens

commit 2927fd4a05483f6cd1357a909b1c0c9aa8292f96
Merge: 3e1276510c 3584ab048c
Author: Javi Martín <35156+javierm@users.noreply.github.com>
Date:   Thu Nov 6 13:23:38 2025 +0100

    Merge pull request #6134 from consuldemocracy/dependabot/npm_and_yarn/stylelint-16.25.0

    Bump stylelint from 16.20.0 to 16.25.0

commit 3584ab048c7bd04b853fef56a425aa55e6294777
Author: Javi Martín <javim@elretirao.net>
Date:   Wed Nov 5 19:51:05 2025 +0100

    Replace word-break: break-word with overflow-wrap

    According to W3C documentation [1]:

    > For compatibility with legacy content, the word-break property also
    > supports a deprecated break-word keyword. When specified, this has the
    > same effect as word-break: normal and overflow-wrap: anywhere,
    > regardless of the actual value of the overflow-wrap property.

    This is currently *not* detected by the `property-no-deprecated`
    stylelint rule. However, since this rule detects other places where we
    should use `overflow-wrap`, we're changing it as part of the same pull
    request.

    Note that, as of November 2025, 98.22% of the browsers support
    `overflow-wrap: anywhere`. We're still making this change because we
    only use this property in two specific places and it isn't very likely
    that long words will really be a problem with the remaining 1.78%.

    By the way, I'm not sure why we use this property in the budget
    invesment show paragraphs and not in other similar places. It was
    introduced in commit e3878ff43, alongside other changes which don't seem
    to be related. When in doubt, we leave things as they were, so we're
    doing the same thing here.

    [1] https://www.w3.org/TR/css-text-3/#word-break-property
    [2] https://caniuse.com/mdn-css_properties_overflow-wrap_anywhere

commit d063475769c8494e7f67ec33a9eb2dc2029b6bd8
Author: Javi Martín <javim@elretirao.net>
Date:   Wed Nov 5 19:02:58 2025 +0100

    Use CSS instead of utility classes in options table

    This way we make it easier to customize this component. In this specific
    case, ideally we'd remove some of the CSS as well. For now we're leaving
    it as it was for compatibility reasons.

commit 2d72144048b664a25feed7909386eca861629533
Author: Javi Martín <javim@elretirao.net>
Date:   Wed Nov 5 18:39:19 2025 +0100

    Extract component to render question options table

    This way it's easier to know that the styles for the `break` HTML class
    and the JavaScript for sortable elements (which we shouldn't use, by the
    way, because of its accessibility issues) are only used here.

commit d6f6b94ae457491da7f38cf92d67224e74f5f9a2
Author: Javi Martín <javim@elretirao.net>
Date:   Wed Nov 5 19:16:52 2025 +0100

    Fix wrong selector for sortable tables

    We renamed the HTML class to `table-sortable` in commit 99f8bb449. It
    was incorrectly being applied to the question options table.

commit a5e788dde4b32c4eb627f2715c96c7b163f039c9
Author: Javi Martín <javim@elretirao.net>
Date:   Tue Nov 4 15:39:51 2025 +0100

    Add and apply property-no-deprecated stylelint rule

    This rule was introduced in stylelint 16.23. Out of the deprecated
    properties it detects, we were only using `word-wrap`.

    According to the CSS Working Group [1]:

    > For legacy reasons, UAs must treat word-wrap as a legacy name alias of
    > the overflow-wrap property.

    Since there's universal browser support for `overflow-wrap: break-word`
    [2], we can safely replace `word-wrap` with `overflow-wrap`.

    [1] https://drafts.csswg.org/css-text/#overflow-wrap-property
    [2] https://caniuse.com/mdn-css_properties_overflow-wrap_break-word

commit 917c9e6ac4fdd5af350a19d2becec900185a8886
Author: Javi Martín <javim@elretirao.net>
Date:   Tue Nov 4 13:19:44 2025 +0100

    Add no-invalid-position-declaration stylelint rule

    This rule was introduced in stylelint 16.23. We were always following
    it, and it's unlikely that we miss it before opening a pull request, but
    it might be useful during development.

commit f9f718543fa633da5d3b9c0345c55b65c84b33db
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Nov 4 12:19:13 2025 +0000

    Bump stylelint from 16.20.0 to 16.25.0

    Bumps [stylelint](https://github.com/stylelint/stylelint) from 16.20.0 to 16.25.0.
    - [Release notes](https://github.com/stylelint/stylelint/releases)
    - [Changelog](https://github.com/stylelint/stylelint/blob/main/CHANGELOG.md)
    - [Commits](https://github.com/stylelint/stylelint/compare/16.20.0...16.25.0)

    ---
    updated-dependencies:
    - dependency-name: stylelint
      dependency-version: 16.25.0
      dependency-type: direct:development
      update-type: version-update:semver-minor
    ...

    Signed-off-by: dependabot[bot] <support@github.com>

commit 3e1276510c4d43b1251954032b2919645af35550
Merge: 520f0c42d4 8e6a5eac78
Author: Javi Martín <35156+javierm@users.noreply.github.com>
Date:   Wed Nov 5 18:21:26 2025 +0100

    Merge pull request #6093 from consuldemocracy/dependabot/bundler/rubocop-1.81.1

    Bump rubocop from 1.76.1 to 1.81.7

commit ad654949abf084ad5486bef631425004aed2ed93
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Oct 13 11:59:37 2025 +0200

    Add and apply stylistic/max-empty-lines rule

    We were already using a similar rule in Ruby files.

commit 8d7deef41360b1cdf6800775ce0a0977b4beac11
Author: Javi Martín <javim@elretirao.net>
Date:   Mon Sep 12 04:34:36 2022 +0200

    Don't flash the menu button on desktop screens

    The button flashed briefly when loading the page. This was even more
    obvious when using devices with slow internet connections.

    Using CSS instead of JavaScript to hide the menu solves the issue, since
    styles are loaded before scripts.

commit 618fc4b2c08b52f04244ad126cb28811ba7212c6
Author: Javi Martín <javim@elretirao.net>
Date:   Sun Apr 14 01:59:23 2024 +0200

    Move responsive menu styles to its proper file

    We forgot to do so in commit 49cb6e010.

commit 8e6a5eac7836ae26dbdfe08feb44ec29ac7792fd
Author: Javi Martín <javim@elretirao.net>
Date:   Fri Oct 31 14:44:06 2025 +0100

    Add Style/ArrayIntersectWithSingleElement rule

    This rule was introduced in rubocop 1.81. Even though it doesn't
    currently affect us, it makes sense.

commit d18c627392c1d628cd949020d7989bd0dbf71a03
Author: Javi Martín <javim@elretirao.net>
Date:   Fri Oct 31 14:40:32 2025 +0100

    Add and apply Layout/EmptyLinesAfterModuleInclusion rule

    This rule was added in rubocop 1.79. We were inconsistent about it, so
    we're adding it to get more consistency.

commit 7f749bb9bb8eefa5113c0c44f9211bfb7f386a16
Author: Javi Martín <javim@elretirao.net>
Date:   Fri Oct 31 14:31:35 2025 +0100

    Add and apply Style/CollectionQuerying rubocop rule

    This rule was added in rubocop 1.77. We were following it most of the
    time. It makes the code more readable in my humble opinion.

commit 1fa3cf8ce7e479aabb29d0746773fa40a6559dd1
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Fri Oct 31 13:26:52 2025 +0000

    Bump rubocop from 1.76.1 to 1.81.1

    This release includes some updates in the Style/RedundantParentheses and
    Naming/PredicateMethod rules. We're changing the code accordingly.

    Bumps [rubocop](https://github.com/rubocop/rubocop) from 1.76.1 to 1.81.1.
    - [Release notes](https://github.com/rubocop/rubocop/releases)
    - [Changelog](https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md)
    - [Commits](https://github.com/rubocop/rubocop/compare/v1.76.1...v1.81.1)

    ---
    updated-dependencies:
    - dependency-name: rubocop
      dependency-version: 1.81.1
      dependency-type: direct:development
      update-type: version-update:semver-minor
    ...

    Signed-off-by: dependabot[bot] <support@github.com>

commit 413d0ed9beffe7ff8ce62c37edd9e1224e18c8d6
Author: Javi Martín <javim@elretirao.net>
Date:   Fri Oct 31 15:31:20 2025 +0100

    Return the persisted line in add_investment

    This method was returning a boolean value and caused a
    `Naming/PredicateMethod` when upgrading rubocop.

    So, instead, we're returning the created line when it was successfully
    created, and `nil` when it wasn't.

    Having said that, I'm not sure why we added the `.persisted?` back in
    commit 3eb22ab7b since as far as I can tell we don't use the return
    value for anything. The test added in commit da43e9e2e for this change
    passes if we simply return `lines.create(investment: investment)`.

    For now I'm leaving the `persisted?` check just in case, but removing it
    might be fine.

commit 15f7632f3d3e9cb9edf4fdcada7b8bb68d3451ff
Author: Javi Martín <javim@elretirao.net>
Date:   Fri Oct 31 15:11:22 2025 +0100

    Refactor notifiable_available? method

    This method was calling `check_availability`, which returned a boolean
    value and caused a `Naming/PredicateMethod` when upgrading rubocop.

    So we're changing the logic a little bit to remove the
    `check_availability` method and merge the tests of `check_availability`
    and `notifiable_available?` (which were almost identical) together.

commit 2fdfefe55dc7cba1cc76026f04bba131b080f1bc
Author: Javi Martín <javim@elretirao.net>
Date:   Fri Oct 31 14:56:57 2025 +0100

    Use Verification::Email.valid_token? instead of .find

    This way it's more obvious that the method is supposed to return a
    boolean. When upgrading rubocop, we get a `Naming/PredicateMethod` error
    due to `.find` returning a boolean.

commit 520f0c42d488ea8b142ab3e09f63c17abced9d79
Merge: ec6252cc41 cc9f7904ac
Author: Javi Martín <35156+javierm@users.noreply.github.com>
Date:   Wed Nov 5 14:26:38 2025 +0100

    Merge pull request #6142 from consuldemocracy/dependabot/bundler/rubocop-rspec_rails-2.31.0

    Bump rubocop-rspec_rails from 2.30.0 to 2.31.0

commit cc9f7904acc77b95786663bb56795a58d422de57
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Wed Nov 5 13:11:50 2025 +0000

    Bump rubocop-rspec_rails from 2.30.0 to 2.31.0

    We're changing the `.rubocop.yml` file because we were getting a
    warning:

    ```
    rubocop-rspec_rails extension supports plugin, specify `plugins:
    rubocop-rspec_rails` instead of `require: rubocop-rspec_rails` in
    .rubocop.yml.  For more information, see
    https://docs.rubocop.org/rubocop/plugin_migration_guide.html.
    ```

    Bumps [rubocop-rspec_rails](https://github.com/rubocop/rubocop-rspec_rails) from 2.30.0 to 2.31.0.
    - [Release notes](https://github.com/rubocop/rubocop-rspec_rails/releases)
    - [Changelog](https://github.com/rubocop/rubocop-rspec_rails/blob/master/CHANGELOG.md)
    - [Commits](https://github.com/rubocop/rubocop-rspec_rails/compare/v2.30.0...v2.31.0)

    ---
    updated-dependencies:
    - dependency-name: rubocop-rspec_rails
      dependency-version: 2.31.0
      dependency-type: direct:development
      update-type: version-update:semver-minor
    ...

    Signed-off-by: dependabot[bot] <support@github.com>

commit ec6252cc416cfc980b4e44ba2e37b0805fa58516
Merge: c3f34030fe 0ca94e5443
Author: Javi Martín <35156+javierm@users.noreply.github.com>
Date:   Wed Nov 5 14:06:09 2025 +0100

    Merge pull request #6106 from consuldemocracy/dependabot/bundler/rubocop-rails-2.33.4

    Bump rubocop-rails from 2.29.1 to 2.33.4

commit 0ca94e54437bef65d38148c9e243f8871b10273f
Author: Javi Martín <javim@elretirao.net>
Date:   Fri Oct 31 13:10:20 2025 +0100

    Add and apply Rails/FindByOrAssignmentMemoization rule

    This rule was added in rubocop-rails 2.33.

    At first, I wasn't very fond of this rule. It made the code less
    readable even if it improved performace in some cases.

    Then I realized that in the `Admin::MachineLearning::SettingComponent`
    we were using `find_by` when we should be using `find_by!` instead, and
    we detected that thanks to this rule.

    So, only for that reason, I'm adding this rule, but I'm fine if we
    remove it.

commit 048bdb2e9ef5ad22bd9937f47ad01823a44f09f0
Author: Javi Martín <javim@elretirao.net>
Date:   Fri Oct 31 13:02:09 2025 +0100

    Add and apply Rails/OrderArguments rubocop rule

    This rule was introduced in rubocop-rails 2.33. We were following it
    most of the time.

commit 0c5dc24cc23f23f270f9a294257e7bffd854d56e
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Fri Oct 31 11:01:51 2025 +0000

    Bump rubocop-rails from 2.29.1 to 2.33.4

    We're changing the `.rubocop.yml` file because we were getting a
    warning:

    ```
    rubocop-rails extension supports plugin, specify `plugins:
    rubocop-rails` instead of `require: rubocop-rails` in .rubocop.yml. For
    more information, see
    https://docs.rubocop.org/rubocop/plugin_migration_guide.html.
    ```

    Bumps [rubocop-rails](https://github.com/rubocop/rubocop-rails) from 2.29.1 to 2.33.4.
    - [Release notes](https://github.com/rubocop/rubocop-rails/releases)
    - [Changelog](https://github.com/rubocop/rubocop-rails/blob/master/CHANGELOG.md)
    - [Commits](https://github.com/rubocop/rubocop-rails/compare/v2.29.1...v2.33.4)

    ---
    updat…
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants