Add filters on budget investments index page
Now it's easier to change the investments filter. Previously we had to go back to the budget index page, change the filter there, and then select one heading. Now the links to change the current filter in the budget index page aren't needed anymore.
This commit is contained in:
@@ -70,6 +70,7 @@
|
||||
//= require advanced_search
|
||||
//= require registration_form
|
||||
//= require suggest
|
||||
//= require filter_selector
|
||||
//= require forms
|
||||
//= require valuation_budget_investment_form
|
||||
//= require embed_video
|
||||
@@ -133,6 +134,7 @@ var initialize_modules = function() {
|
||||
App.RegistrationForm.initialize();
|
||||
App.Suggest.initialize();
|
||||
App.Forms.initialize();
|
||||
App.FilterSelector.initialize();
|
||||
App.ValuationBudgetInvestmentForm.initialize();
|
||||
App.EmbedVideo.initialize();
|
||||
App.FixedBar.initialize();
|
||||
|
||||
8
app/assets/javascripts/filter_selector.js
Normal file
8
app/assets/javascripts/filter_selector.js
Normal file
@@ -0,0 +1,8 @@
|
||||
(function() {
|
||||
"use strict";
|
||||
App.FilterSelector = {
|
||||
initialize: function() {
|
||||
App.Forms.submitOnChange(".filter-selector select");
|
||||
}
|
||||
};
|
||||
}).call(this);
|
||||
@@ -8,8 +8,8 @@
|
||||
}
|
||||
});
|
||||
},
|
||||
submitOnChange: function() {
|
||||
$("body").on("change", ".js-submit-on-change", function() {
|
||||
submitOnChange: function(selector) {
|
||||
$("body").on("change", selector, function() {
|
||||
$(this).closest("form").submit();
|
||||
return false;
|
||||
});
|
||||
@@ -58,7 +58,7 @@
|
||||
},
|
||||
initialize: function() {
|
||||
App.Forms.disableEnter();
|
||||
App.Forms.submitOnChange();
|
||||
App.Forms.submitOnChange(".js-submit-on-change");
|
||||
App.Forms.toggleLink();
|
||||
App.Forms.synchronizeInputs();
|
||||
App.Forms.hideOrShowFieldsAfterSelection();
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
@import "milestones";
|
||||
@import "pages";
|
||||
@import "dashboard";
|
||||
@import "filter_selector";
|
||||
@import "legislation";
|
||||
@import "legislation_process";
|
||||
@import "legislation_process_form";
|
||||
|
||||
14
app/assets/stylesheets/filter_selector.scss
Normal file
14
app/assets/stylesheets/filter_selector.scss
Normal file
@@ -0,0 +1,14 @@
|
||||
.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;
|
||||
}
|
||||
}
|
||||
5
app/components/shared/filter_selector_component.html.erb
Normal file
5
app/components/shared/filter_selector_component.html.erb
Normal file
@@ -0,0 +1,5 @@
|
||||
<%= 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 %>
|
||||
22
app/components/shared/filter_selector_component.rb
Normal file
22
app/components/shared/filter_selector_component.rb
Normal file
@@ -0,0 +1,22 @@
|
||||
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
|
||||
@@ -1,8 +1,4 @@
|
||||
module BudgetsHelper
|
||||
def show_links_to_budget_investments(budget)
|
||||
["balloting", "reviewing_ballots", "finished"].include? budget.phase
|
||||
end
|
||||
|
||||
def budget_voting_styles_select_options
|
||||
Budget::VOTING_STYLES.map do |style|
|
||||
[Budget.human_attribute_name("voting_style_#{style}"), style]
|
||||
|
||||
@@ -55,29 +55,6 @@
|
||||
<h3><%= t("budgets.index.map") %></h3>
|
||||
<%= render_map(nil, "budgets", false, nil, @budgets_coordinates) %>
|
||||
</div>
|
||||
|
||||
<ul class="no-bullet margin-top">
|
||||
<% show_links = show_links_to_budget_investments(current_budget) %>
|
||||
<% if show_links %>
|
||||
<li>
|
||||
<%= link_to budget_path(current_budget) do %>
|
||||
<small><%= t("budgets.index.investment_proyects") %></small>
|
||||
<% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
<li>
|
||||
<%= link_to budget_path(current_budget, filter: "unfeasible") do %>
|
||||
<small><%= t("budgets.index.unfeasible_investment_proyects") %></small>
|
||||
<% end %>
|
||||
</li>
|
||||
<% if show_links %>
|
||||
<li>
|
||||
<%= link_to budget_path(current_budget, filter: "unselected") do %>
|
||||
<small><%= t("budgets.index.not_selected_investment_proyects") %></small>
|
||||
<% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -70,6 +70,8 @@
|
||||
<%= render("shared/order_links", i18n_namespace: "budgets.investments.index") %>
|
||||
<% end %>
|
||||
|
||||
<%= render Shared::FilterSelectorComponent.new(i18n_namespace: "budgets.investments.index") %>
|
||||
|
||||
<% if investments_default_view? %>
|
||||
|
||||
<% @investments.each do |investment| %>
|
||||
|
||||
@@ -127,6 +127,7 @@ ignore_missing:
|
||||
## Consider these keys used:
|
||||
ignore_unused:
|
||||
- "budgets.phase.*"
|
||||
- "budgets.investments.index.filter*"
|
||||
- "budgets.investments.index.orders.*"
|
||||
- "budgets.index.section_header.*"
|
||||
- "budgets.ballots.show.amount_available.*"
|
||||
|
||||
@@ -69,9 +69,6 @@ en:
|
||||
prev_phase: Previous phase
|
||||
current_phase: Current phase
|
||||
map: Budget investments' proposals located geographically
|
||||
investment_proyects: List of all investment projects
|
||||
unfeasible_investment_proyects: List of all unfeasible investment projects
|
||||
not_selected_investment_proyects: List of all investment projects not selected for balloting
|
||||
finished_budgets: Finished participatory budgets
|
||||
see_results: See results
|
||||
section_footer:
|
||||
@@ -120,6 +117,13 @@ en:
|
||||
verified_only: "To create a new budget investment %{verify}."
|
||||
create: "Create a budget investment"
|
||||
not_logged_in: "To create a new budget investment you must %{sign_in} or %{sign_up}."
|
||||
filter: "Filtering projects by"
|
||||
filters:
|
||||
not_unfeasible: "Not unfeasible"
|
||||
selected: "Selected"
|
||||
unfeasible: "Unfeasible"
|
||||
unselected: "Unselected"
|
||||
winners: "Winners"
|
||||
orders:
|
||||
random: random
|
||||
confidence_score: highest rated
|
||||
|
||||
@@ -69,9 +69,6 @@ es:
|
||||
prev_phase: Fase anterior
|
||||
current_phase: Fase actual
|
||||
map: Proyectos localizables geográficamente
|
||||
investment_proyects: Ver lista completa de proyectos de gasto
|
||||
unfeasible_investment_proyects: Ver lista de proyectos de gasto inviables
|
||||
not_selected_investment_proyects: Ver lista de proyectos de gasto no seleccionados para la votación final
|
||||
finished_budgets: Presupuestos participativos terminados
|
||||
see_results: Ver resultados
|
||||
section_footer:
|
||||
@@ -120,6 +117,13 @@ es:
|
||||
verified_only: "Para crear un nuevo proyecto de gasto %{verify}."
|
||||
create: "Crear proyecto de gasto"
|
||||
not_logged_in: "Para crear un nuevo proyecto de gasto debes %{sign_in} o %{sign_up}."
|
||||
filter: "Filtrando proyectos"
|
||||
filters:
|
||||
not_unfeasible: "No inviables"
|
||||
selected: "Seleccionados"
|
||||
unfeasible: "Inviables"
|
||||
unselected: "No seleccionados"
|
||||
winners: "Ganadores"
|
||||
orders:
|
||||
random: Aleatorios
|
||||
confidence_score: Mejor valorados
|
||||
|
||||
15
spec/components/shared/filter_selector_component_spec.rb
Normal file
15
spec/components/shared/filter_selector_component_spec.rb
Normal file
@@ -0,0 +1,15 @@
|
||||
require "rails_helper"
|
||||
|
||||
describe Shared::FilterSelectorComponent, type: :component do
|
||||
it "renders a form with a select" do
|
||||
component = Shared::FilterSelectorComponent.new(i18n_namespace: "budgets.investments.index")
|
||||
allow(component).to receive(:url_for).and_return("/")
|
||||
allow(component).to receive(:valid_filters).and_return(["unfeasible", "winners"])
|
||||
allow(component).to receive(:current_filter).and_return(nil)
|
||||
|
||||
render_inline component
|
||||
|
||||
expect(page).to have_select "Filtering projects by"
|
||||
expect(page).to have_selector "form[method='get'].filter-selector select"
|
||||
end
|
||||
end
|
||||
@@ -139,53 +139,10 @@ describe "Budgets" do
|
||||
expect(page).not_to have_link "#{heading.name} €1,000,000"
|
||||
expect(page).to have_content "#{heading.name} €1,000,000"
|
||||
|
||||
expect(page).to have_link "List of all investment projects",
|
||||
href: budget_path(budget)
|
||||
|
||||
expect(page).to have_link "List of all unfeasible investment projects",
|
||||
href: budget_path(budget, filter: "unfeasible")
|
||||
|
||||
expect(page).to have_link "List of all investment projects not selected for balloting",
|
||||
href: budget_path(budget, filter: "unselected")
|
||||
|
||||
expect(page).to have_css("div.map")
|
||||
end
|
||||
end
|
||||
|
||||
scenario "Show investment links only on balloting or later" do
|
||||
budget = create(:budget)
|
||||
create(:budget_heading, budget: budget)
|
||||
|
||||
allowed_phase_list.each do |phase|
|
||||
budget.update!(phase: phase)
|
||||
|
||||
visit budgets_path
|
||||
|
||||
expect(page).to have_content(I18n.t("budgets.index.investment_proyects"))
|
||||
expect(page).to have_content(I18n.t("budgets.index.unfeasible_investment_proyects"))
|
||||
expect(page).to have_content(I18n.t("budgets.index.not_selected_investment_proyects"))
|
||||
end
|
||||
end
|
||||
|
||||
scenario "Not show investment links earlier of balloting " do
|
||||
budget = create(:budget)
|
||||
create(:budget_heading, budget: budget)
|
||||
phases_without_links = ["informing"]
|
||||
not_allowed_phase_list = Budget::Phase::PHASE_KINDS -
|
||||
phases_without_links -
|
||||
allowed_phase_list
|
||||
|
||||
not_allowed_phase_list.each do |phase|
|
||||
budget.update!(phase: phase)
|
||||
|
||||
visit budgets_path
|
||||
|
||||
expect(page).not_to have_content(I18n.t("budgets.index.investment_proyects"))
|
||||
expect(page).to have_content(I18n.t("budgets.index.unfeasible_investment_proyects"))
|
||||
expect(page).not_to have_content(I18n.t("budgets.index.not_selected_investment_proyects"))
|
||||
end
|
||||
end
|
||||
|
||||
scenario "No budgets" do
|
||||
Budget.destroy_all
|
||||
|
||||
|
||||
@@ -151,6 +151,51 @@ describe "Budget Investments" do
|
||||
end
|
||||
end
|
||||
|
||||
scenario "Index filter by status", :js do
|
||||
budget.update!(phase: "finished")
|
||||
|
||||
create(:budget_investment, :feasible, heading: heading, title: "Feasible investment")
|
||||
create(:budget_investment, :unfeasible, heading: heading, title: "Unfeasible investment")
|
||||
create(:budget_investment, :unselected, heading: heading, title: "Unselected investment")
|
||||
create(:budget_investment, :selected, heading: heading, title: "Selected investment")
|
||||
create(:budget_investment, :winner, heading: heading, title: "Winner investment")
|
||||
|
||||
visit budget_investments_path(budget, heading_id: heading.id)
|
||||
|
||||
expect(page).to have_select "Filtering projects by",
|
||||
options: ["Not unfeasible", "Unfeasible", "Unselected", "Selected", "Winners"]
|
||||
|
||||
select "Unfeasible", from: "Filtering projects by"
|
||||
|
||||
expect(page).to have_css ".budget-investment", count: 1
|
||||
expect(page).to have_content "Unfeasible investment"
|
||||
|
||||
select "Unselected", from: "Filtering projects by"
|
||||
|
||||
expect(page).to have_css ".budget-investment", count: 2
|
||||
expect(page).to have_content "Unselected investment"
|
||||
expect(page).to have_content "Feasible investment"
|
||||
|
||||
select "Selected", from: "Filtering projects by"
|
||||
|
||||
expect(page).to have_css ".budget-investment", count: 2
|
||||
expect(page).to have_content "Selected investment"
|
||||
expect(page).to have_content "Winner investment"
|
||||
|
||||
select "Winners", from: "Filtering projects by"
|
||||
|
||||
expect(page).to have_css ".budget-investment", count: 1
|
||||
expect(page).to have_content "Winner investment"
|
||||
|
||||
select "Not unfeasible", from: "Filtering projects by"
|
||||
|
||||
expect(page).to have_css ".budget-investment", count: 4
|
||||
expect(page).to have_content "Selected investment"
|
||||
expect(page).to have_content "Unselected investment"
|
||||
expect(page).to have_content "Feasible investment"
|
||||
expect(page).to have_content "Winner investment"
|
||||
end
|
||||
|
||||
context("Search") do
|
||||
scenario "Search by text" do
|
||||
investment1 = create(:budget_investment, heading: heading, title: "Get Schwifty")
|
||||
|
||||
Reference in New Issue
Block a user