From 95c1aa43e8e0560bc94ea229890ff1b700a4e77f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Fuentes?= Date: Tue, 21 Nov 2017 13:21:56 +0100 Subject: [PATCH 1/6] added csv download link to budget_investments (issue 1625) --- .../admin/budget_investments_controller.rb | 44 +++++++++++++++++++ app/helpers/budgets_helper.rb | 18 ++++++++ .../budget_investments/_investments.html.erb | 26 +++-------- 3 files changed, 69 insertions(+), 19 deletions(-) diff --git a/app/controllers/admin/budget_investments_controller.rb b/app/controllers/admin/budget_investments_controller.rb index 4b6bd6b3a..749bb84a7 100644 --- a/app/controllers/admin/budget_investments_controller.rb +++ b/app/controllers/admin/budget_investments_controller.rb @@ -1,4 +1,7 @@ class Admin::BudgetInvestmentsController < Admin::BaseController + + require 'csv' + include FeatureFlags feature_flag :budgets @@ -12,6 +15,12 @@ class Admin::BudgetInvestmentsController < Admin::BaseController before_action :load_investments, only: [:index, :toggle_selection] def index + respond_to do |format| + format.html + format.csv do + send_data set_csv, filename: 'budget_investments.csv' + end + end end def show @@ -43,6 +52,41 @@ class Admin::BudgetInvestmentsController < Admin::BaseController private + def set_csv + attributes = [t("admin.budget_investments.index.table_id"), + t("admin.budget_investments.index.table_title"), + t("admin.budget_investments.index.table_supports"), + t("admin.budget_investments.index.table_admin"), + t("admin.budget_investments.index.table_valuator"), + t("admin.budget_investments.index.table_geozone"), + t("admin.budget_investments.index.table_feasibility"), + t("admin.budget_investments.index.table_valuation_finished"), + t("admin.budget_investments.index.table_selection")] + csv_string = CSV.generate(headers: true) do |csv| + csv << attributes + @investments.each do |investment| + id = investment.id.to_s + title = investment.title + total_votes = investment.total_votes.to_s + if investment.administrator.present? + administrator = investment.administrator.name + else + administrator = t("admin.budget_investments.index.no_admin_assigned") + end + if investment.valuators.empty? + valuators = t("admin.budget_investments.index.no_valuators_assigned") + else + valuators = investment.valuators.collect(&:description_or_name).join(', ') + end + heading_name = investment.heading.name + price = t("admin.budget_investments.index.feasibility.#{investment.feasibility}", price: investment.formatted_price) + valuation_finished = investment.valuation_finished? ? t('shared.yes') : t('shared.no') + csv << [id, title, total_votes, administrator, valuators, heading_name, price, valuation_finished] + end + end + csv_string + end + def load_investments @investments = Budget::Investment.scoped_filter(params, @current_filter) .order(cached_votes_up: :desc, created_at: :desc) diff --git a/app/helpers/budgets_helper.rb b/app/helpers/budgets_helper.rb index 3b4c81f7e..e6d9f16d4 100644 --- a/app/helpers/budgets_helper.rb +++ b/app/helpers/budgets_helper.rb @@ -1,5 +1,23 @@ module BudgetsHelper + def csv_params + csv_params = params.clone.merge(format: :csv) + csv_params.delete(:page) + csv_params + end + + def investment_selected_link_options(investment) + if investment.selected? + {link_class: "button small expanded", + text: t("admin.budget_investments.index.selected") } + elsif investment.feasible? && investment.valuation_finished? + {link_class: "button small hollow expanded", + text: t("admin.budget_investments.index.select")} + else + {} + end + end + def budget_phases_select_options Budget::PHASES.map { |ph| [ t("budgets.phase.#{ph}"), ph ] } end diff --git a/app/views/admin/budget_investments/_investments.html.erb b/app/views/admin/budget_investments/_investments.html.erb index f90c75ac7..f824d1a80 100644 --- a/app/views/admin/budget_investments/_investments.html.erb +++ b/app/views/admin/budget_investments/_investments.html.erb @@ -1,4 +1,7 @@ -

<%= page_entries_info @investments %>

+
+ <%= link_to 'download current selecction',admin_budget_budget_investments_path(csv_params), class: 'advanced-search small' %> +

<%= page_entries_info @investments %>

