Commit Graph

578 Commits

Author SHA1 Message Date
Javi Martín
35659d4419 Replace initialjs-rails with custom avatar code
The initialjs-rails gem hasn't been maintained for years, and it
currently requires `railties < 7.0`, meaning we can't upgrade to Rails 7
while we depend on it.

Since the code in the gem is simple, and we were already rewriting its
most complex part (generating a background color), we can implement the
same code, only we're using Ruby instead of JavaScript. This way, the
avatars will be shown on browsers without JavaScript as well. Since
we're adding a component test that checks SVG images are displayed even
without JavaScript, we no longer need the test that checked images were
displayed after AJAX requests.

Now the tests show the user experience better; people don't care about
the internal name used to select the initial (which is what we were
checking); they care about the initial actually displayed.

Note initialjs generated an <img> tag using a `src="data:image/svg+xml;`
attribute. We're generating an <svg> tag instead, because it's easier.
For this reason, we need to change the code slightly, giving the <svg>
tag the `img` role and using `aria-label` so its contents won't be read
aloud by screen readers. We could give it a `presentation` role instead
and forget about `aria-label`, but then screen readers would read the
text anyway (or, at least, some of them would).
2024-04-11 18:48:33 +02:00
Javi Martín
bee00db34f Use a node package to install jquery-fileupload
Although the gem is called jquery-fileupload-rails, the node package is
called blueimp-file-upload.

Note we're using the same version as provided by the gem.

The jquery-fileupload gem provided a `basic.js` file (which we were
requiring), which had the following content:

