Commit Graph

15091 Commits

Author SHA1 Message Date
Javi Martín
24ccf23ed8 Don't save the answer if the voter is not recorded
Up until now, we were assuming the voter was valid, but were not raising
an exception if it wasn't. And in the user interface everything seemed
to be working properly.

We were having this issue when skipping verification, when there could
be voters without a document number, which would be considered invalid.

Raising an exception when failing to save the voter and making sure the
answer and the voter are saved inside a transaction solves the problem.
2020-08-07 11:52:24 +02:00
Javier Martín
50372f4370 Merge pull request #4066 from consul/oauth_buttons
Show Wordpress login button if it's the only one enabled
2020-08-06 13:53:57 +02:00
Javier Martín
5fb951eeac Merge pull request #4063 from consul/approval_voting
Add approval voting to budgets
2020-08-06 13:52:19 +02:00
Ziyan Junaideen
1e3e8c1304 Add approval voting to budgets
Co-Authored-By: Javi Martín <javim@elretirao.net>
2020-08-06 12:38:18 +02:00
Javier Martín
a8f261ed95 Merge pull request #4073 from rockandror/javascript_fixes
Javascript fixes
2020-08-05 14:07:16 +02:00
Javi Martín
017eeda3d4 Remove redundant call to $(document).ready()
The `$()` function is a shortcut for `$(document).ready()`, and we were
attaching events to `$(document).ready()` inside the `$()` function.

In a similar way, we were handling the `page:load` and `ajax:complete`
events inside the `$()` function. But when those events trigger, the DOM
is already ready.

Besides, we don't have to wait for the DOM to be ready before attaching
events to the `document` element. Quoting jQuery's `.on()`
documentation:

> The document element is available in the head of the document before
> loading any other HTML, so it is safe to attach events there without
> waiting for the document to be ready.

Co-Authored-By: Senén Rodero Rodríguez <senenrodero@gmail.com>
2020-08-05 11:34:57 +02:00
Javi Martín
983bf49b38 Simplify code related to Foundation's sticky
In the past we had huge problems trying to make it work with Turbolinks.
However, after updating foundation-rails in commit 58071fd6, these hacks
aren't necessary anymore.

We're adding a test for the scenario of visiting a page using
Turbolinks, which was missing, so we're sure we aren't breaking
anything.

Note the sticky will still not work after using the browser back button.
We haven't been able to make it work with turbolinks-classic; we'll fix
this issue when upgrading turbolinks.
2020-08-05 11:34:57 +02:00
Senén Rodero Rodríguez
fde6fb4d97 Initialize only visible maps when page is loaded
Its known that initializing a map when it is inside a hidden element
wont work when hidden element is shown, so its makes sense to
avoid initialization of hidden maps.

When a map lives within a hidden layer we need to initialize the
map after the event of showing that hidden layer, in our case when
admin settings tab is shown.
2020-08-05 11:34:57 +02:00
Senén Rodero Rodríguez
99f8bb4491 Fix collission with sortable.js script
TableSortable and Sortable javascripts were using the same CSS
class name to define completely different and separated
behaviours causing unexpected errors. Now `sortable.js` script
will use `.sortable` class and `table_sortable.js` will use
`.table-sortable` instead.
2020-08-05 10:28:13 +02:00
Senén Rodero Rodríguez
cda545f2fc Remove uneeded lines
There is no elements with class `js-participation-allowed` within all
application code.
2020-08-04 20:32:14 +02:00
Senén Rodero Rodríguez
149ce945c0 Simplify initialization code for tags links
By using an event delegation handler on document body there is no need
to check if element was already initialized (idempotency) anymore.
2020-08-04 20:32:14 +02:00
Senén Rodero Rodríguez
45a80af793 Do not remove click event definition before defining it
Use delegated handlers instead so there is not risk to run method
multiple times.
2020-08-04 20:31:52 +02:00
Javier Martín
009c33d4e5 Merge pull request #4062 from consul/voting_styles
Refactor ballot / ballot line voting logic
2020-07-30 22:01:43 +02:00
Javi Martín
82ef5149c5 Remove redundant progress bar
We were displaying two progress bars for the same thing, and hiding one
of them.

Displaying just one of them and readjusting the styles accordingly is a
bit more intuitive IMHO.