+
@@ -55,24 +58,9 @@ <%= investment.valuation_finished? ? t('shared.yes'): t('shared.no') %> <% if params[:filter] == 'selected' %> From 56f4c3c3b9d9ec3a53f7bca53e757e54b1db0585 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Fuentes?= Date: Wed, 22 Nov 2017 11:03:21 +0100 Subject: [PATCH 2/6] added test to csv download and style corrections --- .../admin/budget_investments_controller.rb | 22 +++++++++---------- .../features/admin/budget_investments_spec.rb | 16 ++++++++++++++ 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/app/controllers/admin/budget_investments_controller.rb b/app/controllers/admin/budget_investments_controller.rb index 749bb84a7..de2e34d84 100644 --- a/app/controllers/admin/budget_investments_controller.rb +++ b/app/controllers/admin/budget_investments_controller.rb @@ -65,19 +65,19 @@ class Admin::BudgetInvestmentsController < Admin::BaseController csv_string = CSV.generate(headers: true) do |csv| csv << attributes @investments.each do |investment| - id = investment.id.to_s + id = investment.id.to_s title = investment.title total_votes = investment.total_votes.to_s - if investment.administrator.present? - administrator = investment.administrator.name - else - administrator = t("admin.budget_investments.index.no_admin_assigned") - end - if investment.valuators.empty? - valuators = t("admin.budget_investments.index.no_valuators_assigned") - else - valuators = investment.valuators.collect(&:description_or_name).join(', ') - end + administrator = if investment.administrator.present? + investment.administrator.name + else + t("admin.budget_investments.index.no_admin_assigned") + end + valuators = if investment.valuators.empty? + t("admin.budget_investments.index.no_valuators_assigned") + else + investment.valuators.collect(&:description_or_name).join(', ') + end heading_name = investment.heading.name price = t("admin.budget_investments.index.feasibility.#{investment.feasibility}", price: investment.formatted_price) valuation_finished = investment.valuation_finished? ? t('shared.yes') : t('shared.no') diff --git a/spec/features/admin/budget_investments_spec.rb b/spec/features/admin/budget_investments_spec.rb index 2bc1dabf2..7cf4a294d 100644 --- a/spec/features/admin/budget_investments_spec.rb +++ b/spec/features/admin/budget_investments_spec.rb @@ -625,7 +625,23 @@ feature 'Admin budget investments' do expect(page).not_to have_link('Selected') end end + end + context "Selecting csv" do + + scenario "Downloading CSV file" do + create(:budget_investment, :unfeasible, budget: @budget) + create(:budget_investment, :feasible, budget: @budget) + + visit admin_budget_budget_investments_path(@budget, format: :csv) + + header = page.response_headers['Content-Disposition'] + header.should match /^attachment/ + header.should match /filename="budget_investments.csv"$/ + + expect(page).to have_content "Budget Investment 1 title" + expect(page).to have_content "Budget Investment 2 title" + end end end From d7cc5d14c6bf3e473bd0bd702605211f2adfdd14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Fuentes?= Date: Wed, 22 Nov 2017 11:36:11 +0100 Subject: [PATCH 3/6] fixed test --- spec/features/admin/budget_investments_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spec/features/admin/budget_investments_spec.rb b/spec/features/admin/budget_investments_spec.rb index 7cf4a294d..3c287593b 100644 --- a/spec/features/admin/budget_investments_spec.rb +++ b/spec/features/admin/budget_investments_spec.rb @@ -630,8 +630,8 @@ feature 'Admin budget investments' do context "Selecting csv" do scenario "Downloading CSV file" do - create(:budget_investment, :unfeasible, budget: @budget) - create(:budget_investment, :feasible, budget: @budget) + investment1 = create(:budget_investment, :unfeasible, budget: @budget) + investment2 = create(:budget_investment, :feasible, budget: @budget) visit admin_budget_budget_investments_path(@budget, format: :csv) @@ -639,8 +639,8 @@ feature 'Admin budget investments' do header.should match /^attachment/ header.should match /filename="budget_investments.csv"$/ - expect(page).to have_content "Budget Investment 1 title" - expect(page).to have_content "Budget Investment 2 title" + expect(page).to have_content investment2.title + expect(page).to have_content investment1.title end end From 4f096a005d4a16225965b93de0f03aa012936129 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Fuentes?= Date: Wed, 22 Nov 2017 11:53:41 +0100 Subject: [PATCH 4/6] more style corrections --- spec/features/admin/budget_investments_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/features/admin/budget_investments_spec.rb b/spec/features/admin/budget_investments_spec.rb index 3c287593b..55b5af3ce 100644 --- a/spec/features/admin/budget_investments_spec.rb +++ b/spec/features/admin/budget_investments_spec.rb @@ -636,8 +636,8 @@ feature 'Admin budget investments' do visit admin_budget_budget_investments_path(@budget, format: :csv) header = page.response_headers['Content-Disposition'] - header.should match /^attachment/ - header.should match /filename="budget_investments.csv"$/ + header.should match(/^attachment/) + header.should match(/filename="budget_investments.csv"$/) expect(page).to have_content investment2.title expect(page).to have_content investment1.title From b3461b20511094f8899b86d7dd1d7b85108def42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Fuentes?= Date: Wed, 22 Nov 2017 16:32:50 +0100 Subject: [PATCH 5/6] final details --- .../admin/budget_investments_controller.rb | 3 ++- .../admin/budget_investments/_investments.html.erb | 2 +- spec/features/admin/budget_investments_spec.rb | 13 +++++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/app/controllers/admin/budget_investments_controller.rb b/app/controllers/admin/budget_investments_controller.rb index de2e34d84..12baf20d4 100644 --- a/app/controllers/admin/budget_investments_controller.rb +++ b/app/controllers/admin/budget_investments_controller.rb @@ -79,7 +79,8 @@ class Admin::BudgetInvestmentsController < Admin::BaseController investment.valuators.collect(&:description_or_name).join(', ') end heading_name = investment.heading.name - price = t("admin.budget_investments.index.feasibility.#{investment.feasibility}", price: investment.formatted_price) + feasibility_string = "admin.budget_investments.index.feasibility.#{investment.feasibility}" + price = t(feasibility_string, price: investment.formatted_price) valuation_finished = investment.valuation_finished? ? t('shared.yes') : t('shared.no') csv << [id, title, total_votes, administrator, valuators, heading_name, price, valuation_finished] end diff --git a/app/views/admin/budget_investments/_investments.html.erb b/app/views/admin/budget_investments/_investments.html.erb index f824d1a80..8d2a5191e 100644 --- a/app/views/admin/budget_investments/_investments.html.erb +++ b/app/views/admin/budget_investments/_investments.html.erb @@ -58,7 +58,7 @@ <%= investment.valuation_finished? ? t('shared.yes'): t('shared.no') %> <% if params[:filter] == 'selected' %>
- <% if investment.selected? %> - <%= link_to_unless investment.budget.finished?, t("admin.budget_investments.index.selected"), - toggle_selection_admin_budget_budget_investment_path(@budget, - investment, - filter: params[:filter], - page: params[:page]), - method: :patch, - remote: true, - class: "button small expanded" %> - <% elsif investment.feasible? && investment.valuation_finished? %> - <%= link_to_unless investment.budget.finished?, t("admin.budget_investments.index.select"), - toggle_selection_admin_budget_budget_investment_path(@budget, - investment, - filter: params[:filter], - page: params[:page]), - method: :patch, - remote: true, - class: "button small hollow expanded" %> + <%= options = investment_selected_link_options(investment) %> + <%= link_to toggle_selection_admin_budget_budget_investment_path(@budget, investment, filter: params[:filter], page: params[:page]), method: :patch, remote: true, class: options[:link_class] do %> + <%= options[:text] %> <% end %> - <%= options = investment_selected_link_options(investment) %> + <% options = investment_selected_link_options(investment) %> <%= link_to toggle_selection_admin_budget_budget_investment_path(@budget, investment, filter: params[:filter], page: params[:page]), method: :patch, remote: true, class: options[:link_class] do %> <%= options[:text] %> <% end %> diff --git a/spec/features/admin/budget_investments_spec.rb b/spec/features/admin/budget_investments_spec.rb index 55b5af3ce..f67e6d475 100644 --- a/spec/features/admin/budget_investments_spec.rb +++ b/spec/features/admin/budget_investments_spec.rb @@ -642,6 +642,19 @@ feature 'Admin budget investments' do expect(page).to have_content investment2.title expect(page).to have_content investment1.title end + + scenario "Downloading CSV file with applied filter" do + investment1 = create(:budget_investment, :unfeasible, budget: @budget, title: 'compatible') + investment2 = create(:budget_investment, :finished, budget: @budget, title: 'valuation_finished') + visit admin_budget_budget_investments_path(@budget, format: :csv, filter: :valuation_finished) + + header = page.response_headers['Content-Disposition'] + header.should match(/^attachment/) + header.should match(/filename="budget_investments.csv"$/) + + expect(page).to have_content investment2.title + expect(page).to_not have_content investment1.title + end end end From 29018e306226a4fceb221c07287392ee5bb7553a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Fuentes?= Date: Tue, 9 Jan 2018 11:44:44 +0100 Subject: [PATCH 6/6] changes made at the request of voodoorai2000 --- .../admin/budget_investments_controller.rb | 43 ++----------------- app/helpers/budgets_helper.rb | 10 ++++- app/models/budget/investment.rb | 41 ++++++++++++++++++ .../budget_investments/_investments.html.erb | 5 +-- .../features/admin/budget_investments_spec.rb | 39 +++++++++++++---- 5 files changed, 84 insertions(+), 54 deletions(-) diff --git a/app/controllers/admin/budget_investments_controller.rb b/app/controllers/admin/budget_investments_controller.rb index 12baf20d4..0208fccd8 100644 --- a/app/controllers/admin/budget_investments_controller.rb +++ b/app/controllers/admin/budget_investments_controller.rb @@ -1,7 +1,5 @@ class Admin::BudgetInvestmentsController < Admin::BaseController - require 'csv' - include FeatureFlags feature_flag :budgets @@ -18,7 +16,8 @@ class Admin::BudgetInvestmentsController < Admin::BaseController respond_to do |format| format.html format.csv do - send_data set_csv, filename: 'budget_investments.csv' + send_data Budget::Investment.to_csv(@investments, {headers: true}), + filename: 'budget_investments.csv' end end end @@ -52,46 +51,10 @@ class Admin::BudgetInvestmentsController < Admin::BaseController private - def set_csv - attributes = [t("admin.budget_investments.index.table_id"), - t("admin.budget_investments.index.table_title"), - t("admin.budget_investments.index.table_supports"), - t("admin.budget_investments.index.table_admin"), - t("admin.budget_investments.index.table_valuator"), - t("admin.budget_investments.index.table_geozone"), - t("admin.budget_investments.index.table_feasibility"), - t("admin.budget_investments.index.table_valuation_finished"), - t("admin.budget_investments.index.table_selection")] - csv_string = CSV.generate(headers: true) do |csv| - csv << attributes - @investments.each do |investment| - id = investment.id.to_s - title = investment.title - total_votes = investment.total_votes.to_s - administrator = if investment.administrator.present? - investment.administrator.name - else - t("admin.budget_investments.index.no_admin_assigned") - end - valuators = if investment.valuators.empty? - t("admin.budget_investments.index.no_valuators_assigned") - else - investment.valuators.collect(&:description_or_name).join(', ') - end - heading_name = investment.heading.name - feasibility_string = "admin.budget_investments.index.feasibility.#{investment.feasibility}" - price = t(feasibility_string, price: investment.formatted_price) - valuation_finished = investment.valuation_finished? ? t('shared.yes') : t('shared.no') - csv << [id, title, total_votes, administrator, valuators, heading_name, price, valuation_finished] - end - end - csv_string - end - def load_investments @investments = Budget::Investment.scoped_filter(params, @current_filter) .order(cached_votes_up: :desc, created_at: :desc) - .page(params[:page]) + @investments = @investments.page(params[:page]) unless request.format.csv? end def budget_investment_params diff --git a/app/helpers/budgets_helper.rb b/app/helpers/budgets_helper.rb index e6d9f16d4..a14b86538 100644 --- a/app/helpers/budgets_helper.rb +++ b/app/helpers/budgets_helper.rb @@ -1,11 +1,19 @@ module BudgetsHelper def csv_params - csv_params = params.clone.merge(format: :csv) + csv_params = params.clone.merge(format: :csv).symbolize_keys csv_params.delete(:page) csv_params end + def investment_selected_link(investment) + options = investment_selected_link_options(investment) + path = toggle_selection_admin_budget_budget_investment_path(@budget, + investment, filter: params[:filter], page: params[:page]) + link_options = {method: :patch, remote: true, class: options[:link_class]} + link_to options[:text], path, link_options + end + def investment_selected_link_options(investment) if investment.selected? {link_class: "button small expanded", diff --git a/app/models/budget/investment.rb b/app/models/budget/investment.rb index f40878702..4e2e5d0b0 100644 --- a/app/models/budget/investment.rb +++ b/app/models/budget/investment.rb @@ -1,5 +1,6 @@ class Budget class Investment < ActiveRecord::Base + require 'csv' include Measurable include Sanitizable include Taggable @@ -262,6 +263,46 @@ class Budget investments end + def self.to_csv(investments, options = {}) + attrs = [I18n.t("admin.budget_investments.index.table_id"), + I18n.t("admin.budget_investments.index.table_title"), + I18n.t("admin.budget_investments.index.table_supports"), + I18n.t("admin.budget_investments.index.table_admin"), + I18n.t("admin.budget_investments.index.table_valuator"), + I18n.t("admin.budget_investments.index.table_geozone"), + I18n.t("admin.budget_investments.index.table_feasibility"), + I18n.t("admin.budget_investments.index.table_valuation_finished"), + I18n.t("admin.budget_investments.index.table_selection")] + csv_string = CSV.generate(options) do |csv| + csv << attrs + investments.each do |investment| + id = investment.id.to_s + title = investment.title + total_votes = investment.total_votes.to_s + admin = if investment.administrator.present? + investment.administrator.name + else + I18n.t("admin.budget_investments.index.no_admin_assigned") + end + vals = if investment.valuators.empty? + I18n.t("admin.budget_investments.index.no_valuators_assigned") + else + investment.valuators.collect(&:description_or_name).join(', ') + end + heading_name = investment.heading.name + price_string = "admin.budget_investments.index.feasibility"\ + ".#{investment.feasibility}" + price = I18n.t(price_string, price: investment.formatted_price) + valuation_finished = investment.valuation_finished? ? + I18n.t('shared.yes') : + I18n.t('shared.no') + csv << [id, title, total_votes, admin, vals, heading_name, price, + valuation_finished] + end + end + csv_string + end + private def set_denormalized_ids diff --git a/app/views/admin/budget_investments/_investments.html.erb b/app/views/admin/budget_investments/_investments.html.erb index 8d2a5191e..75bde7002 100644 --- a/app/views/admin/budget_investments/_investments.html.erb +++ b/app/views/admin/budget_investments/_investments.html.erb @@ -58,10 +58,7 @@ <%= investment.valuation_finished? ? t('shared.yes'): t('shared.no') %> - <% options = investment_selected_link_options(investment) %> - <%= link_to toggle_selection_admin_budget_budget_investment_path(@budget, investment, filter: params[:filter], page: params[:page]), method: :patch, remote: true, class: options[:link_class] do %> - <%= options[:text] %> - <% end %> + <%= investment_selected_link(investment) %> diff --git a/spec/features/admin/budget_investments_spec.rb b/spec/features/admin/budget_investments_spec.rb index f67e6d475..c3fc69473 100644 --- a/spec/features/admin/budget_investments_spec.rb +++ b/spec/features/admin/budget_investments_spec.rb @@ -630,23 +630,44 @@ feature 'Admin budget investments' do context "Selecting csv" do scenario "Downloading CSV file" do - investment1 = create(:budget_investment, :unfeasible, budget: @budget) - investment2 = create(:budget_investment, :feasible, budget: @budget) + investment = create(:budget_investment, :feasible, budget: @budget, + price: 100) + valuator = create(:valuator, user: create(:user, username: 'Rachel', + email: 'rachel@val.org')) + investment.valuators << valuator + + admin = create(:administrator, user: create(:user, username: 'Gema')) + investment.update(administrator_id: admin.id) visit admin_budget_budget_investments_path(@budget, format: :csv) header = page.response_headers['Content-Disposition'] - header.should match(/^attachment/) - header.should match(/filename="budget_investments.csv"$/) + expect(header).to match(/^attachment/) + expect(header).to match(/filename="budget_investments.csv"$/) - expect(page).to have_content investment2.title - expect(page).to have_content investment1.title + valuators = investment.valuators.collect(&:description_or_name).join(', ') + feasibility_string = "admin.budget_investments.index"\ + ".feasibility.#{investment.feasibility}" + price = I18n.t(feasibility_string, price: investment.formatted_price) + + expect(page).to have_content investment.title + expect(page).to have_content investment.total_votes.to_s + expect(page).to have_content investment.id.to_s + expect(page).to have_content investment.heading.name + + expect(page).to have_content investment.administrator.name + expect(page).to have_content valuators + expect(page).to have_content price + expect(page).to have_content I18n.t('shared.no') end scenario "Downloading CSV file with applied filter" do - investment1 = create(:budget_investment, :unfeasible, budget: @budget, title: 'compatible') - investment2 = create(:budget_investment, :finished, budget: @budget, title: 'valuation_finished') - visit admin_budget_budget_investments_path(@budget, format: :csv, filter: :valuation_finished) + investment1 = create(:budget_investment, :unfeasible, budget: @budget, + title: 'compatible') + investment2 = create(:budget_investment, :finished, budget: @budget, + title: 'finished') + visit admin_budget_budget_investments_path(@budget, format: :csv, + filter: :valuation_finished) header = page.response_headers['Content-Disposition'] header.should match(/^attachment/)