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.
This commit is contained in:
Javi Martín
2021-09-16 00:19:48 +02:00
parent 57e727ba60
commit 36d795f69c
14 changed files with 57 additions and 87 deletions

View File

@@ -70,7 +70,6 @@
//= require advanced_search //= require advanced_search
//= require registration_form //= require registration_form
//= require suggest //= require suggest
//= require filter_selector
//= require forms //= require forms
//= require valuation_budget_investment_form //= require valuation_budget_investment_form
//= require embed_video //= require embed_video
@@ -135,7 +134,6 @@ var initialize_modules = function() {
App.RegistrationForm.initialize(); App.RegistrationForm.initialize();
App.Suggest.initialize(); App.Suggest.initialize();
App.Forms.initialize(); App.Forms.initialize();
App.FilterSelector.initialize();
App.ValuationBudgetInvestmentForm.initialize(); App.ValuationBudgetInvestmentForm.initialize();
App.EmbedVideo.initialize(); App.EmbedVideo.initialize();
App.FixedBar.initialize(); App.FixedBar.initialize();

View File

@@ -1,8 +0,0 @@
(function() {
"use strict";
App.FilterSelector = {
initialize: function() {
App.Forms.submitOnChange(".filter-selector select");
}
};
}).call(this);

View File

@@ -27,7 +27,6 @@
@import "milestones"; @import "milestones";
@import "pages"; @import "pages";
@import "dashboard"; @import "dashboard";
@import "filter_selector";
@import "legislation"; @import "legislation";
@import "legislation_process"; @import "legislation_process";
@import "legislation_process_form"; @import "legislation_process_form";

View File

@@ -0,0 +1,19 @@
.investments-filters {
border-top: 1px solid $border;
ul {
font-size: $small-font-size;
list-style: none;
margin-left: 0;
a {
display: inline-block;
padding-bottom: $line-height / 4;
padding-top: $line-height / 4;
}
[aria-current] {
font-weight: bold;
}
}
}

View File

@@ -1,14 +0,0 @@
.filter-selector {
text-align: right;
label {
display: inline-block;
font-size: $small-font-size;
margin-right: $line-height / 2;
padding-top: $line-height / 2;
}
select {
width: auto;
}
}

View File

@@ -0,0 +1,4 @@
<div class="investments-filters">
<h2 class="sidebar-title" id="investments_filters_header"><%= t("budgets.investments.index.filter") %></h2>
<%= link_list(*filters, "aria-labelledby": "investments_filters_header") %>
</div>

View File

@@ -0,0 +1,19 @@
class Budgets::Investments::FiltersComponent < ApplicationComponent
delegate :valid_filters, :current_filter, :link_list, :current_path_with_query_params, to: :helpers
def render?
valid_filters&.any?
end
private
def filters
valid_filters.map do |filter|
[
t("budgets.investments.index.filters.#{filter}"),
current_path_with_query_params(filter: filter, page: 1),
current_filter == filter
]
end
end
end

View File

@@ -1,5 +0,0 @@
<%= form_tag({}, method: :get, enforce_utf8: false, class: "filter-selector") do %>
<%= query_parameters_tags %>
<%= label_tag "filter_selector_filter", t("#{i18n_namespace}.filter") %>
<%= select_tag "filter", options_for_select(filter_options, current_filter), id: "filter_selector_filter" %>
<% end %>

View File

@@ -1,22 +0,0 @@
class Shared::FilterSelectorComponent < ApplicationComponent
delegate :valid_filters, :current_filter, to: :helpers
attr_reader :i18n_namespace
def initialize(i18n_namespace:)
@i18n_namespace = i18n_namespace
end
private
def query_parameters_tags
safe_join(request.query_parameters.reject do |name, _|
["page", "filter"].include?(name)
end.map do |name, value|
hidden_field_tag name, value, id: "filter_selector_#{name}"
end)
end
def filter_options
valid_filters.map { |filter| [t("#{i18n_namespace}.filters.#{filter}"), filter] }
end
end

View File

@@ -12,9 +12,6 @@ module Search
end end
def parse_advanced_search_terms def parse_advanced_search_terms
if params[:advanced_search].is_a? String
params[:advanced_search] = JSON.parse(params[:advanced_search].gsub("=>", ":"))
end
@advanced_search_terms = params[:advanced_search] if params[:advanced_search].present? @advanced_search_terms = params[:advanced_search] if params[:advanced_search].present?
parse_search_date parse_search_date
end end

View File

@@ -59,9 +59,12 @@
</div> </div>
<% end %> <% end %>
<%= render Budgets::Investments::FiltersComponent.new %>
<% if @heading && !@heading.content_blocks.where(locale: I18n.locale).empty? %> <% if @heading && !@heading.content_blocks.where(locale: I18n.locale).empty? %>
<%= render "budgets/investments/content_blocks" %> <%= render "budgets/investments/content_blocks" %>
<% end %> <% end %>
<% if @map_location&.available? %> <% if @map_location&.available? %>
<%= render "budgets/investments/map" %> <%= render "budgets/investments/map" %>
<% end %> <% end %>

View File

@@ -70,8 +70,6 @@
<%= render("shared/order_links", i18n_namespace: "budgets.investments.index") %> <%= render("shared/order_links", i18n_namespace: "budgets.investments.index") %>
<% end %> <% end %>
<%= render Shared::FilterSelectorComponent.new(i18n_namespace: "budgets.investments.index") %>
<% if investments_default_view? %> <% if investments_default_view? %>
<% @investments.each do |investment| %> <% @investments.each do |investment| %>

View File

@@ -1,14 +0,0 @@
require "rails_helper"
describe Shared::FilterSelectorComponent do
it "renders a form with a select" do
component = Shared::FilterSelectorComponent.new(i18n_namespace: "budgets.investments.index")
allow(component).to receive(:valid_filters).and_return(["unfeasible", "winners"])
allow(component).to receive(:current_filter).and_return(nil)
with_request_url("/") { render_inline component }
expect(page).to have_select "Filtering projects by"
expect(page).to have_selector "form[method='get'].filter-selector select"
end
end

View File

@@ -139,32 +139,31 @@ describe "Budget Investments" do
visit budget_investments_path(budget, heading_id: heading.id) visit budget_investments_path(budget, heading_id: heading.id)
expect(page).to have_select "Filtering projects by", expect(page).to have_content "FILTERING PROJECTS BY"
options: ["Not unfeasible", "Unfeasible", "Unselected", "Selected", "Winners"]
select "Unfeasible", from: "Filtering projects by" click_link "Unfeasible"
expect(page).to have_css ".budget-investment", count: 1 expect(page).to have_css ".budget-investment", count: 1
expect(page).to have_content "Unfeasible investment" expect(page).to have_content "Unfeasible investment"
select "Unselected", from: "Filtering projects by" click_link "Unselected"
expect(page).to have_css ".budget-investment", count: 2 expect(page).to have_css ".budget-investment", count: 2
expect(page).to have_content "Unselected investment" expect(page).to have_content "Unselected investment"
expect(page).to have_content "Feasible investment" expect(page).to have_content "Feasible investment"
select "Selected", from: "Filtering projects by" click_link "Selected"
expect(page).to have_css ".budget-investment", count: 2
expect(page).to have_content "Selected investment" expect(page).to have_content "Selected investment"
expect(page).to have_content "Winner investment" expect(page).to have_content "Winner investment"
expect(page).to have_css ".budget-investment", count: 2
select "Winners", from: "Filtering projects by" click_link "Winners"
expect(page).to have_css ".budget-investment", count: 1 expect(page).to have_css ".budget-investment", count: 1
expect(page).to have_content "Winner investment" expect(page).to have_content "Winner investment"
select "Not unfeasible", from: "Filtering projects by" click_link "Not unfeasible"
expect(page).to have_css ".budget-investment", count: 4 expect(page).to have_css ".budget-investment", count: 4
expect(page).to have_content "Selected investment" expect(page).to have_content "Selected investment"
@@ -203,13 +202,10 @@ describe "Budget Investments" do
visit budget_investments_path(budget, heading: heading) visit budget_investments_path(budget, heading: heading)
click_on "Advanced search" click_button "Advanced search"
fill_in "With the text", with: "environment"
within(".advanced-search-form") do select "Last 24 hours", from: "By date"
fill_in "With the text", with: "environment" click_button "Filter"
select "Last 24 hours", from: "By date"
click_button "Filter"
end
expect(page).to have_content "There is 1 investment containing the term 'environment'" expect(page).to have_content "There is 1 investment containing the term 'environment'"
expect(page).to have_css ".budget-investment", count: 1 expect(page).to have_css ".budget-investment", count: 1
@@ -218,7 +214,7 @@ describe "Budget Investments" do
expect(page).not_to have_content "Unfeasible environment" expect(page).not_to have_content "Unfeasible environment"
expect(page).not_to have_content "Unfeasible health" expect(page).not_to have_content "Unfeasible health"
select "Unfeasible", from: "Filtering projects by" click_link "Unfeasible"
expect(page).not_to have_content "Feasible environment" expect(page).not_to have_content "Feasible environment"
expect(page).to have_content "There is 1 investment containing the term 'environment'" expect(page).to have_content "There is 1 investment containing the term 'environment'"