Commit Graph

210 Commits

Author SHA1 Message Date
Javi Martín
d18c627392 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.
2025-11-05 14:27:12 +01:00
dependabot[bot]
1fa3cf8ce7 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>
2025-11-05 14:27:11 +01:00
taitus
93b35fcecc Redirect root path requests to the tenants administration
When the `multitenancy_management_mode` is enabled.

In order to avoid infinite redirects when regular users try to access
the admin section, we're redirecting to the account page in this case.
Otherwise, the admin section would redirect to the root path, which
would redirect to the admin section, which would redirect to the root
path, and so on.
2024-11-06 11:17:58 +01:00
CoslaJohn
424cedc0c8 Restrict access to admin functions by IP
There are many possible ways to implement this feature:

* Adding a custom middleware
* Using rack-attack with a blocklist
* Using routes constraints

We're choosing to use a controller concern with a redirect because it's
what we do to handle unauthorized cancancan exceptions.
2024-10-30 15:59:50 +01:00
Javi Martín
f7e2d724dd Replace ahoy events with real data
We were tracking some events with Ahoy, but in an inconsistent way. For
example, we were tracking when a debate was created, but (probably
accidentally) we were only tracking proposals when they were created
from the management section. For budget investments and their supports,
we weren't using Ahoy events but checking their database tables instead.
And we were only using ahoy events for the charts; for the other stats,
we were using the real data.

While we could actually fix these issues and start tracking events
correctly, existing production data would remain broken because we
didn't track a certain event when it happened. And, besides, why should
we bother, for instance, to track when a debate is created, when we can
instead access that information in the debates table?

There are probably some features related to tracking an event and their
visits, but we weren't using them, and we were storing more user data
than we needed to.

So we're removing the track events, allowing us to simplify the code and
make it more consistent. We aren't removing the `ahoy_events` table in
case existing Consul Democracy installations use it, but we'll remove it
after releasing version 2.2.0 and adding a warning in the release notes.

This change fixes the proposal created chart, since we were only
tracking proposals created in the management section, and opens the
possibility to add more charts in the future using data we didn't track
with Ahoy.

Also note the "Level 2 user Graph" test wasn't testing the graph, so
we're changing it in order to test it. We're also moving it next to the
other graphs test and, since we were tracking the event when we were
confirming the phone, we're renaming to "Level 3 users".

Finally, note that, since we were tracking events when something was
created, we're including the `with_hidden` scope. This is also
consistent with the other stats shown in the admin section as well as
the public stats.
2024-05-09 14:28:32 +02:00
Javi Martín
1ee30c0bb7 Remove the create action from CommentableActions
We were only using it in one place: the debates controller. All the
other controllers including CommentableActions were overwriting this
action, except the ones in the admin area, where creating proposals,
debates or investments isn't possible.

Note this means that, most of the times, we weren't tracking events
creating a resource.

Also note that since, as mentioned in commit 3752fef6b, there are no
geozones in the debates form, we don't have to load them when creating a
debate fails due to validation rules.
2024-05-09 14:24:53 +02:00
Javi Martín
fdfdbcbd0d Add and apply Style/ArgumentsForwarding rule
We were using generic names like `args` and `options` which don't really
add anything to `*` or `**` because Ruby required us to.

That's no longer the case in Ruby 3.2, so we can simplify the code a
bit.
2024-04-11 17:59:40 +02:00
dependabot[bot]
f4203909db Bump rubocop from 1.56.4 to 1.61.0
This version fixes false negatives for Lint/SymbolConversion when using
string interpolation, for Style/RedundantArgument when using the safe
navigation operator, for Style/RedundantParentheses when logical
operators are involved and for Style/RedundantReturn with lambda ending
with return. We're applying the new rules.

