Using a field with `type="tel"` causes most mobile phone browsers to
show a numeric keyboard which makes it easy to enter phone numbers.
We aren't using a number field because some browsers show "spinners" to
increment/decrement numbers (which doesn't make much sense in a phone
number) and because they don't allow characters like spaces. Phone
numbers can have characters like spaces, dashes, parenthesis, asterisks,
the plus sign, ...
Since phone number formats vary depending on the region, and sometimes
even within the same region several different formats can be used, for
now we aren't offering any kind of format validation. We could offer a
format validation that rejects just letters (although there are cases
where letters are actually allowed). However, this causes issues at both
the server side and the client side.
We could use a client-side validation adding a `pattern` attribute to
the field, but that would be something unlike anything else we use in
the application, and we would need to to write some JavaScript in order
to use a proper error message.
On the other hand, if we add a server-side validation, we might find out
existing users are invalid, and it would be impossible to update them in
the many places where we update users assuming they were valid in the
first place. We'd have to add a rake task to update existing user
records and make sure they contain a valid phone number or create a
setting so this validation only applies to new CONSUL installations.
Another option would be to add a per-form validation, so the phone
number is only validated in pages where it is introduced.
All the mentioned scenarios offer certain complexities. So, for now,
we're keeping things simple.
Co-Authored-By: decabeza <alberto@decabeza.es>
Now that we also have the "go back to CONSUL" link, the layouts are so
similar that it isn't worth it maintaining both of them separately.
With this change, people using small screens also get the "menu" button
in the management section, just like they do everywhere else.
We're adding the `namespace != "management"` condition so the menu still
shows up in the officing namespace.
We were making some typos during development in the name of the keys and
tests were still passing.
We're also removing some texts that were never used.
Some developers work on CONSUL installations where Spanish and/or
English aren't part of the available locales. In those cases, the
`dev_seed` task was crashing because we were using attributes like
`name_en` and `name_es`.
So we're using attributes for random locales instead.
We're using a proc so we don't have code like this all over the place:
random_locales.map do |locale|
I18n.with_locale(locale) do
phase.name = I18n.t("budgets.phase.#{phase.kind}")
phase.save!
end
end
This would make the code harder to read and would execute a `save!` once
per locale, which would make the task much slower.
We could also avoid the procs writing something like:
def random_locales_attributes(**attribute_names_with_values)
random_locales.each_with_object({}) do |locale, attributes|
I18n.with_locale(locale) do
attribute_names_with_values.each do |attribute_name, (i18n_key, i18n_args)|
value = I18n.t(i18n_key, (i18n_args || {}).merge(language: I18n.t("i18n.language.name")))
attributes["#{attribute_name}_#{locale.to_s.underscore}"] = value
end
end
end
end
And calling the method with with:
random_locales_attributes(name: ["seeds.budgets.name", year: Date.current.year - 1])
However, this code would also be different that what we usually do, we'd
have to apply some magic to pass the `language:` parameter, and the
strings wouldn't be recognized by i18n-tasks, so we aren't sure we're
really gaining anything.
These locales are officially maintained by CONSUL developers, so we're
using them when available.
This way we'll be able to use `random_locales` in places where we're
manually using English and Spanish, giving support to other locales
while maintaining compatibility with the current version.
Originally there was a link pointing to the FAQ page but it was removed
in commit e14b7b67fb because by default the FAQ page in CONSUL only
contains a placeholder text.
We aren't sure where this link should point:
* FAQ page, only if the FAQ page is published
* Help page, only when the help feature is enabled
* CONSUL technical documentation page
So, for now, we're choosing the easiest solution which is removing the
text completely.
We already support Errbit and Airbrake as error monitoring services.
Since some people might not want to setup Errbit and might prefer
Rollbar over Airbrake, we're referencing it in the custom gemfile.
We haven't updated the gem for years and don't know whether it
still works with our current Ruby and Rails versions.
Besides, dependabot keeps opening pull requests to update it. In theory
we could just ignore the dependabot pull requests for this dependency,
but unfortunately right now we can't add a dependabot config file
because it would open pull requests on forks as well.
Finally, there are other companies offering similar services for Rails
applications, and it's up to each CONSUL installation to decide which
one is better for them. We might add a self-hosted performance
monitoring tool in the future.
Since other CONSUL installations might be using Newrelic, and in general
we recommend adding an application monitoring tool, we're suggesting it
in the custom gemfile. In the name of neutrality, we're also adding
Sentry. We might add other services in the future.
The `commentable_url` method wasn't updated when we added legislation
proposals.
Back when we first created this method, we couldn't pass budget
investments or topics directly to `polymorphic_url` because they are
nested resources. That isn't the case since commit ff93f5a59, so now we
can simplify this method.
We're keeping the `commentable_url` method for now in order to keep
compatibility with custom changes that might use it, although this
method isn't consistent with the `commentable_path` method (which
receives a comment, and not a commentable), and so we might have to
revisit this code in the future.
With the `update_without_changes`, previous translations are kept
even when the source string changed utterly. Using this option caused
some problems when updating source language strings, as the
translators do not get any notification, and the old translation keeps
approved, so translators do not have an easy way to find those strings
in Crowdin.
With the `update_as_unapproved` option, translators and Crowdin
managers can find those translations that need to be updated by
searching among not approved translations.
Quoting Crowdin's docs [1]:
> update_without_changes - preserve translations and validations of
changed strings
> update_as_unapproved - preserve translations of changed strings
and remove validations of those translations if they exist
[1] https://support.crowdin.com/configuration-file/#changed-strings-update
This test was failing sometimes. One possible cause (although it might
not be the only one) is we were querying the database with
`Campaing.last` after starting the process running the browser with a
`visit`. In the past doing so has resulted in database inconsistencies
while running the tests.
Since after running the test more than 1500 times we weren't able to
reproduce the failure, it's possible that this change doesn't fix the
issue which caused the test to fail, but in the worst case scenario we
reduce the number of possible reasons why it fails.
So now:
* In the first few phases, no filters are shown (just like before)
* During the valuation phase, we show "Active" and "Unfeasible"
* During the final voting, we show "Active" (which now refers to the
selected investments), "Not selected for the final voting" and
"Unfeasible"
* When the budget is finished, we show "Winners", "Not selected for the
final voting" and "Unfeasible"
Now each investment is shown in one (and only one) of the filters
(except when the budget is finished; in this case we don't show selected
investments which didn't win), and we remove the confusing "Not
unfeasible" filter by only showing it during the valuation phase (before
filters are selected) and renaming it to "Active". We also rearrange the
filters so the default one for each phase is shown first.
The idea of using the "Active" text for investments which can be
selected during the selection phase and voted during the final voting is
experimental. Right now, for simplicity, since we assume filters will
always use the same text, we're removing the "Active" filter when the
budget is finished, since having both "Winners" and "Active" filters
would be confusing.
The last expectation we were using in this test is satisfied before
going back to the admin stats page, as the campaing2 name is not
present before clicking the `Go back` link. Because of this, the
test could end while the request thrown by the `Go back` link is
not completed yet, which can collide with the following test and
cause a flake spec.
As mentioned in commit 36d795f69, investment filters aren't that
important; actually, most citizens won't use them at all, and are there
mainly for transparency purposes.
So we're moving them to the bottom of the sidebar, just like the links
for selected/archived/retired proposals in the proposals section.
The `open` method can be used to open files or URLs and it's deprecated
in Ruby 2.7. In this case, it's clear we're dealing with a URL, so we
can use `URI.parse`.
The code was a bit strange, since it returned a value and had a side
effect: opening the URL. I'm not sure about the intention of the code;
my best guess is we wanted to test the URL exists and was accessible
before returning it (and, if that's the case, IMHO the code should be a
bit more explicit in order to show the intention behind it), but it
could also be an unintended side effect which was there by accident.
Now the URL is no longer opened; if the URL isn't accessible, we'll find
out when trying to connect to it with the Savon client.
In commit 5a4921a1a we replaced `URI.parse` with `URI.open` due to some
issues during our tests with S3.
However, there are some security issues with `URI.open` [1], since it
might allow some users to execute code on the server.
So we're using `URI.parse#open` instead.
[1] https://docs.rubocop.org/rubocop/cops_security.html#securityopen