In general, we don't use links inside admin tables because we don't know
where the link will point to, and use "view" actions/links instead.
However, in this case, we're showing a URL, so it's perfectly obvious
where the link will point to. And so it makes sense to use the URL as a
link instead of using a "view" action/link.
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.
Creating a schema takes about 3-4 seconds on my machine, so omitting
the callbacks makes tests much faster.
To do so, we're using the `insert!` method added in Rails 6.0, which
inserts a record without executing callbacks or validations. To make the
tests look consistent, we're adding a FactoryBot strategy which uses
`insert!` instead of `create!`.
Note this strategy is useless in most cases because it doesn't work when
models have translatable attributes or associations. However, IMHO it's
worth it even if we only use it for tenants.
We could also use `Tenant.insert!` instead, but then we would have to
add all the mandatory attributes, and in this case the code is clearer
if we only add the attributes we need for the test.
Just like we respond with "not found" for any other record. This
improves the user experience because with the "Not found" error message
people realize the URL is wrong instead of thinking that they broke the
application.
While creating the "venus" tenant for every test makes the code cleaner,
it also makes the tests much slower, so we aren't doing so in tests
where we don't use this tenant.
We were displaying an icon showing that certain actions can't be
performed. However, people who can't see the icons were hearing that
they _can_ perform certain actions while the opposite is true.
We've considered other options to solve this problem. One was to split
the list in two: actions that can be performed and actions that can't be
performed. It was tricky because in some cases we're listing that
actions that can be performed now and in other cases we're displaying
the actions that people will be able to perform once they verify their
account.
Another option was to include the word "Cannot" as a prefix instead of
"Additional verification needed". We haven't done so because, while in
English we say "cannot do this thing", in other languages they say
"this thing cannot do".
So we've gone with a solution where people hearing what's on the screen
know what's going on and we don't have to make big changes in the code.
As mentioned in commit 925f04e3f, icon classes make screen readers
announce strange symbols and aren't properly displayed for people who
have changed their preferred font family.
This way we simplify the ERB code.
Due to the bug mentioned in the previous commit, we're keeping the
original code instead of using `can?` to check permissions.
We were using similar code in four different places; six, if we count
the welcome pages seeds. Reducing duplication in the pages seeds is a
bit tricky because administrators are supposed to edit their content and
might remove the HTML class we use to define styles. However, we can
share the code everywhere else.
Note that there's a bug in the application since we show that level 2
users cannot vote for budget projects but we give them permission to do
so in the abilities model. We're keeping the same behavior after this
refactoring but we might change it in the future.
Coveralls stopped working back in July when we reached build number 3790
because back when we used Travis we created builds from numbers 3791 to
35700.
After trying to change the numbers in several ways, all of them
resulting in a "No build matching CI build number" message, we're trying
the Github Action provided by Coveralls instead. In order to make it
work, we need to add the `simplecov-lcov` gem and generate the report at
`coverage/lcov.info`. Note that, for some reason, `simplecov-lcov`
doesn't seem to depend on `simplecov` and we need `simplecov` 0.18 or
later, so we're manually adding this dependency as well.
We were assigning variants in a controller, in the context of a request.
However, when sending emails, there is no request and no controller is
involved, so we also need to set the variant in the ApplicationMailer
class.
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
ViewComponent 2.78.0 adds support for variants with dashes and dots in
their names; since we're going to add variants named after a subdomain,
we need this feature.
Back in commit 36e452437, we wrote:
> The `reload` method added to max_votes validation is needed because
> the author gets here with some changes because of the around_action
> `switch_locale`, which adds some changes to the current user record
> and therefore, the lock method raises an exception when trying to lock
> it requiring us to save or discard those record changes.
This happened when `current_user` didn't have a locale stored in the
database and the `current_locale` method returned the default locale.
And the test "Poll Votation Type Multiple answers" would indeed fail if
we removed the `reload` method. However, we can remove the need to
reload the record by avoiding the mentioned changes on the current user
record.
So we're changing the `User#locale` method so it doesn't modify the user
record.
This way we'll avoid having all tenant organizations named "CONSUL" by
default, and we'll also use different email senders per tenant, which
will reduce the change of the emails being marked as spam.
We were using `consul.dev` as default, which might be fine for the
development environment, but it's something that definitely needs to be
changed on production.
Now we're providing a better default setting: using the same domain
which is used to generate URLs in emails. This also makes it easier to
configure new tenants, since the setting will default to whatever host
the new tenant is using.
The `|| "consul.dev"` part might not be needed; I'm keeping it because
I'm not sure production environents would not experience any new issues
if we don't add it, but we might remove it in the future.
One of these tests has failed once because there wasn't a user with the
right confirmation token. While I haven't been able to reproduce the
issue, there's a chance it's caused by a `visit` call to the
confirmation path which might start before the redirect request to the
successful sign up page has finished.
I'm not sure this is the case, though, but, worst case scenario, if the
test fails again we'll know it isn't because of a missing expectation.
When voting investment projects, the sidebar was rendered without the
`@heading_content_blocks` being set. That resulted in a 500 error when
the heading had content blocks.
By extracting the logic to a component, we make sure the heading content
blocks are properly set every time this code is rendered, no matter
which controller is rendering the view.
We were already doing the same for the main header color; now we also
make it easier to use different top links, subnavigation and footer
colors per tenant.
Just like we do with SCSS variables, we use the brand-secondary color
for the top links when the `--top-links` variable isn't defined.
Just like we did with SCSS variables, we use the `--main-header` CSS
variable and, if it isn't defined, we use the `--brand` CSS variable
instead.
Note that we're still using the `inverted-selection` mixin based on the
default `$main-header` color, so it's possible that we get the inverted
selection in the main header when using a dark color with `$main-header`
but a light color with `--main-header`, which doesn't make much sense.
Not sure whether there's anything we can do about it.
Until now, overwriting the styles for a certain tenant was a very
tedious task. For example, if we wanted to use a different brand color
for a tenant, we had to manually overwrite the styles for every element
using that color.
It isn't possible to use different SCSS variables per tenant unless we
generate a different stylesheet per tenant. However, doing so would make
the CSS compilation take way too long on installations with more than a
couple of tenants, and it wouldn't allow to get the colors dynamically
from the database, which we intend to support in the future.
So we're using CSS variables instead. These variables are supported by
97% of the browsers (as of October 2022), and for the other 3% of the
browsers we're using the default colors (SCSS variables) instead.
CSS variables have some limitations: for instance, it isn't possible to
use functions like `lighten`, `darken` or `scale-color` with CSS
variables, so the application might behave in a strange way when we use
these functions.
It also isn't possible to automatically get whether black or white text
makes a better contrast with a certain background color. To overcome
this limitation, we're providing variables ending with `-contrast`. For
instance, since the default `$brand` color is a dark one, when assigning
a light color to `--brand`, we probably want to assign
`--brand-contrast: #{$black}` as well, so the text is still readable.
Until now, we didn't have specific variables for the headers and were
using the brand colors instead. Now we maintain the brand colors as
default values, but allow overwriting them.
For the navigation and footer, we didn't even have variables.
Back in commit 5dbd69486, I said:
> I'm choosing to use the same color for solid and hollow buttons
> because these elements are usually isolated and so from the UX
> perspective they are similar; links, on the other hand, are often in
> the middle of some text.
However, I made a mistake. The crucial factor is that solid buttons
might have a light background if we choose the brand color to be a light
one, and in this case they automatically get black text. However, hollow
buttons always have a light background and so we can't use a light color
for the text and border of these buttons.