Bumps [rubocop](https://github.com/rubocop/rubocop) from 1.56.4 to 1.61.0.
- [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.56.4...v1.61.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-02 16:31:10 +02:00
taitus
6059aab674 Allow saving a position when create a widget card
We are ensuring that only position field is rendered only on
non-header cards.

Note that we have 3 sections that use widget cards:
- Homepage (cards and header cards)
- Custompages (only have cards)
- Sdg Homepage (cards and header cards)
2024-03-21 18:15:50 +01:00
Javi Martín
0aee568977 Add and apply Rails/RedundantActiveRecordAllMethod
This rule was introduced in rubocop-rails 2.21.0.
2023-11-20 14:22:12 +01:00
Javi Martín
28aafbd4bc Add and apply Style/InvertibleUnlessCondition rule
This rule was added in rubocop 1.44.0. It's useful to avoid accidental
`unless !condition` clauses.

Note we aren't replacing `unless zero?` with `if nonzero?` because we
never use `nonzero?`; using it sounds like `if !zero?`.

Replacing `unless any?` with `if none?` is only consistent if we also replace
`unless present?` with `if blank?`, so we're also adding this case. For
consistency, we're also replacing `unless blank?` with `if present?`.

We're also simplifying code dealing with `> 0` conditions in order to
make the code (hopefully) easier to understand.

Also for consistency, we're enabling the `Style/InverseMethods` rule,
which follows a similar idea.
2023-09-07 19:14:03 +02:00
Javi Martín
a1439d0790 Apply Layout/LineLength rubocop rule
Note we're excluding a few files:

* Configuration files that weren't generated by us
* Migration files that weren't generated by us
* The Gemfile, since it includes an important comment that must be on
  the same line as the gem declaration
* The Budget::Stats class, since the heading statistics are a mess and
  having shorter lines would require a lot of refactoring
2023-08-30 14:46:35 +02:00
Matheus Miranda
de13e789dd Add polygon geographies to Budgets' map
Note that in the budgets wizard test we now create district with no
associated geozone, so the text "all city" will appear in the districts
table too, meaning we can't use `within "section", text: "All city" do`
anymore since it would result in an ambiguous match.

Co-Authored-By: Julian Herrero <microweb10@gmail.com>
Co-Authored-By: Javi Martín <javim@elretirao.net>
2023-05-31 16:56:15 +02:00
Javi Martín
b0b7d0f25b Remove unused legislation proposals map action
The only view that linked to this action was never used and so it was
deleted in commit 0bacd5baf.

Since now the proposals controller is the only one place rendering the
`shared/map` partial, we're moving it to the proposals views.
2023-05-04 15:27:10 +02:00
Javi Martín
2f0327acf8 Use remote translations objects instead of hashes
This way we can simplify the code dealing with the translatable
association.
2023-02-16 17:52:17 +01:00
Javi Martín
d09a47a023 Move remote translations concern methods to the model
This way it'll be easier to change the code.
2023-02-16 17:52:17 +01:00
Javi Martín
efc46fe6c8 Add Performance/StringIdentifierArgument rule
It was added in rubocop-performance 1.13.0. We were already applying it
in most places.

We aren't adding it for performance reasons but in order to make the
code more consistent.
2023-01-11 16:05:20 +01:00
Javi Martín
72704d7761 Use separate actions to enable/disable budget phases
This is consistent with the way we use separate actions to hide and
restore records, which is similar to enabling and disabling a record. We
might do something similar with the `toggle_selection` actions in the
future. For now, we're only doing it with budget phases because we're
going to add a similar switch control to hide and restore tenants.

We're also making these actions idempotent, so sending many requests to
the same action will get the same result, which wasn't the case with the
`toggle` action. Although it's a low probability case, the `toggle`
action could result in disabling a phase when trying to enable it if
someone else has enabled it between the time the page loaded and the
time the admin clicked on the "enable" button.
2022-12-28 14:34:00 +01:00
Javi Martín
18611f32f1 Allow rendering different views per tenant
Sometimes it might be convenient to use completely different views for
different tenants. For example, a certain tenant might use a footer that
has nothing to do with the default one.

For these cases, instead of adding `case Tenant.current_schema`
conditions to the view, it might be tidier to use a different file.

For this purpose, we're using Rails variants [1], which means that a
tenant named `mytenant` will use a template ending with
`.html+mytenant.erb` if it's available.

This works with components too, but has a limitation: when using the
`custom/` folder to add ERB files for a tenant, the default tenant ERB
file needs to be added to the `custom/` folder as well; if there aren't
changes to this file, a symbolic link will do.

For example, if we're writing a custom `admin/action_component` view for
the tenant `milky-way` but don't need to change this file for the
default tenant:

1. Create `app/components/custom/admin/action_component.rb` according to
   the components customizations documentation [2]
2. Create the custom view for the `milky-way` tenant and save it under
   `app/components/custom/admin/action_component.html+milky-way.erb`
3. Enter the `app/components/custom/admin/` folder and run `ln -s
   ../../admin/action_component.html.erb`

We're also adding some controller tests. Since Rails doesn't load the
middleware during controller tests, we're stubbing the `current_schema`
method directly instead of changing the subdomain of the request.

[1] https://guides.rubyonrails.org/v6.0/layouts_and_rendering.html#the-variants-option
[2] https://docs.consulproject.org/docs/english-documentation/customization/components
2022-11-29 14:01:22 +01:00
Javi Martín
18f1d5c1a3 Allow different remote translation keys per tenant
Note we don't need to update the tests; the tests themselves help us
confirm that `Rails.application.secrets` and `Tenant.current_secrets`
return the same object on single-tenant applications.
2022-11-11 01:39:29 +01:00
Jacek Skrzypacz
2af7e32415 Add search form for hidden content
Added search for comments and proposal_notifications, added tsv column
for search and rake tasks to update/create tsv vector.
2022-08-23 14:30:38 +02:00
Javi Martín
f6fefde91d Extract concern to share hidden content code 2022-08-23 14:30:38 +02:00
Javi Martín
11832cc07d Make it easier to customize allowed parameters
When customizing CONSUL, one of the most common actions is adding a new
field to a form.

This requires modifying the permitted/allowed parameters. However, in
most cases, the method returning these parameters returned an instance
of `ActionController::Parameters`, so adding more parameters to it
wasn't easy.

So customizing the code required copying the method returning those
parameters and adding the new ones. For example:

```
def something_params
  params.require(:something).permit(
    :one_consul_attribute,
    :another_consul_attribute,
    :my_custom_attribute
  )
end
```

This meant that, if the `something_params` method changed in CONSUL, the
customization of this method had to be updated as well.

So we're extracting the logic returning the parameters to a method which
returns an array. Now this code can be customized without copying the
original method:

```
alias_method :consul_allowed_params, :allowed_params

def allowed_params
  consul_allowed_params + [:my_custom_attribute]
end
```
2022-04-07 19:35:40 +02:00
Javi Martín
b98244afd9 Remove votes query optimizations
Just like we did in commit 0214184b2d for investments, we're removing
some possible optimizations (we don't have any benchmarks proving they
affect performance at all) in order to simplify the code.

The investement votes component `delegate` code was accidentally left
but isn't used since commit 0214184b2, so we're removing it now that
we're removing the `voted_for?` helper method.
2022-02-21 18:47:13 +01:00
Senén Rodero Rodríguez
7ad838c57d Translate budget and budget phase main link url 2021-11-05 16:40:36 +01:00
Javi Martín
756a16f67a Remove investment filters in groups
The interface was a bit confusing, since after clicking on "See
unfeasible investments" (or similar), we were on a page where no
investments were shown.

Besides, since commit 7e3dd47d5, the group page is only linked from the
"my ballot" page, through a link inviting the user to vote in that
group, and it's only possible to vote selected investments (which is the
default filter during the final voting phase).

The only reason we had these links here was these links weren't present
in the investments page. But they're present there since commit
04605d5d5, so we don't need them in the group page anymore.
2021-10-29 15:01:40 +02:00
Javi Martín
1bfcfca2e2 Move method to get available filters to the model
We're naming the method `investments_filters`, with the word
"investments" in plural, to be consistent with the method
`investments_orders`.
2021-10-29 14:53:33 +02:00
Javi Martín
36d795f69c Move investment filters to the sidebar
As mentioned in commit bc0f04075, a <select> field which submits its
form on change causes many accessibility and usability issues. In this
case there was also an incompatibility with the advanced search filter
which caused a bug solved in commit 541a5fa89.

So the question is where to position the filters and how to display
them. One factor to take into the account is how relevant these filters
are, particularly compared to the links to select the prefered order,
since we don't usually give users the choice of both filters and orders.

Our filters don't really make sense until the valuation phase starts,
since before that phase investments aren't selected nor their
feasibility is decided.

After that phase, the only phase where citizens are really involved
is the final voting; the rest of the phases are done by valuators and
administrators. In the final voting, citizens can only vote on selected
projects, and that's the default filter during that phase.

So these filters are mainly there for information purposes, and not to
help citizens in the phases where they're actually involved (accepting
projects, selecting projects and balloting).