We're also getting the text inside the progress bar out of it; its
purpose inside an element with the `progressbar` role is to provide the
same information as the progress bar (which we aren't exactly doing,
although it could be argued that we do), and in order to be accessible
we should provide the same text in the `aria-valuetext` field, which we
aren't doing. This also simplifies our CSS, which was working because we
defined a padding which covered the height of the hidden extra progress
bar and would have needed quite a few changes if we kept just one
progress bar with text inside it. We can also remove a few CSS rules
which we added to override foundation's rules for the
`progress-meter-text` class.
2020-07-30 16:20:00 +02:00
Javi Martín
2216cb91d1 Use local variables in progress bar partial
We were even passing the `ballot` local variable in some places, which
was ignored because we were using instace variables.
2020-07-30 16:20:00 +02:00
Javi Martín
8edcbcfd3b Fix aria-valuenow attibute in ballot progress bar
We were setting it to 0, and so screen reader users might be confused by
it.

The easiest way to reuse the code and using it for both this attribute
and the width of the progress bar is to move this method to the voting
style, just like the other methods used in this view.

Note the progressbar ARIA role might not be right, since this isn't a
task which is "progressing", but an indicator of the amount spent and
amount available, which is exactly what the <meter> HTML5 tag was
designed for.

We might use a <meter> tag in the future. For now, I'm leaving it as it
is because I'm not certain about how well <meter> is supported in
accessibility tools, and because it's definitely not supported in
Internet Explorer 11, which we haven't officially dropped support for.
2020-07-30 16:20:00 +02:00
Javi Martín
ceee25fdc9 Don't re-render the ballot twice
We were rendering an individual ballot, and then rendering all ballots
(including the already rendered one). So we can skip the first part, as
pointed out by microweb10 in the comments of pull request 3036.
2020-07-30 16:20:00 +02:00
Javi Martín
160964fcdc Make method to check a line can be added generic
In the Knapsack voting style, we can't add an investment if its cost is
greater than the money we've got left, but in other voting styles money
might not be the issue.

So we're introducing the term "resources" and adapting the code
accordingly.
2020-07-30 16:20:00 +02:00
Javi Martín
5f726df8be Extract methods showing voting style information
The idea is that different voting styles will display different
information messages.
2020-07-30 16:19:58 +02:00
Javi Martín
ad6d830c1f Make translations more consistent
We're passing the amount as a paramenter to the "remaining" text, so it
makes sense to pass it to the "amount spent" text as well.

Here we're also changing the I18n key to the text saying users can
change their vote, so it's easier to note the text is about changing
their vote, and not about the projects they have voted so far.
2020-07-28 13:06:31 +02:00
Javi Martín
ad094e5063 Extract class to handle voting style logic
Since we're going to introduce a new voting style which will not be
based on money, we're extracting the logic specific to the current
voting style to a new class.

This way adding new voting styles will be easier.
2020-07-28 13:06:31 +02:00
Javi Martín
c22e800329 Remove code duplication
We were calling the same method three times.
2020-07-28 13:06:31 +02:00
Javi Martín
a38cdb4df3 Remove unnecessary safe navigation operator
The heading is used with `find_by_slug_or_id`, which raises an exception
if it isn't found, so executing `@heading.group` after it does not need
the safe navigation operator.
2020-07-28 13:06:31 +02:00
Javi Martín
a9900e3f27 Remove duplication calculating insufficient funds
We were using the same logic twice.

I've moved the logic to the Ballot model, which to me is a more natural
place to calculate whether there's enough money left than the Investment
model. After all, the remaining money is in the ballot, and not in the
investment.
2020-07-28 13:06:31 +02:00
Javi Martín
a32c0f8154 Remove unused parameter
The `refresh_ballots` partial ignores the `investment` parameter
completely; instead, it iterates over the investments in the
`@investments` instance variable.
2020-07-28 13:06:31 +02:00
Javi Martín
aff213b0ef Remove redundant calls to load resources
We already load the budget and the ballot in `before_action` calls, so
we don't have to load them again.
2020-07-28 13:06:30 +02:00
Javi Martín
7ce2d8b7eb Remove unused methods
One method was calling `reason_for_not_being_ballotable_by` passing just
one parameter instead of two.

The other method was calling the method `amount_spent`, which does not
exist in the Budget class.