```
//= require jquery-fileupload/vendor/jquery.ui.widget
//= require jquery-fileupload/jquery.iframe-transport
//= require jquery-fileupload/jquery.fileupload
``

This file isn't available in the Node.js package, so we're adapting its
contents in our application.js file. Since we're already requiring
jQuery UI widget, we're omitting that line.
2024-04-03 00:15:48 +02:00
Javi Martín
2fa713c644 Use node packages to install Foundation
Since Foundation hasn't released a new gem for years, we haven't been
able to upgrade Foundation to its most recent version.

Thanks to this change, we'll be able to do so.

Note we're using motion-ui version 2.0.3 because version 2.0.5 (the
latest at the moment) requires Dart Sass.
2024-04-02 14:41:42 +02:00
Javi Martín
f46558b4dd Replace rails-assets.org with Node.js packages
Now that we use NPM, we don't need the wrapper provided by rails-assets
anymore.
2024-03-30 05:10:13 +01:00
Senén Rodero Rodríguez
3e9f2b8319 Load markers cluster layer by chunks
In order to avoid locking the browser for a long time.
when there are a lot of markers in the map:

https://github.com/Leaflet/Leaflet.markercluster#handling-lots-of-markers
2024-01-29 17:56:54 +01:00
Pierre Mesure
e5a6a5bf1d Adding clustering 2024-01-29 17:56:54 +01:00
Senén Rodero Rodríguez
ef14636b6c Sort variables alphabetically 2024-01-29 17:56:54 +01:00
Senén Rodero Rodríguez
0186484fac Use leaflet npm version instead of the gem 2024-01-29 17:56:54 +01:00
Julian Herrero
60a0fcfea5 Refresh CSRF Token when using Turbolinks 2023-11-30 18:57:29 +01:00
taitus
7c771b28b5 Add password complexity 2023-10-24 19:00:43 +02:00
Javi Martín
a8bd5eb192 Rename document/image fields HTML classes
Using the `document` or `documents` classes meant styles defined for the
public list of documents conflict with these ones.

So now we're using HTML classes that match the name of the Ruby
component classes, as we usually do.
2023-10-23 15:49:01 +02:00
Javi Martín
3b6fb85c51 Use node packages to install jQuery and jQuery UI
Other packages depend on jQuery, so that's why these are the first one
we move from the Gemfile to the package.json file.

This way we can also test whether dependabot correctly opens pull
requests to update Node packages.

I've tried several configuration options for the asset pipeline in order
to be able to include images referenced in jQuery UI CSS files. So far,
adding the `node_modules/jquery-ui/themes/base` folder to the assets
paths is the only way I've found to make it work. Hopefully we can find
a better solution in the future so we don't have to study the internals
of every Node package in order to integrate it with the assets pipeline.
2023-10-17 13:12:20 +02:00
Javi Martín
21a268ab96 Remove alert for Internet Explorer 8 and below
Internet Explorer 8 was released in 2009 and people using it already
know that most web pages look broken on it, so we don't need to warn
them.

Removing it makes our application layout file much easier to read and
modify.
2023-09-07 19:44:54 +02:00
Javi Martín
175c1a752b Remove old comment referencing the project name
It was obvious which project the comment was about. Also, no point
having a TODO referencing what to do after upgrading to Rails 5.1, since
we did it years ago.
2023-07-12 16:05:33 +02:00
Javi Martín
629756dd15 Change URLs referencing our GitHub repositories 2023-07-12 16:05:26 +02:00
Javi Martín
970a64e276 Enable mousewheel when focusing on the map
Zooming with the mousewheel is useful when you want to use it, but
annoying when you don't want to.

Here we're taking an intermediary approach: by default, the mousewheel
isn't active, but it will be active after focusing on the map, so it can
be used both to scroll and to zoom.

This behavior presents usability issues, though, since we aren't making
users aware of the way the mousewheel works, and even if they were
aware, it could be confusing anyway. However, I currently think it's
better than always enabling or always disabling the mousewheel (might
change my mind, though).

Note that the "focus" event is only used on the map, so if we click on a
marker or navigate to a marker with the keyboard without focusing on the
map first, the mousewheel isn't enabled. The same would happen if we
used the "click" event.

We might use the Leaflet.GestureHandling plugin in the future to deal
with this issue and the scroll on touch screens.
2023-06-29 15:54:07 +02:00
Senén Rodero Rodríguez
3fa3c90db6 Fix map markers navigation for keyboard users
By using the bindPopup function instead of the click event
popups work when using the keyboard.

Note that now we are loading all the map markers in the first
request in a single query to the database (needed when there
is a lot or markers to show). Because of that we removed the
AJAX endpoint.
2023-06-26 20:33:35 +02:00
Javi Martín
a9029be93d Include heading geozone in investments sidebar map
Note that, in this case, we aren't binding a popup to the polygon
because the link would point to the same page we're already in.
2023-05-31 16:56:15 +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
8b14522bf5 Use a button instead of a link to remove a marker
Using a button for interactive elements is better, as explained in
commit 5311daadf.

Since buttons with "type=button" do nothing by default, we no longer
need to call `preventDefault()` when clicking it.
2023-05-04 15:32:33 +02:00
Javi Martín
b0680628ba Extract function to add investment markers 2023-05-04 15:27:15 +02:00
Javi Martín
21ce7689c2 Don't overwrite marker when creating investment markers
The `marker` variable is like a global variable inside the
`initializeMap` function, so assigning it inside the `createMarker`
function was changing its value in other places.

So we're using different variable names like `newMarker` in order to
make the code easier to follow. Now we "only" change the `marker`
variable in functions that modify the marker.
2023-05-04 15:27:15 +02:00
Javi Martín
74d165ae7a Extract function to create a map 2023-05-04 15:27:15 +02:00
Javi Martín
2e8bc11c2a Extract functions to update map form fields 2023-05-04 15:27:15 +02:00
Javi Martín
f8053c9532 Extract function to get popup in map JavaScript 2023-05-04 15:27:15 +02:00
Javi Martín
4087066c59 Extract function to add map attribution 2023-05-04 15:27:15 +02:00
Javi Martín
00cd91c6b2 Extract functions to get coordinates in map JS
We had 130 lines long function, and we're trying to reduce its size so
it's easier to follow the code.
2023-05-04 15:27:15 +02:00
Senén Rodero Rodríguez
c3439ab539 Keep the same attribution as it was in previous versions 2023-04-14 14:38:53 +02:00
Senén Rodero Rodríguez
3341c45e61 Disable scroll wheel for zooming in favor of map zoom buttons
It's causing annoying behaviour for desktop users when scrolling
the page to the bottom and there is more content below the
map.

The behaviour of touchable devices does not seem to be
affected by this change and keeps behaving the same.
2023-03-28 12:15:26 +02:00
Javi Martín
e1e16d21c3 Allow having tenants with different domains
Some institutions using CONSUL have expressed interest in this feature
since some of their tenants might already have their own domains.

We've considered many options for the user interface to select whether
we're using a subdomain or a domain, like having two separate fields,
using a check box, ... In the end we've chosen radio buttons because
they make it easier to follow a logical sequence: first you decide
whether you're introducing a domain or subdomain, and then you enter it.

We've also considered hiding this option and assuming "if it's got a
dot, it's a domain". However, this wouldn't work with nested subdomains
and it wouldn't work with domains which are simply machine names.

Note that a group of radio buttons (or check boxes) is difficult to
style when the text of the label might expand over more than one line
(as is the case here on small screens); in this case, most solutions
result in the second line of the label appearing immediately under the
radio button, instead of being aligned with the first line of the label.
That's why I've added a container for the input+label combination.
2022-12-13 13:10:02 +01:00
decabeza
815a526d78 Add VotationType fields to admin poll question form 2022-10-18 10:38:59 +02:00
decabeza
d2cc110678 Use this instead of the CSS selector .sortable
In this context, `this` already points to the element, so there is no
need to search it again.
2022-10-18 10:38:59 +02:00
Senén Rodero Rodríguez
64676be246 Remove token column from poll_voters table
As it is no longer used as originally pretended [1][2].

[1] Check consul/consul pull request 1994
[2] Check consul/consul pull request 3539
2022-09-22 10:34:07 +02:00
Javi Martín
5a0fde4048 Allow selecting the time when a poll starts/ends
We were already saving it as a time, but we didn't offer an interface to
select the time due to lack of decent browser support for this field
back when this feature was added.

However, nowadays all major browsers support this field type and, at the
time of writing, at least 86.5% of the browsers support it [1]. This
percentage could be much higher, since support in 11.25% of the browsers
is unknown.

Note we still need to support the case where this field isn't supported,
and so we offer a fallback and on the server side we don't assume we're
always getting a time. We're doing a strange hack so we set the field
type to text before changing its value; otherwise old Firefox browsers
crashed.

Also note that, until now, we were storing end dates in the database as
a date with 00:00 as its time, but we were considering the poll to be
open until 23:59 that day. So, in order to keep backwards compatibility,
we're adding a task to update the dates of existing polls so we get the
same behavior we had until now.

This also means budget polls are now created so they end at the
beginning of the day when the balloting phase ends. This is consistent
with the dates we display in the budget phases table.

Finally, there's one test where we're using `beginning_of_minute` when
creating a poll. That's because Chrome provides an interface to enter a
time in a `%H:%M` format when the "seconds" value of the provided time
is zero. However, when the "seconds" value isn't zero, Chrome provides
an interface to enter a time in a `%H:%M:%S` format. Since Capybara
doesn't enter the seconds when using `fill_in` with a time, the test
failed when Capybara tried to enter a time in the `%H:%M` format when
Chrome expected a time in the `%H:%M:%S` format.

To solve this last point, an alternative would be to manually provide
the format when using `fill_in` so it includes the seconds.

[1] https://caniuse.com/mdn-html_elements_input_type_datetime-local
2022-09-14 15:14:23 +02:00
Senén Rodero
3ecf2feb2e Merge pull request #4601 from consul/budgets_hide_money
Add hide money option for approval budgets
2022-03-30 09:58:29 +02:00
decabeza
80e64590b7 Allow enable 'hide_money' check on admin budget form
Add new 'hide_money' field to admin budget form.

Only display new field 'hide_money' when voting style is 'approval'
2022-03-29 14:49:25 +02:00
Javi Martín
ea026dbe5e Require custom JavaScript after everything else
This way we make sure the custom JavaScript will overwrite anything in
the original code.
2022-03-18 17:20:33 +01:00
Javi Martín
95c1999cca Make it easier to customize JavaScript functions
When there was a custom JavaScript file, we weren't loading the original
one, meaning that, in order to customize it, it was necessary to copy
the whole original file and then changing it.

Now we're loading both the original and the custom file, so the custom
file can simply add more functions or overwrite the ones we'd like to
customize, without copying the whole file.

Existing copies of original files will still overwrite the whole file
and won't be affected.
2022-03-18 16:43:14 +01:00
Javi Martín
abec716308 Show "not allowed" message on click
Defining a behavior on hover means making it different for people using
a keyboard or a touchscreen (most of the population, nowadays).

In this case, we had an accessibility issue where the message wouldn't
disappear once it appeared. That meant that, after tabbing through all
the links and buttons in, for instance, the debates index, the page
would be filled with "participation not allowed" messages, and in order
to see the information about how many people have voted, reloading the
page was required.

For touchscreen users the behavior was similar to what we get on hover,
although we've found some inconsistencies when trying to support several
elements on the same page.

We think in proposals it makes sense to hide the "support" button when
users click on it, and the same applies to the buttonsto support and
vote investment projects. However, we aren't hiding the buttons to
agree/disagree with a debate in order to keep the information about the
current number of people agreeing and disagreeing visible.

Note we're removing some support spec methods because after these
changes the duplication isn't as obvious as it was in the past.
2022-02-23 16:43:37 +01:00
Javi Martín
a0b4e35dbd Show login to comment message in annotations
This way it's consistent with what we get when there are no comments. It
only appears once on the page so it isn't overwhelming.
2022-02-21 18:48:09 +01:00
Javi Martín
9154614577 Always show not allowed message in legislation debates
This message is only shown in the `show` action, so it's shown at most
once in the whole page, so it doesn't take up too much space and it
isn't as overwhelming as if we were showing it on the index page, once
per debate.

We're only showing it when there are closed options, though, since
there's already a message to sign in to comment when the question
accepts open answers.
2022-02-21 18:48:09 +01:00
Javi Martín
9a625fe59f Remove redundant "participation not allowed" code
Very similar code is present in the `votes.js` file. Since the only
elements with the `js-participation-not-allowed` class also matched the
`div.supports div.participation-not-allowed` selector, for these
elements the events were executed twice.

So we can get rid of the `js-participation` class alongside all the
JavaScript code referencing it.
2022-02-21 18:47:13 +01:00
Javi Martín
f11fd2b13e Remove duplication in comments votes component
We're also simplifying the code a bit by removing the
`participation-allowed` HTML class, which wasn't used in any other votes
component.
2022-02-21 18:47:13 +01: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
Javi Martín
b2dd6bcc16 Remove placeholder in SDG related list
Its value is difficult to read due to the low contrast between the color
of the field and the color of the placeholder text, and we already have
the same information in the hint above it.
2021-10-01 16:19:21 +02:00
Javi Martín
f638e50174 Wait for suggestions to finish loading in tests
Sometimes tests were hanging indefinitely. Debugging shows that in some
cases it's due to submitting a form before the AJAX request to get
proposals, debates or investments suggestions is finished, since having
an AJAX and a non-AJAX request at the same time when running the test
sometimes leads to unexpected results.

In our case, we were having many timeouts in Github Actions in the
branches where we use both ActiveStorage and Paperclip to store files
(based on pull request 4598). I can reproduce it in those branches
running the following test ("Should show new image after successful
creation with one uploaded file"), although only when my laptop isn't
plugged (!!):

```
rspec './spec/system/proposals_spec.rb[1:33:1:14]'
```

Since we didn't have a proper way to know the AJAX request had finished,
we're adding a `suggest-success` class to the element showing the
suggestions when that happens. Then in the tests we can look for that
class after filling in the title of a proposal, debate or investments.
Just for clarity's sake, we're also adding the `suggest-loading` class
when the suggestions are loading.

In order not to have expectations everywhere about the suggestions,
we're extracting methods to fill in those titles in the tests. Note we
aren't using these methods in the "edit" actions (suggestions are not
showing when editing) or in tests with the `no_js` tag (since
suggestions only work with JavaScript).
2021-09-22 18:29:23 +02:00
Machine Learning
4d27bbebad Add experimental machine learning 2021-08-16 16:31:04 +02:00
Javi Martín
930bb753c5 Use a rake task to delete cached attachments
Our previous system to delete cached attachments didn't work for
documents because the `custom_hash_data` is different for files created
from a file and files created from cached attachments.

When creating a document attachment, the name of the file is taken into
account to calculate the hash. Let's say the original file name is
"logo.pdf", and the generated hash is "123456". The cached attachment
will be "123456.pdf", so the generated hash using the cached attachment
will be something different, like "28af3". So the file that will be
removed will be "28af3.pdf", and not "123456.pdf", which will still be
present.

Furthermore, there are times where users choose a file and then they
close the browser or go to a different page. In those cases, we weren't
deleting the cached attachments either.

So we're adding a rake task to delete these files once a day. This way
we can simplify the logic we were using to destroy cached attachments.

Note there's related a bug in documents: when editing a record (for
example, a proposal), if the title of the document changes, its hash
changes, and so it will be impossible to generate a link to that
document. Changing the way this hash is generated is not an option
because it would break links to existing files. We'll try to fix it when
moving to Active Storage.
2021-07-30 17:30:11 +02:00
Javi Martín
6c63aaee76 Fix removing existing image and adding a new one
We introduced a bug in commit acbd1b023.

When editing a record and removing an existing image, we don't remove
the HTML fields associated with that image but simply hide them, and
then we add fields to create a new image when clicking on "Add image".

This is standard cocoon behavior. However, since in the case of images
there's a `has_one` relation, cocoon doesn't add unique identifiers to
the new fields, generating duplicate IDs, which is invalid HTML.

Since there's a duplicate file input ID, clicking on the "Choose image"
label we aren't clicking on the new input but on the old one. This means
we aren't correctly attaching an image. The tests passed because
Capybara uses the equivalent of a keyboard to select the field, and in
this case everything worked properly.

So we need to delete the existing elements before inserting new ones.
We're adding a test to check there aren't duplicate IDs.
2021-07-27 19:27:29 +02:00
Javi Martín
cc6f9391fc Fix attaching files using the keyboard
We were hiding the file input and styling the label as a button instead.
Since clicking on a label has the same effect as clicking on the input,
the input worked properly for mouse and touch screen users.

However, hiding the input makes it inaccessible for keyboard users,
since labels don't get keyboard focus, but inputs do.

So we must not hide the input but make it invisible instead. But we
still need to hide the input (alongside the label) after a file has been
attached.

We could add some extra JavaScript to hide the input when we hide the
label. Since the JavaScript is already quite complex and my first few
attempts at changing it failed, I've opted to assume that the input (and
its label) must be hidden whenever there's already a file name, and
implement that rule with CSS.

Note we're using the `:focus-within` pseudoclass to style a label when
focus is on the input. This rule (at the time of writing) is only
supported by 93.5% of the browsers. Keyboard users without a screen
reader and using the other 6.5% of the browsers will still be able to
focus on the field but might not notice the field has received focus.
Since the percentage of affected users will decrease over time and until
now 100% of keyboard users were completely unable to focus on these
fields, for now we think this is a good-enough solution.
2021-07-13 17:09:05 +02:00