Orders, on the other hand, play a crucial role during the final voting
phase. Since citizens might have already voted for a few projects and
have, let's say, 100,000€ left, ordering by price allows them to find
which projects are within their remaining budget.

In conclusion, orders are more important than filters, and so they
should have a more prominent place.

For consistency with the proposals section, where we've got some links
in the sidebar (bottom part of the page on small screens) providing a
similar funcionality, like accessing selected proposals or archived or
retired proposals, we're moving the investments filters to the sidebar
(bottom part of the page on small screens) as well.
2021-10-29 14:53:33 +02:00
Julian Herrero
2b709f1a36 Groups and headings CRUD from budget view
Before, users needed to navigate to the list of groups in order to
add, edit or delete a group.

Also, they need to navigate to the list of groups first, and then to
the list of headings for that group in order to add, edit or delete a
heading.

Now, it's possible to do all these actions for any group or heading
from the participatory budget view to bring simplicity and to reduce
the number of clicks from a user perspective.

Co-Authored-By: Javi Martín <javim@elretirao.net>
2021-10-25 18:01:47 +02:00
Javi Martín
46d8bc4f0e Use a switch to enable/disable budget phases
In the past it would have been confusing to add a way to directly
enable/disable a phase in the phases table because it was in the middle
of the form. So we would have had next to each other controls that don't
do anything until the form is sent and controls which modify the
database immediately. That's why we couldn't add the checkboxes we used
when using the wizard.