So both methods would make the application crash if they were called.
Luckily, they aren't, so the application doesn't crash.
2020-07-27 16:49:58 +02:00
Javi Martín
7c425c00aa Remove unnecessary condition
The ballot is used in the previous lines, so there's no point checking
whether it's present.
2020-07-27 16:49:58 +02:00
Javier Martín
792ebdb175 Merge pull request #4068 from consul/bug_delete_users
Do not delete users when deleting legislation answers
2020-07-27 14:55:37 +02:00
Javi Martín
1b21171602 Remove duplication in CSS for omniauth buttons
We were adding the same styles five times.
2020-07-27 14:47:42 +02:00
Julian Herrero
b7b05b55fe Show Wordpress login button if it's the only one enabled 2020-07-27 14:47:42 +02:00
Javi Martín
b1c2a4a9f2 Make it easier to add new omniauth buttons
Since we're using the exact same logic for all existing buttons, we can
just get the list of available ones and loop through them.
2020-07-27 14:47:42 +02:00
Javi Martín
ed2b217a08 Remove duplication in oauth actions
We were writing the same code twice, with the only difference being the
text "Sign up" in the sign_up action, and "Sign in" in the sign_in
action.

Note we're renaming the `omniauth.info_*` I18n keys so we don't need to
add new exceptions to the `ignore_unused` list, and so it's consistent
with all the other keys under the `omniauth` key.
2020-07-27 14:46:20 +02:00
Julian Herrero
46c78fc3ef Do not delete users when deleting legislation answers
When a legislation process is deleted, everything related will be
deleted, including the answers. This `dependent: :destroy` was causing
that users accounts were being accidentally deleted.
2020-07-27 14:32:22 +02:00
Javier Martín
c03ada579d Merge pull request #4061 from consul/ballot_race_condition
Fix race condition with ballot lines
2020-07-27 13:01:37 +02:00
Javier Martín
54095d7928 Merge pull request #4064 from consul/remove_google_plus
Remove Google plus share button
2020-07-21 13:03:59 +02:00
Javier Martín
7ee3eecae3 Merge pull request #3980 from consul/erased-users
Filter erased users and show erase reason in admin
2020-07-17 23:00:12 +02:00
decabeza
f72f255d15 Filter erased users and show erase reason in admin 2020-07-17 22:21:52 +02:00
decabeza
e3539544a8 Remove google plus share button 2020-07-17 16:24:20 +02:00
Javier Martín
74627641b3 Merge pull request #4034 from consul/help_page_processes
Add processes feature info section in the help page
2020-07-16 23:32:15 +02:00
Javier Martín
53f054ff69 Merge pull request #4050 from consul/stemming_spec
Improve test checking order by relevance
2020-07-14 18:12:21 +02:00
Javi Martín
d9eeb1ad15 Improve test checking order by relevance
The test wasn't working when postgres used the English dictionary
because in English the word "what" was ignored (or, at least, not given
enough relevance) while searching. When we wrote the test, it passed
because back then we always used the Spanish dictionary. However, when
we switched to a dictionary based on the default locale (in commit
d99875cd), we had to force this test to keep using the Spanish
dictionary.

Using the Spanish dictionary in a test where all texts are in English is
strange to say the least ;). So here we're making the test a bit easier
to understand.

Since now we're only using the `:spanish_search` tag in one test, I've
decided to remove it and simply add it to that test's setup.
2020-07-14 14:49:39 +02:00
Javier Martín
ae0fb131d4 Merge pull request #4028 from consul/rails5.2_compatibility
Add Rails 5.2 compatibility
2020-07-14 13:40:30 +02:00
Javi Martín
9318c4f1e9 Bump pg_search from 2.0.1 to 2.3.0
Using pg_search 2.0.1 with Rails 5.2 results in deprecation warnings:

DEPRECATION WARNING: Dangerous query method (method whose arguments used
as raw SQL) called with non-attribute argument(s):
"pg_search_978c2f8941354cf552831b.rank DESC, \"tags\".\"id\" ASC".
Non-attribute arguments will be disallowed in Rails 6.0. This method
should not be called with user-provided values, such as request
parameters or model attributes. Known-safe values can be passed by
wrapping them in Arel.sql().

