Before this change, two important things depend on the format of each key,
where to render it in the administration panel and which kind of interface
to use for each setting. Following this strategy led us to a very complex
code, very difficult to maintain or modify. So, we do not want to depend
on the setting key structure anymore to decide how or where to render each
setting.
With this commit, we get rid of the key format-based rules. Now we render
each setting explicitly passing to it the type and the tab where it belongs.
Instead of using a setting nested param `setting[:tab]`. We only need
the tab param when rendering settings in the administration section.
This change will make it easier rendering the correct tab after
updating settings.
In the admin section, when clicking on a link that leads to a page in
the public area, sometimes the page was opened in the same window and
sometimes it would open in a new window, with no clear criteria
regarding when either scenario would take place.
This was really confusing, so now we're more consistent and open
(almost) every link in the same window. The main reason behind it is
simple: if we add `target: _blank`, people who want to open those links
in the same window can no longer do so, so we're taking control away
from them. However, if we don't add this attribute, people can choose
whether to open the link on the same tab or to open it on a new one,
since all browsers implement a method to do so.
More reasons behind this decision can be found in "Opening Links in New
Browser Windows and Tabs" [1].
We're keeping some exceptions, though:
* Opening the link to edit an investment on the same tab would result in
losing all the investment filters already applied when searching for
investments, so until we implement a way to keep these filters, we're
also opening the link to edit an investment in a new tab
* For now, we're also opening links to download files in a new window;
we'll deal with this case in the future
[1] https://www.nngroup.com/articles/new-browser-windows-and-tabs/
In some places, we were using `blank` instead of `_blank`. Most browsers
treat `blank` like `_blank`, though, so most people didn't experience
any difference.
In another place, we were incorrectly passing the `target` option inside
an `options:` hash, resulting in invalid HTML.
Quoting usability experts Jakob Nielsen and Anna Kaley [1]:
> [Opening PDF files in new tabs] is problematic, because it assumes
> users will always do the exact same things with certain file formats,
> which isn’t always the case.
There are many examples of this situation. For example, some people
(myself included) configure their browser so it downloads PDF files
instead of opening them in the browser. In this situation, a new tab is
opened, a blank page is displayed, the file is downloaded, and then
either the tab is closed or the blank page needs to be manually closed.
The end result is really annoying.
Other situations include people who use a mobile phone browser, where
navigating through tabs is generally much harder than doing so on a
desktop browser.
But IMHO the most important point is: every browser already provides a
way to open "regular" links in a new tab, so people can choose what to
do, but if we decide to open the link in a new tab, we take control away
from them, and people who'd like to open the link in the same tab might
feel frustrated.
In these cases, the links either say "download" or include the word
"PDF", so people know in advance that they're going to download/open a
PDF file, and so we're giving them information and, by removing the
`target` attribute, we're giving them control over their browser so they
can choose what's convenient for them.
[1] https://www.nngroup.com/articles/new-browser-windows-and-tabs
We were adding <div> tags with the `images` or `documents` HTML class
prettly much every time we rendered a NestedComponent. We're now
including the HTML class inside the component, as we usually do.
We're also rendering the nested components directly, since it's been a
while since the partials were changed to simply render the components.
There's a link next to it that does the exact same thing and includes
the word "download", which was confusing in some cases since people
might think that links with different texts lead to different pages.
This way we make it easier to modify.
Note that, since the title of the page is "Administration" and it's in
the "Admin" section, we're adding an option to the `header` method in
order to avoid having a confusing title like "Administration - Admin".
Also note that, by removing the `title` HTML class, we avoid inheriting
styles from the `dashboard.scss` stylesheet, and now the heading is
displayed in the position it was meant to.
Finally, the concept of using a `main-class` for the current page comes
from a branch (currently in development) which will replace the <div>
tag with the `admin-content` class with a `main` tag.
Previously the condition was needed because _without it_ the Admin::Poll::Questions::Answers::ImagesController would have resulted in settings? evaluating to true. This was undesired because that controller was scoped under Polls, so only polls? should have evaluated to true. Now that we have moved the images link to the customization menu, this check is not necessary anymore.
There were already some menu items to customization pages under the "Site content" menu. It therefore makes sense to move "Custom images" and "Custom content blocks" (which were previously
located under "Settings") to "Site content" as well.
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
For the HashAlignment rule, we're using the default `key` style (keys
are aligned and values aren't) instead of the `table` style (both keys
and values are aligned) because, even if we used both in the
application, we used the `key` style a lot more. Furthermore, the
`table` style looks strange in places where there are both very long and
very short keys and sometimes we weren't even consistent with the
`table` style, aligning some keys without aligning other keys.
Ideally we could align hashes to "either key or table", so developers
can decide whether keeping the symmetry of the code is worth it in a
case-per-case basis, but Rubocop doesn't allow this option.
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>
Not sure why it was added in commit 9fb5019f0, but it made the table
look funny on some screens, particularly after adding the extra field
we're about to add.
This is consistent with the component for balloting stats. We're about
to change both components, and the changes are easier to follow if
they're similar.
We're also using consistent names in methods.
To get the heading where a user voted, we were relying on the
`balloted_heading_id` field.
Our guess is this was done so the total number of users is the same as
the sum of users who voted on a heading. That is, if 2000 people voted
just on the "All city" heading, 1000 voted just on the "North district"
heading, and 500 people voted on both, instead of showing "3500 people
voted in total, 2500 voted in all city, 1500 voted in north district",
we show something like "3500 people voted in total, 2250 voted in all
city, and 1250 voted in north district".
However, this approach has some disadvantages.
The first disadvantage is, the stats aren't correct. In the case above,
2500 voted on the "All city heading", so the statistics for this heading
don't show reality.
The second one is we weren't considering the last heading where users
voted inside the budget being displayed, but the last heading where
users voted, period. That means that, if all the people above voted on a
later budget, the stats for the budget above would become "3500 people
voted in total, 0 voted in all city, and 0 voted in north district".
That also means we were including headings from previous budgets in the
statistics for more recent budgets when people hadn't voted on the
recent ones.
So we're removing the `balloted_heading_id` since its data is lost once
people vote on a new budget. And, in order to show the right stats and
simplify the code, we're no longer trying to add votes just to one
heading when users vote on several headings.
Co-Authored-By: Julian Nicolas Herrero <microweb10@gmail.com>
The <th> elements should be inside <tr> elements.
Since we're changing this code, we're also adding <thead> and <tbody>
tags because that's what we usually do and it makes it easier to select
<tr> tags from either the table head or the table body using CSS or
JavaScript.
We're also moving the tests, but we're keeping one system test in order
to test the controller and the navigation to get to this page.
Note we're slightly changing the order of the methods in the component;
the order of the instance variables was `user_`, `vote_`, `vote_`,
`user_`, which was hard to follow.
We were passing a hash of options instead of converting them to keyword
parameters, which resulted in warnings on Ruby 2.7:
```
app/components/admin/table_actions_component.html.erb:5: warning: Using
the last argument as keyword parameters is deprecated; maybe ** should
be added to the call
app/components/admin/table_actions_component.html.erb:9: warning: Using
the last argument as keyword parameters is deprecated; maybe ** should
be added to the call
app/components/admin/widget/cards/row_component.html.erb:20: warning:
Using the last argument as keyword parameters is deprecated; maybe **
should be added to the call
app/components/admin/widget/cards/table_component.html.erb:14: warning:
Using the last argument as keyword parameters is deprecated; maybe **
should be added to the call
```
We weren't showing the year when a page was created/updated, and we
were displaying the created date instead of the updated one.
Co-Authored-By: Diego Calvo <diego.calvo@enreda.coop>
Note we could use `acts_as_paranoid` with the `without_default_scope`
option, but we aren't doing so because it isn't possible to consider
deleted records in uniqueness validations with the paranoia gem [1].
I've added tests for these cases so we don't accidentally add
`acts_as_paranoid` in the future.
Also note we're extracting a `RowComponent` because, when
enabling/disabling a tenant, we're also enabling/disabling the link
pointing to its URL, and so we need to update the URL column after the
AJAX call.
[1] See issues 285 and 319 in https://github.com/rubysherpas/paranoia/