Now the phases aren't on the same page as the budget form, so we can
edit them independently. We're using a switch, so it's consistent with
the way we enable/disable features. We could have used checkboxes, but
with checkboxes, users expect they aren't changing anything until they
click on a button to send the form, so we'd have to add a button, and it
might be missed since we're going to add "buttons" for headings and
groups to this page which won't send a form but will be links.

Since we're changing the element with JavaScript after an AJAX call, we
need a way to find the button we're changing. The easiest way is adding
an ID attribute to all admin actions buttons/links.
2021-10-25 18:01:47 +02:00
Julian Herrero
541a5fa89f Avoid error when combining investments advanced search with filters 2021-09-15 22:05:18 +02:00
Javi Martín
4150d7f1be Move proposals form partial to a component
Since now categories are loaded in both the investment form component
and proposal form component, and their controllers are the only
"commentable" controllers using the `@categories` instance variable, we
can remove the `load_categories` call in `CommentableActions` affecting
the create and update actions.
2021-07-13 15:25:29 +02:00
Javi Martín
c3e0a6b089 Remove duplication rendering comments
We were using the same code 5 times, with the only slight variation
being the extra heading in the debates section.
2021-06-27 23:22:00 +02:00
Julian Herrero
db9ac79e05 Add main link to each phase of the budget
Co-authored-by: decabeza <alberto@decabeza.es>
2021-06-09 21:51:39 +02:00
Julian Herrero
43ad69bbaf Allow attaching an image to budget phases
Co-authored-by: decabeza <alberto@decabeza.es>
2021-06-09 21:47:58 +02:00
Julian Herrero
eb77d09425 Add phases step to budget creation 2021-06-08 18:45:55 +02:00
Julian Herrero
f8d6ba12d7 Add headings step to budget creation
Co-Authored-By: decabeza <alberto@decabeza.es>
2021-06-08 18:45:53 +02:00
Alberto
b304c640e1 Add groups step to budget creation
Note we're keeping this section's original design (which had one button
to add a new group which after being pressed was replaced by a button to
cancel) but we aren't using Foundation's `data-toggle` because there
were a couple of usability and accessibility issues.