We're not upgrading to the latest pg_search because it only supports
ActiveRecord >= 5.2.
2020-07-14 13:16:08 +02:00
Javi Martín
17f442c723 Extract method to get a few random records
In Ruby 5.2, we get a warning when using the "RANDOM()" function:

DEPRECATION WARNING: Dangerous query method (method whose arguments are
used as raw SQL) called with non-attribute argument(s): "RANDOM()".
Non-attribute arguments will be disallowed in Rails 6.0. This method
should not be called with user-provided values, such as request
parameters or model attributes. Known-safe values can be passed by
wrapping them in Arel.sql().

This warning doesn't make much sense, though, since RANDOM() is a common
function which is not dangerous at all. However, since the warning is
annoying, we'll probably have to find a way to deal with it.

So I'm extracting all our RANDOM() usages into a method. This way we'll
only have to change one method to avoid this warning.

I've chosen `sample` because it's similar to Ruby's Array#sample, and
because `order_by_random` would be confusing if we consider we already
have a method called `sort_by_random`.
2020-07-14 12:32:14 +02:00
Javi Martín
057679248f Use be_not_found instead of be_missing
We were getting a deprecation message in Rails 5.2:

The missing? predicate is deprecated and will be removed in Rails 6.0.
Please use not_found? as provided by Rack::Response::Helpers
2020-07-14 12:32:14 +02:00
Javi Martín
1b34c061bb Use where.not instead of where(NOT IN)
This way we simplify the code a bit and reduce our usage of raw SQL.
2020-07-14 12:32:12 +02:00
Javi Martín
d2d517059d Fix race condition with ballot lines
With two concurrent requests, it's possible to create two ballot lines
when only one of them should be created.

The reason is the code validating the line is not thread safe:

```
if ballot.amount_available(investment.heading) < investment.price.to_i
  errors.add(:money, "insufficient funds")
end
```

If the second request executes this code after the first request has
executed it but before the first request has saved the record to the
database, both records will pass this validation and both will be saved
to the database.

So we need to introduce a lock. Now when the second request tries to
lock the ballot, it finds it's already locked by the first request, and
will wait for the transaction of the first request to finish before
checking whether there are sufficient funds.

Note we need to disable transactions during the test; otherwise the
second thread will wait for the first one to finish.

Also note that we need to update a couple of tests because records are
reloaded when they're locked.

In one case, reloading the ballot causes `ballot.user` to be `nil`,
since the user is hidden. So we hide the user after creating all its
associated records (which is the scenario that would take place in real
life).

In the other case, reloading the ballot causes `ballot.user` to reload
as well. So we need to reload the user object used in the test too so it
gets the updates done on `ballot.user`.

I haven't been able to reproduce this behavior in a system test. The
following test works with Rails 5.0, but it stopped working when we
moved to system tests in commit 9427f014. After that commit, for reasons
I haven't been able to debug (reintroducing truncation with
DatabaseClaner didn't seem to affect this test, and neither did
increasing the number of threads in Puma), the two AJAX requests
executed here are no longer simultaneous; the second request waits for
the first one to finish.

scenario "Race conditions with simultaneous requests", :js do
  allow_any_instance_of(Budget::Ballot::Line).to receive(:check_sufficient_funds) do |object|
    allow(object).to receive(:check_sufficient_funds).and_call_original
    object.check_sufficient_funds
    sleep 0.3
  end

  ["First", "Second"].each do |title|
    create(:budget_investment, :selected,
      heading: california,
      price:   california.price,
      title:   title
    )
  end

  login_as(user)
  visit budget_investments_path(budget, heading_id: california.id)

  within(".budget-investment", text: "First") { click_link "Vote" }
  within(".budget-investment", text: "Second") { click_link "Vote" }

  expect(page).to have_link "Remove vote"
  expect(Budget::Ballot::Line.count).to eq 1
end
2020-07-12 22:11:40 +02:00
Javier Martín
226000214d Merge pull request #4054 from consul/allow_delete_polls_with_videos
Allow deleting polls with answers including videos
2020-07-09 13:50:35 +02:00
Julian Herrero
89962ba61a Allow deleting polls with answers including videos
If a poll has a question with an answer containing a related video,
an error was raised because the poll ID was referenced in another
table.
2020-07-09 13:39:15 +02:00