From fcfee3a906b26ab950a0a3a2d153ffe7851e5fb0 Mon Sep 17 00:00:00 2001 From: Julian Herrero Date: Tue, 11 Dec 2018 18:21:14 +0100 Subject: [PATCH 1/5] apply missing requeriments in PR #3043 In this PR https://github.com/consul/consul/pull/3043 there were some change requests. In order to keep moving we decided to merge the PR and do the changes ourselves. --- .../site_customization/content_blocks/index.html.erb | 2 +- .../budgets/investments/_content_blocks.html.erb | 12 ++++++------ app/views/budgets/investments/_sidebar.html.erb | 1 - config/locales/en/admin.yml | 4 ++-- config/locales/es/admin.yml | 4 ++-- 5 files changed, 11 insertions(+), 12 deletions(-) diff --git a/app/views/admin/site_customization/content_blocks/index.html.erb b/app/views/admin/site_customization/content_blocks/index.html.erb index d779b130c..ccc13bcf2 100644 --- a/app/views/admin/site_customization/content_blocks/index.html.erb +++ b/app/views/admin/site_customization/content_blocks/index.html.erb @@ -54,5 +54,5 @@ <% else %>
<%= t("admin.site_customization.content_blocks.no_blocks") %> - +
<% end %> diff --git a/app/views/budgets/investments/_content_blocks.html.erb b/app/views/budgets/investments/_content_blocks.html.erb index b5996bf7a..de86b50fe 100644 --- a/app/views/budgets/investments/_content_blocks.html.erb +++ b/app/views/budgets/investments/_content_blocks.html.erb @@ -1,9 +1,9 @@ <% if @heading.allow_custom_content %> -
+
- + <% end %> diff --git a/app/views/budgets/investments/_sidebar.html.erb b/app/views/budgets/investments/_sidebar.html.erb index 9361ad503..40322dbc9 100644 --- a/app/views/budgets/investments/_sidebar.html.erb +++ b/app/views/budgets/investments/_sidebar.html.erb @@ -28,7 +28,6 @@ <%= render "shared/tag_cloud", taggable: 'budget/investment' %> <%= render 'budgets/investments/categories' %> - <% if @heading && can?(:show, @ballot) %> diff --git a/config/locales/en/admin.yml b/config/locales/en/admin.yml index 6b85afdf0..520d57698 100644 --- a/config/locales/en/admin.yml +++ b/config/locales/en/admin.yml @@ -1,6 +1,4 @@ en: - true_value: 'Yes' - false_value: 'No' admin: header: title: Administration @@ -1088,6 +1086,8 @@ en: setting_value: Value no_description: "No description" shared: + true_value: "Yes" + false_value: "No" booths_search: button: Search placeholder: Search booth by name diff --git a/config/locales/es/admin.yml b/config/locales/es/admin.yml index 784b213d0..fda2cb75f 100644 --- a/config/locales/es/admin.yml +++ b/config/locales/es/admin.yml @@ -1,6 +1,4 @@ es: - true_value: 'Si' - false_value: 'No' admin: header: title: Administración @@ -1084,6 +1082,8 @@ es: setting_value: Valor no_description: "Sin descripción" shared: + true_value: "Sí" + false_value: "No" booths_search: button: Buscar placeholder: Buscar urna por nombre From 01033e537197c77ac57ea841fcd44f0f456b09e8 Mon Sep 17 00:00:00 2001 From: Julian Herrero Date: Wed, 12 Dec 2018 11:00:16 +0100 Subject: [PATCH 2/5] change coordinates to make the map to be centered in Madrid --- db/dev_seeds/budgets.rb | 20 ++++++++++---------- spec/factories/budgets.rb | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/db/dev_seeds/budgets.rb b/db/dev_seeds/budgets.rb index cb1a17ed7..f5465cc55 100644 --- a/db/dev_seeds/budgets.rb +++ b/db/dev_seeds/budgets.rb @@ -41,30 +41,30 @@ section "Creating Budgets" do city_group.headings.create!(name: I18n.t('seeds.budgets.groups.all_city'), price: 1000000, population: 1000000, - latitude: '-40.123241', - longitude: '25.123249') + latitude: '40.416775', + longitude: '-3.703790') districts_group = budget.groups.create!(name: I18n.t('seeds.budgets.groups.districts')) districts_group.headings.create!(name: I18n.t('seeds.geozones.north_district'), price: rand(5..10) * 100000, population: 350000, - latitude: '15.234521', - longitude: '-15.234234') + latitude: '40.416775', + longitude: '-3.703790') districts_group.headings.create!(name: I18n.t('seeds.geozones.west_district'), price: rand(5..10) * 100000, population: 300000, - latitude: '14.125125', - longitude: '65.123124') + latitude: '40.416775', + longitude: '-3.703790') districts_group.headings.create!(name: I18n.t('seeds.geozones.east_district'), price: rand(5..10) * 100000, population: 200000, - latitude: '23.234234', - longitude: '-47.134124') + latitude: '40.416775', + longitude: '-3.703790') districts_group.headings.create!(name: I18n.t('seeds.geozones.central_district'), price: rand(5..10) * 100000, population: 150000, - latitude: '-26.133213', - longitude: '-10.123231') + latitude: '40.416775', + longitude: '-3.703790') end end diff --git a/spec/factories/budgets.rb b/spec/factories/budgets.rb index 6f7a0680a..da7b0f1b9 100644 --- a/spec/factories/budgets.rb +++ b/spec/factories/budgets.rb @@ -78,8 +78,8 @@ FactoryBot.define do sequence(:name) { |n| "Heading #{n}" } price 1000000 population 1234 - latitude '-25.172741' - longitude '40.127241' + latitude '40.416775' + longitude '-3.703790' trait :drafting_budget do association :group, factory: [:budget_group, :drafting_budget] From 25e1afea485c3878560fd527fdf0d0fc9577281b Mon Sep 17 00:00:00 2001 From: Julian Herrero Date: Thu, 13 Dec 2018 10:00:54 +0100 Subject: [PATCH 3/5] fix map rendering for budget headings --- app/assets/stylesheets/layout.scss | 7 +++++++ .../budgets/investments_controller.rb | 6 +----- app/models/budget/heading.rb | 6 ++++-- app/models/map_location.rb | 8 ++++++++ app/views/budgets/ballot/lines/create.js.erb | 2 ++ app/views/budgets/ballot/lines/destroy.js.erb | 2 ++ app/views/budgets/investments/_map.html.erb | 6 +++--- .../budgets/investments/_sidebar.html.erb | 4 +++- spec/features/budgets/investments_spec.rb | 16 +++++++++++++++ spec/models/budget/heading_spec.rb | 20 ++++++------------- 10 files changed, 52 insertions(+), 25 deletions(-) diff --git a/app/assets/stylesheets/layout.scss b/app/assets/stylesheets/layout.scss index 59b851e79..7f4e1bb82 100644 --- a/app/assets/stylesheets/layout.scss +++ b/app/assets/stylesheets/layout.scss @@ -879,6 +879,13 @@ footer { } } +.sidebar-map { + + .map { + z-index: -1; + } +} + .sidebar-title { border-top: 2px solid $brand; display: inline-block; diff --git a/app/controllers/budgets/investments_controller.rb b/app/controllers/budgets/investments_controller.rb index a456ff54e..c0e91b080 100644 --- a/app/controllers/budgets/investments_controller.rb +++ b/app/controllers/budgets/investments_controller.rb @@ -1,6 +1,5 @@ module Budgets class InvestmentsController < ApplicationController - OSM_DISTRICT_LEVEL_ZOOM = 12 include FeatureFlags include CommentableActions @@ -180,10 +179,7 @@ module Budgets end def load_map - @map_location = MapLocation.new - @map_location.zoom = OSM_DISTRICT_LEVEL_ZOOM - @map_location.latitude = @heading.latitude.to_f - @map_location.longitude = @heading.longitude.to_f + @map_location = MapLocation.load_from_heading(@heading) end end diff --git a/app/models/budget/heading.rb b/app/models/budget/heading.rb index 20f9aa921..50c5d3992 100644 --- a/app/models/budget/heading.rb +++ b/app/models/budget/heading.rb @@ -1,5 +1,7 @@ class Budget class Heading < ActiveRecord::Base + OSM_DISTRICT_LEVEL_ZOOM = 12.freeze + include Sluggable belongs_to :group @@ -12,9 +14,9 @@ class Budget validates :price, presence: true validates :slug, presence: true, format: /\A[a-z0-9\-_]+\z/ validates :population, numericality: { greater_than: 0 }, allow_nil: true - validates :latitude, length: { maximum: 22, minimum: 1 }, presence: true, \ + validates :latitude, length: { maximum: 22 }, allow_blank: true, \ format: /\A(-|\+)?([1-8]?\d(?:\.\d{1,})?|90(?:\.0{1,6})?)\z/ - validates :longitude, length: { maximum: 22, minimum: 1}, presence: true, \ + validates :longitude, length: { maximum: 22 }, allow_blank: true, \ format: /\A(-|\+)?((?:1[0-7]|[1-9])?\d(?:\.\d{1,})?|180(?:\.0{1,})?)\z/ delegate :budget, :budget_id, to: :group, allow_nil: true diff --git a/app/models/map_location.rb b/app/models/map_location.rb index f66d71e34..d141c167d 100644 --- a/app/models/map_location.rb +++ b/app/models/map_location.rb @@ -18,4 +18,12 @@ class MapLocation < ActiveRecord::Base } end + def self.load_from_heading(heading) + map = new + map.zoom = Budget::Heading::OSM_DISTRICT_LEVEL_ZOOM + map.latitude = heading.latitude.to_f if heading.latitude.present? + map.longitude = heading.longitude.to_f if heading.latitude.present? + map + end + end diff --git a/app/views/budgets/ballot/lines/create.js.erb b/app/views/budgets/ballot/lines/create.js.erb index b1c9f76be..6edf8a0f2 100644 --- a/app/views/budgets/ballot/lines/create.js.erb +++ b/app/views/budgets/ballot/lines/create.js.erb @@ -9,3 +9,5 @@ $("#<%= dom_id(@investment) %>_ballot").html('<%= j render("/budgets/investments investment: @investment, investment_ids: @investment_ids, ballot: @ballot %> + +App.Map.initialize(); diff --git a/app/views/budgets/ballot/lines/destroy.js.erb b/app/views/budgets/ballot/lines/destroy.js.erb index 82c303047..94120d3a9 100644 --- a/app/views/budgets/ballot/lines/destroy.js.erb +++ b/app/views/budgets/ballot/lines/destroy.js.erb @@ -10,3 +10,5 @@ $("#<%= dom_id(@investment) %>_ballot").html('<%= j render("/budgets/investments investment: @investment, investment_ids: @investment_ids, ballot: @ballot %> + +App.Map.initialize(); diff --git a/app/views/budgets/investments/_map.html.erb b/app/views/budgets/investments/_map.html.erb index af04ef639..37aa50f67 100644 --- a/app/views/budgets/investments/_map.html.erb +++ b/app/views/budgets/investments/_map.html.erb @@ -2,7 +2,7 @@
diff --git a/app/views/budgets/investments/_sidebar.html.erb b/app/views/budgets/investments/_sidebar.html.erb index 40322dbc9..e509aa17f 100644 --- a/app/views/budgets/investments/_sidebar.html.erb +++ b/app/views/budgets/investments/_sidebar.html.erb @@ -24,7 +24,9 @@ <% if @heading && !@heading.content_blocks.where(locale: I18n.locale).empty? %> <%= render 'budgets/investments/content_blocks' %> <% end %> -<%= render 'budgets/investments/map' %> +<% if @map_location&.available? %> + <%= render 'budgets/investments/map' %> +<% end %> <%= render "shared/tag_cloud", taggable: 'budget/investment' %> <%= render 'budgets/investments/categories' %> diff --git a/spec/features/budgets/investments_spec.rb b/spec/features/budgets/investments_spec.rb index 93f2f3799..641ab61fa 100644 --- a/spec/features/budgets/investments_spec.rb +++ b/spec/features/budgets/investments_spec.rb @@ -89,6 +89,22 @@ feature 'Budget Investments' do end end + scenario 'Index should show a map if heading has coordinates defined', :js do + create(:budget_investment, heading: heading) + visit budget_investments_path(budget, heading_id: heading.id) + within("#sidebar") do + expect(page).to have_css(".map_location") + end + + unlocated_heading = create(:budget_heading, name: "No Map", price: 500, group: group, + longitude: nil, latitude: nil) + create(:budget_investment, heading: unlocated_heading) + visit budget_investments_path(budget, heading_id: unlocated_heading.id) + within("#sidebar") do + expect(page).not_to have_css(".map_location") + end + end + context("Search") do scenario 'Search by text' do diff --git a/spec/models/budget/heading_spec.rb b/spec/models/budget/heading_spec.rb index edd96a8b8..816d7507e 100644 --- a/spec/models/budget/heading_spec.rb +++ b/spec/models/budget/heading_spec.rb @@ -7,6 +7,12 @@ describe Budget::Heading do it_behaves_like "sluggable", updatable_slug_trait: :drafting_budget + describe "::OSM_DISTRICT_LEVEL_ZOOM" do + it "should be defined" do + expect(Budget::Heading::OSM_DISTRICT_LEVEL_ZOOM).to be 12 + end + end + describe "name" do before do create(:budget_heading, group: group, name: 'object name') @@ -45,13 +51,6 @@ describe Budget::Heading do end describe "save latitude" do - it "Doesn't allow latitude == nil" do - expect(build(:budget_heading, group: group, name: 'Latitude is nil', population: 12412512, latitude: nil, longitude: '12.123412')).not_to be_valid - end - - it "Doesn't allow latitude == ''" do - expect(build(:budget_heading, group: group, name: 'Latitude is an empty string', population: 12412512, latitude: '', longitude: '12.123412')).not_to be_valid - end it "Doesn't allow latitude < -90" do heading = create(:budget_heading, group: group, name: 'Latitude is < -90') @@ -150,13 +149,6 @@ describe Budget::Heading do describe "save longitude" do - it "Doesn't allow longitude == nil" do - expect(build(:budget_heading, group: group, name: 'Longitude is nil', population: 12412512, latitude: '12.123412', longitude: nil)).not_to be_valid - end - - it "Doesn't allow longitude == ''" do - expect(build(:budget_heading, group: group, name: 'Longitude is an empty string', population: 12412512, latitude: '12.127412', longitude: '')).not_to be_valid - end it "Doesn't allow longitude < -180" do heading = create(:budget_heading, group: group, name: 'Longitude is < -180') From 8fb8f70efd5bb6b21a953305100b74e1e9a1eaeb Mon Sep 17 00:00:00 2001 From: Julian Herrero Date: Thu, 13 Dec 2018 10:03:30 +0100 Subject: [PATCH 4/5] cleanup (due to new CRUD for budget groups and headings) --- app/helpers/admin_helper.rb | 4 -- app/views/admin/budget_groups/create.js.erb | 2 - app/views/admin/budget_groups/update.js.erb | 7 --- .../admin/budget_headings/_errors.html.erb | 7 --- app/views/admin/budget_headings/create.js.erb | 2 - app/views/admin/budget_headings/edit.js.erb | 1 - app/views/admin/budget_headings/update.js.erb | 1 - app/views/admin/budgets/_group.html.erb | 48 --------------- app/views/admin/budgets/_group_form.html.erb | 28 --------- app/views/admin/budgets/_groups.html.erb | 21 ------- app/views/admin/budgets/_heading.html.erb | 27 --------- .../admin/budgets/_heading_form.html.erb | 58 ------------------- .../budgets/_max_headings_label.html.erb | 2 - 13 files changed, 208 deletions(-) delete mode 100644 app/views/admin/budget_groups/create.js.erb delete mode 100644 app/views/admin/budget_groups/update.js.erb delete mode 100644 app/views/admin/budget_headings/_errors.html.erb delete mode 100644 app/views/admin/budget_headings/create.js.erb delete mode 100644 app/views/admin/budget_headings/edit.js.erb delete mode 100644 app/views/admin/budget_headings/update.js.erb delete mode 100644 app/views/admin/budgets/_group.html.erb delete mode 100644 app/views/admin/budgets/_group_form.html.erb delete mode 100644 app/views/admin/budgets/_groups.html.erb delete mode 100644 app/views/admin/budgets/_heading.html.erb delete mode 100644 app/views/admin/budgets/_heading_form.html.erb delete mode 100644 app/views/admin/budgets/_max_headings_label.html.erb diff --git a/app/helpers/admin_helper.rb b/app/helpers/admin_helper.rb index afce592a9..903a1e0a3 100644 --- a/app/helpers/admin_helper.rb +++ b/app/helpers/admin_helper.rb @@ -89,10 +89,6 @@ module AdminHelper user_roles(user).join(", ") end - def display_budget_goup_form(group) - group.errors.messages.size > 0 ? "" : "display:none" - end - private def namespace diff --git a/app/views/admin/budget_groups/create.js.erb b/app/views/admin/budget_groups/create.js.erb deleted file mode 100644 index cb926a7c6..000000000 --- a/app/views/admin/budget_groups/create.js.erb +++ /dev/null @@ -1,2 +0,0 @@ -$("#<%= dom_id(@budget) %>_groups").html('<%= j render("admin/budgets/groups", groups: @groups) %>'); -App.Forms.toggleLink(); \ No newline at end of file diff --git a/app/views/admin/budget_groups/update.js.erb b/app/views/admin/budget_groups/update.js.erb deleted file mode 100644 index c4f9774ba..000000000 --- a/app/views/admin/budget_groups/update.js.erb +++ /dev/null @@ -1,7 +0,0 @@ -<% if @group.errors.any? %> - $("#group-form-<%= @group.id %>").html('<%= j render("admin/budgets/group_form", group: @group, budget: @group.budget, button_title: t("admin.budgets.form.submit"), id: "group-form-#{@group.id}", css_class: "group-toggle-#{@group.id}" ) %>'); -<% else %> - $("#group-name-<%= @group.id %>").html('<%= @group.name %>') - $("#max-heading-label-<%=@group.id%>").html('<%= j render("admin/budgets/max_headings_label", current: @group.max_votable_headings, max: @group.headings.count, group: @group) %>') - $(".group-toggle-<%= @group.id %>").toggle() -<% end %> diff --git a/app/views/admin/budget_headings/_errors.html.erb b/app/views/admin/budget_headings/_errors.html.erb deleted file mode 100644 index bb3e5482e..000000000 --- a/app/views/admin/budget_headings/_errors.html.erb +++ /dev/null @@ -1,7 +0,0 @@ -
-
    - <% errors.each do |error| %> -
  • <%= error %>
  • - <% end %> -
-
diff --git a/app/views/admin/budget_headings/create.js.erb b/app/views/admin/budget_headings/create.js.erb deleted file mode 100644 index 5d8eefb2d..000000000 --- a/app/views/admin/budget_headings/create.js.erb +++ /dev/null @@ -1,2 +0,0 @@ -$("#<%= dom_id(@budget_group) %>").html('<%= j render("admin/budgets/group", group: @budget_group, headings: @headings) %>'); -App.Forms.toggleLink(); \ No newline at end of file diff --git a/app/views/admin/budget_headings/edit.js.erb b/app/views/admin/budget_headings/edit.js.erb deleted file mode 100644 index 5f9ac48f8..000000000 --- a/app/views/admin/budget_headings/edit.js.erb +++ /dev/null @@ -1 +0,0 @@ -$("#heading-<%=@heading.id%>").html("<%= j render("admin/budgets/heading_form", group: @budget_group, budget: @budget, heading: @heading) %>"); diff --git a/app/views/admin/budget_headings/update.js.erb b/app/views/admin/budget_headings/update.js.erb deleted file mode 100644 index 6466959cd..000000000 --- a/app/views/admin/budget_headings/update.js.erb +++ /dev/null @@ -1 +0,0 @@ -$("#<%= dom_id(@budget_group) %>").html('<%= j render("admin/budgets/group", group: @budget_group, headings: @budget_group.headings) %>'); diff --git a/app/views/admin/budgets/_group.html.erb b/app/views/admin/budgets/_group.html.erb deleted file mode 100644 index e4b313207..000000000 --- a/app/views/admin/budgets/_group.html.erb +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - <% if headings.present? %> - - - - - - - - <% end %> - - - - - <% if headings.blank? %> - - - - <% end %> - - - - - - <% headings.each do |heading| %> - <%= render "admin/budgets/heading", group: group, budget: @budget, heading: heading %> - <% end %> - -
- <%= content_tag(:span, group.name, class:"group-toggle-#{group.id}", id:"group-name-#{group.id}") %> - - <%= content_tag(:span, (render 'admin/budgets/max_headings_label', current: group.max_votable_headings, max: group.headings.count, group: group if group.max_votable_headings), class:"small group-toggle-#{group.id}", id:"max-heading-label-#{group.id}") %> - - <%= render 'admin/budgets/group_form', budget: @budget, group: group, id: "group-form-#{group.id}", button_title: t("admin.budgets.form.submit"), css_class: "group-toggle-#{group.id}" %> - <%= link_to t("admin.budgets.form.edit_group"), "#", class: "button float-right js-toggle-link hollow", data: { "toggle-selector" => ".group-toggle-#{group.id}" } %> - <%= link_to t("admin.budgets.form.add_heading"), "#", class: "button float-right js-toggle-link", data: { "toggle-selector" => "#group-#{group.id}-new-heading-form" } %> -
<%= t("admin.budgets.form.table_heading") %><%= t("admin.budgets.form.table_amount") %><%= t("admin.budgets.form.table_population") %><%= t("admin.budgets.form.table_allow_custom_contents") %><%= t("admin.actions.actions") %>
-
- <%= t("admin.budgets.form.no_heading") %> -
-
diff --git a/app/views/admin/budgets/_group_form.html.erb b/app/views/admin/budgets/_group_form.html.erb deleted file mode 100644 index 0bb83b1b7..000000000 --- a/app/views/admin/budgets/_group_form.html.erb +++ /dev/null @@ -1,28 +0,0 @@ -<%= form_for [:admin, budget, group], html: {id: id, style: display_budget_goup_form(group), class: css_class}, remote: true do |f| %> - - <%= f.label :name, t("admin.budgets.form.group") %> - -
- <%= f.text_field :name, - label: false, - maxlength: 50, - placeholder: t("admin.budgets.form.group"), - class: "input-group-field" %> - - <% if group.persisted? %> -
- <%= f.label :name, t("admin.budgets.form.max_votable_headings") %> - - <%= f.select :max_votable_headings, - (1..group.headings.count), - label: false, - placeholder: t("admin.budgets.form.max_votable_headings"), - class: "input-group-field" %> -
- <% end %> - -
- <%= f.submit button_title, class: "button success" %> -
-
-<% end %> diff --git a/app/views/admin/budgets/_groups.html.erb b/app/views/admin/budgets/_groups.html.erb deleted file mode 100644 index dbee9576c..000000000 --- a/app/views/admin/budgets/_groups.html.erb +++ /dev/null @@ -1,21 +0,0 @@ -

<%= t('admin.budgets.show.groups', count: groups.count) %>

-<%= link_to t("admin.budgets.form.add_group"), "#", class: "button float-right js-toggle-link", data: { "toggle-selector" => "#new-group-form" } %> - -<% if groups.blank? %> -
- <%= t("admin.budgets.form.no_groups") %> -
-<% end %> - -<%= render 'admin/budgets/group_form', - budget: @budget, - group: Budget::Group.new, - id: "new-group-form", - button_title: t("admin.budgets.form.create_group"), - css_class: '' %> - -<% groups.each do |group| %> -
- <%= render "admin/budgets/group", group: group, headings: group.headings.order(:id) %> -
-<% end %> diff --git a/app/views/admin/budgets/_heading.html.erb b/app/views/admin/budgets/_heading.html.erb deleted file mode 100644 index e06bb96d1..000000000 --- a/app/views/admin/budgets/_heading.html.erb +++ /dev/null @@ -1,27 +0,0 @@ - - - <%= heading.name %> - - - <%= heading.budget.formatted_heading_price(heading) %> - - - <%= heading.population %> - - - <%= heading.allow_custom_content ? t("true_value") : t("false_value") %> - - - <%= link_to t("admin.actions.edit"), - edit_admin_budget_budget_group_budget_heading_path(budget_id: group.budget.id, budget_group_id: group.id, id: heading.id), - class: "button hollow", - remote: true %> - <% if heading.can_be_deleted? %> - <%= link_to t('admin.administrators.administrator.delete'), - #admin_budget_budget_group_budget_headings_path(group.budget.id, group.id), - [:admin, group.budget, group, heading], - method: :delete, - class: "button hollow alert" %> - <% end %> - - diff --git a/app/views/admin/budgets/_heading_form.html.erb b/app/views/admin/budgets/_heading_form.html.erb deleted file mode 100644 index a102b421a..000000000 --- a/app/views/admin/budgets/_heading_form.html.erb +++ /dev/null @@ -1,58 +0,0 @@ -<%= form_for [:admin, budget, group, heading], remote: true do |f| %> - <%= render 'shared/errors', resource: heading %> - <%= f.text_field :name, - label: t("admin.budgets.form.heading"), - maxlength: 50, - placeholder: t("admin.budgets.form.heading") %> - -
-
- <%= f.text_field :price, - label: t("admin.budgets.form.amount"), - maxlength: 8, - placeholder: t("admin.budgets.form.amount") %> -
-
-
-
-

- <%= t("admin.budgets.form.population_help_text") %> -

- <%= f.text_field :population, - label: t("admin.budgets.form.population"), - maxlength: 8, - placeholder: t("admin.budgets.form.population"), - data: {toggle_focus: "population-info"}, - aria: {describedby: "budgets-population-help-text"} %> -
-
- -
-
-
-
- <%= f.text_field :latitude, - label: t("admin.budgets.form.latitude"), - maxlength: 22, - placeholder: "latitude" %> -
-
-
-
- <%= f.text_field :longitude, - label: t("admin.budgets.form.longitude"), - maxlength: 22, - placeholder: "longitude" %> -
-
- -
-
- <%= f.check_box :allow_custom_content, label: t('admin.budgets.form.allow_content_block') %> -
-
- - <%= f.submit t("admin.budgets.form.save_heading"), class: "button success" %> -<% end %> diff --git a/app/views/admin/budgets/_max_headings_label.html.erb b/app/views/admin/budgets/_max_headings_label.html.erb deleted file mode 100644 index f2c438d4f..000000000 --- a/app/views/admin/budgets/_max_headings_label.html.erb +++ /dev/null @@ -1,2 +0,0 @@ -<%= t("admin.budgets.form.max_votable_headings")%> -<%= t("admin.budgets.form.current_of_max_headings", current: current, max: max) %> From 6439be44f120e82b4d9240a86217e68463dc9304 Mon Sep 17 00:00:00 2001 From: Julian Herrero Date: Thu, 13 Dec 2018 10:34:01 +0100 Subject: [PATCH 5/5] change CRUD for budget groups and headings To make it more consistent with the rest of the Admin panel, the CRUD for budget groups and headings has been changed from the old "all-in-one" form to a separate form for each resource. --- .../admin/budget_groups_controller.rb | 52 ++++- .../admin/budget_headings_controller.rb | 63 ++++-- app/controllers/admin/budgets_controller.rb | 7 +- .../budgets/ballot/lines_controller.rb | 8 + app/views/admin/budget_groups/_form.html.erb | 18 ++ .../admin/budget_groups/_header.html.erb | 5 + app/views/admin/budget_groups/edit.html.erb | 3 + app/views/admin/budget_groups/index.html.erb | 44 ++++ app/views/admin/budget_groups/new.html.erb | 3 + .../admin/budget_headings/_form.html.erb | 40 ++++ .../admin/budget_headings/_header.html.erb | 5 + app/views/admin/budget_headings/edit.html.erb | 3 + .../admin/budget_headings/index.html.erb | 47 ++++ app/views/admin/budget_headings/new.html.erb | 3 + app/views/admin/budgets/index.html.erb | 4 +- app/views/admin/budgets/show.html.erb | 4 +- config/locales/en/admin.yml | 74 +++--- config/locales/es/admin.yml | 71 +++--- config/routes/admin.rb | 4 +- spec/features/admin/budget_groups_spec.rb | 210 +++++++++++++----- spec/features/admin/budget_headings_spec.rb | 208 +++++++++++++++++ spec/features/admin/budgets_spec.rb | 103 --------- spec/features/budgets/ballots_spec.rb | 28 +++ 23 files changed, 757 insertions(+), 250 deletions(-) create mode 100644 app/views/admin/budget_groups/_form.html.erb create mode 100644 app/views/admin/budget_groups/_header.html.erb create mode 100644 app/views/admin/budget_groups/edit.html.erb create mode 100644 app/views/admin/budget_groups/index.html.erb create mode 100644 app/views/admin/budget_groups/new.html.erb create mode 100644 app/views/admin/budget_headings/_form.html.erb create mode 100644 app/views/admin/budget_headings/_header.html.erb create mode 100644 app/views/admin/budget_headings/edit.html.erb create mode 100644 app/views/admin/budget_headings/index.html.erb create mode 100644 app/views/admin/budget_headings/new.html.erb create mode 100644 spec/features/admin/budget_headings_spec.rb diff --git a/app/controllers/admin/budget_groups_controller.rb b/app/controllers/admin/budget_groups_controller.rb index d8048de48..b6def19ed 100644 --- a/app/controllers/admin/budget_groups_controller.rb +++ b/app/controllers/admin/budget_groups_controller.rb @@ -2,20 +2,60 @@ class Admin::BudgetGroupsController < Admin::BaseController include FeatureFlags feature_flag :budgets + before_action :load_budget + before_action :load_group, except: [:index, :new, :create] + + def index + @groups = @budget.groups.order(:id) + end + + def new + @group = @budget.groups.new + end + + def edit + end + def create - @budget = Budget.find(params[:budget_id]) - @budget.groups.create(budget_group_params) - @groups = @budget.groups.includes(:headings) + @group = @budget.groups.new(budget_group_params) + if @group.save + redirect_to groups_index, notice: t("admin.budget_groups.create.notice") + else + render :new + end end def update - @budget = Budget.find(params[:budget_id]) - @group = @budget.groups.find(params[:id]) - @group.update(budget_group_params) + if @group.update(budget_group_params) + redirect_to groups_index, notice: t("admin.budget_groups.update.notice") + else + render :edit + end + end + + def destroy + if @group.headings.any? + redirect_to groups_index, alert: t("admin.budget_groups.destroy.unable_notice") + else + @group.destroy + redirect_to groups_index, notice: t("admin.budget_groups.destroy.success_notice") + end end private + def load_budget + @budget = Budget.includes(:groups).find(params[:budget_id]) + end + + def load_group + @group = @budget.groups.find(params[:id]) + end + + def groups_index + admin_budget_groups_path(@budget) + end + def budget_group_params params.require(:budget_group).permit(:name, :max_votable_headings) end diff --git a/app/controllers/admin/budget_headings_controller.rb b/app/controllers/admin/budget_headings_controller.rb index 6af316eb4..8143f3690 100644 --- a/app/controllers/admin/budget_headings_controller.rb +++ b/app/controllers/admin/budget_headings_controller.rb @@ -2,36 +2,65 @@ class Admin::BudgetHeadingsController < Admin::BaseController include FeatureFlags feature_flag :budgets - def create - @budget = Budget.find(params[:budget_id]) - @budget_group = @budget.groups.find(params[:budget_group_id]) - @budget_group.headings.create(budget_heading_params) - @headings = @budget_group.headings + before_action :load_budget + before_action :load_group + before_action :load_heading, except: [:index, :new, :create] + + def index + @headings = @group.headings.order(:id) + end + + def new + @heading = @group.headings.new end def edit - @budget = Budget.find(params[:budget_id]) - @budget_group = @budget.groups.find(params[:budget_group_id]) - @heading = Budget::Heading.find(params[:id]) + end + + def create + @heading = @group.headings.new(budget_heading_params) + if @heading.save + redirect_to headings_index, notice: t('admin.budget_headings.create.notice') + else + render :new + end end def update - @budget = Budget.find(params[:budget_id]) - @budget_group = @budget.groups.find(params[:budget_group_id]) - @heading = Budget::Heading.find(params[:id]) - @heading.assign_attributes(budget_heading_params) - render :edit unless @heading.save + if @heading.update(budget_heading_params) + redirect_to headings_index, notice: t('admin.budget_headings.update.notice') + else + render :edit + end end def destroy - @heading = Budget::Heading.find(params[:id]) - @heading.destroy - @budget = Budget.find(params[:budget_id]) - redirect_to admin_budget_path(@budget) + if @heading.can_be_deleted? + @heading.destroy + redirect_to headings_index, notice: t('admin.budget_headings.destroy.success_notice') + else + redirect_to headings_index, alert: t('admin.budget_headings.destroy.unable_notice') + end end private + def load_budget + @budget = Budget.includes(:groups).find(params[:budget_id]) + end + + def load_group + @group = @budget.groups.find(params[:group_id]) + end + + def load_heading + @heading = @group.headings.find(params[:id]) + end + + def headings_index + admin_budget_group_headings_path(@budget, @group) + end + def budget_heading_params params.require(:budget_heading).permit(:name, :price, :population, :allow_custom_content, :latitude, :longitude) end diff --git a/app/controllers/admin/budgets_controller.rb b/app/controllers/admin/budgets_controller.rb index 04b8ea0b2..dab8dcad2 100644 --- a/app/controllers/admin/budgets_controller.rb +++ b/app/controllers/admin/budgets_controller.rb @@ -11,12 +11,13 @@ class Admin::BudgetsController < Admin::BaseController end def show - @budget = Budget.includes(groups: :headings).find(params[:id]) end - def new; end + def new + end - def edit; end + def edit + end def calculate_winners return unless @budget.balloting_process? diff --git a/app/controllers/budgets/ballot/lines_controller.rb b/app/controllers/budgets/ballot/lines_controller.rb index d5d5468a2..9e693064c 100644 --- a/app/controllers/budgets/ballot/lines_controller.rb +++ b/app/controllers/budgets/ballot/lines_controller.rb @@ -17,6 +17,7 @@ module Budgets def create load_investment load_heading + load_map @ballot.add_investment(@investment) end @@ -24,6 +25,7 @@ module Budgets def destroy @investment = @line.investment load_heading + load_map @line.destroy load_investments @@ -74,6 +76,12 @@ module Budgets @ballot_referer = session[:ballot_referer] end + def load_map + @investments ||= [] + @investments_map_coordinates = MapLocation.where(investment: @investments).map(&:json_data) + @map_location = MapLocation.load_from_heading(@heading) + end + end end end diff --git a/app/views/admin/budget_groups/_form.html.erb b/app/views/admin/budget_groups/_form.html.erb new file mode 100644 index 000000000..5da9493d8 --- /dev/null +++ b/app/views/admin/budget_groups/_form.html.erb @@ -0,0 +1,18 @@ +
+ <%= form_for [:admin, @budget, @group], url: path do |f| %> + + <%= f.text_field :name, + label: t("admin.budget_groups.form.name"), + maxlength: 50, + placeholder: t("admin.budget_groups.form.name") %> + + <% if @group.persisted? %> + <%= f.select :max_votable_headings, + (1..@group.headings.count), + label: t("admin.budget_groups.max_votable_headings"), + placeholder: t("admin.budget_groups.max_votable_headings") %> + <% end %> + + <%= f.submit t("admin.budget_groups.form.#{action}"), class: "button success" %> + <% end %> +
diff --git a/app/views/admin/budget_groups/_header.html.erb b/app/views/admin/budget_groups/_header.html.erb new file mode 100644 index 000000000..32962bd93 --- /dev/null +++ b/app/views/admin/budget_groups/_header.html.erb @@ -0,0 +1,5 @@ +<%= back_link_to admin_budget_groups_path(@budget) %> + +

<%= @budget.name %>

+ +

<%= t("admin.budget_groups.form.#{action}") %>

diff --git a/app/views/admin/budget_groups/edit.html.erb b/app/views/admin/budget_groups/edit.html.erb new file mode 100644 index 000000000..4ed1ad7f9 --- /dev/null +++ b/app/views/admin/budget_groups/edit.html.erb @@ -0,0 +1,3 @@ +<%= render "header", action: "edit" %> + +<%= render "form", path: admin_budget_group_path(@budget, @group), action: "edit" %> diff --git a/app/views/admin/budget_groups/index.html.erb b/app/views/admin/budget_groups/index.html.erb new file mode 100644 index 000000000..506698fb7 --- /dev/null +++ b/app/views/admin/budget_groups/index.html.erb @@ -0,0 +1,44 @@ +

<%= @budget.name %>

+ +<%= link_to t("admin.budget_groups.form.create"), + new_admin_budget_group_path, + class: "button float-right" %> + +<% if @groups.any? %> +

<%= t("admin.budget_groups.amount", count: @groups.count) %>

+ + + + + + + + + + + + <% @groups.each do |group| %> + + + + + + + + <% end %> + +
<%= t("admin.budget_groups.name") %><%= t("admin.budget_groups.max_votable_headings") %><%= t("admin.budget_groups.headings_name") %><%= t("admin.budget_groups.headings_edit") %><%= t("admin.actions.actions") %>
<%= link_to group.name, edit_admin_budget_group_path(@budget, group) %><%= group.max_votable_headings %><%= group.headings.count %><%= link_to t("admin.budget_groups.headings_manage"), + admin_budget_group_headings_path(@budget, group) %> + <%= link_to t("admin.actions.edit"), + edit_admin_budget_group_path(@budget, group), + class: "button hollow" %> + <%= link_to t("admin.actions.delete"), + admin_budget_group_path(@budget, group), + method: :delete, + class: "button hollow alert" %> +
+<% else %> +
+ <%= t("admin.budget_groups.no_groups") %> +
+<% end %> diff --git a/app/views/admin/budget_groups/new.html.erb b/app/views/admin/budget_groups/new.html.erb new file mode 100644 index 000000000..461427d44 --- /dev/null +++ b/app/views/admin/budget_groups/new.html.erb @@ -0,0 +1,3 @@ +<%= render "header", action: "create" %> + +<%= render "form", path: admin_budget_groups_path(@budget), action: "create" %> diff --git a/app/views/admin/budget_headings/_form.html.erb b/app/views/admin/budget_headings/_form.html.erb new file mode 100644 index 000000000..ebc5aa2ae --- /dev/null +++ b/app/views/admin/budget_headings/_form.html.erb @@ -0,0 +1,40 @@ +
+ + <%= form_for [:admin, @budget, @group, @heading], url: path do |f| %> + + <%= f.text_field :name, + label: t("admin.budget_headings.form.name"), + maxlength: 50, + placeholder: t("admin.budget_headings.form.name") %> + + <%= f.text_field :price, + label: t("admin.budget_headings.form.amount"), + maxlength: 8, + placeholder: t("admin.budget_headings.form.amount") %> + + <%= f.label :population, t("admin.budget_headings.form.population") %> +

+ <%= t("admin.budget_headings.form.population_info") %> +

+ <%= f.text_field :population, + label: false, + maxlength: 8, + placeholder: t("admin.budget_headings.form.population"), + data: {toggle_focus: "population-info"}, + aria: {describedby: "budgets-population-help-text"} %> + + <%= f.text_field :latitude, + label: t("admin.budget_headings.form.latitude"), + maxlength: 22, + placeholder: "latitude" %> + + <%= f.text_field :longitude, + label: t("admin.budget_headings.form.longitude"), + maxlength: 22, + placeholder: "longitude" %> + + <%= f.check_box :allow_custom_content, label: t("admin.budget_headings.form.allow_content_block") %> + + <%= f.submit t("admin.budget_headings.form.#{action}"), class: "button success" %> + <% end %> +
diff --git a/app/views/admin/budget_headings/_header.html.erb b/app/views/admin/budget_headings/_header.html.erb new file mode 100644 index 000000000..dde0f14ec --- /dev/null +++ b/app/views/admin/budget_headings/_header.html.erb @@ -0,0 +1,5 @@ +<%= back_link_to admin_budget_group_headings_path(@budget, @group) %> + +

<%= "#{@budget.name} / #{@group.name}" %>

+ +

<%= t("admin.budget_headings.form.#{action}") %>

diff --git a/app/views/admin/budget_headings/edit.html.erb b/app/views/admin/budget_headings/edit.html.erb new file mode 100644 index 000000000..a01fa70a4 --- /dev/null +++ b/app/views/admin/budget_headings/edit.html.erb @@ -0,0 +1,3 @@ +<%= render "header", action: "edit" %> + +<%= render "form", path: admin_budget_group_heading_path(@budget, @group, @heading), action: "edit" %> diff --git a/app/views/admin/budget_headings/index.html.erb b/app/views/admin/budget_headings/index.html.erb new file mode 100644 index 000000000..a5a2a75af --- /dev/null +++ b/app/views/admin/budget_headings/index.html.erb @@ -0,0 +1,47 @@ +<%= back_link_to admin_budget_groups_path(@budget) %> + +
+

<%= "#{@budget.name} / #{@group.name}" %>

+<%= link_to t("admin.budget_headings.form.create"), + new_admin_budget_group_heading_path, + class: "button float-right" %> + +<% if @headings.any? %> +

<%= t("admin.budget_headings.amount", count: @headings.count) %>

+ + + + + + + + + + + + <% @headings.each do |heading| %> + + + + + + + + <% end %> + +
<%= t("admin.budget_headings.name") %><%= t("admin.budget_headings.form.amount") %><%= t("admin.budget_headings.form.population") %><%= t("admin.budget_headings.form.allow_content_block") %><%= t("admin.actions.actions") %>
<%= link_to heading.name, edit_admin_budget_group_heading_path(@budget, @group, heading) %><%= @budget.formatted_heading_price(heading) %><%= heading.population %> + <%= heading.allow_custom_content ? t("admin.shared.true_value") : t("admin.shared.false_value") %> + + <%= link_to t("admin.actions.edit"), + edit_admin_budget_group_heading_path(@budget, @group, heading), + class: "button hollow" %> + <%= link_to t("admin.actions.delete"), + admin_budget_group_heading_path(@budget, @group, heading), + method: :delete, + class: "button hollow alert" %> +
+<% else %> +
+ <%= t("admin.budget_headings.no_headings") %> +
+<% end %> diff --git a/app/views/admin/budget_headings/new.html.erb b/app/views/admin/budget_headings/new.html.erb new file mode 100644 index 000000000..0566a5a5e --- /dev/null +++ b/app/views/admin/budget_headings/new.html.erb @@ -0,0 +1,3 @@ +<%= render "header", action: "create" %> + +<%= render "form", path: admin_budget_group_headings_path(@budget, @group), action: "create" %> diff --git a/app/views/admin/budgets/index.html.erb b/app/views/admin/budgets/index.html.erb index f90baac51..a7d44fdcb 100644 --- a/app/views/admin/budgets/index.html.erb +++ b/app/views/admin/budgets/index.html.erb @@ -23,7 +23,7 @@ <% @budgets.each do |budget| %> - <%= budget.name %> + <%= link_to budget.name, admin_budget_path(budget) %> <%= t("budgets.phase.#{budget.phase}") %> @@ -34,7 +34,7 @@ class: "button hollow medium" %> - <%= link_to t("admin.budgets.index.edit_groups"), admin_budget_path(budget) %> + <%= link_to t("admin.budgets.index.edit_groups"), admin_budget_groups_path(budget) %> <%= link_to t("admin.budgets.index.edit_budget"), edit_admin_budget_path(budget) %> diff --git a/app/views/admin/budgets/show.html.erb b/app/views/admin/budgets/show.html.erb index 063b025ea..2e46f79c8 100644 --- a/app/views/admin/budgets/show.html.erb +++ b/app/views/admin/budgets/show.html.erb @@ -2,6 +2,4 @@

<%= @budget.name %>

-
- <%= render "groups", groups: @budget.groups.order(:id) %> -
+<%= render "form" %> diff --git a/config/locales/en/admin.yml b/config/locales/en/admin.yml index 520d57698..2db1da6b0 100644 --- a/config/locales/en/admin.yml +++ b/config/locales/en/admin.yml @@ -107,38 +107,56 @@ en: unable_notice: You cannot destroy a Budget that has associated investments new: title: New participatory budget - show: - groups: - one: 1 Group of budget headings - other: "%{count} Groups of budget headings" - form: - group: Group name - no_groups: No groups created yet. Each user will be able to vote in only one heading per group. - add_group: Add new group - create_group: Create group - edit_group: Edit group - submit: Save group - heading: Heading name - add_heading: Add heading - amount: Amount - population: "Population (optional)" - population_help_text: "This data is used exclusively to calculate the participation statistics" - save_heading: Save heading - no_heading: This group has no assigned heading. - table_heading: Heading - table_amount: Amount - table_population: Population - table_allow_custom_contents: Custom content allowed - population_info: "Budget Heading population field is used for Statistic purposes at the end of the Budget to show for each Heading that represents an area with population what percentage voted. The field is optional so you can leave it empty if it doesn't apply." - max_votable_headings: "Maximum number of headings in which a user can vote" - current_of_max_headings: "%{current} of %{max}" - allow_content_block: Allow content block - latitude: Latitude - longitude: Longitude winners: calculate: Calculate Winner Investments calculated: Winners being calculated, it may take a minute. recalculate: Recalculate Winner Investments + budget_groups: + name: "Name" + headings_name: "Headings" + headings_edit: "Edit Headings" + headings_manage: "Manage headings" + max_votable_headings: "Maximum number of headings in which a user can vote" + no_groups: "No groups created yet. Each user will be able to vote in only one heading per group." + amount: + one: "There is 1 group" + other: "There are %{count} groups" + create: + notice: "Group created successfully!" + update: + notice: "Group updated successfully" + destroy: + success_notice: "Group deleted successfully" + unable_notice: "You cannot destroy a Group that has associated headings" + form: + create: "Create new group" + edit: "Edit group" + name: "Group name" + submit: "Save group" + budget_headings: + name: "Name" + no_headings: "No headings created yet. Each user will be able to vote in only one heading per group." + amount: + one: "There is 1 heading" + other: "There are %{count} headings" + create: + notice: "Heading created successfully!" + update: + notice: "Heading updated successfully" + destroy: + success_notice: "Heading deleted successfully" + unable_notice: "You cannot destroy a Heading that has associated investments" + form: + name: "Heading name" + amount: "Amount" + population: "Population (optional)" + population_info: "Budget Heading population field is used for Statistic purposes at the end of the Budget to show for each Heading that represents an area with population what percentage voted. The field is optional so you can leave it empty if it doesn't apply." + latitude: "Latitude" + longitude: "Longitude" + allow_content_block: "Allow content block" + create: "Create new heading" + edit: "Edit heading" + submit: "Save heading" budget_phases: edit: start_date: Start date diff --git a/config/locales/es/admin.yml b/config/locales/es/admin.yml index fda2cb75f..b03fc5d04 100644 --- a/config/locales/es/admin.yml +++ b/config/locales/es/admin.yml @@ -107,35 +107,56 @@ es: unable_notice: No se puede eliminar un presupuesto con proyectos asociados new: title: Nuevo presupuesto ciudadano - show: - groups: - one: 1 Grupo de partidas presupuestarias - other: "%{count} Grupos de partidas presupuestarias" - form: - group: Nombre del grupo - no_groups: No hay grupos creados todavía. Cada usuario podrá votar en una sola partida de cada grupo. - add_group: Añadir nuevo grupo - create_group: Crear grupo - edit_group: Editar grupo - submit: Guardar grupo - heading: Nombre de la partida - add_heading: Añadir partida - amount: Cantidad - population: "Población (opcional)" - population_help_text: "Este dato se utiliza exclusivamente para calcular las estadísticas de participación" - save_heading: Guardar partida - no_heading: Este grupo no tiene ninguna partida asignada. - table_heading: Partida - table_amount: Cantidad - table_population: Población - population_info: "El campo población de las partidas presupuestarias se usa con fines estadísticos únicamente, con el objetivo de mostrar el porcentaje de votos habidos en cada partida que represente un área con población. Es un campo opcional, así que puedes dejarlo en blanco si no aplica." - max_votable_headings: "Máximo número de partidas en que un usuario puede votar" - current_of_max_headings: "%{current} de %{max}" - allow_content_block: Permite bloque de contenidos winners: calculate: Calcular proyectos ganadores calculated: Calculando ganadores, puede tardar un minuto. recalculate: Recalcular propuestas ganadoras + budget_groups: + name: "Nombre" + headings_name: "Partidas" + headings_edit: "Editar Partidas" + headings_manage: "Gestionar partidas" + max_votable_headings: "Máximo número de partidas en que un usuario puede votar" + no_groups: "No hay grupos creados todavía. Cada usuario podrá votar en una sola partida de cada grupo." + amount: + one: "Hay 1 grupo de partidas presupuestarias" + other: "Hay %{count} grupos de partidas presupuestarias" + create: + notice: "¡Grupo creado con éxito!" + update: + notice: "Grupo actualizado" + destroy: + success_notice: "Grupo eliminado correctamente" + unable_notice: "No se puede eliminar un grupo con partidas asociadas" + form: + create: "Crear nuevo grupo" + edit: "Editar grupo" + name: "Nombre del grupo" + submit: "Guardar grupo" + budget_headings: + name: "Nombre" + no_headings: "No hay partidas creadas todavía. Cada usuario podrá votar en una sola partida de cada grupo." + amount: + one: "Hay 1 partida presupuestarias" + other: "Hay %{count} partidas presupuestarias" + create: + notice: "¡Partida presupuestaria creada con éxito!" + update: + notice: "Partida presupuestaria actualizada" + destroy: + success_notice: "Partida presupuestaria eliminada correctamente" + unable_notice: "No se puede eliminar una partida presupuestaria con proyectos asociados" + form: + name: "Nombre de la partida" + amount: "Cantidad" + population: "Población (opcional)" + population_info: "El campo población de las partidas presupuestarias se usa con fines estadísticos únicamente, con el objetivo de mostrar el porcentaje de votos habidos en cada partida que represente un área con población. Es un campo opcional, así que puedes dejarlo en blanco si no aplica." + latitude: "Latitud" + longitude: "Longitud" + allow_content_block: "Permitir bloque de contenidos" + create: "Crear nueva partida" + edit: "Editar partida" + submit: "Guardar partida" budget_phases: edit: start_date: Fecha de Inicio diff --git a/config/routes/admin.rb b/config/routes/admin.rb index a6ccf2de3..caa49f5fb 100644 --- a/config/routes/admin.rb +++ b/config/routes/admin.rb @@ -57,8 +57,8 @@ namespace :admin do put :calculate_winners end - resources :budget_groups do - resources :budget_headings + resources :groups, except: [:show], controller: "budget_groups" do + resources :headings, except: [:show], controller: "budget_headings" end resources :budget_investments, only: [:index, :show, :edit, :update] do diff --git a/spec/features/admin/budget_groups_spec.rb b/spec/features/admin/budget_groups_spec.rb index d69867b8c..b3e6d5eaa 100644 --- a/spec/features/admin/budget_groups_spec.rb +++ b/spec/features/admin/budget_groups_spec.rb @@ -1,89 +1,177 @@ require 'rails_helper' -feature 'Admin can change the groups name' do +feature "Admin budget groups" do - let(:budget) { create(:budget, phase: 'drafting') } - let(:group) { create(:budget_group, budget: budget) } + let(:budget) { create(:budget, phase: "drafting") } background do admin = create(:administrator) login_as(admin.user) end - scenario "Show button" do - visit admin_budget_path(group.budget) - - within("#budget_group_#{group.id}") do - expect(page).to have_content('Edit group') - end - end - - scenario "Change name" do - group.update(name: 'Google') - expect(group.name).to eq('Google') - end - - scenario "Can change name when the budget isn't drafting, but the slug remains" do - old_slug = group.slug - budget.update(phase: 'reviewing') - group.update(name: 'Google') - - expect(group.name).to eq('Google') - expect(group.slug).to eq old_slug - end - - scenario "Can't repeat names" do - budget.groups << create(:budget_group, name: 'group_name') - group.name = 'group_name' - - expect(group).not_to be_valid - expect(group.errors.size).to eq(1) - end - - context "Maximum votable headings" do + context "Feature flag" do background do - 3.times { create(:budget_heading, group: group) } + Setting["feature.budgets"] = nil end - scenario "Defaults to 1 heading per group", :js do - visit admin_budget_path(group.budget) + after do + Setting["feature.budgets"] = true + end - expect(page).to have_content('Maximum number of headings in which a user can vote 1 of 3') + scenario "Disabled with a feature flag" do + expect { visit admin_budget_groups_path(budget) }.to raise_exception(FeatureFlags::FeatureDisabled) + end - within("#budget_group_#{group.id}") do - click_link 'Edit group' + end - expect(page).to have_select('budget_group_max_votable_headings', selected: '1') + context "Index" do + + scenario "Displaying no groups for budget" do + visit admin_budget_groups_path(budget) + + expect(page).to have_content "No groups created yet. Each user will be able to vote in only one heading per group." + end + + scenario "Displaying groups" do + group1 = create(:budget_group, budget: budget) + + group2 = create(:budget_group, budget: budget) + create(:budget_heading, group: group2) + + group3 = create(:budget_group, budget: budget, max_votable_headings: 2) + 3.times { create(:budget_heading, group: group3) } + + visit admin_budget_groups_path(budget) + expect(page).to have_content "There are 3 groups" + + within "#budget_group_#{group1.id}" do + expect(page).to have_content(group1.name) + expect(page).to have_content(group1.max_votable_headings) + expect(page).to have_content(group1.headings.count) + expect(page).to have_link "Manage headings", href: admin_budget_group_headings_path(budget, group1) + end + + within "#budget_group_#{group2.id}" do + expect(page).to have_content(group2.name) + expect(page).to have_content(group2.max_votable_headings) + expect(page).to have_content(group2.headings.count) + expect(page).to have_link "Manage headings", href: admin_budget_group_headings_path(budget, group2) + end + + within "#budget_group_#{group3.id}" do + expect(page).to have_content(group3.name) + expect(page).to have_content(group3.max_votable_headings) + expect(page).to have_content(group3.headings.count) + expect(page).to have_link "Manage headings", href: admin_budget_group_headings_path(budget, group3) end end - scenario "Update", :js do - visit admin_budget_path(group.budget) + scenario "Delete a group without headings" do + group = create(:budget_group, budget: budget) - within("#budget_group_#{group.id}") do - click_link 'Edit group' + visit admin_budget_groups_path(budget) + within("#budget_group_#{group.id}") { click_link "Delete" } - select '2', from: 'budget_group_max_votable_headings' - click_button 'Save group' - end - - expect(page).to have_content('Maximum number of headings in which a user can vote 2 of 3') - - within("#budget_group_#{group.id}") do - click_link 'Edit group' - - expect(page).to have_select('budget_group_max_votable_headings', selected: '2') - end + expect(page).to have_content "Group deleted successfully" + expect(page).not_to have_selector "#budget_group_#{group.id}" end - scenario "Do not display maximum votable headings' select in new form", :js do - visit admin_budget_path(group.budget) + scenario "Try to delete a group with headings" do + group = create(:budget_group, budget: budget) + create(:budget_heading, group: group) - click_link 'Add new group' + visit admin_budget_groups_path(budget) + within("#budget_group_#{group.id}") { click_link "Delete" } - expect(page).to have_field('budget_group_name') - expect(page).not_to have_field('budget_group_max_votable_headings') + expect(page).to have_content "You cannot destroy a Group that has associated headings" + expect(page).to have_selector "#budget_group_#{group.id}" + end + + end + + context "New" do + + scenario "Create group" do + visit admin_budget_groups_path(budget) + click_link "Create new group" + + fill_in "Group name", with: "All City" + + click_button "Create new group" + + expect(page).to have_content "Group created successfully!" + expect(page).to have_link "All City" + end + + scenario "Maximum number of headings in which a user can vote is set to 1 by default" do + visit new_admin_budget_group_path(budget) + fill_in "Group name", with: "All City" + + click_button "Create new group" + + expect(page).to have_content "Group created successfully!" + expect(Budget::Group.first.max_votable_headings).to be 1 + end + + scenario "Group name is mandatory" do + visit new_admin_budget_group_path(budget) + click_button "Create new group" + + expect(page).not_to have_content "Group created successfully!" + expect(page).to have_css("label.error", text: "Group name") + expect(page).to have_content "can't be blank" + end + + end + + context "Edit" do + + scenario "Show group information" do + group = create(:budget_group, budget: budget, max_votable_headings: 2) + 2.times { create(:budget_heading, group: group) } + + visit admin_budget_groups_path(budget) + within("#budget_group_#{group.id}") { click_link "Edit" } + + expect(page).to have_field "Group name", with: group.name + expect(page).to have_field "Maximum number of headings in which a user can vote", with: "2" + end + + end + + context "Update" do + let!(:group) { create(:budget_group, budget: budget, name: "All City") } + + scenario "Updates group" do + 2.times { create(:budget_heading, group: group) } + + visit edit_admin_budget_group_path(budget, group) + expect(page).to have_field "Group name", with: "All City" + + fill_in "Group name", with: "Districts" + select "2", from: "Maximum number of headings in which a user can vote" + click_button "Edit group" + + expect(page).to have_content "Group updated successfully" + + visit edit_admin_budget_group_path(budget, group) + expect(page).to have_field "Group name", with: "Districts" + expect(page).to have_field "Maximum number of headings in which a user can vote", with: "2" + end + + scenario "Group name is already used" do + create(:budget_group, budget: budget, name: "Districts") + + visit edit_admin_budget_group_path(budget, group) + expect(page).to have_field "Group name", with: "All City" + + fill_in "Group name", with: "Districts" + click_button "Edit group" + + expect(page).not_to have_content "Group updated successfully" + expect(page).to have_css("label.error", text: "Group name") + expect(page).to have_content "has already been taken" end end diff --git a/spec/features/admin/budget_headings_spec.rb b/spec/features/admin/budget_headings_spec.rb new file mode 100644 index 000000000..92e1fe4fd --- /dev/null +++ b/spec/features/admin/budget_headings_spec.rb @@ -0,0 +1,208 @@ +require 'rails_helper' + +feature "Admin budget headings" do + + let(:budget) { create(:budget, phase: "drafting") } + let(:group) { create(:budget_group, budget: budget) } + + background do + admin = create(:administrator) + login_as(admin.user) + end + + context "Feature flag" do + + background do + Setting["feature.budgets"] = nil + end + + after do + Setting["feature.budgets"] = true + end + + scenario "Disabled with a feature flag" do + expect { visit admin_budget_group_headings_path(budget, group) }.to raise_exception(FeatureFlags::FeatureDisabled) + end + + end + + context "Index" do + + scenario "Displaying no headings for group" do + visit admin_budget_group_headings_path(budget, group) + + expect(page).to have_content "No headings created yet. Each user will be able to vote in only one heading per group." + end + + scenario "Displaying headings" do + heading1 = create(:budget_heading, group: group, price: 1000, allow_custom_content: true) + heading2 = create(:budget_heading, group: group, price: 2000, population: 10000) + heading3 = create(:budget_heading, group: group, price: 3000, population: 10000) + + visit admin_budget_group_headings_path(budget, group) + expect(page).to have_content "There are 3 headings" + + within "#budget_heading_#{heading1.id}" do + expect(page).to have_content(heading1.name) + expect(page).to have_content "€1,000" + expect(page).not_to have_content "10000" + expect(page).to have_content "Yes" + expect(page).to have_link "Edit", href: edit_admin_budget_group_heading_path(budget, group, heading1) + expect(page).to have_link "Delete", href: admin_budget_group_heading_path(budget, group, heading1) + end + + within "#budget_heading_#{heading2.id}" do + expect(page).to have_content(heading2.name) + expect(page).to have_content "€2,000" + expect(page).to have_content "10000" + expect(page).to have_content "No" + expect(page).to have_link "Edit", href: edit_admin_budget_group_heading_path(budget, group, heading2) + expect(page).to have_link "Delete", href: admin_budget_group_heading_path(budget, group, heading2) + end + + within "#budget_heading_#{heading3.id}" do + expect(page).to have_content(heading3.name) + expect(page).to have_content "€3,000" + expect(page).to have_content "10000" + expect(page).to have_content "No" + expect(page).to have_link "Edit", href: edit_admin_budget_group_heading_path(budget, group, heading3) + expect(page).to have_link "Delete", href: admin_budget_group_heading_path(budget, group, heading3) + end + end + + scenario "Delete a heading without investments" do + heading = create(:budget_heading, group: group) + + visit admin_budget_group_headings_path(budget, group) + within("#budget_heading_#{heading.id}") { click_link "Delete" } + + expect(page).to have_content "Heading deleted successfully" + expect(page).not_to have_selector "#budget_heading_#{heading.id}" + end + + scenario "Try to delete a heading with investments" do + heading = create(:budget_heading, group: group) + investment = create(:budget_investment, heading: heading) + + visit admin_budget_group_headings_path(budget, group) + within("#budget_heading_#{heading.id}") { click_link "Delete" } + + expect(page).to have_content "You cannot destroy a Heading that has associated investments" + expect(page).to have_selector "#budget_heading_#{heading.id}" + end + + end + + context "New" do + + scenario "Create heading" do + visit admin_budget_group_headings_path(budget, group) + click_link "Create new heading" + + fill_in "Heading name", with: "All City" + fill_in "Amount", with: "1000" + fill_in "Population (optional)", with: "10000" + check "Allow content block" + + click_button "Create new heading" + + expect(page).to have_content "Heading created successfully!" + expect(page).to have_link "All City" + expect(page).to have_content "€1,000" + expect(page).to have_content "10000" + expect(page).to have_content "Yes" + end + + scenario "Heading name is mandatory" do + visit new_admin_budget_group_heading_path(budget, group) + click_button "Create new heading" + + expect(page).not_to have_content "Heading created successfully!" + expect(page).to have_css("label.error", text: "Heading name") + expect(page).to have_content "can't be blank" + end + + scenario "Heading amount is mandatory" do + visit new_admin_budget_group_heading_path(budget, group) + click_button "Create new heading" + + expect(page).not_to have_content "Heading created successfully!" + expect(page).to have_css("label.error", text: "Amount") + expect(page).to have_content "can't be blank" + end + + end + + context "Edit" do + + scenario "Show heading information" do + heading = create(:budget_heading, group: group) + + visit admin_budget_group_headings_path(budget, group) + within("#budget_heading_#{heading.id}") { click_link "Edit" } + + expect(page).to have_field "Heading name", with: heading.name + expect(page).to have_field "Amount", with: heading.price + expect(page).to have_field "Population (optional)", with: heading.population + expect(page).to have_field "Longitude", with: heading.longitude + expect(page).to have_field "Latitude", with: heading.latitude + expect(find_field("Allow content block")).not_to be_checked + end + + end + + context "Update" do + let(:heading) { create(:budget_heading, + group: group, + name: "All City", + price: 1000, + population: 10000, + longitude: 20.50, + latitude: -10.50, + allow_custom_content: true) } + + scenario "Updates group" do + visit edit_admin_budget_group_heading_path(budget, group, heading) + + expect(page).to have_field "Heading name", with: "All City" + expect(page).to have_field "Amount", with: 1000 + expect(page).to have_field "Population (optional)", with: 10000 + expect(page).to have_field "Longitude", with: 20.50 + expect(page).to have_field "Latitude", with: -10.50 + expect(find_field("Allow content block")).to be_checked + + fill_in "Heading name", with: "Districts" + fill_in "Amount", with: "2000" + fill_in "Population (optional)", with: "20000" + fill_in "Longitude", with: "-40.47" + fill_in "Latitude", with: "25.25" + uncheck "Allow content block" + click_button "Edit heading" + + expect(page).to have_content "Heading updated successfully" + + visit edit_admin_budget_group_heading_path(budget, group, heading) + expect(page).to have_field "Heading name", with: "Districts" + expect(page).to have_field "Amount", with: 2000 + expect(page).to have_field "Population (optional)", with: 20000 + expect(page).to have_field "Longitude", with: -40.47 + expect(page).to have_field "Latitude", with: 25.25 + expect(find_field("Allow content block")).not_to be_checked + end + + scenario "Heading name is already used" do + create(:budget_heading, group: group, name: "Districts") + + visit edit_admin_budget_group_heading_path(budget, group, heading) + expect(page).to have_field "Heading name", with: "All City" + + fill_in "Heading name", with: "Districts" + click_button "Edit heading" + + expect(page).not_to have_content "Heading updated successfully" + expect(page).to have_css("label.error", text: "Heading name") + expect(page).to have_content "has already been taken" + end + + end +end diff --git a/spec/features/admin/budgets_spec.rb b/spec/features/admin/budgets_spec.rb index 3ab17c18f..ffd67f457 100644 --- a/spec/features/admin/budgets_spec.rb +++ b/spec/features/admin/budgets_spec.rb @@ -227,109 +227,6 @@ feature 'Admin budgets' do end end - - context 'Manage groups and headings' do - - scenario 'Create group', :js do - budget = create(:budget, name: 'Yearly budget') - - visit admin_budgets_path - - within("#budget_#{budget.id}") do - click_link 'Edit headings groups' - end - - expect(page).to have_content '0 Groups of budget headings' - expect(page).to have_content 'No groups created yet.' - - click_link 'Add new group' - - fill_in 'budget_group_name', with: 'Health' - click_button 'Create group' - - expect(page).to have_content '1 Group of budget headings' - expect(page).to have_content 'Health' - expect(page).to have_content 'Yearly budget' - expect(page).not_to have_content 'No groups created yet.' - - visit admin_budgets_path - within("#budget_#{budget.id}") do - click_link 'Edit headings groups' - end - - expect(page).to have_content '1 Group of budget headings' - expect(page).to have_content 'Health' - expect(page).to have_content 'Yearly budget' - expect(page).not_to have_content 'No groups created yet.' - end - - scenario 'Create heading', :js do - budget = create(:budget, name: 'Yearly budget') - group = create(:budget_group, budget: budget, name: 'Districts improvments') - - visit admin_budget_path(budget) - - within("#budget_group_#{group.id}") do - expect(page).to have_content 'This group has no assigned heading.' - click_link 'Add heading' - - fill_in 'budget_heading_name', with: 'District 9 reconstruction' - fill_in 'budget_heading_price', with: '6785' - fill_in 'budget_heading_population', with: '100500' - fill_in 'budget_heading_latitude', with: '40.416775' - fill_in 'budget_heading_longitude', with: '-3.703790' - click_button 'Save heading' - end - - visit admin_budget_path(budget) - - within("#budget_group_#{group.id}") do - expect(page).not_to have_content 'This group has no assigned heading.' - expect(page).to have_content 'District 9 reconstruction' - expect(page).to have_content '€6,785' - expect(page).to have_content '100500' - end - end - - scenario 'Update heading', :js do - budget = create(:budget, name: 'Yearly budget') - group = create(:budget_group, budget: budget, name: 'Districts improvments') - heading = create(:budget_heading, group: group, name: "District 1") - heading = create(:budget_heading, group: group, name: "District 3") - - visit admin_budget_path(budget) - - within("#heading-#{heading.id}") do - click_link 'Edit' - - fill_in 'budget_heading_name', with: 'District 2' - fill_in 'budget_heading_price', with: '10000' - fill_in 'budget_heading_population', with: '6000' - click_button 'Save heading' - end - - expect(page).to have_content 'District 2' - expect(page).to have_content '€10,000' - expect(page).to have_content '6000' - end - - scenario 'Delete heading', :js do - budget = create(:budget, name: 'Yearly budget') - group = create(:budget_group, budget: budget, name: 'Districts improvments') - heading = create(:budget_heading, group: group, name: "District 1") - - visit admin_budget_path(budget) - - expect(page).to have_content 'District 1' - - within("#heading-#{heading.id}") do - click_link 'Delete' - end - - expect(page).not_to have_content 'District 1' - end - - end end def translated_phase_name(phase_kind: kind) diff --git a/spec/features/budgets/ballots_spec.rb b/spec/features/budgets/ballots_spec.rb index 309f1b531..5d93cee85 100644 --- a/spec/features/budgets/ballots_spec.rb +++ b/spec/features/budgets/ballots_spec.rb @@ -161,6 +161,34 @@ feature 'Ballots' do end end + scenario "the Map shoud be visible before and after", :js do + investment = create(:budget_investment, :selected, heading: new_york, price: 10000) + + visit budget_path(budget) + click_link "States" + click_link "New York" + + within("#sidebar") do + expect(page).to have_content "OpenStreetMap" + end + + add_to_ballot(investment) + + within("#sidebar") do + expect(page).to have_content investment.title + expect(page).to have_content "OpenStreetMap" + end + + within("#budget_investment_#{investment.id}") do + click_link "Remove vote" + end + + within("#sidebar") do + expect(page).not_to have_content investment.title + expect(page).to have_content "OpenStreetMap" + end + end + end #Break up or simplify with helpers