First, using `data-toggle` multiple times and applying it to multiple
elements led to the "cancel" button not being available after submitting
a form with errors. Fixing it made the code more complicated.

Second, the "Add new group" button always had the `aria-expanded`
attribute set to "true", so my screen reader was announcing the button
as expanded even when it wasn't. I didn't manage to fix it using
`data-toggle`.

Finally, after pressing either the "Add new group" and "Cancel" buttons,
the keyboard focus was lost since the elements disappeared.

So we're simplifying the HTML and adding some custom JavaScript to be
able to handle the focus and manually setting the `aria-expanded`
attribute.

Co-Authored-By: Javi Martín <javim@elretirao.net>
Co-Authored-By: Julian Herrero <microweb10@gmail.com>
2021-06-08 18:45:13 +02:00
taitus
ac144d172d Move document attributes to concern 2021-04-09 16:21:00 +02:00
taitus
c173568404 Move map_location attributes to concern 2021-04-09 16:20:59 +02:00
Javi Martín
3509b99ce4 Use different filters on different budget phases
We use the same criteria we use when deciding the default filter.
2021-03-17 13:44:02 +01:00
Javi Martín
c322b2c4a2 Remove unused investments filter
We weren't using the "Feasible" filter anywhere in the
application, and it's hard for users to know the difference between
"Feasible" and "Not unfeasible".
2021-03-15 15:19:18 +01:00
Julian Herrero
5d38e4702f Adjust default budget filter
Apart from 'balloting', there are more phases between
'publishing_prices' and 'finished'. So, it doesn't make sense that the
filter 'selected' is only applied to those two. With this change the
filter will be applied as follow:

'not_unfeasible' for phases:
- informing
- accepting
- reviewing
- selecting
- valuating

selected for phases:
- publishing_prices
- balloting
- reviewing_ballots

winners for phases:
- finished
2021-03-15 15:19:18 +01:00
Javi Martín
6bd20ef5ff Extract concern to handle investments filters
We were defining the same filters in three different controllers. We
were also adding a method in the ApplicationController which only made
sense in the same three controllers.
2021-03-15 13:31:28 +01:00
Javi Martín
ba4b1a91e1 Allow using a different URL on widget card forms 2021-02-26 16:16:51 +01:00
Javi Martín
3d97708cc5 Simplify calls to filter_by 2021-02-24 20:20:25 +01:00
Javi Martín
a7bbdb1bd0 Simplify rendering a banner
Now the banner component accepts either a banner or a section and loads
the banner if it's a section, so we don't have to add the `@banners`
variable in several controllers.
2021-01-20 17:22:05 +01:00
Senén Rodero Rodríguez
94a4b67675 Use local variables at shared/filter_subnav partial
So we can use it from components too.
2021-01-19 13:51:06 +01:00
Javi Martín
4c0bb894eb Use polymorphic routes to manage cards
We use a different logic to load the card depending on the controller
we're using, and then share the rest of the code. This way we simplify
the code a bit, since we don't have to check for the page_id parameter.
2021-01-12 14:50:37 +01:00
Javi Martín
9f689c21a2 Rename filter method to filter_by
Ruby 2.6 introduces `Enumerable#filter` as an alias to
`Enumerable#select`, and so our Filterable.filter method will not work
with Ruby 2.6.

So we're renaming the method to `filter_by`, which is similar to
`find_by`. We could also change the `filter` method so if a block is
given it delegates to `Enumerable#filter`, the same way ActiveRecord
handles the `select` method, but IMHO this is easier to follow.
2020-10-29 11:29:45 +01:00